source: MondoRescue/branches/2.2.5/mondo/src/mondorestore/mondo-prep.c@ 1881

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