source: MondoRescue/branches/2.2.2/mondo/src/mondorestore/mondo-prep.c@ 1315

Last change on this file since 1315 was 1315, checked in by Bruno Cornec, 17 years ago

Log files are now consistent: mondoarchive.log for mondoarchive (containing also mindi.log) and mondorestore.log for mondorestore (copied from /tmp (ram) to /var/log (disk) at the end of the restore)
One include has been created for each bianry containing only that declaration ofr the moment, but which will be extended to include all local definitions (ps_* e.g.)
Doc updated accordingly
LOGFILE in restore process is now passed in the environment and not duplicated anymore
LogIt is not redifined either
LOGFILE should be put in environment by mondoarchive for mindi's usage but that's a step left for later.

  • Property svn:keywords set to Id
File size: 79.6 KB
Line 
1/***************************************************************************
2mondo-prep.c - description
3-----------------
4
5begin: Fri Apr 19 16:40:35 EDT 2002
6copyright : (C) 2002 Mondo Hugo Rabson
7email : Hugo Rabson <hugorabson@msn.com>
8edited by : by Stan Benoit 4/2002
9email : troff@nakedsoul.org
10cvsid : $Id: mondo-prep.c 1315 2007-04-16 14:13:59Z bruno $
11***************************************************************************/
12
13/***************************************************************************
14 * *
15 * This program is free software; you can redistribute it and/or modify *
16 * it under the terms of the GNU General Public License as published by *
17 * the Free Software Foundation; either version 2 of the License, or *
18 * (at your option) any later version. *
19 * *
20 ***************************************************************************/
21
22/* mondo-prep.c Hugo Rabson
23
24
25
2607/20
27- when starting RAID, don't do it twice :)
28- moved Joshua's new get_phys_size_of_drive() code
29 from resize_drive... into get_phys_size_of_drive()
30
3106/29
32- make sure software RAID devices are formatted IF user says they're to be
33- drivelist is struct now, not char[][]
34
3506/26
36- drop make_relevant_partition_bootable(); do it yourself in C (mostly)
37- offer to reboot if partition table is locked up by the kernel
38
3906/22
40- be sure not to resize non-NTFS images when restoring
41- set non-NTFS images' partition types properly
42
4306/19
44- shut down all LVMs and VGs before prepping
45
4605/07
47- usage of parted2fdisk instead of fdisk alone (ia32/ia64 compatibility)
48 BCO
49
5003/31
51- rewrote partitioning and formatting code to call fdisk once per disk
52
5310/21/2003
54- suspend/resume Newt gui before/after calling do_my_funky_lvm_stuff()
55
5610/20
57- rewrote format_everything() - what a mess it was.
58 It now does things in three phases:-
59 - formats software RAID devices (/dev/md0, etc.)
60 - formats and configures LVM devices
61 - formats regular partitions (/dev/hda1, /dev/sdb2, etc.)
62 and any LVMs recently prepped
63
6410/07
65- use strstr(format, "raid") instead of strcmp(format,"raid") to determin
66 if partition is a RAID component
67
6809/23
69- better comments
70
7109/18
72- better logging of RAID activity
73
7405/05
75- added Joshua Oreman's FreeBSD patches
76
7704/30
78- added textonly mode
79
8004/24
81- added lots of assert()'s and log_OS_error()'s
82
8304/21
84- format_everything() --- don't let bar go too far
85- mkfs -c to check for bad blocks when formatting
86
8704/04
88- misc clean-up (Tom Mortell)
89
9001/15/2003
91- added code for LVM and SW Raid (Brian Borgeson)
92
9312/10/2002
94- line 1238: friendlier output
95
9611/20
97- when wiping a given device in preparation for partitioning + formatting
98 it, don't wipe the MBR; just the partition table. That allows for
99 stupid-ass Compaq users who like to play with their MBR's.
100- disable mountlist.txt-->mountlist.txt.pre-resize copying (superfluous)
101
10209/09
103- run_program_and_log_output() now takes boolean operator to specify
104 whether it will log its activities in the event of _success_
105
10607/01 - 07/31
107- added hooks to libmondo
108- RAID enhancements (Philippe de Muyter)
109
11001/01 - 03/31
111- partition_device() will refuse to partition /dev/mdX now (cos it's a
112 virtual drive); however, it will return 0 (i.e. not an error)
113- make_list_of_drives() will exclude /dev/md* from list
114- mkreiserfs -ff instead of -q (Andy Glass)
115- don't resize drive if drive not found (or if its size cannot be det'd)
116- when generating list of drives from mountlist, skip the 'p' at the end
117 of drive name if /dev/ida/ or /dev/cciss/; just do it (Michael Eisenberg)
118- don't specify journal size when formatting ext3
119 (used to have -Jsize=10 in the call to mkfs)
120- handles files >2GB in size
121- format interactively, if Interactive Mode
122- removed reference to g_tape_size
123- when executing /tmp/i-want-my-lvm, only record the error# if the command
124 was _not_ an 'insmod' command
125- pass partition size to fdisk in Kilobytes now, not Megabytes
126- log fdisk's output to /tmp/mondo-restore.log if it fails
127- don't try to format partitions of type 'image'
128- don't type to set types of 'image' partitions
129- if format code is 1 or 2 chars then assume it is a hex string
130- took out all '/ /' comments
131- don't extrapolate/add partition from RAID dev to mountlist if it's already
132 present in mountlist
133- less repetitive logging in the event of vacuum-packing of last part'n
134- no extrapolation at all: RAID partitions should be listed in mountlist
135 already, thanks to either Mindi v0.5x or the mountlist editor itself
136- no longer say, 'and logging to...' when setting a partition's type
137- don't run mkfs on RAID partitions (/dev/hd*, /dev/sd*); just set type
138- the setting of a partition's type now takes place in a separate subroutine
139 from the subroutine that actually creates the partition
140- no need to set type if 83: 83 is the default (under fdisk)
141- turned on '-Wall'; cleaned up some cruft
142- if vacuum-packing partition (i.e. size=0MB --> max) then say, "(maximum)"
143 not, "(0 MB)"
144
14511/22/2001
146- preliminary code review
147- created on Nov 22nd, 2001
148*/
149
150/**
151 * @file
152 * Functions for prepping hard drives: partitioning, formatting, etc.
153 */
154
155
156#include "../common/my-stuff.h"
157#include "../common/mondostructures.h"
158#include "mondoprep.h"
159#include "../common/libmondo.h"
160#include "mondo-rstr-tools-EXT.h"
161#include <sys/ioctl.h>
162#include <linux/hdreg.h>
163#include <math.h>
164
165
166#define FDISK_LOG "/tmp/fdisk.log"
167
168#ifdef __FreeBSD__
169#define DKTYPENAMES
170#define FSTYPENAMES
171#include <sys/disklabel.h>
172#include <sys/disk.h>
173#include <err.h>
174#include <libgen.h>
175#define OSSWAP(x,y) y
176#else
177#define OSSWAP(x,y) x
178#endif
179
180#define ARCHIVES_PATH MNT_CDROM"/archives"
181#define MONDO_WAS_HERE "MONDOWOZEREMONDOWOZEREMONDOWOZEREhahahaMOJOJOJO"
182
183//static char cvsid[] = "$Id: mondo-prep.c 1315 2007-04-16 14:13:59Z bruno $";
184
185extern char *g_mountlist_fname;
186extern long g_current_progress, g_maximum_progress;
187
188extern bool g_text_mode;
189
190extern void pause_for_N_seconds(int, char *);
191
192
193FILE *g_fprep = NULL;
194
195
196
197int g_partition_table_locked_up = 0;
198
199
200
201
202
203
204
205
206
207
208void wipe_MBRs_and_reboot_if_necessary(struct mountlist_itself *mountlist)
209{
210 char *command;
211 char *tmp;
212 int lino;
213 int i;
214 FILE *fout;
215 char *buf;
216 const int blocksize = 512;
217 struct list_of_disks *drivelist = NULL;
218// If LVMs are present and a zero-and-reboot wasn't recently undertaken
219// then zero & insist on reboot.
220 malloc_string(command);
221 malloc_string(tmp);
222 buf = malloc(blocksize);
223 if (does_file_exist("/tmp/i-want-my-lvm")) // FIXME - cheating :)
224 {
225 drivelist = malloc(sizeof(struct list_of_disks));
226 make_list_of_drives_in_mountlist(mountlist, drivelist);
227 for (lino = 0; lino < drivelist->entries; lino++) {
228 sprintf(command,
229 "dd if=%s bs=512 count=1 2> /dev/null | grep \"%s\"",
230 drivelist->el[lino].device, MONDO_WAS_HERE);
231 if (!run_program_and_log_output(command, 1)) {
232 log_msg(1, "Found MONDO_WAS_HERE marker on drive#%d (%s)",
233 lino, drivelist->el[lino].device);
234 break;
235 }
236 }
237
238 if (lino == drivelist->entries) {
239// zero & reboot
240 log_to_screen
241 ("I am sorry for the inconvenience but I must ask you to reboot.");
242 log_to_screen
243 ("I need to reset the Master Boot Record; in order to be");
244 log_to_screen
245 ("sure the kernel notices, I must reboot after doing it.");
246 log_to_screen("Please hit 'Enter' to reboot.");
247 for (lino = 0; lino < drivelist->entries; lino++) {
248 for (i = 0; i < blocksize; i++) {
249 buf[i] = 0;
250 }
251 sprintf(buf, "%s\n", MONDO_WAS_HERE);
252 fout = fopen(drivelist->el[lino].device, "w+");
253 if (!fout) {
254 log_msg(1, "Unable to open+wipe %s",
255 drivelist->el[lino].device);
256 } else {
257 if (1 != fwrite(buf, blocksize, 1, fout)) {
258 log_msg(1, "Failed to wipe %s",
259 drivelist->el[lino].device);
260 } else {
261 log_msg(1, "Successfully wiped %s",
262 drivelist->el[lino].device);
263 }
264 fclose(fout);
265 }
266 }
267 system("sync");
268 system("sync");
269 system("sync");
270 popup_and_OK
271 ("I must now reboot. Please leave the boot media in the drive and repeat your actions - e.g. type 'nuke' - and it should work fine.");
272 system("reboot");
273 }
274 }
275// Still here? Cool!
276 paranoid_free(command);
277 paranoid_free(tmp);
278 log_msg(1, "Cool. I didn't have to wipe anything.");
279}
280
281
282
283
284
285
286int fput_string_one_char_at_a_time(FILE * fout, char *str)
287{
288 int i, j;
289 FILE *fq;
290
291 if (ferror(fout)) {
292 return (-1);
293 }
294 log_msg(5, "Writing string '%s', one char at a time", str);
295 j = strlen(str);
296 for (i = 0; i < j; i++) {
297 log_msg(6, "Writing %d ('%c')", str[i], str[i]);
298 if ((fq = fopen(FDISK_LOG, "a+"))) {
299 fputc(str[i], fq);
300 fclose(fq);
301 }
302 fputc(str[i], fout);
303 fflush(fout);
304 usleep(1000L * 100L);
305 if (str[i] < 32) {
306 usleep(1000L * 10L);
307 }
308 }
309 log_msg(5, "Returning");
310
311 return (i);
312}
313
314
315
316
317
318
319
320
321
322
323/**
324 * @addtogroup prepGroup
325 * @{
326 */
327/**
328 * Execute the commands in /tmp/i-want-my-lvm.
329 * These should probably be commands to set up LVM.
330 * @return The number of errors encountered (0 for success).
331 */
332
333
334int do_my_funky_lvm_stuff(bool just_erase_existing_volumes,
335 bool vacuum_pack)
336{
337 /** buffers **********************************************/
338 char *tmp;
339 char *tmp1 = NULL;
340 char *incoming;
341 char *command;
342 char *lvscan_sz;
343 char *lvremove_sz;
344 char *pvscan_sz;
345 char *vgscan_sz;
346 char *vgcreate_sz;
347 char *vgchange_sz;
348 char *vgremove_sz;
349// char *do_this_last;
350
351 /** char **************************************************/
352 char *p;
353 char *q;
354
355 /** int ***************************************************/
356 int retval = 0;
357 int res = 0;
358 int i;
359 int lvmversion = 1;
360 long extents;
361 fpos_t orig_pos;
362
363 /** pointers **********************************************/
364 FILE *fin;
365
366 /** end *****************************************************/
367
368#ifdef __FreeBSD__
369 return (0);
370#endif
371
372 if (!(fin = fopen("/tmp/i-want-my-lvm", "r"))) {
373 log_OS_error("/tmp/i-want-my-lvm");
374 return (1);
375 }
376
377 malloc_string(tmp);
378 malloc_string(incoming);
379 malloc_string(lvscan_sz);
380 malloc_string(lvremove_sz);
381 malloc_string(vgscan_sz);
382 malloc_string(pvscan_sz);
383 malloc_string(vgcreate_sz);
384 malloc_string(vgchange_sz);
385 malloc_string(vgremove_sz);
386// malloc_string(do_this_last); // postpone lvcreate call if necessary
387 command = malloc(512);
388
389// do_this_last[0] = '\0';
390 iamhere("STARTING");
391 log_msg(1, "OK, opened i-want-my-lvm. Shutting down LVM volumes...");
392 if (find_home_of_exe("lvm")) // found it :) cool
393 {
394 strcpy(lvscan_sz, "lvm lvscan");
395 strcpy(lvremove_sz, "lvm lvremove");
396 strcpy(vgscan_sz, "lvm vgscan");
397 strcpy(pvscan_sz, "lvm pvscan");
398 strcpy(vgcreate_sz, "lvm vgcreate");
399 strcpy(vgchange_sz, "lvm vgchange");
400 strcpy(vgremove_sz, "lvm vgremove");
401 } else {
402 strcpy(lvscan_sz, "lvscan");
403 strcpy(lvremove_sz, "lvremove");
404 strcpy(vgscan_sz, "vgscan");
405 strcpy(pvscan_sz, "pvscan");
406 strcpy(vgcreate_sz, "vgcreate");
407 strcpy(vgchange_sz, "vgchange");
408 strcpy(vgremove_sz, "vgremove");
409 }
410 sprintf(command,
411 "for i in `%s | cut -d\"'\" -f2 | sort -r` ; do echo \"Shutting down lv $i\" >> "
412 MONDO_LOGFILE "; %s -f $i; done", lvscan_sz, lvremove_sz);
413 run_program_and_log_output(command, 5);
414 sleep(1);
415 sprintf(command,
416 "for i in `%s | grep -i lvm | cut -d'\"' -f2` ; do %s -a n $i ; %s $i; echo \"Shutting down vg $i\" >> "
417 MONDO_LOGFILE "; done", vgscan_sz, vgchange_sz, vgremove_sz);
418 run_program_and_log_output(command, 5);
419 if (just_erase_existing_volumes) {
420 paranoid_fclose(fin);
421 log_msg(1, "Closed i-want-my-lvm. Finished erasing LVMs.");
422 retval = 0;
423 goto end_of_i_want_my_lvm;
424 }
425
426 log_msg(1, "OK, rewound i-want-my-lvm. Doing funky stuff...");
427 rewind(fin);
428 for (fgets(incoming, 512, fin); !feof(fin); fgets(incoming, 512, fin)) {
429 fgetpos(fin, &orig_pos);
430 if (incoming[0] != '#') {
431 continue;
432 }
433 if (res && strstr(command, "create") && vacuum_pack) {
434 sleep(2);
435 system("sync");
436 system("sync");
437 system("sync");
438 }
439 if ((p = strstr(incoming, "vgcreate"))) {
440// include next line(s) if they end in /dev (cos we've got a broken i-want-my-lvm)
441 for (fgets(tmp, 512, fin); !feof(fin); fgets(tmp, 512, fin)) {
442 if (tmp[0] == '#') {
443 fsetpos(fin, &orig_pos);
444 break;
445 } else {
446 fgetpos(fin, &orig_pos);
447 strcat(incoming, tmp);
448 }
449 }
450 for (q = incoming; *q != '\0'; q++) {
451 if (*q < 32) {
452 *q = ' ';
453 }
454 }
455 strcpy(tmp, p + strlen("vgcreate") + 1);
456 for (q = tmp; *q > 32; q++);
457 *q = '\0';
458 log_msg(1, "Deleting old entries at /dev/%s", tmp);
459// sprintf(command, "%s -f %s", vgremove_sz, tmp);
460// run_program_and_log_output(command, 1);
461 sprintf(command, "rm -Rf /dev/%s", tmp);
462 run_program_and_log_output(command, 1);
463 run_program_and_log_output(vgscan_sz, 1);
464 run_program_and_log_output(pvscan_sz, 1);
465 log_msg(3,
466 "After working around potentially broken i-want-my-lvm, incoming[] is now '%s'",
467 incoming);
468 }
469 for (p = incoming + 1; *p == ' '; p++);
470 strcpy(command, p);
471 for (p = command; *p != '\0'; p++);
472 for (; *(p - 1) < 32; p--);
473 *p = '\0';
474 res = run_program_and_log_output(command, 5);
475 if (res > 0 && (p = strstr(command, "lvm "))) {
476 *p = *(p + 1) = *(p + 2) = ' ';
477 res = run_program_and_log_output(command, 5);
478 }
479 log_msg(0, "%s --> %d", command, res);
480 if (res > 0) {
481 res = 1;
482 }
483 if (res && strstr(command, "lvcreate") && vacuum_pack) {
484 res = 0;
485 if (strstr(command, "lvm lvcreate"))
486 lvmversion = 2;
487 log_it("%s... so I'll get creative.", tmp);
488 if (lvmversion == 2) {
489 asprintf(&tmp1, "tail -n5 %s | grep Insufficient | tail -n1", MONDO_LOGFILE);
490 strcpy(tmp, call_program_and_get_last_line_of_output(tmp1));
491 free(tmp1);
492 } else {
493 asprintf(&tmp1, "tail -n5 %s | grep lvcreate | tail -n1", MONDO_LOGFILE);
494 strcpy(tmp, call_program_and_get_last_line_of_output(tmp1));
495 free(tmp1);
496 }
497 for (p = tmp; *p != '\0' && !isdigit(*p); p++);
498 extents = atol(p);
499 log_msg(5, "p='%s' --> extents=%ld", p, extents);
500 p = strstr(command, "-L");
501 if (!p) {
502 log_msg(0, "Fiddlesticks. '%s' returned %d", command, res);
503 } else {
504 if (lvmversion == 2) {
505 *p++ = '-';
506 *p++ = 'l';
507 *p++ = ' ';
508 for (q = p; *q != ' '; q++) {
509 *q = ' ';
510 }
511 sprintf(p, "%ld", extents);
512 i = strlen(p);
513 *(p + i) = ' ';
514 } else {
515 p++;
516 p++;
517 p++;
518 for (q = p; *q != ' '; q++) {
519 *(q - 1) = ' ';
520 }
521 sprintf(p, "%ld%c", extents, 'm');
522 i = strlen(p);
523 *(p + i) = ' ';
524 }
525 log_msg(5, "Retrying with '%s'", command);
526 res = run_program_and_log_output(command, 5);
527 if (res > 0) {
528 res = 1;
529 }
530 if (g_fprep) {
531 fprintf(g_fprep, "%s\n", command);
532 }
533 log_msg(0, "%s --> %d", command, res);
534 if (!res) {
535 log_msg(5, "YAY! This time, it succeeded.");
536 }
537 }
538 }
539 if (strstr(command, "vgcreate")) {
540 log_msg(0, "In case you're interested...");
541 run_program_and_log_output(vgscan_sz, 1);
542 run_program_and_log_output(pvscan_sz, 1);
543 }
544 if (res != 0 && !strstr(command, "insmod")) {
545 retval++;
546 }
547 sprintf(tmp, "echo \"%s\" >> /tmp/out.sh", command);
548 system(tmp);
549 sleep(1);
550 }
551 paranoid_fclose(fin);
552 log_msg(1, "Closed i-want-my-lvm. Finished doing funky stuff.");
553 end_of_i_want_my_lvm:
554 paranoid_free(tmp);
555 paranoid_free(incoming);
556 paranoid_free(command);
557 paranoid_free(lvscan_sz);
558 paranoid_free(lvremove_sz);
559 paranoid_free(vgscan_sz);
560 paranoid_free(pvscan_sz);
561 paranoid_free(vgcreate_sz);
562 paranoid_free(vgchange_sz);
563 paranoid_free(vgremove_sz);
564// paranoid_free(do_this_last);
565 system("sync");
566 system("sync");
567 system("sync");
568 sleep(1);
569 iamhere("ENDING");
570 if (retval > 2) {
571 log_msg(1, "%d errors. I'm reporting this.", retval);
572 return (retval);
573 } else {
574 log_msg(1, "Not many errors. Returning 0.");
575 return (0);
576 }
577}
578
579
580/**
581 * Add RAID partitions while copying @p old_mountlist to @p new_mountlist.
582 * We go through @p old_mountlist and check if any RAID device (/dev/md? on Linux)
583 * is in it; if it is, then we put the disks contained within that RAID device
584 * into the mountlist as well.
585 * @param old_mountlist The mountlist to read.
586 * @param new_mountlist The mountlist to write, with the RAID partitions added.
587 * @return 0 for success, nonzero for failure.
588 */
589int extrapolate_mountlist_to_include_raid_partitions(struct mountlist_itself
590 *new_mountlist, struct mountlist_itself
591 *old_mountlist)
592{
593 /** pointers *********************************************************/
594 FILE *fin;
595
596 /** int **************************************************************/
597 int lino;
598 int j;
599
600 /** buffers **********************************************************/
601 char *incoming;
602 char *tmp;
603
604 /** pointers *********************************************************/
605 char *p;
606
607 /** init *************************************************************/
608 new_mountlist->entries = 0;
609
610 /** end **************************************************************/
611
612 malloc_string(incoming);
613 malloc_string(tmp);
614 assert(new_mountlist != NULL);
615 assert(old_mountlist != NULL);
616
617#ifdef __FreeBSD__
618 log_to_screen
619 ("I don't know how to extrapolate the mountlist on FreeBSD. Sorry.");
620 return (1);
621#endif
622
623 for (lino = 0; lino < old_mountlist->entries; lino++) {
624 if (strstr(old_mountlist->el[lino].device, RAID_DEVICE_STUB)) // raid
625 {
626 if (!does_file_exist("/etc/raidtab")) {
627 log_to_screen
628 ("Cannot find /etc/raidtab - cannot extrapolate the fdisk entries");
629 finish(1);
630 }
631 if (!(fin = fopen("/etc/raidtab", "r"))) {
632 log_OS_error("Cannot open /etc/raidtab");
633 finish(1);
634 }
635 for (fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin)
636 && !strstr(incoming, old_mountlist->el[lino].device);
637 fgets(incoming, MAX_STR_LEN - 1, fin));
638 if (!feof(fin)) {
639 sprintf(tmp, "Investigating %s",
640 old_mountlist->el[lino].device);
641 log_it(tmp);
642 for (fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin)
643 && !strstr(incoming, "raiddev");
644 fgets(incoming, MAX_STR_LEN - 1, fin)) {
645 if (strstr(incoming, OSSWAP("device", "drive"))
646 && !strchr(incoming, '#')) {
647 for (p = incoming + strlen(incoming);
648 *(p - 1) <= 32; p--);
649 *p = '\0';
650 for (p--; p > incoming && *(p - 1) > 32; p--);
651 sprintf(tmp, "Extrapolating %s", p);
652 log_it(tmp);
653 for (j = 0;
654 j < new_mountlist->entries
655 && strcmp(new_mountlist->el[j].device, p);
656 j++);
657 if (j >= new_mountlist->entries) {
658 strcpy(new_mountlist->
659 el[new_mountlist->entries].device, p);
660 strcpy(new_mountlist->
661 el[new_mountlist->entries].mountpoint,
662 "raid");
663 strcpy(new_mountlist->
664 el[new_mountlist->entries].format,
665 "raid");
666 new_mountlist->el[new_mountlist->entries].
667 size = old_mountlist->el[lino].size;
668 new_mountlist->entries++;
669 } else {
670 sprintf(tmp,
671 "Not adding %s to mountlist: it's already there",
672 p);
673 log_it(tmp);
674 }
675 }
676 }
677 }
678 paranoid_fclose(fin);
679 } else {
680 strcpy(new_mountlist->el[new_mountlist->entries].device,
681 old_mountlist->el[lino].device);
682 strcpy(new_mountlist->el[new_mountlist->entries].mountpoint,
683 old_mountlist->el[lino].mountpoint);
684 strcpy(new_mountlist->el[new_mountlist->entries].format,
685 old_mountlist->el[lino].format);
686 new_mountlist->el[new_mountlist->entries].size =
687 old_mountlist->el[lino].size;
688 new_mountlist->entries++;
689 }
690 }
691 paranoid_free(incoming);
692 paranoid_free(tmp);
693
694 return (0);
695}
696
697
698/**
699 * Create @p RAID device using information from @p structure.
700 * This will create the specified RAID devive using information provided in
701 * raidlist by means of the mdadm tool.
702 * @param raidlist The structure containing all RAID information
703 * @param device The RAID device to create.
704 * @return 0 for success, nonzero for failure.
705 */
706int create_raid_device_via_mdadm(struct raidlist_itself *raidlist, char *device)
707{
708 /** int **************************************************************/
709 int i = 0;
710 int j = 0;
711 int res = 0;
712
713 /** buffers ***********************************************************/
714 char *devices = NULL;
715 char *strtmp = NULL;
716 char *level = NULL;
717 char *program = NULL;
718
719 // leave straight away if raidlist is initial or has no entries
720 if (!raidlist || raidlist->entries == 0) {
721 log_msg(1, "No RAID arrays found.");
722 return 1;
723 } else {
724 log_msg(1, "%d RAID arrays found.", raidlist->entries);
725 }
726 // find raidlist entry for requested device
727 for (i = 0; i < raidlist->entries; i++) {
728 if (!strcmp(raidlist->el[i].raid_device, device)) break;
729 }
730 // check whether RAID device was found in raidlist
731 if (i == raidlist->entries) {
732 log_msg(1, "RAID device %s not found in list.", device);
733 return 1;
734 }
735 // create device list from normal disks followed by spare ones
736 asprintf(&devices, raidlist->el[i].data_disks.el[0].device);
737 for (j = 1; j < raidlist->el[i].data_disks.entries; j++) {
738 asprintf(&strtmp, "%s", devices);
739 paranoid_free(devices);
740 asprintf(&devices, "%s %s", strtmp,
741 raidlist->el[i].data_disks.el[j].device);
742 paranoid_free(strtmp);
743 }
744 for (j = 0; j < raidlist->el[i].spare_disks.entries; j++) {
745 asprintf(&strtmp, "%s", devices);
746 paranoid_free(devices);
747 asprintf(&devices, "%s %s", strtmp,
748 raidlist->el[i].spare_disks.el[j].device);
749 paranoid_free(strtmp);
750 }
751 // translate RAID level
752 if (raidlist->el[i].raid_level == -2) {
753 asprintf(&level, "multipath");
754 } else if (raidlist->el[i].raid_level == -1) {
755 asprintf(&level, "linear");
756 } else {
757 asprintf(&level, "raid%d", raidlist->el[i].raid_level);
758 }
759 // create RAID device:
760 // - RAID device, number of devices and devices mandatory
761 // - parity algorithm, chunk size and spare devices optional
762 // - faulty devices ignored
763 // - persistent superblock always used as this is recommended
764 asprintf(&program,
765 "mdadm --create --force --run --auto=yes %s --level=%s --raid-devices=%d",
766 raidlist->el[i].raid_device, level,
767 raidlist->el[i].data_disks.entries);
768 if (raidlist->el[i].parity != -1) {
769 asprintf(&strtmp, "%s", program);
770 paranoid_free(program);
771 switch(raidlist->el[i].parity) {
772 case 0:
773 asprintf(&program, "%s --parity=%s", strtmp, "la");
774 break;
775 case 1:
776 asprintf(&program, "%s --parity=%s", strtmp, "ra");
777 break;
778 case 2:
779 asprintf(&program, "%s --parity=%s", strtmp, "ls");
780 break;
781 case 3:
782 asprintf(&program, "%s --parity=%s", strtmp, "rs");
783 break;
784 default:
785 fatal_error("Unknown RAID parity algorithm.");
786 break;
787 }
788 paranoid_free(strtmp);
789 }
790 if (raidlist->el[i].chunk_size != -1) {
791 asprintf(&strtmp, "%s", program);
792 paranoid_free(program);
793 asprintf(&program, "%s --chunk=%d", strtmp, raidlist->el[i].chunk_size);
794 paranoid_free(strtmp);
795 }
796 if (raidlist->el[i].spare_disks.entries > 0) {
797 asprintf(&strtmp, "%s", program);
798 paranoid_free(program);
799 asprintf(&program, "%s --spare-devices=%d", strtmp,
800 raidlist->el[i].spare_disks.entries);
801 paranoid_free(strtmp);
802 }
803 asprintf(&strtmp, "%s", program);
804 paranoid_free(program);
805 asprintf(&program, "%s %s", strtmp, devices);
806 paranoid_free(strtmp);
807 res = run_program_and_log_output(program, 1);
808 // free memory
809 paranoid_free(devices);
810 paranoid_free(level);
811 paranoid_free(program);
812 // return to calling instance
813 return res;
814}
815
816
817/**
818 * Format @p device as a @p format filesystem.
819 * This will use the format command returned by which_format_command_do_i_need().
820 * If @p device is an LVM PV, it will not be formatted, and LVM will be started
821 * (if not already done). If it's an imagedev, software RAID component, or
822 * (under BSD) swap partition, no format will be done.
823 * @param device The device to format.
824 * @param format The filesystem type to format it as.
825 * @return 0 for success, nonzero for failure.
826 */
827int format_device(char *device, char *format, struct raidlist_itself *raidlist)
828{
829 /** int **************************************************************/
830 int res;
831 int retval = 0;
832#ifdef __FreeBSD__
833 static bool vinum_started_yet = FALSE;
834#endif
835
836 /** buffers ***********************************************************/
837 char *program;
838 char *tmp;
839
840 /** end ****************************************************************/
841
842 malloc_string(program);
843 malloc_string(tmp);
844 assert_string_is_neither_NULL_nor_zerolength(device);
845 assert(format != NULL);
846
847 if (strstr(format, "raid")) { // do not form RAID disks; do it to /dev/md* instead
848 sprintf(tmp, "Not formatting %s (it is a RAID disk)", device);
849 log_it(tmp);
850 paranoid_free(program);
851 paranoid_free(tmp);
852 return (0);
853 }
854#ifdef __FreeBSD__
855 if (strcmp(format, "swap") == 0) {
856 log_it("Not formatting %s - it's swap", device);
857 paranoid_free(program);
858 paranoid_free(tmp);
859 return (0);
860 }
861#endif
862 if (strlen(format) <= 2) {
863 sprintf(tmp,
864 "%s has a really small format type ('%s') - this is probably a hexadecimal string, which would suggest the partition is an image --- I shouldn't format it",
865 device, format);
866 log_it(tmp);
867 paranoid_free(program);
868 paranoid_free(tmp);
869 return (0);
870 }
871 if (is_this_device_mounted(device)) {
872 sprintf(tmp, "%s is mounted - cannot format it ", device);
873 log_to_screen(tmp);
874 paranoid_free(program);
875 paranoid_free(tmp);
876 return (1);
877 }
878 if (strstr(device, RAID_DEVICE_STUB)) {
879 newtSuspend();
880#ifdef __FreeBSD__
881 if (!vinum_started_yet) {
882 if (!does_file_exist("/tmp/raidconf.txt")) {
883 log_to_screen
884 ("/tmp/raidconf.txt does not exist. I therefore cannot start Vinum.");
885 } else {
886 int res;
887 res =
888 run_program_and_log_output
889 ("vinum create /tmp/raidconf.txt", TRUE);
890 if (res) {
891 log_to_screen
892 ("`vinum create /tmp/raidconf.txt' returned errors. Please fix them and re-run mondorestore.");
893 finish(1);
894 }
895 vinum_started_yet = TRUE;
896 }
897 }
898
899 if (vinum_started_yet) {
900 FILE *fin;
901 char line[MAX_STR_LEN];
902 sprintf(tmp,
903 "Initializing Vinum device %s (this may take a *long* time)",
904 device);
905 log_to_screen(tmp);
906 /* format raid partition */
907 // sprintf (program, "mkraid --really-force %s", device); --- disabled -- BB, 02/12/2003
908 sprintf(program,
909 "for plex in `vinum lv -r %s | grep '^P' | tr '\t' ' ' | tr -s ' ' | cut -d' ' -f2`; do echo $plex; done > /tmp/plexes",
910 basename(device));
911 system(program);
912 if (g_fprep) {
913 fprintf(g_fprep, "%s\n", program);
914 }
915 fin = fopen("/tmp/plexes", "r");
916 while (fgets(line, MAX_STR_LEN - 1, fin)) {
917 if (strchr(line, '\n'))
918 *(strchr(line, '\n')) = '\0'; // get rid of the \n on the end
919
920 sprintf(tmp, "Initializing plex: %s", line);
921 open_evalcall_form(tmp);
922 sprintf(tmp, "vinum init %s", line);
923 system(tmp);
924 while (1) {
925 sprintf(tmp,
926 "vinum lp -r %s | grep '^S' | head -1 | tr -s ' ' | cut -d: -f2 | cut -f1 | sed 's/^ //' | sed 's/I //' | sed 's/%%//'",
927 line);
928 FILE *pin = popen(tmp, "r");
929 char status[MAX_STR_LEN / 4];
930 fgets(status, MAX_STR_LEN / 4 - 1, pin);
931 pclose(pin);
932
933 if (!strcmp(status, "up")) {
934 break; /* it's done */
935 }
936 update_evalcall_form(atoi(status));
937 usleep(250000);
938 }
939 close_evalcall_form();
940 }
941 fclose(fin);
942 unlink("/tmp/plexes");
943 /* retval+=res; */
944 }
945#else
946 sprintf(tmp, "Initializing RAID device %s", device);
947 log_to_screen(tmp);
948
949// Shouldn't be necessary.
950 log_to_screen("Stopping %s", device);
951 stop_raid_device(device);
952 system("sync");
953 sleep(1);
954 if (g_fprep) {
955 fprintf(g_fprep, "%s\n", program);
956 }
957
958 log_msg(1, "Making %s", device);
959 // use mkraid if it exists, otherwise use mdadm
960 if (run_program_and_log_output("which mkraid", FALSE)) {
961 res = create_raid_device_via_mdadm(raidlist, device);
962 log_msg(1, "Creating RAID device %s via mdadm returned %d", device, res);
963 } else {
964 sprintf(program, "mkraid --really-force %s", device);
965 res = run_program_and_log_output(program, 1);
966 log_msg(1, "%s returned %d", program, res);
967 system("sync");
968 sleep(3);
969 start_raid_device(device);
970 if (g_fprep) {
971 fprintf(g_fprep, "%s\n", program);
972 }
973 }
974 system("sync");
975 sleep(2);
976// log_to_screen("Starting %s", device);
977// sprintf(program, "raidstart %s", device);
978// res = run_program_and_log_output(program, 1);
979// log_msg(1, "%s returned %d", program, res);
980// system("sync"); sleep(1);
981#endif
982 system("sync");
983 sleep(1);
984 newtResume();
985 }
986//#ifndef __FreeBSD__
987//#endif
988
989 if (!strcmp(format, "lvm")) {
990 log_msg(1, "Don't format %s - it's part of an lvm volume", device);
991 paranoid_free(program);
992 paranoid_free(tmp);
993 return (0);
994 }
995 res = which_format_command_do_i_need(format, program);
996 sprintf(tmp, "%s %s", program, device);
997 if (strstr(program, "kludge")) {
998 strcat(tmp, " /");
999 }
1000 sprintf(program, "sh -c 'echo -en \"y\\ny\\ny\\n\" | %s'", tmp);
1001 sprintf(tmp, "Formatting %s as %s", device, format);
1002 update_progress_form(tmp);
1003 res = run_program_and_log_output(program, FALSE);
1004 if (res && strstr(program, "kludge")) {
1005 sprintf(tmp, "Kludge failed; using regular mkfs.%s to format %s",
1006 format, device);
1007#ifdef __FreeBSD__
1008 sprintf(program, "newfs_msdos -F 32 %s", device);
1009#else
1010#ifdef __IA64__
1011 /* For EFI partitions take fat16
1012 * as we want to make small ones */
1013 sprintf(program, "mkfs -t %s -F 16 %s", format, device);
1014#else
1015 sprintf(program, "mkfs -t %s -F 32 %s", format, device);
1016#endif
1017#endif
1018 res = run_program_and_log_output(program, FALSE);
1019 if (g_fprep) {
1020 fprintf(g_fprep, "%s\n", program);
1021 }
1022 }
1023 retval += res;
1024 if (retval) {
1025 strcat(tmp, "...failed");
1026 } else {
1027 strcat(tmp, "...OK");
1028 }
1029
1030 log_to_screen(tmp);
1031 paranoid_free(program);
1032 paranoid_free(tmp);
1033 system("sync");
1034 sleep(1);
1035 return (retval);
1036}
1037
1038
1039
1040
1041
1042/**
1043 * Format all drives (except those excluded by format_device()) in @p mountlist.
1044 * @param mountlist The mountlist containing partitions to be formatted.
1045 * @param interactively If TRUE, then prompt the user before each partition.
1046 * @return The number of errors encountered (0 for success).
1047 */
1048int format_everything(struct mountlist_itself *mountlist, bool interactively,
1049 struct raidlist_itself *raidlist)
1050{
1051 /** int **************************************************************/
1052 int retval = 0;
1053 int lino;
1054 int res;
1055// int i;
1056// struct list_of_disks *drivelist;
1057
1058 /** long *************************************************************/
1059 long progress_step;
1060
1061 /** bools ************************************************************/
1062 bool do_it;
1063
1064 /** buffers **********************************************************/
1065 char *tmp;
1066
1067 /** pointers *********************************************************/
1068 struct mountlist_line *me; // mountlist entry
1069 /** end **************************************************************/
1070
1071 assert(mountlist != NULL);
1072 malloc_string(tmp);
1073 sprintf(tmp, "format_everything (mountlist, interactively = %s",
1074 (interactively) ? "true" : "false");
1075 log_it(tmp);
1076 mvaddstr_and_log_it(g_currentY, 0, "Formatting partitions ");
1077 open_progress_form("Formatting partitions",
1078 "I am now formatting your hard disk partitions.",
1079 "This may take up to five minutes.", "",
1080 mountlist->entries + 1);
1081
1082 progress_step =
1083 (mountlist->entries >
1084 0) ? g_maximum_progress / mountlist->entries : 1;
1085// start soft-raids now (because LVM might depend on them)
1086// ...and for simplicity's sake, let's format them at the same time :)
1087 log_msg(1, "Stopping all RAID devices");
1088 stop_all_raid_devices(mountlist);
1089 system("sync");
1090 system("sync");
1091 system("sync");
1092 sleep(2);
1093 log_msg(1, "Prepare soft-RAIDs"); // prep and format too
1094 for (lino = 0; lino < mountlist->entries; lino++) {
1095 me = &mountlist->el[lino]; // the current mountlist entry
1096 log_msg(2, "Examining %s", me->device);
1097 if (!strncmp(me->device, "/dev/md", 7)) {
1098 if (interactively) {
1099 // ask user if we should format the current device
1100 sprintf(tmp, "Shall I format %s (%s) ?", me->device,
1101 me->mountpoint);
1102 do_it = ask_me_yes_or_no(tmp);
1103 } else {
1104 do_it = TRUE;
1105 }
1106 if (do_it) {
1107 // NB: format_device() also stops/starts RAID device if necessary
1108 retval += format_device(me->device, me->format, raidlist);
1109 }
1110 g_current_progress += progress_step;
1111 }
1112 }
1113 system("sync");
1114 system("sync");
1115 system("sync");
1116 sleep(2);
1117// This last step is probably necessary
1118// log_to_screen("Re-starting software RAIDs...");
1119// start_all_raid_devices(mountlist);
1120// system("sync"); system("sync"); system("sync");
1121// sleep(5);
1122// do LVMs now
1123 log_msg(1, "Creating LVMs");
1124 if (does_file_exist("/tmp/i-want-my-lvm")) {
1125 wait_until_software_raids_are_prepped("/proc/mdstat", 100);
1126 log_to_screen("Configuring LVM");
1127 if (!g_text_mode) {
1128 newtSuspend();
1129 }
1130/*
1131 for(i=0; i<3; i++)
1132 {
1133 res = do_my_funky_lvm_stuff(FALSE, FALSE);
1134 if (!res) { break; }
1135 sleep(3);
1136 res = do_my_funky_lvm_stuff(TRUE, FALSE);
1137 sleep(3);
1138 }
1139 if (res) {
1140 log_msg(1, "Vacuum-packing...");
1141*/
1142 res = do_my_funky_lvm_stuff(FALSE, TRUE);
1143/*
1144 }
1145*/
1146 if (!g_text_mode) {
1147 newtResume();
1148 }
1149 if (!res) {
1150 log_to_screen("LVM initialized OK");
1151 } else {
1152 log_to_screen("Failed to initialize LVM");
1153 }
1154 // retval += res;
1155 if (res) {
1156 retval++;
1157 }
1158 sleep(3);
1159 }
1160// do regulars at last
1161 sleep(2); // woo!
1162 log_msg(1, "Formatting regulars");
1163 for (lino = 0; lino < mountlist->entries; lino++) {
1164 me = &mountlist->el[lino]; // the current mountlist entry
1165 if (!strcmp(me->mountpoint, "image")) {
1166 sprintf(tmp, "Not formatting %s - it's an image", me->device);
1167 log_it(tmp);
1168 } else if (!strcmp(me->format, "raid")) {
1169 sprintf(tmp, "Not formatting %s - it's a raid-let",
1170 me->device);
1171 log_it(tmp);
1172 continue;
1173 } else if (!strcmp(me->format, "lvm")) {
1174 sprintf(tmp, "Not formatting %s - it's an LVM", me->device);
1175 log_it(tmp);
1176 continue;
1177 } else if (!strncmp(me->device, "/dev/md", 7)) {
1178 sprintf(tmp, "Already formatted %s - it's a soft-RAID dev",
1179 me->device);
1180 log_it(tmp);
1181 continue;
1182 } else if (!does_file_exist(me->device)
1183 && strncmp(me->device, "/dev/hd", 7)
1184 && strncmp(me->device, "/dev/sd", 7)) {
1185 sprintf(tmp,
1186 "Not formatting %s yet - doesn't exist - probably an LVM",
1187 me->device);
1188 log_it(tmp);
1189 continue;
1190 } else {
1191 if (interactively) {
1192 // ask user if we should format the current device
1193 sprintf(tmp, "Shall I format %s (%s) ?", me->device,
1194 me->mountpoint);
1195 do_it = ask_me_yes_or_no(tmp);
1196 } else {
1197 do_it = TRUE;
1198 }
1199
1200 if (do_it)
1201 retval += format_device(me->device, me->format, raidlist);
1202 }
1203
1204 // update progress bar
1205 g_current_progress += progress_step;
1206 }
1207
1208
1209 // update progress bar to 100% to compensate for
1210 // rounding errors of the progress_step calculation
1211 if (lino >= mountlist->entries)
1212 g_current_progress = g_maximum_progress;
1213
1214 close_progress_form();
1215
1216 if (retval) {
1217 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1218 log_to_screen
1219 ("Errors occurred during the formatting of your hard drives.");
1220 } else {
1221 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1222 }
1223
1224 sprintf(tmp, "format_everything () - %s",
1225 (retval) ? "failed!" : "finished successfully");
1226 log_it(tmp);
1227
1228 if (g_partition_table_locked_up > 0) {
1229 if (retval > 0 && !interactively) {
1230//123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
1231 log_to_screen
1232 ("Partition table locked up %d times. At least one 'mkfs' (format) command",
1233 g_partition_table_locked_up);
1234 log_to_screen
1235 ("failed. I think these two events are related. Sometimes, fdisk's ioctl() call");
1236 log_to_screen
1237 ("to refresh its copy of the partition table causes the kernel to lock the ");
1238 log_to_screen
1239 ("partition table. I believe this has just happened.");
1240 if (ask_me_yes_or_no
1241 ("Please choose 'yes' to reboot and try again; or 'no' to ignore this warning and continue."))
1242 {
1243 system("sync");
1244 system("sync");
1245 system("sync");
1246 system("reboot");
1247 }
1248 } else {
1249 log_to_screen
1250 ("Partition table locked up %d time%c. However, disk formatting succeeded.",
1251 g_partition_table_locked_up,
1252 (g_partition_table_locked_up == 1) ? '.' : 's');
1253 }
1254 }
1255 newtSuspend();
1256 system("clear");
1257 newtResume();
1258 paranoid_free(tmp);
1259 return (retval);
1260}
1261
1262
1263/**
1264 * Create small dummy partitions to fill in the gaps in partition numbering for @p drivename.
1265 * Each partition created is 32k in size.
1266 * @param drivename The drive to create the dummy partitions on.
1267 * @param devno_we_must_allow_for The lowest-numbered real partition; create
1268 * dummies up to (this - 1).
1269 * @return The number of errors encountered (0 for success).
1270 */
1271int make_dummy_partitions(FILE * pout_to_fdisk, char *drivename,
1272 int devno_we_must_allow_for)
1273{
1274 /** int **************************************************************/
1275 int current_devno;
1276 int previous_devno;
1277 int retval = 0;
1278 int res;
1279
1280 /** buffers **********************************************************/
1281 char *tmp;
1282
1283 /** end **************************************************************/
1284
1285 malloc_string(tmp);
1286 assert_string_is_neither_NULL_nor_zerolength(drivename);
1287
1288 if (devno_we_must_allow_for >= 5) {
1289 sprintf(tmp, "Making dummy primary 1 on %s", drivename);
1290 log_it(tmp);
1291 g_maximum_progress++;
1292 res =
1293 partition_device(pout_to_fdisk, drivename, 1, 0, "ext2",
1294 32000);
1295 retval += res;
1296 previous_devno = 1;
1297 current_devno = 5;
1298 } else {
1299 previous_devno = 0;
1300 current_devno = 1;
1301 }
1302 for (; current_devno < devno_we_must_allow_for; current_devno++) {
1303 sprintf(tmp, "Creating dummy partition %d on %s", current_devno, drivename);
1304 log_it(tmp);
1305 g_maximum_progress++;
1306 res =
1307 partition_device(pout_to_fdisk, drivename, current_devno,
1308 previous_devno, OSSWAP("ext2", "ufs"), 32000);
1309 retval += res;
1310 previous_devno = current_devno;
1311 }
1312 paranoid_free(tmp);
1313 return (previous_devno);
1314}
1315
1316
1317/**
1318 * Decide whether @p mountlist contains any RAID devices.
1319 * @param mountlist The mountlist to examine.
1320 * @return TRUE if it does, FALSE if it doesn't.
1321 */
1322bool mountlist_contains_raid_devices(struct mountlist_itself * mountlist)
1323{
1324 /** int *************************************************************/
1325 int i;
1326 int matching = 0;
1327
1328 /** end **************************************************************/
1329
1330 assert(mountlist != NULL);
1331
1332 for (i = 0; i < mountlist->entries; i++) {
1333 if (strstr(mountlist->el[i].device, RAID_DEVICE_STUB)) {
1334 matching++;
1335 }
1336 }
1337 if (matching) {
1338 return (TRUE);
1339 } else {
1340 return (FALSE);
1341 }
1342}
1343
1344/* The following 2 functions are stolen from /usr/src/sbin/disklabel/disklabel.c */
1345#ifdef __FreeBSD__
1346static void display_disklabel(FILE * f, const struct disklabel *lp)
1347{
1348 int i, j;
1349 const struct partition *pp;
1350
1351 fprintf(f, "# %s\n", "Generated by Mondo Rescue");
1352 if (lp->d_type < DKMAXTYPES)
1353 fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
1354 else
1355 fprintf(f, "type: %u\n", lp->d_type);
1356 fprintf(f, "disk: %.*s\n", (int) sizeof(lp->d_typename),
1357 lp->d_typename);
1358 fprintf(f, "label: %.*s\n", (int) sizeof(lp->d_packname),
1359 lp->d_packname);
1360 fprintf(f, "flags:");
1361 if (lp->d_flags & D_REMOVABLE)
1362 fprintf(f, " removeable");
1363 if (lp->d_flags & D_ECC)
1364 fprintf(f, " ecc");
1365 if (lp->d_flags & D_BADSECT)
1366 fprintf(f, " badsect");
1367 fprintf(f, "\n");
1368 fprintf(f, "bytes/sector: %lu\n", (u_long) lp->d_secsize);
1369 fprintf(f, "sectors/track: %lu\n", (u_long) lp->d_nsectors);
1370 fprintf(f, "tracks/cylinder: %lu\n", (u_long) lp->d_ntracks);
1371 fprintf(f, "sectors/cylinder: %lu\n", (u_long) lp->d_secpercyl);
1372 fprintf(f, "cylinders: %lu\n", (u_long) lp->d_ncylinders);
1373 fprintf(f, "sectors/unit: %lu\n", (u_long) lp->d_secperunit);
1374 fprintf(f, "rpm: %u\n", lp->d_rpm);
1375 fprintf(f, "interleave: %u\n", lp->d_interleave);
1376 fprintf(f, "trackskew: %u\n", lp->d_trackskew);
1377 fprintf(f, "cylinderskew: %u\n", lp->d_cylskew);
1378 fprintf(f, "headswitch: %lu\t\t# milliseconds\n",
1379 (u_long) lp->d_headswitch);
1380 fprintf(f, "track-to-track seek: %ld\t# milliseconds\n",
1381 (u_long) lp->d_trkseek);
1382 fprintf(f, "drivedata: ");
1383 for (i = NDDATA - 1; i >= 0; i--)
1384 if (lp->d_drivedata[i])
1385 break;
1386 if (i < 0)
1387 i = 0;
1388 for (j = 0; j <= i; j++)
1389 fprintf(f, "%lu ", (u_long) lp->d_drivedata[j]);
1390 fprintf(f, "\n\n%u partitions:\n", lp->d_npartitions);
1391 fprintf(f,
1392 "# size offset fstype [fsize bsize bps/cpg]\n");
1393 pp = lp->d_partitions;
1394 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1395 if (pp->p_size) {
1396 fprintf(f, " %c: %8lu %8lu ", 'a' + i, (u_long) pp->p_size,
1397 (u_long) pp->p_offset);
1398 if (pp->p_fstype < FSMAXTYPES)
1399 fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
1400 else
1401 fprintf(f, "%8d", pp->p_fstype);
1402 switch (pp->p_fstype) {
1403
1404 case FS_UNUSED: /* XXX */
1405 fprintf(f, " %5lu %5lu %5.5s ", (u_long) pp->p_fsize,
1406 (u_long) (pp->p_fsize * pp->p_frag), "");
1407 break;
1408
1409 case FS_BSDFFS:
1410 fprintf(f, " %5lu %5lu %5u ", (u_long) pp->p_fsize,
1411 (u_long) (pp->p_fsize * pp->p_frag), pp->p_cpg);
1412 break;
1413
1414 case FS_BSDLFS:
1415 fprintf(f, " %5lu %5lu %5d", (u_long) pp->p_fsize,
1416 (u_long) (pp->p_fsize * pp->p_frag), pp->p_cpg);
1417 break;
1418
1419 default:
1420 fprintf(f, "%20.20s", "");
1421 break;
1422 }
1423 fprintf(f, "\t# (Cyl. %4lu",
1424 (u_long) (pp->p_offset / lp->d_secpercyl));
1425 if (pp->p_offset % lp->d_secpercyl)
1426 putc('*', f);
1427 else
1428 putc(' ', f);
1429 fprintf(f, "- %lu",
1430 (u_long) ((pp->p_offset + pp->p_size +
1431 lp->d_secpercyl - 1) / lp->d_secpercyl -
1432 1));
1433 if (pp->p_size % lp->d_secpercyl)
1434 putc('*', f);
1435 fprintf(f, ")\n");
1436 }
1437 }
1438 fflush(f);
1439}
1440
1441static struct disklabel *get_virgin_disklabel(char *dkname)
1442{
1443 static struct disklabel loclab;
1444 struct partition *dp;
1445 char lnamebuf[BBSIZE];
1446 int f;
1447 u_int secsize, u;
1448 off_t mediasize;
1449
1450 (void) snprintf(lnamebuf, BBSIZE, "%s", dkname);
1451 if ((f = open(lnamebuf, O_RDONLY)) == -1) {
1452 warn("cannot open %s", lnamebuf);
1453 return (NULL);
1454 }
1455
1456 /* New world order */
1457 if ((ioctl(f, DIOCGMEDIASIZE, &mediasize) != 0)
1458 || (ioctl(f, DIOCGSECTORSIZE, &secsize) != 0)) {
1459 close(f);
1460 return (NULL);
1461 }
1462 memset(&loclab, 0, sizeof loclab);
1463 loclab.d_magic = DISKMAGIC;
1464 loclab.d_magic2 = DISKMAGIC;
1465 loclab.d_secsize = secsize;
1466 loclab.d_secperunit = mediasize / secsize;
1467
1468 /*
1469 * Nobody in these enligthened days uses the CHS geometry for
1470 * anything, but nontheless try to get it right. If we fail
1471 * to get any good ideas from the device, construct something
1472 * which is IBM-PC friendly.
1473 */
1474 if (ioctl(f, DIOCGFWSECTORS, &u) == 0)
1475 loclab.d_nsectors = u;
1476 else
1477 loclab.d_nsectors = 63;
1478 if (ioctl(f, DIOCGFWHEADS, &u) == 0)
1479 loclab.d_ntracks = u;
1480 else if (loclab.d_secperunit <= 63 * 1 * 1024)
1481 loclab.d_ntracks = 1;
1482 else if (loclab.d_secperunit <= 63 * 16 * 1024)
1483 loclab.d_ntracks = 16;
1484 else
1485 loclab.d_ntracks = 255;
1486 loclab.d_secpercyl = loclab.d_ntracks * loclab.d_nsectors;
1487 loclab.d_ncylinders = loclab.d_secperunit / loclab.d_secpercyl;
1488 loclab.d_npartitions = MAXPARTITIONS;
1489
1490 /* Various (unneeded) compat stuff */
1491 loclab.d_rpm = 3600;
1492 loclab.d_bbsize = BBSIZE;
1493 loclab.d_interleave = 1;;
1494 strncpy(loclab.d_typename, "amnesiac", sizeof(loclab.d_typename));
1495
1496 dp = &loclab.d_partitions[RAW_PART];
1497 dp->p_size = loclab.d_secperunit;
1498 loclab.d_checksum = dkcksum(&loclab);
1499 close(f);
1500 return (&loclab);
1501}
1502
1503/* End stolen from /usr/src/sbin/disklabel/disklabel.c. */
1504
1505char *canonical_name(char *drivename)
1506{
1507 if (drivename) {
1508 if (strncmp(drivename, "/dev/", 5) == 0) {
1509 return drivename + 5;
1510 }
1511 }
1512 return drivename;
1513}
1514
1515/**
1516 * (BSD only) Create a disklabel on @p drivename according to @p mountlist.
1517 * @param mountlist The mountlist to get the subpartition information from.
1518 * @param drivename The drive or slice to create a disklabel on.
1519 * @param ret If non-NULL, store the created disklabel here.
1520 * @return The number of errors encountered (0 for success).
1521 */
1522int label_drive_or_slice(struct mountlist_itself *mountlist,
1523 char *drivename, struct disklabel *ret)
1524{
1525 char subdev_str[MAX_STR_LEN];
1526 char command[MAX_STR_LEN];
1527 struct disklabel *lp;
1528 int i, lo = 0;
1529 int retval = 0;
1530 char c;
1531 FILE *ftmp;
1532
1533 lp = get_virgin_disklabel(drivename);
1534 for (c = 'a'; c <= 'z'; ++c) {
1535 int idx;
1536 sprintf(subdev_str, "%s%c", drivename, c);
1537 if ((idx = find_device_in_mountlist(mountlist, subdev_str)) < 0) {
1538 lp->d_partitions[c - 'a'].p_size = 0;
1539 lp->d_partitions[c - 'a'].p_fstype = FS_UNUSED;
1540 } else {
1541 lo = c - 'a';
1542 lp->d_partitions[c - 'a'].p_size = mountlist->el[idx].size * 2;
1543 lp->d_partitions[c - 'a'].p_fsize = 0;
1544 lp->d_partitions[c - 'a'].p_frag = 0;
1545 lp->d_partitions[c - 'a'].p_cpg = 0;
1546 if (!strcmp(mountlist->el[idx].format, "ufs")
1547 || !strcmp(mountlist->el[idx].format, "ffs")
1548 || !strcmp(mountlist->el[idx].format, "4.2BSD")) {
1549 lp->d_partitions[c - 'a'].p_fstype = FS_BSDFFS;
1550 lp->d_partitions[c - 'a'].p_fsize = 2048;
1551 lp->d_partitions[c - 'a'].p_frag = 8;
1552 lp->d_partitions[c - 'a'].p_cpg = 64;
1553 } else if (!strcasecmp(mountlist->el[idx].format, "raid")
1554 || !strcasecmp(mountlist->el[idx].format, "vinum")) {
1555 lp->d_partitions[c - 'a'].p_fstype = FS_VINUM;
1556 } else if (!strcmp(mountlist->el[idx].format, "swap")) {
1557 lp->d_partitions[c - 'a'].p_fstype = FS_SWAP;
1558 } else
1559 lp->d_partitions[c - 'a'].p_fstype = FS_OTHER;
1560 }
1561 }
1562
1563 // fix up the offsets
1564 lp->d_partitions[0].p_offset = 0;
1565 lp->d_partitions[RAW_PART].p_offset = 0;
1566 lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
1567 lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
1568
1569 for (i = 1; i < lp->d_npartitions; ++i) {
1570 int lastone;
1571 if ((i == RAW_PART) || (lp->d_partitions[i].p_size == 0))
1572 continue;
1573 for (lastone = i - 1; lastone >= 0; lastone--) {
1574 if ((lp->d_partitions[lastone].p_size)
1575 && (lastone != RAW_PART))
1576 break;
1577 }
1578 lp->d_partitions[i].p_offset =
1579 lp->d_partitions[lastone].p_offset +
1580 lp->d_partitions[lastone].p_size;
1581 }
1582 if (lp->d_partitions[lo].p_offset + lp->d_partitions[lo].p_size >
1583 lp->d_secperunit) {
1584 lp->d_partitions[lo].p_size =
1585 lp->d_secperunit - lp->d_partitions[lo].p_offset;
1586 }
1587
1588 ftmp = fopen("/tmp/disklabel", "w");
1589 display_disklabel(ftmp, lp);
1590 fclose(ftmp);
1591 sprintf(command, "disklabel -wr %s auto", canonical_name(drivename));
1592 retval += run_program_and_log_output(command, TRUE);
1593 sprintf(command, "disklabel -R %s /tmp/disklabel",
1594 canonical_name(drivename));
1595 retval += run_program_and_log_output(command, TRUE);
1596 if (ret)
1597 *ret = *lp;
1598 return retval;
1599}
1600#endif
1601
1602
1603/**
1604 * Partition @p drivename based on @p mountlist.
1605 * @param mountlist The mountlist to use to guide the partitioning.
1606 * @param drivename The drive to partition.
1607 * @return 0 for success, nonzero for failure.
1608 */
1609int partition_drive(struct mountlist_itself *mountlist, char *drivename)
1610{
1611 /** int *************************************************************/
1612 int current_devno;
1613 int previous_devno = 0;
1614 int lino;
1615 int retval = 0;
1616 int i;
1617 FILE *pout_to_fdisk = NULL;
1618
1619#ifdef __FreeBSD__
1620 bool fbsd_part = FALSE;
1621 char subdev_str[MAX_STR_LEN];
1622#endif
1623
1624 /** long long *******************************************************/
1625 long long partsize;
1626
1627 /** buffers *********************************************************/
1628 char *device_str;
1629 char *format;
1630 char *tmp;
1631
1632 /** end *************************************************************/
1633
1634 assert(mountlist != NULL);
1635 assert_string_is_neither_NULL_nor_zerolength(drivename);
1636
1637 malloc_string(device_str);
1638 malloc_string(format);
1639 malloc_string(tmp);
1640
1641 sprintf(tmp, "Partitioning drive %s", drivename);
1642 log_it(tmp);
1643
1644#if __FreeBSD__
1645 log_it("(Not opening fdisk now; that's the Linux guy's job)");
1646 pout_to_fdisk = NULL;
1647#else
1648 make_hole_for_file(FDISK_LOG);
1649 sprintf(tmp, "parted2fdisk %s >> %s 2>> %s", drivename, FDISK_LOG, FDISK_LOG);
1650 pout_to_fdisk = popen(tmp, "w");
1651 if (!pout_to_fdisk) {
1652 log_to_screen("Cannot call parted2fdisk to configure %s", drivename);
1653 paranoid_free(device_str);
1654 paranoid_free(format);
1655 paranoid_free(tmp);
1656 return (1);
1657 }
1658#endif
1659 for (current_devno = 1; current_devno < 99; current_devno++) {
1660 build_partition_name(device_str, drivename, current_devno);
1661 lino = find_device_in_mountlist(mountlist, device_str);
1662
1663 if (lino < 0) {
1664 // device not found in mountlist
1665#if __FreeBSD__
1666 // If this is the first partition (just as a sentinel value),
1667 // then see if the user has picked 'dangerously-dedicated' mode.
1668 // If so, then we just call label_drive_or_slice() and return.
1669 char c;
1670 if (current_devno == 1) {
1671 // try DangerouslyDedicated mode
1672 for (c = 'a'; c <= 'z'; c++) {
1673 sprintf(subdev_str, "%s%c", drivename, c);
1674 if (find_device_in_mountlist(mountlist, subdev_str) >
1675 0) {
1676 fbsd_part = TRUE;
1677 }
1678 }
1679 if (fbsd_part) {
1680 int r = label_drive_or_slice(mountlist,
1681 drivename,
1682 0);
1683 char command[MAX_STR_LEN];
1684 sprintf(command, "disklabel -B %s",
1685 basename(drivename));
1686 if (system(command)) {
1687 log_to_screen
1688 ("Warning! Unable to make the drive bootable.");
1689 }
1690 paranoid_free(device_str);
1691 paranoid_free(format);
1692 paranoid_free(tmp);
1693 return r;
1694 }
1695 }
1696 for (c = 'a'; c <= 'z'; c++) {
1697 sprintf(subdev_str, "%s%c", device_str, c);
1698 if (find_device_in_mountlist(mountlist, subdev_str) > 0) {
1699 fbsd_part = TRUE;
1700 }
1701 }
1702 // Now we check the subpartitions of the current partition.
1703 if (fbsd_part) {
1704 int i, line;
1705
1706 strcpy(format, "ufs");
1707 partsize = 0;
1708 for (i = 'a'; i < 'z'; ++i) {
1709 sprintf(subdev_str, "%s%c", device_str, i);
1710 line = find_device_in_mountlist(mountlist, subdev_str);
1711 if (line > 0) {
1712 // We found one! Add its size to the total size.
1713 partsize += mountlist->el[line].size;
1714 }
1715 }
1716 } else {
1717 continue;
1718 }
1719#else
1720 continue;
1721#endif
1722 }
1723
1724 /* OK, we've found partition /dev/hdxN in mountlist; let's prep it */
1725 /* For FreeBSD, that is /dev/adXsY */
1726
1727 log_it("Found partition %s in mountlist", device_str);
1728 if (!previous_devno) {
1729
1730 log_it("Wiping %s's partition table", drivename);
1731#if __FreeBSD__
1732 // FreeBSD doesn't let you write to blk devices in <512byte chunks.
1733// sprintf(tmp, "dd if=/dev/zero of=%s count=1 bs=512", drivename);
1734// if (run_program_and_log_output(tmp, TRUE)) {
1735 file = open(drivename, O_WRONLY);
1736 if (!file) {
1737 sprintf(tmp,
1738 "Warning - unable to open %s for wiping it's partition table",
1739 drivename);
1740 log_to_screen(tmp);
1741 }
1742
1743 for (i = 0; i < 512; i++) {
1744 if (!write(file, "\0", 1)) {
1745 sprintf(tmp, "Warning - unable to write to %s",
1746 drivename);
1747 log_to_screen(tmp);
1748 }
1749 }
1750 system("sync");
1751#else
1752 iamhere("New, kernel-friendly partition remover");
1753 for (i = 20; i > 0; i--) {
1754 fprintf(pout_to_fdisk, "d\n%d\n", i);
1755 fflush(pout_to_fdisk);
1756 }
1757// sprintf(tmp, "dd if=/dev/zero of=%s count=1 bs=512", drivename);
1758// run_program_and_log_output(tmp, 1);
1759#endif
1760 if (current_devno > 1) {
1761 previous_devno =
1762 make_dummy_partitions(pout_to_fdisk, drivename,
1763 current_devno);
1764 }
1765 }
1766#ifdef __FreeBSD__
1767 if (!fbsd_part) {
1768#endif
1769
1770 strcpy(format, mountlist->el[lino].format);
1771 partsize = mountlist->el[lino].size;
1772
1773#ifdef __FreeBSD__
1774 }
1775#endif
1776
1777#ifndef __IA64__
1778 if (current_devno == 5 && previous_devno == 4) {
1779 log_to_screen
1780 ("You must leave at least one partition spare as the Extended partition.");
1781 paranoid_free(device_str);
1782 paranoid_free(format);
1783 paranoid_free(tmp);
1784 return (1);
1785 }
1786#endif
1787
1788 retval +=
1789 partition_device(pout_to_fdisk, drivename, current_devno,
1790 previous_devno, format, partsize);
1791
1792#ifdef __FreeBSD__
1793 if ((current_devno <= 4) && fbsd_part) {
1794 sprintf(tmp, "disklabel -B %s", basename(device_str));
1795 retval += label_drive_or_slice(mountlist, device_str, 0);
1796 if (system(tmp)) {
1797 log_to_screen
1798 ("Warning! Unable to make the slice bootable.");
1799 }
1800 }
1801#endif
1802
1803 previous_devno = current_devno;
1804 }
1805
1806 if (pout_to_fdisk) {
1807// mark relevant partition as bootable
1808 sprintf(tmp, "a\n%s\n",
1809 call_program_and_get_last_line_of_output
1810 ("make-me-bootable /tmp/mountlist.txt dummy"));
1811 fput_string_one_char_at_a_time(pout_to_fdisk, tmp);
1812// close fdisk
1813 fput_string_one_char_at_a_time(pout_to_fdisk, "w\n");
1814 system("sync");
1815 paranoid_pclose(pout_to_fdisk);
1816 log_msg(0,
1817 "------------------- fdisk.log looks like this ------------------");
1818 sprintf(tmp, "cat %s >> %s", FDISK_LOG, MONDO_LOGFILE);
1819 system(tmp);
1820 log_msg(0,
1821 "------------------- end of fdisk.log... word! ------------------");
1822 sprintf(tmp, "tail -n6 %s | grep -F \"16: \"", FDISK_LOG);
1823 if (!run_program_and_log_output(tmp, 5)) {
1824 g_partition_table_locked_up++;
1825 log_to_screen
1826 ("A flaw in the Linux kernel has locked the partition table.");
1827 }
1828 }
1829 paranoid_free(device_str);
1830 paranoid_free(format);
1831 paranoid_free(tmp);
1832 return (retval);
1833}
1834
1835/**
1836 * Create partition number @p partno on @p drive with @p fdisk.
1837 * @param drive The drive to create the partition on.
1838// * @param partno The partition number of the new partition (1-4 are primary, >=5 is logical).
1839 * @param prev_partno The partition number of the most recently prepped partition.
1840 * @param format The filesystem type of this partition (used to set the type).
1841 * @param partsize The size of the partition in @e bytes.
1842 * @return 0 for success, nonzero for failure.
1843 */
1844int partition_device(FILE * pout_to_fdisk, const char *drive, int partno,
1845 int prev_partno, const char *format,
1846 long long partsize)
1847{
1848 /** int **************************************************************/
1849 int retval = 0;
1850 int res = 0;
1851
1852 /** buffers **********************************************************/
1853 char *program;
1854 char *partition_name;
1855 char *tmp;
1856 char *logfile;
1857 char *output;
1858
1859 /** pointers **********************************************************/
1860 char *p;
1861 char *part_table_fmt;
1862 FILE *fout;
1863
1864 /** end ***************************************************************/
1865
1866 malloc_string(program);
1867 malloc_string(partition_name);
1868 malloc_string(tmp);
1869 malloc_string(logfile);
1870 malloc_string(output);
1871
1872 assert_string_is_neither_NULL_nor_zerolength(drive);
1873 assert(format != NULL);
1874
1875 log_it("partition_device('%s', %d, %d, '%s', %lld) --- starting",
1876 drive, partno, prev_partno, format, partsize);
1877
1878 if (!strncmp(drive, RAID_DEVICE_STUB, strlen(RAID_DEVICE_STUB))) {
1879 sprintf(tmp, "Not partitioning %s - it is a virtual drive", drive);
1880 log_it(tmp);
1881 paranoid_free(program);
1882 paranoid_free(partition_name);
1883 paranoid_free(tmp);
1884 paranoid_free(logfile);
1885 paranoid_free(output);
1886 return (0);
1887 }
1888 build_partition_name(partition_name, drive, partno);
1889 if (partsize <= 0) {
1890 sprintf(tmp, "Partitioning device %s (max size)", partition_name);
1891 } else {
1892 sprintf(tmp, "Partitioning device %s (%lld MB)", partition_name,
1893 (long long) partsize / 1024);
1894 }
1895 update_progress_form(tmp);
1896 log_it(tmp);
1897
1898 if (is_this_device_mounted(partition_name)) {
1899 sprintf(tmp, "%s is mounted, and should not be partitioned",
1900 partition_name);
1901 log_to_screen(tmp);
1902 paranoid_free(program);
1903 paranoid_free(partition_name);
1904 paranoid_free(tmp);
1905 paranoid_free(logfile);
1906 paranoid_free(output);
1907 return (1);
1908/*
1909 } else if (does_partition_exist(drive, partno)) {
1910 sprintf(tmp, "%s already has a partition", partition_name);
1911 log_to_screen(tmp);
1912 return (1);
1913*/
1914 }
1915
1916
1917 /* sprintf(tmp,"Partitioning %s ",partition_name); */
1918 /* mvaddstr_and_log_it(g_currentY+1,30,tmp); */
1919 p = (char *) strrchr(partition_name, '/');
1920 sprintf(logfile, "/tmp/fdisk.log.%s", ++p);
1921 sprintf(program, "parted2fdisk %s >> %s 2>> %s", drive, MONDO_LOGFILE,
1922 MONDO_LOGFILE);
1923
1924 /* BERLIOS: shoould not be called each time */
1925 part_table_fmt = which_partition_format(drive);
1926 output[0] = '\0';
1927 /* make it a primary/extended/logical */
1928 if (partno <= 4) {
1929 sprintf(output + strlen(output), "n\np\n%d\n", partno);
1930 } else {
1931 /* MBR needs an extended partition if more than 4 partitions */
1932 if (strcmp(part_table_fmt, "MBR") == 0) {
1933 if (partno == 5) {
1934 if (prev_partno >= 4) {
1935 log_to_screen
1936 ("You need to leave at least one partition free, for 'extended/logical'");
1937 paranoid_free(program);
1938 paranoid_free(partition_name);
1939 paranoid_free(tmp);
1940 paranoid_free(logfile);
1941 paranoid_free(output);
1942 return (1);
1943 } else {
1944 sprintf(output + strlen(output), "n\ne\n%d\n\n\n",
1945 prev_partno + 1);
1946 }
1947 }
1948 strcat(output + strlen(output), "n\nl\n");
1949 } else {
1950 /* GPT allows more than 4 primary partitions */
1951 sprintf(output + strlen(output), "n\np\n%d\n", partno);
1952 }
1953 }
1954 strcat(output + strlen(output), "\n"); /*start block (ENTER for next free blk */
1955 if (partsize > 0) {
1956 if (!strcmp(format, "7")) {
1957 log_msg(1, "Adding 512K, just in case");
1958 partsize += 512;
1959 }
1960 sprintf(output + strlen(output), "+%lldK", (long long) (partsize));
1961 }
1962 strcat(output + strlen(output), "\n");
1963#if 0
1964/*
1965#endif
1966 sprintf(tmp,"PARTSIZE = +%ld",(long)partsize);
1967 log_it(tmp);
1968 log_it("---fdisk command---");
1969 log_it(output);
1970 log_it("---end of fdisk---");
1971#if 0
1972*/
1973#endif
1974
1975
1976 if (pout_to_fdisk) {
1977 log_msg(1, "Doing the new all-in-one fdisk thing");
1978 log_msg(1, "output = '%s'", output);
1979 fput_string_one_char_at_a_time(pout_to_fdisk, output);
1980 fput_string_one_char_at_a_time(pout_to_fdisk, "\n\np\n");
1981 strcpy(tmp, last_line_of_file(FDISK_LOG));
1982 if (strstr(tmp, " (m ")) {
1983 log_msg(1, "Successfully created partition %d on %s", partno, drive);
1984 } else {
1985 log_msg(1, "last line = %s", tmp);
1986 log_msg(1, "Failed to create partition %d on %s; sending 'Enter'...", partno, drive);
1987 }
1988 if (!retval) {
1989 log_msg(1, "Trying to set partition %d type now on %s", partno, drive);
1990 retval =
1991 set_partition_type(pout_to_fdisk, drive, partno, format,
1992 partsize);
1993 if (retval) {
1994 log_msg(1, "Failed. Trying again...");
1995 retval =
1996 set_partition_type(pout_to_fdisk, drive, partno,
1997 format, partsize);
1998 }
1999 }
2000 if (retval) {
2001 log_msg(1, "...but failed to set type");
2002 }
2003 } else {
2004 strcat(output, "w\n\n");
2005 if (g_fprep) {
2006 fprintf(g_fprep, "echo \"%s\" | %s\n", output, program);
2007 }
2008 /* write to disk; close fdisk's stream */
2009 if (!(fout = popen(program, "w"))) {
2010 log_OS_error("can't popen-out to program");
2011 } else {
2012 fputs(output, fout);
2013 paranoid_pclose(fout);
2014 }
2015 if (!does_partition_exist(drive, partno) && partsize > 0) {
2016 log_it("Vaccum-packing");
2017 g_current_progress--;
2018 res =
2019 partition_device(pout_to_fdisk, drive, partno, prev_partno,
2020 format, -1);
2021 if (res) {
2022 sprintf(tmp, "Failed to vacuum-pack %s", partition_name);
2023 log_it(tmp);
2024 retval++;
2025 } else {
2026 retval = 0;
2027 }
2028 }
2029 if (does_partition_exist(drive, partno)) {
2030 retval =
2031 set_partition_type(pout_to_fdisk, drive, partno, format,
2032 partsize);
2033 if (retval) {
2034 sprintf(tmp, "Partitioned %s but failed to set its type",
2035 partition_name);
2036 log_it(tmp);
2037 } else {
2038 if (partsize > 0) {
2039 sprintf(tmp, "Partition %s created+configured OK",
2040 partition_name);
2041 log_to_screen(tmp);
2042 } else {
2043 log_it("Returning from a successful vacuum-pack");
2044 }
2045 }
2046 } else {
2047 sprintf(tmp, "Failed to partition %s", partition_name);
2048 if (partsize > 0) {
2049 log_to_screen(tmp);
2050 } else {
2051 log_it(tmp);
2052 }
2053 retval++;
2054 }
2055 }
2056 g_current_progress++;
2057 log_it("partition_device() --- leaving");
2058 paranoid_free(program);
2059 paranoid_free(partition_name);
2060 paranoid_free(tmp);
2061 paranoid_free(logfile);
2062 paranoid_free(output);
2063 return (retval);
2064}
2065
2066
2067
2068/**
2069 * Create all partitions listed in @p mountlist.
2070 * @param mountlist The mountlist to use to guide the partitioning.
2071 * @return The number of errors encountered (0 for success).
2072 * @note This sets the partition types but doesn't actually do the formatting.
2073 * Use format_everything() for that.
2074 */
2075int partition_everything(struct mountlist_itself *mountlist)
2076{
2077 /** int ************************************************************/
2078 int lino;
2079 int retval = 0;
2080 int i;
2081 int res;
2082
2083 /** buffer *********************************************************/
2084 struct list_of_disks *drivelist;
2085 /* struct mountlist_itself new_mtlist, *mountlist; */
2086
2087 /** end ************************************************************/
2088
2089 drivelist = malloc(sizeof(struct list_of_disks));
2090 assert(mountlist != NULL);
2091
2092 log_it("partition_everything() --- starting");
2093 mvaddstr_and_log_it(g_currentY, 0, "Partitioning hard drives ");
2094 /* mountlist=orig_mtlist; */
2095 if (mountlist_contains_raid_devices(mountlist)) {
2096 /* mountlist=&new_mtlist; */
2097 /* extrapolate_mountlist_to_include_raid_partitions(mountlist,orig_mtlist); */
2098 log_msg(0,
2099 "Mountlist, including the partitions incorporated in RAID devices:-");
2100 for (i = 0; i < mountlist->entries; i++) {
2101 log_it(mountlist->el[i].device);
2102 }
2103 log_msg(0, "End of mountlist.");
2104 }
2105 log_msg(0, "Stopping all LVMs, just in case");
2106 if (!g_text_mode) {
2107 newtSuspend();
2108 }
2109 do_my_funky_lvm_stuff(TRUE, FALSE); // just remove old partitions
2110 if (!g_text_mode) {
2111 newtResume();
2112 }
2113 log_msg(0, "Stopping all software RAID devices, just in case");
2114 stop_all_raid_devices(mountlist);
2115 log_msg(0, "Done.");
2116
2117/*
2118 if (does_file_exist("/tmp/i-want-my-lvm"))
2119 {
2120 wipe_MBRs_and_reboot_if_necessary(mountlist); // i.e. if it wasn't done recently
2121 }
2122*/
2123
2124 open_progress_form("Partitioning devices",
2125 "I am now going to partition all your drives.",
2126 "This should not take more than five minutes.", "",
2127 mountlist->entries);
2128
2129 make_list_of_drives_in_mountlist(mountlist, drivelist);
2130
2131 /* partition each drive */
2132 for (lino = 0; lino < drivelist->entries; lino++) {
2133 res = partition_drive(mountlist, drivelist->el[lino].device);
2134 retval += res;
2135 }
2136 close_progress_form();
2137 if (retval) {
2138 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
2139 log_to_screen
2140 ("Errors occurred during the partitioning of your hard drives.");
2141 } else {
2142 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2143 paranoid_system("rm -f /tmp/fdisk*.log 2> /dev/null");
2144 }
2145 newtSuspend();
2146 system("clear");
2147 newtResume();
2148 paranoid_free(drivelist);
2149 return (retval);
2150}
2151
2152
2153
2154
2155
2156
2157/**
2158 * Set the type of partition number @p partno on @p drive to @p format.
2159 * @param drive The drive to change the type of a partition on.
2160 * @param partno The partition number on @p drive to change the type of.
2161 * @param format The filesystem type this partition will eventually contain.
2162 * @param partsize The size of this partition, in @e bytes (used for vfat
2163 * type calculations).
2164 * @return 0 for success, nonzero for failure.
2165 */
2166int set_partition_type(FILE * pout_to_fdisk, const char *drive, int partno,
2167 const char *format, long long partsize)
2168{
2169 /** buffers *********************************************************/
2170 char *partition;
2171 char *command;
2172 char *output;
2173 char *tmp;
2174 char *partcode;
2175 char *logfile;
2176
2177 /** pointers *********************************************************/
2178 char *p;
2179 FILE *fout;
2180
2181 /** int **************************************************************/
2182 int res = 0;
2183
2184 /** end **************************************************************/
2185
2186 assert_string_is_neither_NULL_nor_zerolength(drive);
2187 assert(format != NULL);
2188
2189 malloc_string(partition);
2190 malloc_string(command);
2191 malloc_string(output);
2192 malloc_string(tmp);
2193 malloc_string(partcode);
2194 malloc_string(logfile);
2195
2196 build_partition_name(partition, drive, partno);
2197 p = (char *) strrchr(partition, '/');
2198 sprintf(logfile, "/tmp/fdisk-set-type.%s.log", ++p);
2199 if (strcmp(format, "swap") == 0) {
2200 strcpy(partcode, "82");
2201 } else if (strcmp(format, "vfat") == 0) {
2202 if (partsize / 1024 > 8192) {
2203 strcpy(partcode, "c");
2204 } else {
2205 strcpy(partcode, "b");
2206 }
2207 } else if (strcmp(format, "ext2") == 0
2208 || strcmp(format, "reiserfs") == 0
2209 || strcmp(format, "ext3") == 0
2210 || strcmp(format, "xfs") == 0
2211 || strcmp(format, "jfs") == 0) {
2212 strcpy(partcode, "83");
2213 } else if (strcmp(format, "minix") == 0) {
2214 strcpy(partcode, "81");
2215 } else if (strcmp(format, "raid") == 0) {
2216 strcpy(partcode, "fd");
2217 } else if ((strcmp(format, "ufs") == 0)
2218 || (strcmp(format, "ffs") == 0)) { /* raid autodetect */
2219 strcpy(partcode, "a5");
2220 } else if (strcmp(format, "lvm") == 0) {
2221 strcpy(partcode, "8e");
2222 } else if (format[0] == '\0') { /* LVM physical partition */
2223 partcode[0] = '\0';
2224 } else if (strlen(format) >= 1 && strlen(format) <= 2) {
2225 strcpy(partcode, format);
2226 } else {
2227 /* probably an image */
2228 sprintf(tmp,
2229 "Unknown format ('%s') - using supplied string anyway",
2230 format);
2231 mvaddstr_and_log_it(g_currentY++, 0, tmp);
2232#ifdef __FreeBSD__
2233 strcpy(partcode, format); // was a5
2234#else
2235 strcpy(partcode, format); // was 83
2236#endif
2237 }
2238 sprintf(tmp, "Setting %s's type to %s (%s)", partition, format,
2239 partcode);
2240 log_msg(1, tmp);
2241 if (partcode[0] != '\0' && strcmp(partcode, "83")) { /* no need to set type if 83: 83 is default */
2242
2243 if (pout_to_fdisk) {
2244 res = 0;
2245 fput_string_one_char_at_a_time(pout_to_fdisk, "t\n");
2246 if (partno > 1
2247 || strstr(last_line_of_file(FDISK_LOG), " (1-4)")) {
2248 log_msg(5, "Specifying partno (%d) - yay", partno);
2249 sprintf(tmp, "%d\n", partno);
2250 fput_string_one_char_at_a_time(pout_to_fdisk, tmp);
2251 log_msg(5, "A - last line = '%s'",
2252 last_line_of_file(FDISK_LOG));
2253 }
2254
2255 sprintf(tmp, "%s\n", partcode);
2256 fput_string_one_char_at_a_time(pout_to_fdisk, tmp);
2257 log_msg(5, "B - last line = '%s'",
2258 last_line_of_file(FDISK_LOG));
2259 fput_string_one_char_at_a_time(pout_to_fdisk, "\n");
2260 log_msg(5, "C - last line = '%s'",
2261 last_line_of_file(FDISK_LOG));
2262
2263 strcpy(tmp, last_line_of_file(FDISK_LOG));
2264 if (!strstr(tmp, " (m ")) {
2265 log_msg(1, "last line = '%s'; part type set failed", tmp);
2266 res++;
2267 fput_string_one_char_at_a_time(pout_to_fdisk, "\n");
2268 }
2269 fput_string_one_char_at_a_time(pout_to_fdisk, "p\n");
2270 } else {
2271 sprintf(output, "t\n%d\n%s\n", partno, partcode);
2272 strcat(output, "w\n");
2273 sprintf(command, "parted2fdisk %s >> %s 2>> %s", drive,
2274 MONDO_LOGFILE, MONDO_LOGFILE);
2275 log_msg(5, "output = '%s'", output);
2276 log_msg(5, "partno=%d; partcode=%s", partno, partcode);
2277 log_msg(5, "command = '%s'", command);
2278 fout = popen(command, "w");
2279 if (!fout) {
2280 log_OS_error(command);
2281 res = 1;
2282 } else {
2283 res = 0;
2284 fprintf(fout, output);
2285 paranoid_pclose(fout);
2286 }
2287 }
2288 if (res) {
2289 log_OS_error(command);
2290 }
2291 }
2292
2293 paranoid_free(partition);
2294 paranoid_free(command);
2295 paranoid_free(output);
2296 paranoid_free(tmp);
2297 paranoid_free(partcode);
2298 paranoid_free(logfile);
2299
2300 return (res);
2301}
2302
2303
2304int start_raid_device(char *raid_device)
2305{
2306 /** int *************************************************************/
2307 int res;
2308 int retval = 0;
2309
2310 /** buffers *********************************************************/
2311 char *program;
2312
2313 /** end *************************************************************/
2314
2315 assert_string_is_neither_NULL_nor_zerolength(raid_device);
2316 malloc_string(program);
2317
2318#ifdef __FreeBSD__
2319 if (is_this_device_mounted(raid_device)) {
2320 log_it("Can't start %s when it's mounted!", raid_device);
2321 return 1;
2322 }
2323 sprintf(program, "vinum start -f %s", raid_device);
2324#else
2325 sprintf(program, "raidstart %s", raid_device);
2326#endif
2327 log_msg(1, "program = %s", program);
2328 res = run_program_and_log_output(program, 1);
2329 if (g_fprep) {
2330 fprintf(g_fprep, "%s\n", program);
2331 }
2332 if (res) {
2333 log_msg(1, "Warning - failed to start RAID device %s",
2334 raid_device);
2335 }
2336 retval += res;
2337 sleep(1);
2338 return (retval);
2339}
2340
2341
2342
2343/**
2344 * Stop @p raid_device using @p raidstop.
2345 * @param raid_device The software RAID device to stop.
2346 * @return 0 for success, nonzero for failure.
2347 */
2348int stop_raid_device(char *raid_device)
2349{
2350 /** int *************************************************************/
2351 int res;
2352 int retval = 0;
2353
2354 /** buffers *********************************************************/
2355 char *program;
2356
2357 /** end *************************************************************/
2358
2359 assert_string_is_neither_NULL_nor_zerolength(raid_device);
2360 malloc_string(program);
2361
2362#ifdef __FreeBSD__
2363 if (is_this_device_mounted(raid_device)) {
2364 log_it("Can't stop %s when it's mounted!", raid_device);
2365 return 1;
2366 }
2367 sprintf(program, "vinum stop -f %s", raid_device);
2368#else
2369 // use raidstop if it exists, otherwise use mdadm
2370 if (run_program_and_log_output("which raidstop", FALSE)) {
2371 sprintf(program, "mdadm -S %s", raid_device);
2372 } else {
2373 sprintf(program, "raidstop %s", raid_device);
2374 }
2375#endif
2376 log_msg(1, "program = %s", program);
2377 res = run_program_and_log_output(program, 1);
2378 if (g_fprep) {
2379 fprintf(g_fprep, "%s\n", program);
2380 }
2381 if (res) {
2382 log_msg(1, "Warning - failed to stop RAID device %s", raid_device);
2383 }
2384 retval += res;
2385 return (retval);
2386}
2387
2388
2389int start_all_raid_devices(struct mountlist_itself *mountlist)
2390{
2391 int i;
2392 int retval = 0;
2393 int res;
2394
2395 for (i = 0; i < mountlist->entries; i++) {
2396 if (!strncmp
2397 (mountlist->el[i].device, RAID_DEVICE_STUB,
2398 strlen(RAID_DEVICE_STUB))) {
2399 log_msg(1, "Starting %s", mountlist->el[i].device);
2400 res = start_raid_device(mountlist->el[i].device);
2401 retval += res;
2402 }
2403 }
2404 if (retval) {
2405 log_msg(1, "Started all s/w raid devices OK");
2406 } else {
2407 log_msg(1, "Failed to start some/all s/w raid devices");
2408 }
2409 return (retval);
2410}
2411
2412/**
2413 * Stop all software RAID devices listed in @p mountlist.
2414 * @param mountlist The mountlist to stop the RAID devices in.
2415 * @return The number of errors encountered (0 for success).
2416 * @bug @p mountlist is not used.
2417 */
2418int stop_all_raid_devices(struct mountlist_itself *mountlist)
2419{
2420 /** int *************************************************************/
2421 int retval = 0;
2422#ifndef __FreeBSD__
2423 int res;
2424#endif
2425
2426 /** char ************************************************************/
2427 char *incoming;
2428#ifndef __FreeBSD__
2429 char *dev;
2430#endif
2431 /** pointers ********************************************************/
2432#ifndef __FreeBSD__
2433 char *p;
2434#endif
2435 FILE *fin;
2436 int i;
2437
2438 /** end ****************************************************************/
2439
2440 malloc_string(dev);
2441 malloc_string(incoming);
2442 assert(mountlist != NULL);
2443
2444 for (i = 0; i < 3; i++) {
2445#ifdef __FreeBSD__
2446 fin =
2447 popen
2448 ("vinum list | grep '^[PVS]' | sed 's/S/1/;s/P/2/;s/V/3/' | sort | cut -d' ' -f2",
2449 "r");
2450 if (!fin) {
2451 paranoid_free(dev);
2452 paranoid_free(incoming);
2453 return (1);
2454 }
2455 for (fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin);
2456 fgets(incoming, MAX_STR_LEN - 1, fin)) {
2457 retval += stop_raid_device(incoming);
2458 }
2459#else
2460 fin = fopen("/proc/mdstat", "r");
2461 if (!fin) {
2462 log_OS_error("/proc/mdstat");
2463 paranoid_free(dev);
2464 paranoid_free(incoming);
2465 return (1);
2466 }
2467 for (fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin);
2468 fgets(incoming, MAX_STR_LEN - 1, fin)) {
2469 for (p = incoming;
2470 *p != '\0' && (*p != 'm' || *(p + 1) != 'd'
2471 || !isdigit(*(p + 2))); p++);
2472 if (*p != '\0') {
2473 sprintf(dev, "/dev/%s", p);
2474 for (p = dev; *p > 32; p++);
2475 *p = '\0';
2476 res = stop_raid_device(dev);
2477 }
2478 }
2479#endif
2480 }
2481 paranoid_fclose(fin);
2482 if (retval) {
2483 log_msg(1, "Warning - unable to stop some RAID devices");
2484 }
2485 paranoid_free(dev);
2486 paranoid_free(incoming);
2487 system("sync");
2488 system("sync");
2489 system("sync");
2490 sleep(1);
2491 return (retval);
2492}
2493
2494
2495
2496/**
2497 * Decide which command we need to use to format a device of type @p format.
2498 * @param format The filesystem type we are about to format.
2499 * @param program Where to put the binary name for this format.
2500 * @return 0 for success, nonzero for failure.
2501 */
2502int which_format_command_do_i_need(char *format, char *program)
2503{
2504 /** int *************************************************************/
2505 int res = 0;
2506
2507 /** buffers *********************************************************/
2508 char *tmp;
2509
2510 /** end ***************************************************************/
2511
2512 malloc_string(tmp);
2513 assert_string_is_neither_NULL_nor_zerolength(format);
2514 assert(program != NULL);
2515
2516 if (strcmp(format, "swap") == 0) {
2517#ifdef __FreeBSD__
2518 strcpy(program, "true");
2519#else
2520 strcpy(program, "mkswap");
2521#endif
2522 } else if (strcmp(format, "vfat") == 0) {
2523 strcpy(program, "format-and-kludge-vfat");
2524#ifndef __FreeBSD__
2525 } else if (strcmp(format, "reiserfs") == 0) {
2526 strcpy(program, "mkreiserfs -ff");
2527 } else if (strcmp(format, "xfs") == 0) {
2528 strcpy(program, "mkfs.xfs -f -q");
2529 } else if (strcmp(format, "jfs") == 0) {
2530 strcpy(program, "mkfs.jfs");
2531 } else if (strcmp(format, "ext3") == 0) {
2532 strcpy(program, "mkfs -t ext2 -F -j -q");
2533 } else if (strcmp(format, "minix") == 0) {
2534 strcpy(program, "mkfs.minix");
2535#endif
2536 } else if (strcmp(format, "ext2") == 0) {
2537 strcpy(program, "mke2fs -F -q");
2538 } else {
2539#ifdef __FreeBSD__
2540 sprintf(program, "newfs_%s", format);
2541#else
2542 sprintf(program, "mkfs -t %s -c", format); // -c checks for bad blocks
2543#endif
2544 sprintf(tmp, "Unknown format (%s) - assuming '%s' will do", format,
2545 program);
2546 log_it(tmp);
2547 res = 0;
2548 }
2549 paranoid_free(tmp);
2550 return (res);
2551}
2552
2553
2554/**
2555 * Calculate the probable size of @p drive_name by adding up sizes in
2556 * @p mountlist.
2557 * @param mountlist The mountlist to use to calculate the size.
2558 * @param drive_name The drive to calculate the original size of.
2559 * @return The size of @p drive_name in kilobytes.
2560 */
2561long calc_orig_size_of_drive_from_mountlist(struct mountlist_itself
2562 *mountlist, char *drive_name)
2563{
2564 /** long ************************************************************/
2565 long original_size_of_drive;
2566
2567 /** int *************************************************************/
2568 int partno;
2569
2570 /** buffers *********************************************************/
2571 char *tmp;
2572
2573 /** end *************************************************************/
2574
2575 malloc_string(tmp);
2576 assert(mountlist != NULL);
2577 assert_string_is_neither_NULL_nor_zerolength(drive_name);
2578
2579 for (original_size_of_drive = 0, partno = 0;
2580 partno < mountlist->entries; partno++) {
2581 if (strncmp
2582 (mountlist->el[partno].device, drive_name,
2583 strlen(drive_name)) == 0) {
2584 original_size_of_drive += mountlist->el[partno].size;
2585 } else {
2586 sprintf(tmp, "Skipping %s", mountlist->el[partno].device);
2587// log_to_screen(tmp);
2588 }
2589 }
2590 original_size_of_drive = original_size_of_drive / 1024;
2591 paranoid_free(tmp);
2592 return (original_size_of_drive);
2593}
2594
2595
2596/**
2597 * Resize a drive's entries in @p mountlist proportionately to fit its new size.
2598 * There are a few problems with this function:
2599 * - It won't work if there was any unallocated space on the user's hard drive
2600 * when it was backed up.
2601 * - It won't work if the user's hard drive lies about its size (more common
2602 * than you'd think).
2603 *
2604 * @param mountlist The mountlist to use for resizing @p drive_name.
2605 * @param drive_name The drive to resize.
2606 */
2607void resize_drive_proportionately_to_suit_new_drives(struct mountlist_itself
2608 *mountlist,
2609 char *drive_name)
2610{
2611 /**buffers **********************************************************/
2612 char *tmp;
2613
2614 /** int *************************************************************/
2615 int partno, lastpart;
2616 /** remove driveno, noof_drives stan benoit apr 2002**/
2617
2618 /** float ***********************************************************/
2619 float factor;
2620 float new_size;
2621// float newcylinderno;
2622
2623 /** long *************************************************************/
2624 long newsizL;
2625 long current_size_of_drive = 0;
2626 long original_size_of_drive = 0;
2627 long final_size; /* all in Megabytes */
2628 struct mountlist_reference *drivemntlist;
2629
2630 /** structures *******************************************************/
2631
2632 /** end **************************************************************/
2633
2634 malloc_string(tmp);
2635 assert(mountlist != NULL);
2636 assert_string_is_neither_NULL_nor_zerolength(drive_name);
2637
2638 if (strlen(drive_name) >= strlen(RAID_DEVICE_STUB)) {
2639 if (strncmp(drive_name, RAID_DEVICE_STUB, strlen(RAID_DEVICE_STUB))
2640 == 0) {
2641 paranoid_free(tmp);
2642 return;
2643 }
2644 }
2645
2646 /*
2647 sprintf (tmp, "cp -f %s %s.pre-resize", g_mountlist_fname, g_mountlist_fname);
2648 run_program_and_log_output (tmp, FALSE);
2649 */
2650
2651 current_size_of_drive = get_phys_size_of_drive(drive_name);
2652
2653 if (current_size_of_drive <= 0) {
2654 log_it("Not resizing to match %s - can't find drive", drive_name);
2655 paranoid_free(tmp);
2656 return;
2657 }
2658 sprintf(tmp, "Expanding entries to suit drive %s (%ld MB)", drive_name,
2659 current_size_of_drive);
2660 log_to_screen(tmp);
2661
2662 drivemntlist = malloc(sizeof(struct mountlist_reference));
2663 drivemntlist->el =
2664 malloc(sizeof(struct mountlist_line *) * MAX_TAPECATALOG_ENTRIES);
2665
2666 if (!drivemntlist) {
2667 fatal_error("Cannot malloc temporary mountlist\n");
2668 }
2669 create_mountlist_for_drive(mountlist, drive_name, drivemntlist);
2670
2671 for (partno = 0; partno < drivemntlist->entries; partno++) {
2672 original_size_of_drive += drivemntlist->el[partno]->size;
2673 }
2674 original_size_of_drive = original_size_of_drive / 1024;
2675
2676 if (original_size_of_drive <= 0) {
2677 sprintf(tmp, "Cannot resize %s's entries. Drive not found.",
2678 drive_name);
2679 log_to_screen(tmp);
2680 paranoid_free(tmp);
2681 return;
2682 }
2683 factor =
2684 (float) (current_size_of_drive) / (float) (original_size_of_drive);
2685 sprintf(tmp, "Disk %s was %ld MB; is now %ld MB; factor = %f",
2686 drive_name, original_size_of_drive, current_size_of_drive,
2687 factor);
2688 log_to_screen(tmp);
2689
2690 lastpart = drivemntlist->entries - 1;
2691 for (partno = 0; partno < drivemntlist->entries; partno++) {
2692 /* the 'atoi' thing is to make sure we don't try to resize _images_, whose formats will be numeric */
2693 if (!atoi(drivemntlist->el[partno]->format)) {
2694 new_size = (float) (drivemntlist->el[partno]->size) * factor;
2695 } else {
2696 new_size = drivemntlist->el[partno]->size;
2697 }
2698
2699 if (!strcmp(drivemntlist->el[partno]->mountpoint, "image")) {
2700 log_msg(1, "Skipping %s (%s) because it's an image",
2701 drivemntlist->el[partno]->device,
2702 drivemntlist->el[partno]->mountpoint);
2703 newsizL = (long) new_size; // It looks wrong but it's not
2704 } else {
2705 newsizL = (long) new_size;
2706 }
2707 sprintf(tmp, "Changing %s from %lld KB to %ld KB",
2708 drivemntlist->el[partno]->device,
2709 drivemntlist->el[partno]->size, newsizL);
2710 log_to_screen(tmp);
2711 drivemntlist->el[partno]->size = newsizL;
2712 }
2713 final_size = get_phys_size_of_drive(drive_name);
2714 sprintf(tmp, "final_size = %ld MB", final_size);
2715 paranoid_free(tmp);
2716 log_to_screen(tmp);
2717}
2718
2719
2720/**
2721 * Resize all partitions in @p mountlist proportionately (each one
2722 * grows or shrinks by the same percentage) to fit them into the new
2723 * drives (presumably different from the old ones).
2724 * @param mountlist The mountlist to resize the drives in.
2725 */
2726void resize_mountlist_proportionately_to_suit_new_drives(struct mountlist_itself
2727 *mountlist)
2728{
2729 /** buffers *********************************************************/
2730 struct list_of_disks *drivelist;
2731
2732 /** int *************************************************************/
2733 int driveno;
2734
2735 /** end *************************************************************/
2736
2737 drivelist = malloc(sizeof(struct list_of_disks));
2738 assert(mountlist != NULL);
2739
2740 if (g_mountlist_fname[0] == '\0') {
2741 log_it
2742 ("resize_mountlist_prop...() - warning - mountlist fname is blank");
2743 log_it("That does NOT affect the functioning of this subroutine.");
2744 log_it("--- Hugo, 2002/11/20");
2745 }
2746 iamhere("Resizing mountlist");
2747 make_list_of_drives_in_mountlist(mountlist, drivelist);
2748 iamhere("Back from MLoDiM");
2749 for (driveno = 0; driveno < drivelist->entries; driveno++) {
2750 resize_drive_proportionately_to_suit_new_drives(mountlist,
2751 drivelist->
2752 el[driveno].
2753 device);
2754 }
2755 log_to_screen("Mountlist adjusted to suit current hard drive(s)");
2756 paranoid_free(drivelist);
2757}
2758
2759/**
2760 * Create a mountlist_reference structure for @p drive_name in @p mountlist.
2761 * @param mountlist The complete mountlist to get the drive references from.
2762 * @param drive_name The drive to put in @p drivemntlist.
2763 * @param drivemntlist The mountlist_reference structure to put the drive's entries in.
2764 * @note @p drivemntlist and @p drivemntlist->el must be allocated by the caller.
2765 * @author Ralph Grewe
2766 */
2767void create_mountlist_for_drive(struct mountlist_itself *mountlist,
2768 char *drive_name,
2769 struct mountlist_reference *drivemntlist)
2770{
2771 int partno;
2772 char *tmp_drive_name, *c;
2773
2774 assert(mountlist != NULL);
2775 assert(drive_name != NULL);
2776 assert(drivemntlist != NULL);
2777
2778 log_msg(1, "Creating list of partitions for drive %s", drive_name);
2779
2780 tmp_drive_name = strdup(drive_name);
2781 if (!tmp_drive_name)
2782 fatal_error("Out of memory");
2783
2784 /* devfs devices? */
2785 c = strrchr(tmp_drive_name, '/');
2786 if (c && strncmp(c, "/disc", 5) == 0) {
2787 /* yup its devfs, change the "disc" to "part" so the existing code works */
2788 strcpy(c + 1, "part");
2789 }
2790 drivemntlist->entries = 0;
2791 for (partno = 0; partno < mountlist->entries; partno++) {
2792 if (strncmp
2793 (mountlist->el[partno].device, tmp_drive_name,
2794 strlen(tmp_drive_name)) == 0) {
2795 drivemntlist->el[drivemntlist->entries] =
2796 &mountlist->el[partno];
2797 drivemntlist->entries++;
2798 }
2799 }
2800 if (tmp_drive_name)
2801 free(tmp_drive_name);
2802}
2803
2804/* @} - end of prepGroup */
Note: See TracBrowser for help on using the repository browser.