source: MondoRescue/branches/2.2.9/mondo/src/common/libmondo-devices.c@ 2178

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