source: MondoRescue/branches/3.0/mondo/src/mondorestore/mondo-prep.c@ 2899

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