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

Last change on this file since 1924 was 1924, checked in by bruno, 11 years ago

svn merge -r 1902:1923 $SVN_M/branches/2.2.6

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