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

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