source: branches/2.2.8/mondo/src/common/libmondo-devices.c @ 2806

Last change on this file since 2806 was 2806, checked in by Bruno Cornec, 9 years ago

r2178@localhost (orig r2177): bruno | 2009-04-25 02:36:47 +0200

  • 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 2806 2011-04-29 13:39:14Z 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 2806 2011-04-29 13:39:14Z 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.