source: MondoRescue/branches/3.2/mondo/src/mondorestore/mondo-prep.c@ 3292

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