source: MondoRescue/branches/2.2.9/mondo/src/mondorestore/mondo-prep.c@ 2211

Last change on this file since 2211 was 2211, checked in by Bruno Cornec, 15 years ago

r3089@localhost: bruno | 2009-05-18 06:41:05 +0200

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