source: MondoRescue/branches/stable/mondo/src/common/libmondo-devices.c@ 1107

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

log_msg => mr_msg for common files

  • Property svn:keywords set to Id
File size: 71.5 KB
Line 
1/* libmondo-devices.c Subroutines for handling devices
2 $Id: libmondo-devices.c 1107 2007-02-07 23:09:34Z bruno $
3*/
4
5/**
6 * @file
7 * Functions to handle interactions with backup devices.
8 */
9
10#include "my-stuff.h"
11#include "mondostructures.h"
12#include "libmondo-files-EXT.h"
13#include "libmondo-devices.h"
14#include "lib-common-externs.h"
15#include "libmondo-string-EXT.h"
16#include "libmondo-tools-EXT.h"
17#include "libmondo-gui-EXT.h"
18#include "libmondo-fork-EXT.h"
19#include "libmondo-stream-EXT.h"
20
21#include <sys/types.h>
22#ifdef __FreeBSD__
23#define DKTYPENAMES
24#define FSTYPENAMES
25#include <sys/disklabel.h>
26#include <sys/disk.h>
27#elif linux
28#define u64 unsigned long long
29#include <linux/fs.h> /* for BLKGETSIZE64 */
30#include <linux/hdreg.h>
31#endif
32
33/*@unused@*/
34//static char cvsid[] = "$Id: libmondo-devices.c 1107 2007-02-07 23:09:34Z bruno $";
35
36extern int g_current_media_number;
37extern double g_kernel_version;
38
39extern bool g_ISO_restore_mode;
40extern struct s_bkpinfo *g_bkpinfo_DONTUSETHIS;
41extern char *g_erase_tmpdir_and_scratchdir;
42extern char *g_selfmounted_isodir;
43
44static char g_cdrw_drive_is_here[MAX_STR_LEN / 4] = "";
45static char g_cdrom_drive_is_here[MAX_STR_LEN / 4] = "";
46static char g_dvd_drive_is_here[MAX_STR_LEN / 4] = "";
47
48
49/**
50 * ????? @bug ?????
51 * @ingroup globalGroup
52 */
53bool g_restoring_live_from_cd = FALSE;
54
55extern t_bkptype g_backup_media_type; // set by main()
56
57
58
59
60void set_g_cdrom_and_g_dvd_to_bkpinfo_value(struct s_bkpinfo *bkpinfo)
61{
62 strcpy(g_cdrom_drive_is_here, bkpinfo->media_device); // just in case
63 strcpy(g_dvd_drive_is_here, bkpinfo->media_device); // just in case
64}
65
66
67
68/**
69 * Retract all CD trays and wait for autorun to complete.
70 * @ingroup deviceGroup
71 */
72void retract_CD_tray_and_defeat_autorun(void)
73{
74// log_it("rctada: Retracting all CD trays", __LINE__);
75 if (strlen(g_cdrom_drive_is_here) > 0) {
76 inject_device(g_cdrom_drive_is_here);
77 }
78 if (strlen(g_dvd_drive_is_here) > 0) {
79 inject_device(g_dvd_drive_is_here);
80 }
81 if (strlen(g_cdrw_drive_is_here) > 0) {
82 inject_device(g_cdrw_drive_is_here);
83 }
84// log_it("rctada: killing autorun");
85// run_program_and_log_output("killall autorun", TRUE);
86 if (!run_program_and_log_output("ps | grep autorun | grep -v grep", 5)) {
87 log_it("autorun detected; sleeping for 2 seconds");
88 sleep(2);
89 }
90 log_it("rctada: Unmounting all CD drives", __LINE__);
91 run_program_and_log_output("umount /dev/cdr* /dev/dvd*", 5);
92}
93
94
95
96/**
97 * Determine whether we're booted off a ramdisk.
98 * @return @c TRUE (we are) or @c FALSE (we aren't).
99 * @ingroup utilityGroup
100 */
101bool am_I_in_disaster_recovery_mode(void)
102{
103 char *tmp, *comment;
104 bool is_this_a_ramdisk = FALSE;
105
106 malloc_string(tmp);
107 malloc_string(comment);
108 strcpy(tmp, where_is_root_mounted());
109 sprintf(comment, "root is mounted at %s\n", tmp);
110 mr_msg(0, comment);
111 mr_msg(0,
112 "No, Schlomo, that doesn't mean %s is the root partition. It's just a debugging message. Relax. It's part of am_I_in_disaster_recovery_mode().",
113 tmp);
114
115#ifdef __FreeBSD__
116 if (strstr(tmp, "/dev/md")) {
117 is_this_a_ramdisk = TRUE;
118 }
119#else
120 if (!strncmp(tmp, "/dev/ram", 8)
121 || (!strncmp(tmp, "/dev/rd", 7) && !strcmp(tmp, "/dev/rd/")
122 && strncmp(tmp, "/dev/rd/cd", 10)) || strstr(tmp, "rootfs")
123 || !strcmp(tmp, "/dev/root")) {
124 is_this_a_ramdisk = TRUE;
125 } else {
126 is_this_a_ramdisk = FALSE;
127 }
128#endif
129
130 if (is_this_a_ramdisk) {
131 if (!does_file_exist("/THIS-IS-A-RAMDISK")
132 && !does_file_exist("/tmp/mountlist.txt.sample")) {
133 log_to_screen
134 ("Using /dev/root is stupid of you but I'll forgive you.");
135 is_this_a_ramdisk = FALSE;
136 }
137 }
138 if (does_file_exist("/THIS-IS-A-RAMDISK")) {
139 is_this_a_ramdisk = TRUE;
140 }
141 mr_free(tmp);
142 mr_free(comment);
143 mr_msg(1, "Is this a ramdisk? result = %d", is_this_a_ramdisk);
144 return (is_this_a_ramdisk);
145}
146
147
148
149
150
151/**
152 * Turn @c bkpinfo->backup_media_type into a human-readable string.
153 * @return The human readable string (e.g. @c cdr becomes <tt>"cdr"</tt>).
154 * @note The returned string points to static storage that will be overwritten with each call.
155 * @ingroup stringGroup
156 */
157static char *bkptype_to_string(t_bkptype bt)
158{
159 static char output[MAX_STR_LEN / 4];
160 switch (bt) {
161 case none:
162 strcpy(output, "none");
163 break;
164 case iso:
165 strcpy(output, "iso");
166 break;
167 case cdr:
168 strcpy(output, "cdr");
169 break;
170 case cdrw:
171 strcpy(output, "cdrw");
172 break;
173 case cdstream:
174 strcpy(output, "cdstream");
175 break;
176 case nfs:
177 strcpy(output, "nfs");
178 break;
179 case tape:
180 strcpy(output, "tape");
181 break;
182 case udev:
183 strcpy(output, "udev");
184 break;
185 default:
186 strcpy(output, "default");
187 }
188 return (output);
189}
190
191
192
193/**
194 * @addtogroup deviceGroup
195 * @{
196 */
197/**
198 * Eject the tray of the specified CD device.
199 * @param dev The device to eject.
200 * @return the return value of the @c eject command. (0=success, nonzero=failure)
201 */
202int eject_device(char *dev)
203{
204 char *command;
205 int res1 = 0, res2 = 0;
206
207 malloc_string(command);
208
209 if (IS_THIS_A_STREAMING_BACKUP(g_backup_media_type)
210 && g_backup_media_type != udev) {
211 sprintf(command, "mt -f %s offline", dev);
212 res1 = run_program_and_log_output(command, 1);
213 } else {
214 res1 = 0;
215 }
216
217#ifdef __FreeBSD__
218 if (strstr(dev, "acd")) {
219 sprintf(command, "cdcontrol -f %s eject", dev);
220 } else {
221 sprintf(command, "camcontrol eject `echo %s | sed 's|/dev/||'`",
222 dev);
223 }
224#else
225 sprintf(command, "eject %s", dev);
226#endif
227
228 mr_msg(3, "Ejecting %s", dev);
229 res2 = run_program_and_log_output(command, 1);
230 mr_free(command);
231 if (res1 && res2) {
232 return (1);
233 } else {
234 return (0);
235 }
236}
237
238/**
239 * Load (inject) the tray of the specified CD device.
240 * @param dev The device to load/inject.
241 * @return 0 for success, nonzero for failure.
242 */
243int inject_device(char *dev)
244{
245 char *command;
246 int i;
247
248 malloc_string(command);
249
250
251#ifdef __FreeBSD__
252 if (strstr(dev, "acd")) {
253 sprintf(command, "cdcontrol -f %s close", dev);
254 } else {
255 sprintf(command, "camcontrol load `echo %s | sed 's|/dev/||'`",
256 dev);
257 }
258#else
259 sprintf(command, "eject -t %s", dev);
260#endif
261 i = run_program_and_log_output(command, FALSE);
262 mr_free(command);
263 return (i);
264}
265
266
267/**
268 * Determine whether the specified @p device (really, you can use any file)
269 * exists.
270 * @return TRUE if it exists, FALSE if it doesn't.
271 */
272bool does_device_exist(char *device)
273{
274
275 /*@ buffers *********************************************************** */
276 char *tmp;
277 bool ret;
278
279 malloc_string(tmp);
280 assert_string_is_neither_NULL_nor_zerolength(device);
281
282 sprintf(tmp, "ls %s > /dev/null 2> /dev/null", device);
283
284 if (system(tmp)) {
285 ret = FALSE;
286 } else {
287 ret = TRUE;
288 }
289 mr_free(tmp);
290 return (ret);
291}
292
293
294/**
295 * Determine whether a non-Microsoft partition exists on any connected hard drive.
296 * @return TRUE (there's a Linux/FreeBSD partition) or FALSE (Microsoft has taken over yet another innocent PC).
297 */
298bool does_nonMS_partition_exist(void)
299{
300#if __FreeBSD__
301 return
302 !system
303 ("for drive in /dev/ad? /dev/da?; do fdisk $drive | grep -q FreeBSD && exit 0; done; false");
304#else
305 return
306 !system
307 ("parted2fdisk -l 2>/dev/null | grep '^/dev/' | grep -Eqv '(MS|DOS|FAT|NTFS)'");
308#endif
309}
310
311/**
312 * Determine whether the specified @p partno exists on the specified @p drive.
313 * @param drive The drive to search for the partition in.
314 * @param partno The partition number to look for.
315 * @return 0 if it exists, nonzero otherwise.
316 */
317int does_partition_exist(const char *drive, int partno)
318{
319 /*@ buffers **************************************************** */
320 char *program;
321 char *incoming;
322 char *searchstr;
323 char *tmp;
324
325 /*@ ints ******************************************************* */
326 int res = 0;
327
328 /*@ pointers *************************************************** */
329 FILE *fin;
330
331
332 /*@ end vars *************************************************** */
333 assert_string_is_neither_NULL_nor_zerolength(drive);
334 assert(partno >= 0 && partno < 999);
335
336 malloc_string(program);
337 malloc_string(incoming);
338 malloc_string(searchstr);
339 malloc_string(tmp);
340
341#ifdef __FreeBSD__
342 // We assume here that this is running from mondorestore. (It is.)
343 sprintf(program, "ls %s >/dev/null 2>&1", drive,
344 build_partition_name(tmp, drive, partno));
345 return system(program);
346#else
347 tmp[0] = '\0';
348#endif
349
350 sprintf(program, "parted2fdisk -l %s 2> /dev/null", drive);
351 fin = popen(program, "r");
352 if (!fin) {
353 log_it("program=%s", program);
354 log_OS_error("Cannot popen-in program");
355 return (0);
356 }
357 (void) build_partition_name(searchstr, drive, partno);
358 strcat(searchstr, " ");
359 for (res = 0; !res && fgets(incoming, MAX_STR_LEN - 1, fin);) {
360 if (strstr(incoming, searchstr)) {
361 res = 1;
362 }
363 }
364 if (pclose(fin)) {
365 log_OS_error("Cannot pclose fin");
366 }
367 mr_free(program);
368 mr_free(incoming);
369 mr_free(searchstr);
370 mr_free(tmp);
371 return (res);
372}
373
374
375
376
377
378/**
379 * Determine whether given NULL-terminated @p str exists in the MBR of @p dev.
380 * @param dev The device to look in.
381 * @param str The string to look for.
382 * @return TRUE if it exists, FALSE if it doesn't.
383 */
384bool does_string_exist_in_boot_block(char *dev, char *str)
385{
386 /*@ buffers **************************************************** */
387 char *command;
388
389 /*@ end vars *************************************************** */
390 int i;
391
392 assert_string_is_neither_NULL_nor_zerolength(dev);
393 assert_string_is_neither_NULL_nor_zerolength(str);
394
395 malloc_string(command);
396 sprintf(command,
397 "dd if=%s bs=446 count=1 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null",
398 dev, str);
399 i = system(command);
400 mr_free(command);
401 if (i) {
402 return (FALSE);
403 } else {
404 return (TRUE);
405 }
406}
407
408/**
409 * Determine whether specified @p str exists in the first @p n sectors of
410 * @p dev.
411 * @param dev The device to look in.
412 * @param str The string to look for.
413 * @param n The number of 512-byte sectors to search.
414 */
415bool does_string_exist_in_first_N_blocks(char *dev, char *str, int n)
416{
417 /*@ buffers **************************************************** */
418 char *command;
419 /*@ end vars *************************************************** */
420 int i;
421
422 malloc_string(command);
423 sprintf(command,
424 "dd if=%s bs=512 count=%i 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null",
425 dev, n, str);
426 i = system(command);
427 mr_free(command);
428 if (i) {
429 return (FALSE);
430 } else {
431 return (TRUE);
432 }
433}
434
435
436
437/**
438 * Try to mount CD-ROM at @p mountpoint. If the CD-ROM is not found or has
439 * not been specified, call find_cdrom_device() to find it.
440 * @param bkpinfo The backup information structure. The only field used is @c bkpinfo->media_device.
441 * @param mountpoint Where to mount the CD-ROM.
442 * @return 0 for success, nonzero for failure.
443 * @see mount_CDROM_here
444 */
445int find_and_mount_actual_cd(struct s_bkpinfo *bkpinfo, char *mountpoint)
446{
447 /*@ buffers ***************************************************** */
448
449 /*@ int's ****************************************************** */
450 int res;
451 char *dev;
452
453 /*@ end vars **************************************************** */
454
455 malloc_string(dev);
456 assert(bkpinfo != NULL);
457 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
458
459 if (g_backup_media_type == dvd) {
460 strcpy(dev, g_dvd_drive_is_here);
461 if (!dev[0]) {
462 find_dvd_device(dev, FALSE);
463 }
464 } else {
465 strcpy(dev, g_cdrom_drive_is_here);
466 if (!dev[0]) {
467 find_cdrom_device(dev, FALSE);
468 }
469 }
470
471 if (bkpinfo->backup_media_type != iso) {
472 retract_CD_tray_and_defeat_autorun();
473 }
474
475 if (!dev[0] || (res = mount_CDROM_here(dev, mountpoint))) {
476 if (!popup_and_get_string
477 ("CD-ROM device", "Please enter your CD-ROM's /dev device",
478 dev, MAX_STR_LEN / 4)) {
479 res = 1;
480 } else {
481 res = mount_CDROM_here(dev, mountpoint);
482 }
483 }
484 if (res) {
485 mr_msg(1, "mount failed");
486 } else {
487 mr_msg(1, "mount succeeded with %s", dev);
488 }
489 mr_free(dev);
490 return (res);
491}
492
493
494
495
496
497/**
498 * Locate a CD-R/W writer's SCSI node.
499 * @param cdrw_device SCSI node will be placed here.
500 * @return 0 for success, nonzero for failure.
501 */
502
503
504/**
505 * Locate a CD-R/W writer's SCSI node.
506 * @param cdrw_device SCSI node will be placed here.
507 * @return 0 for success, nonzero for failure.
508 */
509int find_cdrw_device(char *cdrw_device)
510{
511 /*@ buffers ************************ */
512 char *comment;
513 char *tmp;
514 char *cdr_exe;
515 char *command;
516
517 malloc_string(comment);
518 malloc_string(tmp);
519 malloc_string(cdr_exe);
520 malloc_string(command);
521 if (g_cdrw_drive_is_here[0]) {
522 strcpy(cdrw_device, g_cdrw_drive_is_here);
523 mr_msg(3, "Been there, done that. Returning %s", cdrw_device);
524 mr_free(comment);
525 mr_free(tmp);
526 mr_free(cdr_exe);
527 mr_free(command);
528 return (0);
529 }
530 if (g_backup_media_type == dvd) {
531 mr_msg(1,
532 "This is dumb. You're calling find_cdrw_device() but you're backing up to DVD. WTF?");
533 mr_free(comment);
534 mr_free(tmp);
535 mr_free(cdr_exe);
536 mr_free(command);
537 return (1);
538 }
539 run_program_and_log_output("insmod ide-scsi", -1);
540 if (find_home_of_exe("cdrecord")) {
541 strcpy(cdr_exe, "cdrecord");
542 } else {
543 strcpy(cdr_exe, "dvdrecord");
544 }
545 tmp[0] = '\0';
546 if (find_home_of_exe(cdr_exe)) {
547 sprintf(command,
548 "%s -scanbus 2> /dev/null | tr -s '\t' ' ' | grep \"[0-9]*,[0-9]*,[0-9]*\" | grep -v \"[0-9]*) \\*\" | grep CD | cut -d' ' -f2 | head -n1",
549 cdr_exe);
550 strcpy(tmp, call_program_and_get_last_line_of_output(command));
551 }
552 if (strlen(tmp) < 2) {
553 mr_free(comment);
554 mr_free(tmp);
555 mr_free(cdr_exe);
556 mr_free(command);
557 return 1;
558 } else {
559 strcpy(cdrw_device, tmp);
560 sprintf(comment, "Found CDRW device - %s", cdrw_device);
561 log_it(comment);
562 strcpy(g_cdrw_drive_is_here, cdrw_device);
563 mr_free(comment);
564 mr_free(tmp);
565 mr_free(cdr_exe);
566 mr_free(command);
567 return (0);
568 }
569}
570
571
572
573
574/**
575 * Attempt to locate a CD-ROM device's /dev entry.
576 * Several different methods may be used to find the device, including
577 * calling @c cdrecord, searching @c dmesg, and trial-and-error.
578 * @param output Where to put the located /dev entry.
579 * @param try_to_mount Whether to mount the CD as part of the test; if mount
580 * fails then return failure.
581 * @return 0 for success, nonzero for failure.
582 */
583int find_cdrom_device(char *output, bool try_to_mount)
584{
585 /*@ pointers **************************************************** */
586 FILE *fin;
587 char *p;
588 char *q;
589 char *r;
590 int retval = 0;
591
592 /*@ bool's ****************************************************** */
593 bool found_it = FALSE;
594
595 /*@ buffers ***************************************************** */
596 char *tmp;
597 char *cdr_exe;
598 char *phrase_one;
599 char *phrase_two;
600 char *command;
601 char *dvd_last_resort;
602 char *mountpoint;
603 static char the_last_place_i_found_it[MAX_STR_LEN] = "";
604
605 /*@ intialize *************************************************** */
606 malloc_string(tmp);
607 malloc_string(cdr_exe);
608 malloc_string(phrase_one);
609 malloc_string(phrase_two);
610 malloc_string(command);
611 malloc_string(dvd_last_resort);
612 malloc_string(mountpoint);
613
614 output[0] = '\0';
615 phrase_one[0] = '\0';
616 phrase_two[0] = '\0';
617 dvd_last_resort[0] = '\0';
618
619 /*@ end vars **************************************************** */
620
621 if (g_cdrom_drive_is_here[0] && !isdigit(g_cdrom_drive_is_here[0])) {
622 strcpy(output, g_cdrom_drive_is_here);
623 mr_msg(3, "Been there, done that. Returning %s", output);
624 retval = 0;
625 goto end_of_find_cdrom_device;
626 }
627 if (the_last_place_i_found_it[0] != '\0' && !try_to_mount) {
628 strcpy(output, the_last_place_i_found_it);
629 mr_msg(3,
630 "find_cdrom_device() --- returning last found location - '%s'",
631 output);
632 retval = 0;
633 goto end_of_find_cdrom_device;
634 }
635
636 sprintf(mountpoint, "/tmp/cd.%d", (int) (random() % 32767));
637 make_hole_for_dir(mountpoint);
638
639 if (find_home_of_exe("cdrecord")) {
640 strcpy(cdr_exe, "cdrecord");
641 } else {
642 strcpy(cdr_exe, "dvdrecord");
643 }
644 tmp[0] = '\0';
645 if (!find_home_of_exe(cdr_exe)) {
646 strcpy(output, "/dev/cdrom");
647 mr_msg(4, "Can't find cdrecord; assuming %s", output);
648 if (!does_device_exist(output)) {
649 mr_msg(4, "That didn't work. Sorry.");
650 retval = 1;
651 goto end_of_find_cdrom_device;
652 } else {
653 retval = 0;
654 goto end_of_find_cdrom_device;
655 }
656 }
657
658 sprintf(command, "%s -scanbus 2> /dev/null", cdr_exe);
659 fin = popen(command, "r");
660 if (!fin) {
661 mr_msg(4, "command=%s", command);
662 log_OS_error("Cannot popen command");
663 return (1);
664 }
665 for (fgets(tmp, MAX_STR_LEN, fin); !feof(fin);
666 fgets(tmp, MAX_STR_LEN, fin)) {
667 p = strchr(tmp, '\'');
668 if (p) {
669 q = strchr(++p, '\'');
670 if (q) {
671 for (r = q; *(r - 1) == ' '; r--);
672 *r = '\0';
673 strcpy(phrase_one, p);
674 p = strchr(++q, '\'');
675 if (p) {
676 q = strchr(++p, '\'');
677 if (q) {
678 while (*(q - 1) == ' ') {
679 q--;
680 }
681 *q = '\0';
682 strcpy(phrase_two, p);
683 }
684 }
685 }
686 }
687 }
688 paranoid_pclose(fin);
689
690#ifndef __FreeBSD__
691 if (strlen(phrase_two) == 0) {
692 mr_msg(4, "Not running phase two. String is empty.");
693 } else {
694 sprintf(command, "dmesg | grep \"%s\" 2> /dev/null", phrase_two);
695 fin = popen(command, "r");
696 if (!fin) {
697 mr_msg(4, "Cannot run 2nd command - non-fatal, fortunately");
698 } else {
699 for (fgets(tmp, MAX_STR_LEN, fin); !feof(fin);
700 fgets(tmp, MAX_STR_LEN, fin)) {
701 mr_msg(5, "--> '%s'", tmp);
702 if (tmp[0] != ' ' && tmp[1] != ' ') {
703 p = strchr(tmp, ':');
704 if (p) {
705 *p = '\0';
706 if (strstr(tmp, "DVD")) {
707 sprintf(dvd_last_resort, "/dev/%s", tmp);
708 mr_msg(4,
709 "Ignoring '%s' because it's a DVD drive",
710 tmp);
711 } else {
712 sprintf(output, "/dev/%s", tmp);
713 found_it = TRUE;
714 }
715 }
716 }
717 }
718 paranoid_pclose(fin);
719 }
720 }
721
722#endif
723#ifdef __FreeBSD__
724 if (!found_it) {
725 mr_msg(4, "OK, approach 2");
726 if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/cdrom"))) {
727 if (!
728 (found_it =
729 set_dev_to_this_if_rx_OK(output, "/dev/cdrom1"))) {
730 if (!
731 (found_it =
732 set_dev_to_this_if_rx_OK(output, "/dev/dvd"))) {
733 if (!
734 (found_it =
735 set_dev_to_this_if_rx_OK(output, "/dev/acd0"))) {
736 if (!
737 (found_it =
738 set_dev_to_this_if_rx_OK(output,
739 "/dev/cd01"))) {
740 if (!
741 (found_it =
742 set_dev_to_this_if_rx_OK(output,
743 "/dev/acd1"))) {
744 if (!
745 (found_it =
746 set_dev_to_this_if_rx_OK(output,
747 "/dev/cd1")))
748 {
749 retval = 1;
750 goto end_of_find_cdrom_device;
751 }
752 }
753 }
754 }
755 }
756 }
757 }
758 }
759#else
760 if (!found_it && strlen(dvd_last_resort) > 0) {
761 mr_msg(4, "Well, I'll use the DVD - %s - as a last resort",
762 dvd_last_resort);
763 strcpy(output, dvd_last_resort);
764 found_it = TRUE;
765 }
766 if (found_it) {
767 sprintf(tmp, "grep \"%s=ide-scsi\" /proc/cmdline &> /dev/null",
768 strrchr(output, '/') + 1);
769 if (system(tmp) == 0) {
770 mr_msg(4,
771 "%s is not right. It's being SCSI-emulated. Continuing.",
772 output);
773 found_it = FALSE;
774 output[0] = '\0';
775 }
776 }
777
778 if (found_it) {
779 mr_msg(4, "(find_cdrom_device) --> '%s'", output);
780 if (!does_device_exist(output)) {
781 found_it = FALSE;
782 mr_msg(4, "OK, I was wrong, I haven't found it... yet.");
783 }
784 }
785
786 if (!found_it) {
787 mr_msg(4, "OK, approach 2");
788 if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/scd0"))) {
789 if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/sr0"))) {
790 if (!
791 (found_it =
792 set_dev_to_this_if_rx_OK(output, "/dev/cdrom"))) {
793 if (!
794 (found_it =
795 set_dev_to_this_if_rx_OK(output,
796 "/dev/cdrom0"))) {
797 if (!
798 (found_it =
799 set_dev_to_this_if_rx_OK(output,
800 "/dev/cdrom1"))) {
801 if (!
802 (found_it =
803 set_dev_to_this_if_rx_OK(output,
804 "/dev/sr1"))) {
805 if (!
806 (found_it =
807 set_dev_to_this_if_rx_OK(output,
808 "/dev/dvd")))
809 {
810 if (!
811 (found_it =
812 set_dev_to_this_if_rx_OK(output,
813 g_cdrw_drive_is_here)))
814 {
815 retval = 1;
816 goto end_of_find_cdrom_device;
817 }
818 }
819 }
820 }
821 }
822 }
823 }
824 }
825 }
826#endif
827
828 if (found_it && try_to_mount) {
829 if (mount_CDROM_here(output, mountpoint)) {
830 mr_msg(4, "[Cardigans] I've changed my mind");
831 found_it = FALSE;
832 } else {
833 sprintf(tmp, "%s/archives", mountpoint);
834 if (!does_file_exist(tmp)) {
835 mr_msg(4, "[Cardigans] I'll take it back");
836 found_it = FALSE;
837 } else {
838 sprintf(command, "umount %s", output);
839 paranoid_system(command);
840 mr_msg(4, "I'm confident the Mondo CD is in %s", output);
841 }
842 }
843 }
844 unlink(mountpoint);
845
846 if (found_it) {
847 if (!does_file_exist(output)) {
848 mr_msg(3, "I still haven't found it.");
849 return (1);
850 }
851 mr_msg(3, "(find_cdrom_device) --> '%s'", output);
852 strcpy(the_last_place_i_found_it, output);
853 strcpy(g_cdrom_drive_is_here, output);
854 retval = 0;
855 goto end_of_find_cdrom_device;
856 }
857
858 sprintf(command,
859 "%s -scanbus | grep \"[0-9],[0-9],[0-9]\" | grep \"[D|C][V|D]\" | grep -n \"\" | grep \"%s\" | cut -d':' -f2",
860 cdr_exe, g_cdrw_drive_is_here);
861 mr_msg(1, "command=%s", command);
862 strcpy(tmp, call_program_and_get_last_line_of_output(command));
863 if (tmp[0]) {
864 strcpy(output, tmp);
865 mr_msg(4, "Finally found it at %s", output);
866 retval = 0;
867 goto end_of_find_cdrom_device;
868 } else {
869 mr_msg(4, "Still couldn't find it.");
870 retval = 1;
871 goto end_of_find_cdrom_device;
872 }
873 end_of_find_cdrom_device:
874 mr_free(tmp);
875 mr_free(cdr_exe);
876 mr_free(phrase_one);
877 mr_free(phrase_two);
878 mr_free(command);
879 mr_free(dvd_last_resort);
880 mr_free(mountpoint);
881 return (retval);
882}
883
884
885
886
887
888int find_dvd_device(char *output, bool try_to_mount)
889{
890 char *command;
891 char *tmp;
892 int retval = 0, devno = -1;
893
894 malloc_string(command);
895 malloc_string(tmp);
896
897 if (g_dvd_drive_is_here[0]) {
898 strcpy(output, g_dvd_drive_is_here);
899 mr_msg(3, "Been there, done that. Returning %s", output);
900 return (0);
901 }
902
903 sprintf(tmp, call_program_and_get_last_line_of_output
904 ("dvdrecord -scanbus 2> /dev/null | grep \") '\" | grep -n \"\" | grep DVD | cut -d':' -f1")
905 );
906 mr_msg(5, "tmp = '%s'", tmp);
907 if (!tmp[0])
908 sprintf(tmp, call_program_and_get_last_line_of_output
909 ("cdrecord -scanbus 2> /dev/null | grep \") '\" | grep -n \"\" | grep DVD | cut -d':' -f1")
910 );
911 if (tmp[0]) {
912 devno = atoi(tmp) - 1;
913 }
914 if (devno >= 0) {
915 retval = 0;
916 sprintf(output, "/dev/scd%d", devno);
917 strcpy(g_dvd_drive_is_here, output);
918 mr_msg(2, "I think DVD is at %s", output);
919 } else {
920 mr_msg(2, "I cannot find DVD");
921 retval = 1;
922 }
923
924 if (try_to_mount) {
925 mr_msg(1, "Ignoring the fact that try_to_mount==TRUE");
926 }
927 return (retval);
928}
929
930
931
932
933
934#include <sys/ioctl.h>
935
936/**
937 * Find the size of the specified @p drive, in megabytes. Uses @c ioctl calls
938 * and @c dmesg.
939 * @param drive The device to find the size of.
940 * @return size in megabytes.
941 */
942long get_phys_size_of_drive(char *drive)
943{
944 int fd;
945#if linux
946 unsigned long long s = 0;
947 int fileid, cylinders = 0, cylindersleft = 0;
948 int cylindersize = 0;
949 int gotgeo = 0;
950
951
952 struct hd_geometry hdgeo;
953#elif __FreeBSD__
954 off_t s;
955#endif
956
957 long outvalA = -1;
958 long outvalB = -1;
959 long outvalC = -1;
960
961 if ((fd = open(drive, O_RDONLY)) != -1) {
962 if (ioctl(fd,
963#if linux
964#ifdef BLKGETSIZE64
965 BLKGETSIZE64,
966#else
967 BLKGETSIZE,
968#endif
969#elif __FreeBSD__
970 DIOCGMEDIASIZE,
971#endif
972 &s) != -1) {
973 close(fd);
974 // s>>11 works for older disks but not for newer ones
975 outvalB =
976#if linux
977#ifdef BLKGETSIZE64
978 s >> 20
979#else
980 s >> 11
981#endif
982#else
983 s >> 20
984#endif
985 ;
986 }
987 }
988
989 if (outvalB <= 0) {
990 mr_msg(1, "Error getting size of %s: %s", drive, strerror(errno));
991#if linux
992 fileid = open(drive, O_RDONLY);
993 if (fileid) {
994 if (ioctl(fileid, HDIO_GETGEO, &hdgeo) != -1) {
995 if (hdgeo.cylinders && hdgeo.heads && hdgeo.sectors) {
996 cylindersleft = cylinders = hdgeo.cylinders;
997 cylindersize = hdgeo.heads * hdgeo.sectors / 2;
998 outvalA = cylindersize * cylinders / 1024;
999 mr_msg(2, "Got Harddisk geometry, C:%d, H:%d, S:%d",
1000 hdgeo.cylinders, hdgeo.heads, hdgeo.sectors);
1001 gotgeo = 1;
1002 } else {
1003 mr_msg(1, "Harddisk geometry wrong");
1004 }
1005 } else {
1006 mr_msg(1,
1007 "Error in ioctl() getting new hard disk geometry (%s), resizing in unsafe mode",
1008 strerror(errno));
1009 }
1010 close(fileid);
1011 } else {
1012 mr_msg(1, "Failed to open %s for reading: %s", drive,
1013 strerror(errno));
1014 }
1015 if (!gotgeo) {
1016 mr_msg(1, "Failed to get harddisk geometry, using old mode");
1017 }
1018/*
1019 if ((fd = open (drive, O_RDONLY)) != -1) {
1020 if (ioctl (fd, HDIO_GETGEO, &hdgeo) != -1) {
1021 close (fd);
1022 mr_msg (2, "Geometry of drive %s is C:%d, H:%d, S%d, its size is %d MB", drive, hdgeo.cylinders, hdgeo.heads, hdgeo.sectors, (hdgeo.cylinders * hdgeo.heads * hdgeo.sectors / 2 / 1024));
1023 if ( hdgeo.cylinders && hdgeo.heads && hdgeo.sectors ) {
1024 outvalB = ((long) (hdgeo.cylinders * hdgeo.heads * hdgeo.sectors / 2 / 1024));
1025 }
1026 }
1027 close (fd);
1028 */
1029#endif
1030 }
1031// OLDER DISKS will give ridiculously low value for outvalB (so outvalA is returned) :)
1032// NEWER DISKS will give sane value for outvalB (close to outvalA, in other words) :)
1033
1034 outvalC = (outvalA > outvalB) ? outvalA : outvalB;
1035
1036// mr_msg (5, "drive = %s, error = %s", drive, strerror (errno));
1037// fatal_error ("GPSOD: Unable to get size of drive");
1038 mr_msg(1, "%s --> %ld or %ld --> %ld", drive, outvalA, outvalB,
1039 outvalC);
1040
1041 return (outvalC);
1042}
1043
1044/* The old version */
1045#if 0
1046long get_phys_size_of_drive(char *drive)
1047{
1048 /*@ pointers **************************************************** */
1049#if linux
1050 FILE *fin;
1051 char *p;
1052 char *q;
1053 char *r;
1054 /*@ buffers ***************************************************** */
1055 char *tmp;
1056 char *command;
1057
1058 /*@ long ******************************************************** */
1059 long outL;
1060 long tempLa;
1061 long tempLb;
1062 long tempLc;
1063
1064#endif
1065
1066 struct hd_geometry hdgeo;
1067 int fd;
1068
1069#ifdef __FreeBSD__
1070 off_t o;
1071
1072 if ((fd = open(drive, O_RDONLY)) != -1) {
1073 if (ioctl(fd, DIOCGMEDIASIZE, &o) != -1) {
1074 close(fd);
1075 return (long) (o / (off_t) (1024 * 1024));
1076 }
1077 close(fd);
1078 }
1079 mr_msg(4, "drive = %s, error = %s", drive, strerror(errno));
1080 fatal_error("GPSOD: Unable to get size of drive");
1081#else
1082
1083 malloc_string(tmp);
1084 malloc_string(command);
1085
1086 if ((fd = open(drive, O_RDONLY)) != -1) {
1087 if (ioctl(fd, HDIO_GETGEO, &hdgeo) != -1) {
1088 close(fd);
1089 mr_msg(2,
1090 "Geometry of drive %s is C:%d, H:%d, S%d, its size is %d MB",
1091 drive, hdgeo.cylinders, hdgeo.heads, hdgeo.sectors,
1092 (hdgeo.cylinders * hdgeo.heads * hdgeo.sectors / 2 /
1093 1024));
1094 if (hdgeo.cylinders && hdgeo.heads && hdgeo.sectors) {
1095 return ((long)
1096 (hdgeo.cylinders * hdgeo.heads * hdgeo.sectors /
1097 2 / 1024));
1098 }
1099 }
1100 close(fd);
1101 }
1102
1103 assert_string_is_neither_NULL_nor_zerolength(drive);
1104
1105 sprintf(command,
1106 "parted2fdisk -l %s | head -n4 | tr -s '\n' '\t' | tr -s ' ' '\t' | cut -f8,14,16",
1107 drive);
1108 strcpy(tmp, call_program_and_get_last_line_of_output(command));
1109 if (tmp[0]) {
1110 p = tmp;
1111 q = strchr(p, ' ');
1112 if (q) {
1113 *(q++) = '\0';
1114 r = strchr(q, ' ');
1115 if (r) {
1116 *(r++) = '\0';
1117 tempLa = atol(p);
1118 tempLb = atol(q);
1119 tempLc = atol(r);
1120 outL = tempLa * tempLb / 1024 * tempLc / 1024;
1121 if (outL > 100) {
1122 mr_free(tmp);
1123 mr_free(command);
1124 return (outL);
1125 }
1126 }
1127 }
1128 }
1129
1130 /* try to grep for 'Drive xxxx: yyy MB' */
1131 sprintf(command,
1132 "parted2fdisk -l %s | grep MB | tr -s ' ' '\t' | cut -f3",
1133 drive);
1134 strcpy(tmp, call_program_and_get_last_line_of_output(command));
1135 if (atol(tmp) > 0) {
1136 mr_free(tmp);
1137 mr_free(command);
1138 return (atol(tmp));
1139 }
1140
1141 /* else, do it the old-fashioned way */
1142 p = strrchr(drive, (int) '/');
1143 if (p) {
1144 strcpy(tmp, p + 1);
1145 } else {
1146 mr_free(tmp);
1147 mr_free(command);
1148 return (-1);
1149 }
1150 sprintf(command, "dmesg | grep %s 2> /dev/null", tmp);
1151 if (!(fin = popen(command, "r"))) {
1152 log_OS_error("Cannot popen dmesg command");
1153 } else {
1154 fgets(tmp, MAX_STR_LEN - 1, fin);
1155 while (!feof(fin) && !strstr(tmp, "GB") && !strstr(tmp, "MB")) {
1156 fgets(tmp, MAX_STR_LEN - 1, fin);
1157 }
1158 if (pclose(fin)) {
1159 log_OS_error("Cannot pclose dmesg fin");
1160 }
1161 }
1162 if (!(p = strstr(tmp, "GB")) && !(p = strstr(tmp, "MB"))) {
1163 mr_msg(3, "Cannot find %s's size: dmesg isn't helping either.",
1164 drive);
1165 mr_free(tmp);
1166 mr_free(command);
1167 return (-1);
1168 }
1169 for (; !isdigit(*(p - 1)); p--);
1170 *p = '\0';
1171 for (p--; isdigit(*(p - 1)); p--);
1172 outL = atol(p);
1173 if (outL <= 0) {
1174 mr_free(tmp);
1175 mr_free(command);
1176 return (-1);
1177 }
1178 if (strstr(tmp, "GB")) {
1179 outL = outL * 1024;
1180 }
1181 mr_free(tmp);
1182 mr_free(command);
1183 return (outL * 19 / 20);
1184#endif
1185}
1186#endif /* 0 */
1187
1188
1189
1190
1191
1192/**
1193 * Determine whether @p format is supported by the kernel. Uses /proc/filesystems
1194 * under Linux and @c lsvfs under FreeBSD.
1195 * @param format The format to test.
1196 * @return TRUE if the format is supported, FALSE if not.
1197 */
1198bool is_this_a_valid_disk_format(char *format)
1199{
1200 char *good_formats;
1201 char *command;
1202 char *format_sz;
1203
1204 FILE *pin;
1205 int retval;
1206 malloc_string(good_formats);
1207 malloc_string(command);
1208 malloc_string(format_sz);
1209
1210 assert_string_is_neither_NULL_nor_zerolength(format);
1211
1212 sprintf(format_sz, "%s ", format);
1213
1214#ifdef __FreeBSD__
1215 sprintf(command,
1216 "lsvfs | tr -s '\t' ' ' | grep -v Filesys | grep -v -- -- | cut -d' ' -f1 | tr -s '\n' ' '");
1217#else
1218 sprintf(command,
1219 "grep -v nodev /proc/filesystems | tr -s '\t' ' ' | cut -d' ' -f2 | tr -s '\n' ' '");
1220#endif
1221
1222 pin = popen(command, "r");
1223 if (!pin) {
1224 log_OS_error("Unable to read good formats");
1225 retval = 0;
1226 } else {
1227 strcpy(good_formats, " ");
1228 (void) fgets(good_formats + 1, MAX_STR_LEN, pin);
1229 if (pclose(pin)) {
1230 log_OS_error("Cannot pclose good formats");
1231 }
1232 strip_spaces(good_formats);
1233 strcat(good_formats, " swap lvm raid ntfs 7 "); // " ntfs 7 " -- um, cheating much? :)
1234 if (strstr(good_formats, format_sz)) {
1235 retval = 1;
1236 } else {
1237 retval = 0;
1238 }
1239 }
1240 mr_free(good_formats);
1241 mr_free(command);
1242 mr_free(format_sz);
1243 return (retval);
1244}
1245
1246
1247/** @def SWAPLIST_COMMAND The command to list the swap files/partitions in use. */
1248
1249/**
1250 * Determine whether @p device_raw is currently mounted.
1251 * @param device_raw The device to check.
1252 * @return TRUE if it's mounted, FALSE if not.
1253 */
1254bool is_this_device_mounted(char *device_raw)
1255{
1256
1257 /*@ pointers **************************************************** */
1258 FILE *fin;
1259
1260 /*@ buffers ***************************************************** */
1261 char *incoming;
1262 char *device_with_tab;
1263 char *device_with_space;
1264 char *tmp;
1265 int retval = 0;
1266
1267#ifdef __FreeBSD__
1268#define SWAPLIST_COMMAND "swapinfo"
1269#else
1270#define SWAPLIST_COMMAND "cat /proc/swaps"
1271#endif
1272
1273 /*@ end vars **************************************************** */
1274
1275 malloc_string(incoming);
1276 malloc_string(device_with_tab);
1277 malloc_string(device_with_space);
1278 malloc_string(tmp);
1279 assert(device_raw != NULL);
1280// assert_string_is_neither_NULL_nor_zerolength(device_raw);
1281 if (device_raw[0] != '/' && !strstr(device_raw, ":/")) {
1282 mr_msg(1, "%s needs to have a '/' prefixed - I'll do it",
1283 device_raw);
1284 sprintf(tmp, "/%s", device_raw);
1285 } else {
1286 strcpy(tmp, device_raw);
1287 }
1288 mr_msg(1, "Is %s mounted?", tmp);
1289 if (!strcmp(tmp, "/proc") || !strcmp(tmp, "proc")) {
1290 mr_msg(1,
1291 "I don't know how the heck /proc made it into the mountlist. I'll ignore it.");
1292 return (0);
1293 }
1294 sprintf(device_with_tab, "%s\t", tmp);
1295 sprintf(device_with_space, "%s ", tmp);
1296
1297 if (!(fin = popen("mount", "r"))) {
1298 log_OS_error("Cannot popen 'mount'");
1299 return (FALSE);
1300 }
1301 for (fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin);
1302 fgets(incoming, MAX_STR_LEN - 1, fin)) {
1303 if (strstr(incoming, device_with_space) //> incoming
1304 || strstr(incoming, device_with_tab)) // > incoming)
1305 {
1306 paranoid_pclose(fin);
1307 retval = 1;
1308 goto end_of_func;
1309 }
1310 }
1311 paranoid_pclose(fin);
1312 sprintf(tmp, "%s | grep -E \"^%s\" > /dev/null 2> /dev/null",
1313 SWAPLIST_COMMAND, device_with_space);
1314 mr_msg(4, "tmp (command) = '%s'", tmp);
1315 if (!system(tmp)) {
1316 retval = 1;
1317 goto end_of_func;
1318 }
1319 end_of_func:
1320 mr_free(incoming);
1321 mr_free(device_with_tab);
1322 mr_free(device_with_space);
1323 mr_free(tmp);
1324 return (retval);
1325}
1326
1327#ifdef __FreeBSD__
1328// CODE IS FREEBSD-SPECIFIC
1329/**
1330 * Create a loopback device for specified @p fname.
1331 * @param fname The file to associate with a device.
1332 * @return /dev entry for the device, or NULL if it couldn't be allocated.
1333 */
1334char *make_vn(char *fname)
1335{
1336 char *device = (char *) malloc(MAX_STR_LEN);
1337 char *mddevice = (char *) malloc(32);
1338 char command[MAX_STR_LEN];
1339 int vndev = 2;
1340 if (atoi
1341 (call_program_and_get_last_line_of_output
1342 ("/sbin/sysctl -n kern.osreldate")) < 500000) {
1343 do {
1344 sprintf(mddevice, "vn%ic", vndev++);
1345 sprintf(command, "vnconfig %s %s", mddevice, fname);
1346 if (vndev > 10) {
1347 return NULL;
1348 }
1349 }
1350 while (system(command));
1351 } else {
1352 sprintf(command, "mdconfig -a -t vnode -f %s", fname);
1353 mddevice = call_program_and_get_last_line_of_output(command);
1354 if (!strstr(mddevice, "md")) {
1355 return NULL;
1356 }
1357 }
1358 sprintf(device, "/dev/%s", mddevice);
1359 return device;
1360}
1361
1362
1363
1364// CODE IS FREEBSD-SPECIFIC
1365/**
1366 * Deallocate specified @p dname.
1367 * This should be called when you are done with the device created by make_vn(),
1368 * so the system does not run out of @c vn devices.
1369 * @param dname The device to deallocate.
1370 * @return 0 for success, nonzero for failure.
1371 */
1372int kick_vn(char *dname)
1373{
1374 char command[MAX_STR_LEN];
1375
1376 if (strncmp(dname, "/dev/", 5) == 0) {
1377 dname += 5;
1378 }
1379
1380 if (atoi
1381 (call_program_and_get_last_line_of_output
1382 ("/sbin/sysctl -n kern.osreldate")) < 500000) {
1383 sprintf(command, "vnconfig -d %s", dname);
1384 return system(command);
1385 } else {
1386 sprintf(command, "mdconfig -d -u %s", dname);
1387 return system(command);
1388 }
1389 /*NOTREACHED*/ return 255;
1390}
1391#endif
1392
1393
1394/**
1395 * Mount the CD-ROM at @p mountpoint.
1396 * @param device The device (or file if g_ISO_restore_mode) to mount.
1397 * @param mountpoint The place to mount it.
1398 * @return 0 for success, nonzero for failure.
1399 */
1400int mount_CDROM_here(char *device, char *mountpoint)
1401{
1402 /*@ buffer ****************************************************** */
1403 char *command;
1404 char *dev;
1405 char *options;
1406 int retval;
1407
1408 malloc_string(command);
1409 malloc_string(dev);
1410 malloc_string(options);
1411 assert_string_is_neither_NULL_nor_zerolength(device);
1412 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
1413
1414 make_hole_for_dir(mountpoint);
1415 strcpy(options, "ro");
1416 if (isdigit(device[0])) {
1417 find_cdrom_device(device, FALSE);
1418 } else {
1419 strcpy(dev, device);
1420 }
1421 if (g_ISO_restore_mode) {
1422
1423#ifdef __FreeBSD__
1424 strcpy(dev, make_vn(device));
1425 if (!dev) {
1426 sprintf(command, "Unable to mount ISO (make_vn(%s) failed)",
1427 device);
1428 fatal_error(command);
1429 }
1430 strcpy(device, dev);
1431#else
1432 strcat(options, ",loop");
1433#endif
1434
1435 }
1436 mr_msg(4, "(mount_CDROM_here --- device=%s, mountpoint=%s", device,
1437 mountpoint);
1438 /*@ end vars *************************************************** */
1439
1440#ifdef __FreeBSD__
1441 sprintf(command, "mount_cd9660 -r %s %s 2>> %s",
1442 device, mountpoint, MONDO_LOGFILE);
1443
1444#else
1445 sprintf(command, "mount %s -o %s -t iso9660 %s 2>> %s",
1446 device, options, mountpoint, MONDO_LOGFILE);
1447#endif
1448
1449 mr_msg(4, command);
1450 if (strncmp(device, "/dev/", 5) == 0) {
1451 retract_CD_tray_and_defeat_autorun();
1452 }
1453 retval = system(command);
1454 mr_msg(1, "system(%s) returned %d", command, retval);
1455
1456 mr_free(command);
1457 mr_free(dev);
1458 mr_free(options);
1459 return (retval);
1460}
1461
1462
1463
1464
1465
1466
1467/**
1468 * Ask the user for CD number @p cd_number_i_want.
1469 * Sets g_current_media_number once the correct CD is inserted.
1470 * @param bkpinfo The backup information structure. Fields used:
1471 * - @c bkpinfo->backup_media_type
1472 * - @c bkpinfo->prefix
1473 * - @c bkpinfo->isodir
1474 * - @c bkpinfo->media_device
1475 * - @c bkpinfo->please_dont_eject_when_restoring
1476 * @param cd_number_i_want The CD number to ask for.
1477 */
1478void
1479insist_on_this_cd_number(struct s_bkpinfo *bkpinfo, int cd_number_i_want)
1480{
1481
1482 /*@ int ************************************************************* */
1483 int res = 0;
1484
1485
1486 /*@ buffers ********************************************************* */
1487 char *tmp;
1488 char *request;
1489
1490 assert(bkpinfo != NULL);
1491 assert(cd_number_i_want > 0);
1492
1493// mr_msg(3, "Insisting on CD number %d", cd_number_i_want);
1494
1495 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1496 mr_msg(3,
1497 "No need to insist_on_this_cd_number when the backup type isn't CD-R(W) or NFS or ISO");
1498 return;
1499 }
1500 malloc_string(tmp);
1501 malloc_string(request);
1502 sprintf(tmp, "mkdir -p " MNT_CDROM);
1503 run_program_and_log_output(tmp, 5);
1504 if (g_ISO_restore_mode || bkpinfo->backup_media_type == iso
1505 || bkpinfo->backup_media_type == nfs) {
1506 mr_msg(3, "Remounting CD");
1507 g_ISO_restore_mode = TRUE;
1508// FIXME --- I'm tempted to do something about this...
1509// Why unmount and remount again and again?
1510 if (is_this_device_mounted(MNT_CDROM)) {
1511 run_program_and_log_output("umount " MNT_CDROM, 5);
1512 }
1513 system("mkdir -p /tmp/isodir &> /dev/null");
1514 sprintf(tmp, "%s/%s/%s-%d.iso", bkpinfo->isodir,
1515 bkpinfo->nfs_remote_dir, bkpinfo->prefix,
1516 cd_number_i_want);
1517 if (!does_file_exist(tmp)) {
1518 sprintf(tmp, "/tmp/isodir/%s/%s-%d.iso",
1519 bkpinfo->nfs_remote_dir, bkpinfo->prefix,
1520 cd_number_i_want);
1521 if (does_file_exist(tmp)) {
1522 mr_msg(1,
1523 "FIXME - hacking bkpinfo->isodir from '%s' to /tmp/isodir",
1524 bkpinfo->isodir);
1525 strcpy(bkpinfo->isodir, "/tmp/isodir");
1526 }
1527 }
1528 mr_msg(3, "Mounting %s at %s", tmp, MNT_CDROM);
1529 if (mount_CDROM_here(tmp, MNT_CDROM)) {
1530 fatal_error("Mommy!");
1531 }
1532// g_current_media_number = cd_number_i_want;
1533// return;
1534 }
1535 if ((res = what_number_cd_is_this(bkpinfo)) != cd_number_i_want) {
1536 mr_msg(3, "Currently, we hold %d but we want %d", res,
1537 cd_number_i_want);
1538 sprintf(tmp, "Insisting on %s #%d",
1539 media_descriptor_string(bkpinfo->backup_media_type),
1540 cd_number_i_want);
1541 sprintf(request, "Please insert %s #%d and press Enter.",
1542 media_descriptor_string(bkpinfo->backup_media_type),
1543 cd_number_i_want);
1544 mr_msg(3, tmp);
1545 while (what_number_cd_is_this(bkpinfo) != cd_number_i_want) {
1546 paranoid_system("sync");
1547 if (is_this_device_mounted(MNT_CDROM)) {
1548 res =
1549 run_program_and_log_output("umount " MNT_CDROM, FALSE);
1550 } else {
1551 res = 0;
1552 }
1553 if (res) {
1554 log_to_screen("WARNING - failed to unmount CD-ROM drive");
1555 }
1556 if (!bkpinfo->please_dont_eject) {
1557 res = eject_device(bkpinfo->media_device);
1558 } else {
1559 res = 0;
1560 }
1561 if (res) {
1562 log_to_screen("WARNING - failed to eject CD-ROM disk");
1563 }
1564 popup_and_OK(request);
1565 if (!bkpinfo->please_dont_eject) {
1566 inject_device(bkpinfo->media_device);
1567 }
1568 paranoid_system("sync");
1569 }
1570 mr_msg(1, "Thankyou. Proceeding...");
1571 g_current_media_number = cd_number_i_want;
1572 }
1573 mr_free(tmp);
1574 mr_free(request);
1575}
1576
1577/* @} - end of deviceGroup */
1578
1579
1580
1581
1582
1583
1584/**
1585 * Ask user for details of backup/restore information.
1586 * Called when @c mondoarchive doesn't get any parameters.
1587 * @param bkpinfo The backup information structure to fill out with the user's data.
1588 * @param archiving_to_media TRUE if archiving, FALSE if restoring.
1589 * @return 0, always.
1590 * @bug No point of `int' return value.
1591 * @ingroup archiveGroup
1592 */
1593int interactively_obtain_media_parameters_from_user(struct s_bkpinfo
1594 *bkpinfo,
1595 bool
1596 archiving_to_media)
1597// archiving_to_media is TRUE if I'm being called by mondoarchive
1598// archiving_to_media is FALSE if I'm being called by mondorestore
1599{
1600 char *tmp;
1601 char *sz_size;
1602 char *command;
1603 char *comment;
1604 char *prompt;
1605 int i;
1606 FILE *fin;
1607
1608 malloc_string(tmp);
1609 malloc_string(sz_size);
1610 malloc_string(command);
1611 malloc_string(comment);
1612 malloc_string(prompt);
1613 assert(bkpinfo != NULL);
1614 sz_size[0] = '\0';
1615 bkpinfo->nonbootable_backup = FALSE;
1616
1617// Tape, CD, NFS, ...?
1618 srandom(getpid());
1619 bkpinfo->backup_media_type =
1620 (g_restoring_live_from_cd) ? cdr :
1621 which_backup_media_type(bkpinfo->restore_data);
1622 if (bkpinfo->backup_media_type == none) {
1623 log_to_screen("User has chosen not to backup the PC");
1624 finish(1);
1625 }
1626 if (bkpinfo->backup_media_type == tape && bkpinfo->restore_data) {
1627 popup_and_OK("Please remove CD/floppy from drive(s)");
1628 }
1629 mr_msg(3, "media type = %s",
1630 bkptype_to_string(bkpinfo->backup_media_type));
1631 if (archiving_to_media) {
1632 sensibly_set_tmpdir_and_scratchdir(bkpinfo);
1633 }
1634 bkpinfo->cdrw_speed = (bkpinfo->backup_media_type == cdstream) ? 2 : 4;
1635 bkpinfo->compression_level =
1636 (bkpinfo->backup_media_type == cdstream) ? 1 : 5;
1637 bkpinfo->use_lzo =
1638 (bkpinfo->backup_media_type == cdstream) ? TRUE : FALSE;
1639 mvaddstr_and_log_it(2, 0, " ");
1640
1641// Find device's /dev (or SCSI) entry
1642 switch (bkpinfo->backup_media_type) {
1643 case cdr:
1644 case cdrw:
1645 case dvd:
1646 case usb:
1647 if (archiving_to_media) {
1648 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
1649 if (ask_me_yes_or_no
1650 ("Is your computer a laptop, or does the CD writer incorporate BurnProof technology?"))
1651 {
1652 bkpinfo->manual_cd_tray = TRUE;
1653 }
1654 }
1655 if ((bkpinfo->compression_level =
1656 which_compression_level()) == -1) {
1657 log_to_screen("User has chosen not to backup the PC");
1658 finish(1);
1659 }
1660 sprintf(comment, "What speed is your %s (re)writer?",
1661 media_descriptor_string(bkpinfo->backup_media_type));
1662 if (bkpinfo->backup_media_type == dvd) {
1663 find_dvd_device(bkpinfo->media_device, FALSE);
1664 strcpy(tmp, "1");
1665 sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4582 MB
1666 mr_msg(1, "Setting to DVD defaults");
1667 } else if (bkpinfo->backup_media_type == usb) {
1668 strcpy(bkpinfo->media_device, VANILLA_USB_DEVICE);
1669 strcpy(sz_size, "512");
1670 } else {
1671 strcpy(bkpinfo->media_device, VANILLA_SCSI_CDROM);
1672 strcpy(tmp, "4");
1673 strcpy(sz_size, "650");
1674 mr_msg(1, "Setting to CD defaults");
1675 }
1676 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
1677 if (!popup_and_get_string("Speed", comment, tmp, 4)) {
1678 log_to_screen("User has chosen not to backup the PC");
1679 finish(1);
1680 }
1681 }
1682 bkpinfo->cdrw_speed = atoi(tmp); // if DVD then this shouldn't ever be used anyway :)
1683 sprintf(comment,
1684 "How much data (in Megabytes) will each %s store?",
1685 media_descriptor_string(bkpinfo->backup_media_type));
1686 if (!popup_and_get_string("Size", comment, sz_size, 5)) {
1687 log_to_screen("User has chosen not to backup the PC");
1688 finish(1);
1689 }
1690 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1691 bkpinfo->media_size[i] = atoi(sz_size);
1692 }
1693 if (bkpinfo->media_size[0] <= 0) {
1694 log_to_screen("User has chosen not to backup the PC");
1695 finish(1);
1696 }
1697 }
1698 case cdstream:
1699 if (bkpinfo->disaster_recovery) {
1700 strcpy(bkpinfo->media_device, "/dev/cdrom");
1701 mr_msg(2, "CD-ROM device assumed to be at %s",
1702 bkpinfo->media_device);
1703 } else if (bkpinfo->restore_data
1704 || bkpinfo->backup_media_type == dvd) {
1705 if (!bkpinfo->media_device[0]) {
1706 strcpy(bkpinfo->media_device, "/dev/cdrom");
1707 } // just for the heck of it :)
1708 mr_msg(1, "bkpinfo->media_device = %s",
1709 bkpinfo->media_device);
1710 if (bkpinfo->backup_media_type == dvd
1711 || find_cdrom_device(bkpinfo->media_device, FALSE)) {
1712 mr_msg(1, "bkpinfo->media_device = %s",
1713 bkpinfo->media_device);
1714 sprintf(comment,
1715 "Please specify your %s drive's /dev entry",
1716 media_descriptor_string(bkpinfo->
1717 backup_media_type));
1718 if (!popup_and_get_string
1719 ("Device?", comment, bkpinfo->media_device,
1720 MAX_STR_LEN / 4)) {
1721 log_to_screen("User has chosen not to backup the PC");
1722 finish(1);
1723 }
1724 }
1725 mr_msg(2, "%s device found at %s",
1726 media_descriptor_string(bkpinfo->backup_media_type),
1727 bkpinfo->media_device);
1728 } else {
1729 if (find_cdrw_device(bkpinfo->media_device)) {
1730 bkpinfo->media_device[0] = '\0';
1731 }
1732 if (bkpinfo->media_device[0]) {
1733 sprintf(tmp,
1734 "I think I've found your %s burner at SCSI node %s. Is this correct? (Say no if you have an IDE burner and you are running a 2.6 kernel. You will then be prompted for further details.)",
1735 media_descriptor_string(bkpinfo->
1736 backup_media_type),
1737 bkpinfo->media_device);
1738 if (!ask_me_yes_or_no(tmp)) {
1739 bkpinfo->media_device[0] = '\0';
1740 }
1741 }
1742 if (!bkpinfo->media_device[0]) {
1743 if (g_kernel_version < 2.6) {
1744 i = popup_and_get_string("Device node?",
1745 "What is the SCSI node of your CD (re)writer, please?",
1746 bkpinfo->media_device,
1747 MAX_STR_LEN / 4);
1748 } else {
1749 i = popup_and_get_string("/dev entry?",
1750 "What is the /dev entry of your CD (re)writer, please?",
1751 bkpinfo->media_device,
1752 MAX_STR_LEN / 4);
1753 }
1754 if (!i) {
1755 log_to_screen("User has chosen not to backup the PC");
1756 finish(1);
1757 }
1758 }
1759 }
1760 if (bkpinfo->backup_media_type == cdstream) {
1761 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1762 bkpinfo->media_size[i] = 650;
1763 }
1764 }
1765 break;
1766 case udev:
1767 if (!ask_me_yes_or_no
1768 ("This option is for advanced users only. Are you sure?")) {
1769 log_to_screen("User has chosen not to backup the PC");
1770 finish(1);
1771 }
1772 case tape:
1773
1774 if (find_tape_device_and_size(bkpinfo->media_device, sz_size)) {
1775 mr_msg(3, "Ok, using vanilla scsi tape.");
1776 strcpy(bkpinfo->media_device, VANILLA_SCSI_TAPE);
1777 if ((fin = fopen(bkpinfo->media_device, "r"))) {
1778 paranoid_fclose(fin);
1779 } else {
1780 strcpy(bkpinfo->media_device, "/dev/osst0");
1781 }
1782 }
1783 if (bkpinfo->media_device[0]) {
1784 if ((fin = fopen(bkpinfo->media_device, "r"))) {
1785 paranoid_fclose(fin);
1786 } else {
1787 if (does_file_exist("/tmp/mondo-restore.cfg")) {
1788 read_cfg_var("/tmp/mondo-restore.cfg", "media-dev",
1789 bkpinfo->media_device);
1790 }
1791 }
1792 sprintf(tmp,
1793 "I think I've found your tape streamer at %s; am I right on the money?",
1794 bkpinfo->media_device);
1795 }
1796 if (bkpinfo->media_device[0]) {
1797 sprintf(tmp,
1798 "I think I've found your tape streamer at %s; am I right on the money?",
1799 bkpinfo->media_device);
1800 if (!ask_me_yes_or_no(tmp)) {
1801 bkpinfo->media_device[0] = '\0';
1802 }
1803 }
1804 if (!bkpinfo->media_device[0]) {
1805 if (!popup_and_get_string
1806 ("Device name?",
1807 "What is the /dev entry of your tape streamer?",
1808 bkpinfo->media_device, MAX_STR_LEN / 4)) {
1809 log_to_screen("User has chosen not to backup the PC");
1810 finish(1);
1811 }
1812 }
1813 sprintf(tmp, "ls -l %s", bkpinfo->media_device);
1814 if (run_program_and_log_output(tmp, FALSE)) {
1815 log_to_screen("User has not specified a valid /dev entry");
1816 finish(1);
1817 }
1818 mr_msg(4, "sz_size = %s", sz_size);
1819 sz_size[0] = '\0';
1820/*
1821 if ((size_sz[0]=='\0' || atol(size_sz)==0) && archiving_to_media)
1822 {
1823 if (!popup_and_get_string("Tape size", "How much COMPRESSED data will one of your tape cartridges hold? (e.g. 4GB for 4 gigabytes)", size_sz, 16))
1824 { log_to_screen("User has chosen not to backup the PC"); finish(1); }
1825 }
1826*/
1827 if (sz_size[0] == '\0') {
1828 bkpinfo->media_size[0] = 0;
1829 } else {
1830 bkpinfo->media_size[0] =
1831 friendly_sizestr_to_sizelong(sz_size) / 2 - 50;
1832 }
1833 mr_msg(4, "media_size[0] = %ld", bkpinfo->media_size[0]);
1834 if (bkpinfo->media_size[0] <= 0) {
1835 bkpinfo->media_size[0] = 0;
1836 }
1837 for (i = 1; i <= MAX_NOOF_MEDIA; i++) {
1838 bkpinfo->media_size[i] = bkpinfo->media_size[0];
1839 }
1840 if (archiving_to_media) {
1841 if ((bkpinfo->compression_level =
1842 which_compression_level()) == -1) {
1843 log_to_screen("User has chosen not to backup the PC");
1844 finish(1);
1845 }
1846 }
1847 break;
1848
1849
1850
1851 case nfs:
1852 if (!bkpinfo->nfs_mount[0]) {
1853 strcpy(bkpinfo->nfs_mount,
1854 call_program_and_get_last_line_of_output
1855 ("mount | grep \":\" | cut -d' ' -f1 | head -n1"));
1856 }
1857#ifdef __FreeBSD__
1858 if (TRUE)
1859#else
1860 if (!bkpinfo->disaster_recovery)
1861#endif
1862 {
1863 if (!popup_and_get_string
1864 ("NFS dir.",
1865 "Please enter path and directory where archives are stored remotely. (Mondo has taken a guess at the correct value. If it is incorrect, delete it and type the correct one.)",
1866 bkpinfo->nfs_mount, MAX_STR_LEN / 4)) {
1867 log_to_screen("User has chosen not to backup the PC");
1868 finish(1);
1869 }
1870 if (!bkpinfo->restore_data) {
1871 if ((bkpinfo->compression_level =
1872 which_compression_level()) == -1) {
1873 log_to_screen("User has chosen not to backup the PC");
1874 finish(1);
1875 }
1876 }
1877 // check whether already mounted - we better remove
1878 // surrounding spaces and trailing '/' for this
1879 strip_spaces(bkpinfo->nfs_mount);
1880 if (bkpinfo->nfs_mount[strlen(bkpinfo->nfs_mount) - 1] == '/')
1881 bkpinfo->nfs_mount[strlen(bkpinfo->nfs_mount) - 1] = '\0';
1882 sprintf(command, "mount | grep \"%s \" | cut -d' ' -f3",
1883 bkpinfo->nfs_mount);
1884 strcpy(bkpinfo->isodir,
1885 call_program_and_get_last_line_of_output(command));
1886
1887 sprintf(comment,
1888 "How much data (in Megabytes) will each media store?");
1889 if (!popup_and_get_string("Size", comment, sz_size, 5)) {
1890 log_to_screen("User has chosen not to backup the PC");
1891 finish(1);
1892 }
1893 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1894 bkpinfo->media_size[i] = atoi(sz_size);
1895 }
1896 if (bkpinfo->media_size[0] <= 0) {
1897 log_to_screen("User has chosen not to backup the PC");
1898 finish(1);
1899 }
1900 }
1901 if (bkpinfo->disaster_recovery) {
1902 system("umount /tmp/isodir 2> /dev/null");
1903 if (!popup_and_get_string
1904 ("NFS share", "Which remote NFS share should I mount?",
1905 bkpinfo->nfs_mount, MAX_STR_LEN)) {
1906 log_to_screen("User has chosen not to backup the PC");
1907 finish(1);
1908 }
1909 }
1910 if (!is_this_device_mounted(bkpinfo->nfs_mount)) {
1911 sprintf(bkpinfo->isodir, "/tmp/isodir.mondo.%d",
1912 (int) (random() % 32768));
1913 sprintf(command, "mkdir -p %s", bkpinfo->isodir);
1914 run_program_and_log_output(command, 5);
1915 sprintf(tmp, "mount -t nfs -o nolock %s %s", bkpinfo->nfs_mount,
1916 bkpinfo->isodir);
1917 run_program_and_log_output(tmp, 5);
1918 malloc_string(g_selfmounted_isodir);
1919 strcpy(g_selfmounted_isodir, bkpinfo->isodir);
1920 }
1921 if (!is_this_device_mounted(bkpinfo->nfs_mount)) {
1922 popup_and_OK
1923 ("Please mount that partition before you try to backup to or restore from it.");
1924 finish(1);
1925 }
1926 strcpy(tmp, bkpinfo->nfs_remote_dir);
1927 if (!popup_and_get_string
1928 ("Directory", "Which directory within that mountpoint?", tmp,
1929 MAX_STR_LEN)) {
1930 log_to_screen("User has chosen not to backup the PC");
1931 finish(1);
1932 }
1933 strcpy(bkpinfo->nfs_remote_dir, tmp);
1934 // check whether writable - we better remove surrounding spaces for this
1935 strip_spaces(bkpinfo->nfs_remote_dir);
1936 sprintf(command, "echo hi > %s/%s/.dummy.txt", bkpinfo->isodir,
1937 bkpinfo->nfs_remote_dir);
1938 while (run_program_and_log_output(command, FALSE)) {
1939 strcpy(tmp, bkpinfo->nfs_remote_dir);
1940 sprintf(prompt,
1941 "Directory '%s' under mountpoint '%s' does not exist or is not writable. You can fix this or change the directory and retry or cancel the backup.",
1942 bkpinfo->nfs_remote_dir, bkpinfo->isodir);
1943 if (!popup_and_get_string
1944 ("Directory", prompt, tmp, MAX_STR_LEN)) {
1945 log_to_screen("User has chosen not to backup the PC");
1946 finish(1);
1947 }
1948 strcpy(bkpinfo->nfs_remote_dir, tmp);
1949 // check whether writable - we better remove surrounding space s for this
1950 strip_spaces(bkpinfo->nfs_remote_dir);
1951 sprintf(command, "echo hi > %s/%s/.dummy.txt", bkpinfo->isodir,
1952 bkpinfo->nfs_remote_dir);
1953 }
1954 if (!popup_and_get_string
1955 ("Prefix.",
1956 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
1957 bkpinfo->prefix, MAX_STR_LEN / 4)) {
1958 log_to_screen("User has chosen not to backup the PC");
1959 finish(1);
1960 }
1961 mr_msg(3, "prefix set to %s", bkpinfo->prefix);
1962
1963 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1964 bkpinfo->media_size[i] = 650;
1965 }
1966 mr_msg(3, "Just set nfs_remote_dir to %s",
1967 bkpinfo->nfs_remote_dir);
1968 mr_msg(3, "isodir is still %s", bkpinfo->isodir);
1969 break;
1970
1971 case iso:
1972 if (!bkpinfo->disaster_recovery) {
1973 if (!popup_and_get_string
1974 ("Storage dir.",
1975 "Please enter the full path that contains your ISO images. Example: /mnt/raid0_0",
1976 bkpinfo->isodir, MAX_STR_LEN / 4)) {
1977 log_to_screen("User has chosen not to backup the PC");
1978 finish(1);
1979 }
1980 if (archiving_to_media) {
1981 if ((bkpinfo->compression_level =
1982 which_compression_level()) == -1) {
1983 log_to_screen("User has chosen not to backup the PC");
1984 finish(1);
1985 }
1986 if (!popup_and_get_string
1987 ("ISO size.",
1988 "Please enter how big you want each ISO image to be (in megabytes). This should be less than or equal to the size of the CD-R[W]'s or DVD's you plan to backup to.",
1989 sz_size, 16)) {
1990 log_to_screen("User has chosen not to backup the PC");
1991 finish(1);
1992 }
1993 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1994 bkpinfo->media_size[i] = atoi(sz_size);
1995 }
1996 } else {
1997 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1998 bkpinfo->media_size[i] = 650;
1999 }
2000 }
2001 }
2002 if (!popup_and_get_string
2003 ("Prefix.",
2004 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
2005 bkpinfo->prefix, MAX_STR_LEN / 4)) {
2006 log_to_screen("User has chosen not to backup the PC");
2007 finish(1);
2008 }
2009 mr_msg(3, "prefix set to %s", bkpinfo->prefix);
2010 break;
2011 default:
2012 fatal_error
2013 ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
2014 }
2015
2016 if (archiving_to_media) {
2017
2018#ifdef __FreeBSD__
2019 strcpy(bkpinfo->boot_device,
2020 call_program_and_get_last_line_of_output
2021 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
2022#else
2023 strcpy(bkpinfo->boot_device,
2024 call_program_and_get_last_line_of_output
2025 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
2026#endif
2027 i = which_boot_loader(bkpinfo->boot_device);
2028 if (i == 'U') // unknown
2029 {
2030
2031#ifdef __FreeBSD__
2032 if (!popup_and_get_string
2033 ("Boot device",
2034 "What is your boot device? (e.g. /dev/ad0)",
2035 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2036 log_to_screen("User has chosen not to backup the PC");
2037 finish(1);
2038 }
2039 i = which_boot_loader(bkpinfo->boot_device);
2040#else
2041 if (!popup_and_get_string
2042 ("Boot device",
2043 "What is your boot device? (e.g. /dev/hda)",
2044 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2045 log_to_screen("User has chosen not to backup the PC");
2046 finish(1);
2047 }
2048 if (does_string_exist_in_boot_block
2049 (bkpinfo->boot_device, "LILO")) {
2050 i = 'L';
2051 } else
2052 if (does_string_exist_in_boot_block
2053 (bkpinfo->boot_device, "ELILO")) {
2054 i = 'E';
2055 } else
2056 if (does_string_exist_in_boot_block
2057 (bkpinfo->boot_device, "GRUB")) {
2058 i = 'G';
2059 } else {
2060 i = 'U';
2061 }
2062#endif
2063 if (i == 'U') {
2064 if (ask_me_yes_or_no
2065 ("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?"))
2066 {
2067 i = 'R'; // raw
2068 } else {
2069 log_to_screen
2070 ("I cannot find your boot loader. Please run mondoarchive with parameters.");
2071 finish(1);
2072 }
2073 }
2074 }
2075 bkpinfo->boot_loader = i;
2076 strcpy(bkpinfo->include_paths, "/");
2077 if (!popup_and_get_string
2078 ("Backup paths",
2079 "Please enter paths which you want me to backup. The default is '/' (i.e. everything).",
2080 bkpinfo->include_paths, MAX_STR_LEN)) {
2081 log_to_screen("User has chosen not to backup the PC");
2082 finish(1);
2083 }
2084 strcpy(tmp, list_of_NFS_mounts_only());
2085 if (strlen(tmp) > 2) {
2086 if (bkpinfo->exclude_paths[0]) {
2087 strcat(bkpinfo->exclude_paths, " ");
2088 }
2089 strncpy(bkpinfo->exclude_paths, tmp, MAX_STR_LEN);
2090 }
2091// NTFS
2092 strcpy(tmp,
2093 call_program_and_get_last_line_of_output
2094 ("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'"));
2095 if (strlen(tmp) > 2) {
2096 if (!popup_and_get_string
2097 ("NTFS partitions",
2098 "Please enter/confirm the NTFS partitions you wish to backup as well.",
2099 tmp, MAX_STR_LEN / 4)) {
2100 log_to_screen("User has chosen not to backup the PC");
2101 finish(1);
2102 }
2103 strncpy(bkpinfo->image_devs, tmp, MAX_STR_LEN / 4);
2104 }
2105
2106
2107 if (!popup_and_get_string
2108 ("Exclude paths",
2109 "Please enter paths which you do NOT want to backup. Separate them with spaces. NB: /tmp and /proc are always excluded. :-) Just hit 'Enter' if you want to do a full system backup.",
2110 bkpinfo->exclude_paths, MAX_STR_LEN)) {
2111 log_to_screen("User has chosen not to backup the PC");
2112 finish(1);
2113 }
2114 bkpinfo->make_cd_use_lilo = FALSE;
2115 bkpinfo->backup_data = TRUE;
2116 bkpinfo->verify_data =
2117 ask_me_yes_or_no
2118 ("Will you want to verify your backups after Mondo has created them?");
2119
2120#ifndef __FreeBSD__
2121 if (!ask_me_yes_or_no
2122 ("Are you confident that your kernel is a sane, sensible, standard Linux kernel? Say 'no' if you are using a Gentoo <1.4 or Debian <3.0, please."))
2123#endif
2124 {
2125 strcpy(bkpinfo->kernel_path, "FAILSAFE");
2126 }
2127
2128 if (!ask_me_yes_or_no
2129 ("Are you sure you want to proceed? Hit 'no' to abort.")) {
2130 log_to_screen("User has chosen not to backup the PC");
2131 finish(1);
2132 }
2133 } else {
2134 bkpinfo->restore_data = TRUE; // probably...
2135 }
2136
2137 if (bkpinfo->backup_media_type == iso
2138 || bkpinfo->backup_media_type == nfs) {
2139 g_ISO_restore_mode = TRUE;
2140 }
2141#ifdef __FreeSD__
2142// skip
2143#else
2144 if (bkpinfo->backup_media_type == nfs) {
2145 sprintf(tmp, "mount | grep \"%s\" | cut -d' ' -f3",
2146 bkpinfo->nfs_mount);
2147// strcpy(bkpinfo->isodir, call_program_and_get_last_line_of_output(tmp));
2148 mr_msg(3, "I think the NFS mount is mounted at %s",
2149 bkpinfo->isodir);
2150 }
2151 log_it("isodir = %s", bkpinfo->isodir);
2152 log_it("nfs_mount = '%s'", bkpinfo->nfs_mount);
2153#endif
2154
2155 log_it("media device = %s", bkpinfo->media_device);
2156 log_it("media size = %ld", bkpinfo->media_size[1]);
2157 log_it("media type = %s",
2158 bkptype_to_string(bkpinfo->backup_media_type));
2159 log_it("prefix = %s", bkpinfo->prefix);
2160 log_it("compression = %ld", bkpinfo->compression_level);
2161 log_it("include_paths = '%s'", bkpinfo->include_paths);
2162 log_it("exclude_paths = '%s'", bkpinfo->exclude_paths);
2163 log_it("scratchdir = '%s'", bkpinfo->scratchdir);
2164 log_it("tmpdir = '%s'", bkpinfo->tmpdir);
2165 log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device,
2166 bkpinfo->boot_loader);
2167 if (bkpinfo->media_size[0] < 0) {
2168 if (archiving_to_media) {
2169 fatal_error("Media size is less than zero.");
2170 } else {
2171 mr_msg(2, "Warning - media size is less than zero.");
2172 bkpinfo->media_size[0] = 0;
2173 }
2174 }
2175 mr_free(tmp);
2176 mr_free(sz_size);
2177 mr_free(command);
2178 mr_free(comment);
2179 mr_free(prompt);
2180 return (0);
2181}
2182
2183
2184
2185
2186/**
2187 * @addtogroup utilityGroup
2188 * @{
2189 */
2190/**
2191 * Get a space-separated list of NFS devices and mounts.
2192 * @return The list created.
2193 * @note The return value points to static data that will be overwritten with each call.
2194 */
2195char *list_of_NFS_devices_and_mounts(void)
2196{
2197 char *exclude_these_devices;
2198 char *exclude_these_directories;
2199 static char result_sz[512];
2200
2201 malloc_string(exclude_these_devices);
2202 malloc_string(exclude_these_directories);
2203 strcpy(exclude_these_directories,
2204 call_program_and_get_last_line_of_output
2205 ("mount -t coda,ncpfs,nfs,smbfs,cifs,afs,mvfs | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' ' ' | awk '{print $0;}'"));
2206 strcpy(exclude_these_devices,
2207 call_program_and_get_last_line_of_output
2208 ("tr -s '\t' ' ' < /etc/fstab | grep -E '( (coda|ncpfs|nfs|smbfs|cifs|mvfs) )' | cut -d' ' -f1 | tr -s '\n' ' ' | awk '{print $0;}'"));
2209 sprintf(result_sz, "%s %s", exclude_these_directories,
2210 exclude_these_devices);
2211 mr_free(exclude_these_devices);
2212 mr_free(exclude_these_directories);
2213 return (result_sz);
2214}
2215
2216
2217
2218
2219/**
2220 * Get a space-separated list of NFS mounts.
2221 * @return The list created.
2222 * @note The return value points to static data that will be overwritten with each call.
2223 * @bug Even though we only want the mounts, the devices are still checked.
2224 */
2225char *list_of_NFS_mounts_only(void)
2226{
2227 char *exclude_these_devices;
2228 char *exclude_these_directories;
2229 static char result_sz[512];
2230
2231 malloc_string(exclude_these_devices);
2232 malloc_string(exclude_these_directories);
2233 strcpy(exclude_these_directories,
2234 call_program_and_get_last_line_of_output
2235 ("mount -t coda,ncpfs,nfs,smbfs,cifs,afs,mvfs | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' ' ' | awk '{print $0;}'"));
2236 strcpy(exclude_these_devices,
2237 call_program_and_get_last_line_of_output
2238 ("tr -s '\t' ' ' < /etc/fstab | grep -E '( (coda|ncpfs|nfs|smbfs|cifs|mvfs) )' | cut -d' ' -f1 | tr -s '\n' ' ' | awk '{print $0;}'"));
2239 sprintf(result_sz, "%s", exclude_these_directories);
2240 mr_free(exclude_these_devices);
2241 mr_free(exclude_these_directories);
2242 return (result_sz);
2243}
2244
2245/* @} - end of utilityGroup */
2246
2247
2248
2249
2250
2251/**
2252 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
2253 * [random] is a random number between 1 and 32767.
2254 * @param store_name_here Where to store the new filename.
2255 * @param stub A random number will be appended to this to make the FIFO's name.
2256 * @ingroup deviceGroup
2257 */
2258void make_fifo(char *store_name_here, char *stub)
2259{
2260 char *tmp;
2261
2262 malloc_string(tmp);
2263 assert_string_is_neither_NULL_nor_zerolength(stub);
2264
2265 sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
2266 (int) (random() % 32768));
2267 make_hole_for_file(store_name_here);
2268 mkfifo(store_name_here, S_IRWXU | S_IRWXG);
2269 sprintf(tmp, "chmod 770 %s", store_name_here);
2270 paranoid_system(tmp);
2271 mr_free(tmp);
2272}
2273
2274
2275
2276
2277
2278
2279/**
2280 * Set the tmpdir and scratchdir to reside on the partition with the most free space.
2281 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
2282 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set.
2283 * @ingroup utilityGroup
2284 */
2285void sensibly_set_tmpdir_and_scratchdir(struct s_bkpinfo *bkpinfo)
2286{
2287 char *tmp, *command, *sz;
2288
2289 malloc_string(tmp);
2290 malloc_string(command);
2291 malloc_string(sz);
2292 assert(bkpinfo != NULL);
2293
2294#ifdef __FreeBSD__
2295 strcpy(tmp,
2296 call_program_and_get_last_line_of_output
2297 ("df -m -P -t nonfs,msdosfs,ntfs,smbfs,smb,cifs,afs,mvfs | tr -s '\t' ' ' | grep -vE \"none|Filesystem\" | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -n | tail -n1 | awk '{print $NF;}'"));
2298#else
2299 strcpy(tmp,
2300 call_program_and_get_last_line_of_output
2301 ("df -m -P -x nfs -x vfat -x ntfs -x smbfs -x smb -x cifs -x afs -x mvfs | sed 's/ /devdev/' | tr -s '\t' ' ' | grep -vE \"none|Filesystem|/dev/shm\" | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -n | tail -n1 | awk '{print $NF;}'"));
2302#endif
2303
2304 if (tmp[0] != '/') {
2305 strcpy(sz, tmp);
2306 strcpy(tmp, "/");
2307 strcat(tmp, sz);
2308 }
2309 if (!tmp[0]) {
2310 fatal_error("I couldn't figure out the tempdir!");
2311 }
2312 sprintf(bkpinfo->tmpdir, "%s/tmp.mondo.%d", tmp,
2313 (int) (random() % 32768));
2314 log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir);
2315
2316 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%d", tmp,
2317 (int) (random() % 32768));
2318 log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
2319
2320 sprintf(g_erase_tmpdir_and_scratchdir, "rm -Rf %s %s", bkpinfo->tmpdir,
2321 bkpinfo->scratchdir);
2322
2323 sprintf(command, "rm -Rf %s/tmp.mondo.* %s/mondo.scratch.*", tmp, tmp);
2324 paranoid_system(command);
2325 mr_free(tmp);
2326 mr_free(command);
2327 mr_free(sz);
2328}
2329
2330
2331
2332
2333
2334
2335/**
2336 * @addtogroup deviceGroup
2337 * @{
2338 */
2339/**
2340 * If we can read @p dev, set @p output to it.
2341 * If @p dev cannot be read, set @p output to "".
2342 * @param dev The device to check for.
2343 * @param output Set to @p dev if @p dev exists, "" otherwise.
2344 * @return TRUE if @p dev exists, FALSE if it doesn't.
2345 */
2346bool set_dev_to_this_if_rx_OK(char *output, char *dev)
2347{
2348 char *command;
2349
2350 malloc_string(command);
2351 if (!dev || dev[0] == '\0') {
2352 output[0] = '\0';
2353 return (FALSE);
2354 }
2355// assert_string_is_neither_NULL_nor_zerolength(dev);
2356 mr_msg(10, "Injecting %s", dev);
2357 inject_device(dev);
2358 if (!does_file_exist(dev)) {
2359 mr_msg(10, "%s doesn't exist. Returning FALSE.", dev);
2360 return (FALSE);
2361 }
2362 sprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null",
2363 512L, dev);
2364 if (!run_program_and_log_output(command, FALSE)
2365 && !run_program_and_log_output(command, FALSE)) {
2366 strcpy(output, dev);
2367 mr_msg(4, "Found it - %s", dev);
2368 return (TRUE);
2369 } else {
2370 output[0] = '\0';
2371 mr_msg(4, "It's not %s", dev);
2372 return (FALSE);
2373 }
2374}
2375
2376
2377
2378
2379
2380/**
2381 * Find out what number CD is in the drive.
2382 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
2383 * @return The current CD number, or -1 if it could not be found.
2384 * @note If the CD is not mounted, it will be mounted
2385 * (and remain mounted after this function returns).
2386 */
2387int what_number_cd_is_this(struct s_bkpinfo *bkpinfo)
2388{
2389 int cd_number = -1;
2390 char *mountdev;
2391 char *tmp;
2392
2393 malloc_string(mountdev);
2394 malloc_string(tmp);
2395 assert(bkpinfo != NULL);
2396// log_it("Asking what_number_cd_is_this");
2397 if (g_ISO_restore_mode) {
2398 sprintf(tmp, "mount | grep iso9660 | awk '{print $3;}'");
2399// log_it("tmp = %s", tmp);
2400
2401 strcpy(mountdev, call_program_and_get_last_line_of_output(tmp));
2402 strcat(mountdev, "/archives/THIS-CD-NUMBER");
2403// log_it("mountdev = %s", mountdev);
2404 cd_number = atoi(last_line_of_file(mountdev));
2405// log_it("cd_number = %d", cd_number);
2406 mr_free(mountdev);
2407 mr_free(tmp);
2408 return (cd_number);
2409 }
2410
2411 strcpy(mountdev, bkpinfo->media_device);
2412 if (!mountdev[0]) {
2413 log_it
2414 ("(what_number_cd_is_this) Warning - media_device unknown. Finding out...");
2415 find_cdrom_device(bkpinfo->media_device, FALSE);
2416 }
2417 if (!is_this_device_mounted(MNT_CDROM)) {
2418 mount_CDROM_here(mountdev, MNT_CDROM);
2419 }
2420 cd_number =
2421 atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
2422// log_it("cd_number..later.. = %d", cd_number);
2423 mr_free(mountdev);
2424 mr_free(tmp);
2425 return (cd_number);
2426}
2427
2428
2429
2430
2431
2432
2433
2434/**
2435 * Find out what device is mounted as root (/).
2436 * @return Root device.
2437 * @note The returned string points to static storage and will be overwritten with every call.
2438 * @bug A bit of a misnomer; it's actually finding out the root device.
2439 * The mountpoint (where it's mounted) will obviously be '/'.
2440 */
2441char *where_is_root_mounted()
2442{
2443 /*@ buffers **************** */
2444 static char tmp[MAX_STR_LEN];
2445
2446
2447#ifdef __FreeBSD__
2448 strcpy(tmp, call_program_and_get_last_line_of_output
2449 ("mount | grep \" on / \" | cut -d' ' -f1"));
2450#else
2451 strcpy(tmp, call_program_and_get_last_line_of_output
2452 ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"));
2453 if (strstr(tmp, "/dev/cciss/")) {
2454 strcpy(tmp, call_program_and_get_last_line_of_output
2455 ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"));
2456 }
2457 if (strstr(tmp, "/dev/md")) {
2458 strcpy(tmp,
2459 call_program_and_get_last_line_of_output
2460 ("mount | grep \" on / \" | cut -d' ' -f1"));
2461 }
2462#endif
2463
2464 return (tmp);
2465}
2466
2467
2468/**
2469 * Find out which boot loader is in use.
2470 * @param which_device Device to look for the boot loader on.
2471 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
2472 * @note Under Linux, all drives are examined, not just @p which_device.
2473 */
2474#ifdef __FreeBSD__
2475char which_boot_loader(char *which_device)
2476{
2477 int count_lilos = 0;
2478 int count_grubs = 0;
2479 int count_boot0s = 0;
2480 int count_dangerouslydedicated = 0;
2481
2482 log_it("looking at drive %s's MBR", which_device);
2483 if (does_string_exist_in_boot_block(which_device, "GRUB")) {
2484 count_grubs++;
2485 }
2486 if (does_string_exist_in_boot_block(which_device, "LILO")) {
2487 count_lilos++;
2488 }
2489 if (does_string_exist_in_boot_block(which_device, "Drive")) {
2490 count_boot0s++;
2491 }
2492 if (does_string_exist_in_first_N_blocks
2493 (which_device, "FreeBSD/i386", 17)) {
2494 count_dangerouslydedicated++;
2495 }
2496 log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
2497 count_grubs, count_lilos, count_elilos, count_boot0s,
2498 count_dangerouslydedicated);
2499
2500 if (count_grubs && !count_lilos) {
2501 return ('G');
2502 } else if (count_lilos && !count_grubs) {
2503 return ('L');
2504 } else if (count_grubs == 1 && count_lilos == 1) {
2505 log_it("I'll bet you used to use LILO but switched to GRUB...");
2506 return ('G');
2507 } else if (count_boot0s == 1) {
2508 return ('B');
2509 } else if (count_dangerouslydedicated) {
2510 return ('D');
2511 } else {
2512 log_it("Unknown boot loader");
2513 return ('U');
2514 }
2515}
2516
2517#else
2518
2519char which_boot_loader(char *which_device)
2520{
2521 /*@ buffer ***************************************************** */
2522 char *list_drives_cmd;
2523 char *current_drive;
2524
2525 /*@ pointers *************************************************** */
2526 FILE *pdrives;
2527
2528 /*@ int ******************************************************** */
2529 int count_lilos = 0;
2530 int count_grubs = 0;
2531
2532 /*@ end vars *************************************************** */
2533
2534 malloc_string(list_drives_cmd);
2535 malloc_string(current_drive);
2536
2537#ifdef __IA64__
2538 /* No choice for it */
2539 return ('E');
2540#endif
2541 assert(which_device != NULL);
2542 // sprintf (list_drives_cmd,
2543 // "fdisk -l | grep /dev | grep cyl | tr ':' ' ' | cut -d' ' -f2");
2544
2545 sprintf(list_drives_cmd,
2546 "parted2fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s",
2547 where_is_root_mounted());
2548 log_it("list_drives_cmd = %s", list_drives_cmd);
2549
2550 if (!(pdrives = popen(list_drives_cmd, "r"))) {
2551 log_OS_error("Unable to open list of drives");
2552 mr_free(list_drives_cmd);
2553 mr_free(current_drive);
2554 return ('\0');
2555 }
2556 for (fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
2557 fgets(current_drive, MAX_STR_LEN, pdrives)) {
2558 strip_spaces(current_drive);
2559 log_it("looking at drive %s's MBR", current_drive);
2560 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
2561 count_grubs++;
2562 strcpy(which_device, current_drive);
2563 break;
2564 }
2565 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
2566 count_lilos++;
2567 strcpy(which_device, current_drive);
2568 break;
2569 }
2570 }
2571 if (pclose(pdrives)) {
2572 log_OS_error("Cannot pclose pdrives");
2573 }
2574 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
2575 mr_free(list_drives_cmd);
2576 mr_free(current_drive);
2577 if (count_grubs && !count_lilos) {
2578 return ('G');
2579 } else if (count_lilos && !count_grubs) {
2580 return ('L');
2581 } else if (count_grubs == 1 && count_lilos == 1) {
2582 log_it("I'll bet you used to use LILO but switched to GRUB...");
2583 return ('G');
2584 } else {
2585 log_it("Unknown boot loader");
2586 return ('U');
2587 }
2588}
2589#endif
2590
2591
2592
2593
2594/**
2595 * Write zeroes over the first 16K of @p device.
2596 * @param device The device to zero.
2597 * @return 0 for success, 1 for failure.
2598 */
2599int zero_out_a_device(char *device)
2600{
2601 FILE *fout;
2602 int i;
2603
2604 assert_string_is_neither_NULL_nor_zerolength(device);
2605
2606 log_it("Zeroing drive %s", device);
2607 if (!(fout = fopen(device, "w"))) {
2608 log_OS_error("Unable to open/write to device");
2609 return (1);
2610 }
2611 for (i = 0; i < 16384; i++) {
2612 fputc('\0', fout);
2613 }
2614 paranoid_fclose(fout);
2615 log_it("Device successfully zeroed.");
2616 return (0);
2617}
2618
2619/**
2620 * Return the device pointed to by @p incoming.
2621 * @param incoming The device to resolve symlinks for.
2622 * @return The path to the real device file.
2623 * @note The returned string points to static storage that will be overwritten with each call.
2624 * @bug Won't work with file v4.0; needs to be written in C.
2625 */
2626char *resolve_softlinks_to_get_to_actual_device_file(char *incoming)
2627{
2628 static char output[MAX_STR_LEN];
2629 char *command;
2630 char *curr_fname;
2631 char *scratch;
2632 char *tmp;
2633 char *p;
2634
2635 struct stat statbuf;
2636 command = malloc(1000);
2637 malloc_string(tmp);
2638 malloc_string(scratch);
2639 malloc_string(curr_fname);
2640 if (!does_file_exist(incoming)) {
2641 log_it
2642 ("resolve_softlinks_to_get_to_actual_device_file --- device not found");
2643 strcpy(output, incoming);
2644 } else {
2645 strcpy(curr_fname, incoming);
2646 lstat(curr_fname, &statbuf);
2647 while (S_ISLNK(statbuf.st_mode)) {
2648 mr_msg(1, "curr_fname = %s", curr_fname);
2649 sprintf(command, "file %s", curr_fname);
2650 strcpy(tmp, call_program_and_get_last_line_of_output(command));
2651 for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' ';
2652 p--);
2653 p++;
2654 strcpy(scratch, p);
2655 for (p = scratch; *p != '\0' && *p != '\''; p++);
2656 *p = '\0';
2657 mr_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp,
2658 scratch);
2659 if (scratch[0] == '/') {
2660 strcpy(curr_fname, scratch); // copy whole thing because it's an absolute softlink
2661 } else { // copy over the basename cos it's a relative softlink
2662 p = curr_fname + strlen(curr_fname);
2663 while (p != curr_fname && *p != '/') {
2664 p--;
2665 }
2666 if (*p == '/') {
2667 p++;
2668 }
2669 strcpy(p, scratch);
2670 }
2671 lstat(curr_fname, &statbuf);
2672 }
2673 strcpy(output, curr_fname);
2674 log_it("resolved %s to %s", incoming, output);
2675 }
2676 mr_free(command);
2677 mr_free(curr_fname);
2678 mr_free(tmp);
2679 return (output);
2680}
2681
2682/* @} - end of deviceGroup */
2683
2684
2685/**
2686 * Return the type of partition format (GPT or MBR)
2687 */
2688char *which_partition_format(const char *drive)
2689{
2690 static char output[4];
2691 char *tmp;
2692 char *command;
2693 char *fdisk;
2694#ifdef __IA64__
2695 struct stat buf;
2696#endif
2697 malloc_string(tmp);
2698 malloc_string(command);
2699 malloc_string(fdisk);
2700 mr_msg(0, "Looking for partition table format type");
2701 sprintf(fdisk, "/sbin/parted2fdisk");
2702 mr_msg(1, "Using %s", fdisk);
2703 sprintf(command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
2704 strcpy(tmp, call_program_and_get_last_line_of_output(command));
2705 if (strstr(tmp, "GPT") == NULL) {
2706 strcpy(output, "MBR");
2707 } else {
2708 strcpy(output, "GPT");
2709 }
2710 mr_msg(0, "Found %s partition table format type", output);
2711 mr_free(command);
2712 mr_free(tmp);
2713 mr_free(fdisk);
2714 return (output);
2715}
2716
2717/* @} - end of deviceGroup */
Note: See TracBrowser for help on using the repository browser.