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

Last change on this file since 1939 was 1939, checked in by Bruno Cornec, 12 years ago

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

  • Property svn:keywords set to Id
File size: 70.8 KB
Line 
1/* libmondo-devices.c                 Subroutines for handling devices
2   $Id: libmondo-devices.c 1939 2008-05-16 23:29:54Z 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 1939 2008-05-16 23:29:54Z 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    /* Why asking to remove the media with tape ?
1579    if (bkpinfo->backup_media_type == tape && bkpinfo->restore_data) {
1580        popup_and_OK(_("Please remove media from drive"));
1581    }
1582    */
1583    mr_msg(3, "media type = %s",
1584            bkptype_to_string(bkpinfo->backup_media_type));
1585    if (archiving_to_media) {
1586        sensibly_set_tmpdir_and_scratchdir();
1587    }
1588    bkpinfo->compression_level =
1589        (bkpinfo->backup_media_type == cdstream) ? 1 : 5;
1590    mvaddstr_and_log_it(2, 0, " ");
1591
1592    // Find device's /dev (or SCSI) entry
1593    switch (bkpinfo->backup_media_type) {
1594    case cdr:
1595    case cdrw:
1596    case dvd:
1597    case usb:
1598        /* Never try to eject a USB device */
1599        if (bkpinfo->backup_media_type == usb) {
1600            bkpinfo->please_dont_eject = TRUE;
1601        }
1602        if (archiving_to_media) {
1603            if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
1604                if (ask_me_yes_or_no
1605                    (_("Does your computer have a manual tray?")))
1606                {
1607                    bkpinfo->manual_tray = TRUE;
1608                }
1609            }
1610            if ((bkpinfo->compression_level =
1611                 which_compression_level()) == -1) {
1612                log_to_screen(_("User has chosen not to backup the PC"));
1613                finish(1);
1614            }
1615            mr_asprintf(&comment, _("What speed is your %s (re)writer?"),
1616                    bkpinfo->backup_media_string);
1617            mr_asprintf(&tmp, "%d", mr_conf->iso_burning_speed);
1618            if (bkpinfo->backup_media_type != usb) {
1619                /* BERLIOS: NOW that tmp isn't static anymore it does NOT work */
1620                if (!popup_and_get_string(_("Speed"), comment, tmp, 4)) {
1621                    log_to_screen(_("User has chosen not to backup the PC"));
1622                    finish(1);
1623                }
1624            }
1625            mr_free(comment);
1626
1627            bkpinfo->writer_speed = atoi(tmp);
1628            mr_free(tmp);
1629
1630            mr_asprintf(&comment, _("What is your media device ?"));
1631            mr_asprintf(&tmp, mr_conf->media_device);
1632
1633            if (!popup_and_get_string("Device", comment, tmp, 5)) {
1634                log_to_screen(_("User has chosen not to backup the PC"));
1635                finish(1);
1636            }
1637            mr_free(comment);
1638
1639            mr_free(bkpinfo->media_device);
1640            bkpinfo->media_device = tmp;
1641
1642            /* Also adapt the burning device if needed */
1643            if ((strcmp(bkpinfo->media_device, mr_conf->media_device) != 0) &&
1644                (strcmp(mr_conf->media_device,mr_conf->iso_burning_dev) != 0)) {
1645                mr_asprintf(&comment, _("What is your burning media device then ?"));
1646                mr_asprintf(&tmp, mr_conf->iso_burning_dev);
1647   
1648                if (!popup_and_get_string("Device", comment, tmp, 5)) {
1649                    log_to_screen(_("User has chosen not to backup the PC"));
1650                    finish(1);
1651                }
1652                mr_free(comment);
1653   
1654                /* BCO: We change the mr_conf struct. Check that it doesn't create pb */
1655                mr_free(bkpinfo->iso_burning_dev);
1656                bkpinfo->iso_burning_dev = tmp;
1657            }
1658
1659            mr_asprintf(&comment,
1660                    _("How much data (in Megabytes) will each %s store?"),
1661                    bkpinfo->backup_media_string);
1662            mr_asprintf(&sz_size, "%d", mr_conf->media_size);
1663
1664            if (!popup_and_get_string("Size", comment, sz_size, 5)) {
1665                log_to_screen(_("User has chosen not to backup the PC"));
1666                finish(1);
1667            }
1668            mr_free(comment);
1669
1670            bkpinfo->media_size = atol(sz_size);
1671            mr_free(sz_size);
1672
1673            if (bkpinfo->media_size <= 0L) {
1674                log_to_screen(_("User has chosen not to backup the PC"));
1675                finish(1);
1676            }
1677        }
1678        /* No break because we continue even for usb */
1679    case cdstream:
1680        if ((bkpinfo->disaster_recovery) && (bkpinfo->backup_media_type != usb)) {
1681            mr_allocstr(bkpinfo->media_device, "/dev/cdrom");
1682            mr_msg(2, "CD-ROM device assumed to be at %s", bkpinfo->media_device);
1683        } else if ((bkpinfo->restore_data && (bkpinfo->backup_media_type != usb))
1684                   || bkpinfo->backup_media_type == dvd) {
1685            if (!bkpinfo->media_device) {
1686                mr_allocstr(bkpinfo->media_device, "/dev/cdrom");
1687            }                   // just for the heck of it :)
1688            mr_msg(1, "bkpinfo->media_device = %s", bkpinfo->media_device);
1689            mr_asprintf(&comment,
1690                _("Please specify your %s drive's /dev entry"), media_descriptor_string(bkpinfo->backup_media));
1691            mr_asprintf(&tmp,"/dev/cdrom");
1692            if (!popup_and_get_string
1693                (_("Device?"), comment, tmp, MAX_STR_LEN / 4)) {
1694                    log_to_screen(_("User has chosen not to backup the PC"));
1695                    finish(1);
1696                }
1697            mr_free(comment);
1698            mr_free(bkpinfo->media_device);
1699            bkpinfo->media_device=tmp;
1700
1701            mr_msg(2, "%s device found at %s",
1702                    bkpinfo->backup_media_string,
1703                    bkpinfo->media_device);
1704        } else {
1705            if (bkpinfo->backup_media_type == usb) {
1706                mr_asprintf(&comment, _("What is the /dev entry of your USB Disk/Key, please ?"));
1707            } else {
1708                mr_asprintf(&comment, _("What is your media device ?"));
1709            }
1710            mr_asprintf(&tmp, mr_conf->media_device);
1711
1712            if (!popup_and_get_string("Device", comment, tmp, 5)) {
1713                log_to_screen(_("User has chosen not to backup the PC"));
1714                finish(1);
1715            }
1716            mr_free(comment);
1717
1718            mr_free(bkpinfo->media_device);
1719            bkpinfo->media_device = tmp;
1720
1721            /* Also adapt the burning device if needed */
1722            if ((strcmp(bkpinfo->media_device, mr_conf->media_device) != 0) &&
1723                (strcmp(mr_conf->media_device,mr_conf->iso_burning_dev) != 0)) {
1724                mr_asprintf(&comment, _("What is your burning media device then ?"));
1725                mr_asprintf(&tmp, mr_conf->iso_burning_dev);
1726   
1727                if (!popup_and_get_string("Device", comment, tmp, 5)) {
1728                    log_to_screen(_("User has chosen not to backup the PC"));
1729                    finish(1);
1730                }
1731                mr_free(comment);
1732   
1733                /* BCO: We change the mr_conf struct. Check that it doesn't create pb */
1734                mr_free(bkpinfo->iso_burning_dev);
1735                bkpinfo->iso_burning_dev = tmp;
1736            }
1737
1738        }
1739        /* BERLIOS: Is it useful ?? */
1740        bkpinfo->media_size = (long)650;
1741        break;
1742
1743    case udev:
1744        if (!ask_me_yes_or_no
1745            (_("This option is for advanced users only. Are you sure?"))) {
1746            log_to_screen(_("User has chosen not to backup the PC"));
1747            finish(1);
1748        }
1749
1750    case tape:
1751        if (bkpinfo->media_device) {
1752            if ((fin = fopen(bkpinfo->media_device, "r"))) {
1753                paranoid_fclose(fin);
1754            } else {
1755                if (does_file_exist("/tmp/mondo-restore.cfg")) {
1756                    /* BERLIOS: NOW that bkpinfo->media_device isn't static anymore it does NOT work */
1757                    read_cfg_var("/tmp/mondo-restore.cfg", "media-dev",
1758                                 bkpinfo->media_device);
1759                }
1760            }
1761            mr_asprintf(&comment,
1762                    _("I think I've found your tape streamer at %s; am I right on the money?"),
1763                    bkpinfo->media_device);
1764            if (!ask_me_yes_or_no(comment)) {
1765                mr_asprintf(&tmp,bkpinfo->media_device);
1766                if (!popup_and_get_string
1767                    (_("Device name?"),
1768                    _("What is the /dev entry of your tape streamer?"),
1769                    tmp, MAX_STR_LEN / 4)) {
1770                    log_to_screen("User has chosen not to backup the PC");
1771                    finish(1);
1772                }
1773                mr_free(bkpinfo->media_device);
1774                bkpinfo->media_device = tmp;
1775            }
1776            mr_free(comment);
1777        } else {
1778            mr_asprintf(&tmp,bkpinfo->media_device);
1779            if (!popup_and_get_string
1780                (_("Device name?"),
1781                 _("What is the /dev entry of your tape streamer?"),
1782                 tmp, MAX_STR_LEN / 4)) {
1783                log_to_screen("User has chosen not to backup the PC");
1784                finish(1);
1785            }
1786            mr_free(bkpinfo->media_device);
1787            bkpinfo->media_device = tmp;
1788        }
1789        mr_asprintf(&tmp, "ls -l %s", bkpinfo->media_device);
1790        if (run_program_and_log_output(tmp, FALSE)) {
1791            log_to_screen(_("User has not specified a valid /dev entry"));
1792            finish(1);
1793        }
1794        mr_free(tmp);
1795        bkpinfo->media_size = 0L;
1796        mr_msg(4, "media_size = %ld", bkpinfo->media_size);
1797        if (archiving_to_media) {
1798            if ((bkpinfo->compression_level =
1799                 which_compression_level()) == -1) {
1800                log_to_screen(_("User has chosen not to backup the PC"));
1801                finish(1);
1802            }
1803        }
1804        break;
1805
1806
1807
1808    case nfs:
1809        /* Never try to eject a NFS device */
1810        bkpinfo->please_dont_eject = TRUE;
1811
1812        /* Initiate bkpinfo nfs_mount path from running environment if not already done */
1813        if (!bkpinfo->nfs_mount[0]) {
1814            strcpy(bkpinfo->nfs_mount,
1815                   call_program_and_get_last_line_of_output
1816                   ("mount | grep \":\" | cut -d' ' -f1 | head -n1"));
1817        }
1818#ifdef __FreeBSD__
1819        if (TRUE)
1820#else
1821        if (!bkpinfo->disaster_recovery)
1822#endif
1823        {
1824            if (!popup_and_get_string
1825                ("NFS dir.",
1826                 "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.)",
1827                 bkpinfo->nfs_mount, MAX_STR_LEN / 4)) {
1828                log_to_screen("User has chosen not to backup the PC");
1829                finish(1);
1830            }
1831            if (!bkpinfo->restore_data) {
1832                if ((bkpinfo->compression_level =
1833                     which_compression_level()) == -1) {
1834                    log_to_screen(_("User has chosen not to backup the PC"));
1835                    finish(1);
1836                }
1837            }
1838            // check whether already mounted - we better remove
1839            // surrounding spaces and trailing '/' for this
1840            mr_strip_spaces(bkpinfo->nfs_mount);
1841            if (bkpinfo->nfs_mount[strlen(bkpinfo->nfs_mount) - 1] == '/')
1842                bkpinfo->nfs_mount[strlen(bkpinfo->nfs_mount) - 1] = '\0';
1843            mr_asprintf(&command, "mount | grep \"%s \" | cut -d' ' -f3",
1844                    bkpinfo->nfs_mount);
1845            strcpy(bkpinfo->isodir,
1846                   call_program_and_get_last_line_of_output(command));
1847            mr_free(command);
1848
1849            if (!bkpinfo->restore_data) {
1850                mr_asprintf(&comment,
1851                    _("How much data (in Megabytes) will each media store?"));
1852                if (!popup_and_get_string(_("Size"), comment, sz_size, 5)) {
1853                    log_to_screen(_("User has chosen not to backup the PC"));
1854                    finish(1);
1855                }
1856            } else {
1857                strcpy(sz_size, "0");
1858            }
1859            mr_free(comment);
1860            bkpinfo->media_size = atol(sz_size);
1861            if (bkpinfo->media_size <= 0L) {
1862                log_to_screen(_("User has chosen not to backup the PC"));
1863                finish(1);
1864            }
1865        }
1866        if (bkpinfo->disaster_recovery) {
1867            sprintf(command ,"umount %s/isodir 2> /dev/null", bkpinfo->tmpdir);
1868            system(command);
1869            if (!popup_and_get_string
1870                ("NFS share", "Which remote NFS share should I mount?",
1871                 bkpinfo->nfs_mount, MAX_STR_LEN)) {
1872                log_to_screen("User has chosen not to backup the PC");
1873                finish(1);
1874            }
1875        }
1876        /* Initiate bkpinfo isodir path from running environment if mount already done */
1877        if (is_this_device_mounted(bkpinfo->nfs_mount)) {
1878            strcpy(bkpinfo->isodir,
1879                   call_program_and_get_last_line_of_output
1880                   ("mount | grep \":\" | cut -d' ' -f3 | head -n1"));
1881        } else {
1882            sprintf(bkpinfo->isodir, "%s/nfsdir", bkpinfo->tmpdir);
1883            mr_asprintf(&command, "mkdir -p %s", bkpinfo->isodir);
1884            run_program_and_log_output(command, 5);
1885            mr_free(command);
1886
1887            mr_asprintf(&tmp, "mount -t nfs -o nolock %s %s", bkpinfo->nfs_mount,
1888                    bkpinfo->isodir);
1889            run_program_and_log_output(tmp, 3);
1890            mr_free(tmp);
1891            malloc_string(g_selfmounted_isodir);
1892            strcpy(g_selfmounted_isodir, bkpinfo->isodir);
1893        }
1894        if (!is_this_device_mounted(bkpinfo->nfs_mount)) {
1895            popup_and_OK
1896                (_("Please mount that partition before you try to backup to or restore from it."));
1897            finish(1);
1898        }
1899        mr_asprintf(&tmp, bkpinfo->nfs_remote_dir);
1900        if (!popup_and_get_string
1901            ("Directory", "Which directory within that mountpoint?", tmp,
1902             MAX_STR_LEN)) {
1903            log_to_screen("User has chosen not to backup the PC");
1904            finish(1);
1905        }
1906        strcpy(bkpinfo->nfs_remote_dir, tmp);
1907        mr_free(tmp);
1908        // check whether writable - we better remove surrounding spaces for this
1909        mr_strip_spaces(bkpinfo->nfs_remote_dir);
1910        mr_asprintf(&tmp1,"%s/%s/.dummy.txt", bkpinfo->isodir,bkpinfo->nfs_remote_dir);
1911        mr_asprintf(&command, "echo hi > '%s'", tmp1);
1912        while (run_program_and_log_output(command, FALSE)) {
1913            mr_asprintf(&tmp, bkpinfo->nfs_remote_dir);
1914            mr_asprintf(&prompt,
1915                     _("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."),
1916                     bkpinfo->nfs_remote_dir, bkpinfo->isodir);
1917            if (!popup_and_get_string
1918                ("Directory", prompt, tmp, MAX_STR_LEN)) {
1919                log_to_screen("User has chosen not to backup the PC");
1920                finish(1);
1921            }
1922            mr_free(prompt);
1923
1924            strcpy(bkpinfo->nfs_remote_dir, tmp);
1925            mr_free(tmp);
1926            // check whether writable - we better remove surrounding space s for this
1927            mr_strip_spaces(bkpinfo->nfs_remote_dir);
1928            paranoid_free(tmp1);
1929            mr_asprintf(&tmp1,"%s/%s/.dummy.txt", bkpinfo->isodir,bkpinfo->nfs_remote_dir);
1930
1931            mr_free(command);
1932            mr_asprintf(&command, "echo hi > '%s'", tmp1);
1933        }
1934        mr_free(command);
1935        unlink(tmp1);
1936        paranoid_free(tmp1);
1937
1938        mr_asprintf(&tmp, mr_conf->prefix);
1939        if (!popup_and_get_string
1940            ("Prefix.",
1941             "Please enter the prefix that will be prepended to your ISO filename.  Example: machine1 to obtain machine1-[1-9]*.iso files",
1942            tmp, MAX_STR_LEN / 4)) {
1943            log_to_screen("User has chosen not to backup the PC");
1944            finish(1);
1945        }
1946        mr_free(bkpinfo->prefix);
1947        bkpinfo->prefix = tmp;
1948        mr_msg(3, "prefix set to %s", bkpinfo->prefix);
1949
1950        if (archiving_to_media) {
1951            if (!popup_and_get_string
1952                ("Size.",
1953                "Please enter how big you want each NFS image to be (in megabytes).",
1954                sz_size, 16)) {
1955                log_to_screen("User has chosen not to backup the PC");
1956                finish(1);
1957            }
1958            bkpinfo->media_size = atol(sz_size);
1959            if (bkpinfo->media_size <= 0L) {
1960                log_to_screen(_("User has chosen not to backup the PC"));
1961                finish(1);
1962            }
1963        }
1964        mr_msg(3, "Just set nfs_remote_dir to %s",
1965                bkpinfo->nfs_remote_dir);
1966        mr_msg(3, "isodir is still %s", bkpinfo->isodir);
1967        break;
1968
1969    case iso:
1970        if (!bkpinfo->disaster_recovery) {
1971            if (!popup_and_get_string
1972                ("Storage dir.",
1973                 "Please enter the full path name to the directory for your ISO images.  Example: /mnt/raid0_0",
1974                 bkpinfo->isodir, MAX_STR_LEN / 4)) {
1975                log_to_screen("User has chosen not to backup the PC");
1976                finish(1);
1977            }
1978            if (archiving_to_media) {
1979                if ((bkpinfo->compression_level =
1980                     which_compression_level()) == -1) {
1981                    log_to_screen(_("User has chosen not to backup the PC"));
1982                    finish(1);
1983                }
1984                if (!popup_and_get_string
1985                    ("ISO size.",
1986                     "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.",
1987                     sz_size, 16)) {
1988                    log_to_screen("User has chosen not to backup the PC");
1989                    finish(1);
1990                }
1991                bkpinfo->media_size = atol(sz_size);
1992            /* BERLIOS: this should be useless
1993            */
1994            } else {
1995                bkpinfo->media_size = (long)650;
1996            }
1997        }
1998        mr_asprintf(&tmp, mr_conf->prefix);
1999        if (!popup_and_get_string
2000            ("Prefix.",
2001             "Please enter the prefix that will be prepended to your ISO filename.  Example: machine1 to obtain machine1-[1-9]*.iso files",
2002             tmp, MAX_STR_LEN / 4)) {
2003            log_to_screen("User has chosen not to backup the PC");
2004            finish(1);
2005        }
2006        mr_free(bkpinfo->prefix);
2007        bkpinfo->prefix = tmp;
2008        mr_msg(3, "prefix set to %s", bkpinfo->prefix);
2009        break;
2010    default:
2011        fatal_error
2012            ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
2013    }
2014    if (archiving_to_media) {
2015
2016#ifdef __FreeBSD__
2017        strcpy(bkpinfo->boot_device,
2018               call_program_and_get_last_line_of_output
2019               ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
2020#else
2021        strcpy(bkpinfo->boot_device,
2022               call_program_and_get_last_line_of_output
2023               ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
2024#endif
2025        i = which_boot_loader(bkpinfo->boot_device);
2026        if (i == 'U')           // unknown
2027        {
2028
2029#ifdef __FreeBSD__
2030            if (!popup_and_get_string
2031                ("Boot device",
2032                 "What is your boot device? (e.g. /dev/ad0)",
2033                 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2034                log_to_screen("User has chosen not to backup the PC");
2035                finish(1);
2036            }
2037            i = which_boot_loader(bkpinfo->boot_device);
2038#else
2039            if (!popup_and_get_string
2040                ("Boot device",
2041                 "What is your boot device? (e.g. /dev/hda)",
2042                 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2043                log_to_screen("User has chosen not to backup the PC");
2044                finish(1);
2045            }
2046            if (does_string_exist_in_boot_block
2047                (bkpinfo->boot_device, "LILO")) {
2048                i = 'L';
2049            } else
2050                if (does_string_exist_in_boot_block
2051                    (bkpinfo->boot_device, "ELILO")) {
2052                i = 'E';
2053            } else
2054                if (does_string_exist_in_boot_block
2055                    (bkpinfo->boot_device, "GRUB")) {
2056                i = 'G';
2057            } else {
2058                i = 'U';
2059            }
2060#endif
2061            if (i == 'U') {
2062                if (ask_me_yes_or_no
2063                    (_("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?")))
2064                {
2065                    i = 'R';    // raw
2066                } else {
2067                    log_to_screen
2068                        (_("I cannot find your boot loader. Please run mondoarchive with parameters."));
2069                    finish(1);
2070                }
2071            }
2072        }
2073        bkpinfo->boot_loader = i;
2074        strcpy(bkpinfo->include_paths, "/");
2075        if (!popup_and_get_string
2076            ("Backup paths",
2077             "Please enter paths which you want me to backup. The default is '/' (i.e. everything).",
2078             bkpinfo->include_paths, MAX_STR_LEN)) {
2079            log_to_screen("User has chosen not to backup the PC");
2080            finish(1);
2081        }
2082        mr_asprintf(&tmp, list_of_NFS_mounts_only());
2083        if (strlen(tmp) > 2) {
2084            if (bkpinfo->exclude_paths != NULL) {
2085                mr_strcat(bkpinfo->exclude_paths, " ");
2086            }
2087            mr_strcat(bkpinfo->exclude_paths,tmp);
2088        }
2089        mr_free(tmp);
2090// NTFS
2091        mr_asprintf(&tmp,
2092               call_program_and_get_last_line_of_output
2093               ("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'"));
2094        if (strlen(tmp) > 2) {
2095            if (!popup_and_get_string
2096                ("NTFS partitions",
2097                 "Please enter/confirm the NTFS partitions you wish to backup as well.",
2098                 tmp, MAX_STR_LEN / 4)) {
2099                log_to_screen("User has chosen not to backup the PC");
2100                finish(1);
2101            }
2102            strncpy(bkpinfo->image_devs, tmp, MAX_STR_LEN / 4);
2103        }
2104        mr_free(tmp);
2105
2106        if (!popup_and_get_string
2107            ("Exclude paths",
2108             "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.",
2109             bkpinfo->exclude_paths, (4*MAX_STR_LEN)-1)) {
2110            log_to_screen("User has chosen not to backup the PC");
2111            finish(1);
2112        }
2113// Interactive mode:
2114#ifdef __IA64__
2115        bkpinfo->make_cd_use_lilo = TRUE;
2116#else
2117        bkpinfo->make_cd_use_lilo = FALSE;
2118#endif
2119        bkpinfo->backup_data = TRUE;
2120        bkpinfo->verify_data =
2121            ask_me_yes_or_no
2122            (_("Will you want to verify your backups after Mondo has created them?"));
2123
2124#ifndef __FreeBSD__
2125        if (!ask_me_yes_or_no
2126            ("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."))
2127#endif
2128        {
2129            mr_allocstr(bkpinfo->kernel_path, "FAILSAFE");
2130        }
2131
2132        if (!ask_me_yes_or_no
2133            (_("Are you sure you want to proceed? Hit 'no' to abort."))) {
2134            log_to_screen(_("User has chosen not to backup the PC"));
2135            finish(1);
2136        }
2137    } else {
2138        bkpinfo->restore_data = TRUE;   // probably...
2139    }
2140
2141    if (bkpinfo->backup_media_type == iso
2142        || bkpinfo->backup_media_type == nfs) {
2143        g_ISO_restore_mode = TRUE;
2144    }
2145#ifdef __FreeBSD__
2146// skip
2147#else
2148    if (bkpinfo->backup_media_type == nfs) {
2149        mr_msg(3, "I think the NFS mount is mounted at %s",
2150                bkpinfo->isodir);
2151    }
2152    log_it("isodir = %s", bkpinfo->isodir);
2153    log_it("nfs_mount = '%s'", bkpinfo->nfs_mount);
2154#endif
2155
2156    log_it("media device = %s", bkpinfo->media_device);
2157    log_it("media size = %ld", bkpinfo->media_size);
2158    log_it("media type = %s", bkpinfo->backup_media_string);
2159    log_it("prefix = %s", bkpinfo->prefix);
2160    log_it("compression tool = %ld", bkpinfo->compression_tool);
2161    log_it("compression suffix = %ld", bkpinfo->compression_suffix);
2162    log_it("compression level = %ld", bkpinfo->compression_level);
2163    log_it("include_paths = '%s'", bkpinfo->include_paths);
2164    log_it("exclude_paths = '%s'", bkpinfo->exclude_paths);
2165    log_it("scratchdir = '%s'", bkpinfo->scratchdir);
2166    log_it("tmpdir = '%s'", bkpinfo->tmpdir);
2167    log_it("image_devs = '%s'", bkpinfo->image_devs);
2168    log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device,
2169           bkpinfo->boot_loader);
2170    if (bkpinfo->media_size < 0L) {
2171        if (archiving_to_media) {
2172            fatal_error("Media size is less than zero.");
2173        } else {
2174            mr_msg(2, "Warning - media size is less than zero.");
2175            bkpinfo->media_size = 0L;
2176        }
2177    }
2178    return (0);
2179}
2180
2181
2182/**
2183 * Get a space-separated list of NFS mounts.
2184 * @return The list created.
2185 * @note The return value points to static data that will be overwritten with each call.
2186 * @bug Even though we only want the mounts, the devices are still checked.
2187 */
2188char *list_of_NFS_mounts_only(void)
2189{
2190    char *exclude_these_devices;
2191    char *exclude_these_directories;
2192    static char result_sz[512];
2193
2194    malloc_string(exclude_these_devices);
2195    malloc_string(exclude_these_directories);
2196    strcpy(exclude_these_directories,
2197           call_program_and_get_last_line_of_output
2198           ("mount -t coda,ncpfs,nfs,smbfs,cifs,afs,ocfs,ocfs2,mvfs | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' ' ' | awk '{print $0;}'"));
2199    strcpy(exclude_these_devices,
2200           call_program_and_get_last_line_of_output
2201           ("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;}'"));
2202    sprintf(result_sz, "%s", exclude_these_directories);
2203    mr_free(exclude_these_devices);
2204    mr_free(exclude_these_directories);
2205    return (result_sz);
2206}
2207/* @} - end of utilityGroup */
2208
2209
2210/**
2211 * Set the tmpdir and scratchdir to reside on the partition with the most free space.
2212 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
2213 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set.
2214 * @ingroup utilityGroup
2215 */
2216void sensibly_set_tmpdir_and_scratchdir()
2217{
2218    char *tmp = NULL;
2219    char *command = NULL;
2220    char *sz = NULL;
2221    int i = 0;
2222
2223    malloc_string(command);
2224    assert(bkpinfo != NULL);
2225
2226#ifdef __FreeBSD__
2227    mr_asprintf(&tmp,
2228           call_program_and_get_last_line_of_output
2229           ("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;}'"));
2230#else
2231    mr_asprintf(&tmp,
2232           call_program_and_get_last_line_of_output
2233           ("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;}'"));
2234#endif
2235
2236    if (tmp[0] != '/') {
2237        mr_asprintf(&sz, "/%s", tmp);
2238        mr_free(tmp);
2239        tmp = sz;
2240    }
2241    if (!tmp[0]) {
2242        fatal_error("I couldn't figure out the tempdir!");
2243    }
2244    setup_tmpdir(tmp);
2245    log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir);
2246
2247    sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%d", tmp, i);
2248    log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
2249
2250    mr_asprintf(&command, "rm -Rf %s/tmp.mondo.* %s/mondo.scratch.*", tmp, tmp);
2251    mr_free(tmp);
2252
2253    paranoid_system(command);
2254    mr_free(command);
2255}
2256
2257
2258/**
2259 * @addtogroup deviceGroup
2260 * @{
2261 */
2262/**
2263 * If we can read @p dev, set @p output to it.
2264 * If @p dev cannot be read, set @p output to "".
2265 * @param dev The device to check for.
2266 * @param output Set to @p dev if @p dev exists, "" otherwise.
2267 * @return TRUE if @p dev exists, FALSE if it doesn't.
2268 */
2269bool set_dev_to_this_if_rx_OK(char *output, char *dev)
2270{
2271    char *command = NULL;
2272
2273    if (!dev || dev[0] == '\0') {
2274        output[0] = '\0';
2275        return (FALSE);
2276    }
2277    mr_msg(10, "Injecting %s", dev);
2278    inject_device(dev);
2279    if (!does_file_exist(dev)) {
2280        mr_msg(10, "%s doesn't exist. Returning FALSE.", dev);
2281        return (FALSE);
2282    }
2283    mr_asprintf(&command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null",
2284            512L, dev);
2285    if (!run_program_and_log_output(command, FALSE)
2286        && !run_program_and_log_output(command, FALSE)) {
2287        strcpy(output, dev);
2288        mr_msg(4, "Found it - %s", dev);
2289        mr_free(command);
2290        return (TRUE);
2291    } else {
2292        output[0] = '\0';
2293        mr_msg(4, "It's not %s", dev);
2294        mr_free(command);
2295        return (FALSE);
2296    }
2297}
2298
2299
2300/**
2301 * Find out what number CD is in the drive.
2302 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
2303 * @return The current CD number, or -1 if it could not be found.
2304 * @note If the CD is not mounted, it will be mounted
2305 * (and remain mounted after this function returns).
2306 */
2307int what_number_cd_is_this()
2308{
2309    int cd_number = -1;
2310    char *mountdev = NULL;
2311    char *tmp = NULL;
2312
2313    assert(bkpinfo != NULL);
2314    if (g_ISO_restore_mode) {
2315        mr_asprintf(&tmp, "mount | grep iso9660 | awk '{print $3;}'");
2316
2317        mr_asprintf(&mountdev, "%s/archives/THIS-CD-NUMBER", call_program_and_get_last_line_of_output(tmp));
2318        cd_number = atoi(last_line_of_file(mountdev));
2319        mr_free(mountdev);
2320        mr_free(tmp);
2321        return (cd_number);
2322    }
2323
2324    mr_asprintf(&mountdev, bkpinfo->media_device);
2325    if (!is_this_device_mounted(MNT_CDROM)) {
2326        if (bkpinfo->backup_media_type == usb) {
2327            mount_USB_here(mountdev, MNT_CDROM);
2328        } else {
2329            mount_CDROM_here(mountdev, MNT_CDROM);
2330        }
2331    }
2332    cd_number =
2333        atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
2334    mr_free(mountdev);
2335    return (cd_number);
2336}
2337
2338
2339/**
2340 * Find out what device is mounted as root (/).
2341 * @return Root device.
2342 * @note The returned string points to static storage and will be overwritten with every call.
2343 * @bug A bit of a misnomer; it's actually finding out the root device.
2344 * The mountpoint (where it's mounted) will obviously be '/'.
2345 */
2346char *where_is_root_mounted()
2347{
2348    /*@ buffers **************** */
2349    static char tmp[MAX_STR_LEN];
2350
2351
2352#ifdef __FreeBSD__
2353    strcpy(tmp, call_program_and_get_last_line_of_output
2354           ("mount | grep \" on / \" | cut -d' ' -f1"));
2355#else
2356    strcpy(tmp, call_program_and_get_last_line_of_output
2357           ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"));
2358    if (strstr(tmp, "/dev/cciss/")) {
2359        strcpy(tmp, call_program_and_get_last_line_of_output
2360               ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"));
2361    }
2362    if (strstr(tmp, "/dev/md")) {
2363        strcpy(tmp,
2364               call_program_and_get_last_line_of_output
2365               ("mount | grep \" on / \" | cut -d' ' -f1"));
2366    }
2367#endif
2368
2369    return (tmp);
2370}
2371
2372
2373/**
2374 * Find out which boot loader is in use.
2375 * @param which_device Device to look for the boot loader on.
2376 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
2377 * @note Under Linux, all drives are examined, not just @p which_device.
2378 */
2379char which_boot_loader(char *which_device)
2380{
2381#ifdef __FreeBSD__
2382    int count_lilos = 0;
2383    int count_grubs = 0;
2384    int count_boot0s = 0;
2385    int count_dangerouslydedicated = 0;
2386
2387    log_it("looking at drive %s's MBR", which_device);
2388    if (does_string_exist_in_boot_block(which_device, "GRUB")) {
2389        count_grubs++;
2390    }
2391    if (does_string_exist_in_boot_block(which_device, "LILO")) {
2392        count_lilos++;
2393    }
2394    if (does_string_exist_in_boot_block(which_device, "Drive")) {
2395        count_boot0s++;
2396    }
2397    if (does_string_exist_in_first_N_blocks
2398        (which_device, "FreeBSD/i386", 17)) {
2399        count_dangerouslydedicated++;
2400    }
2401    log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
2402           count_grubs, count_lilos, count_elilos, count_boot0s,
2403           count_dangerouslydedicated);
2404
2405    if (count_grubs && !count_lilos) {
2406        return ('G');
2407    } else if (count_lilos && !count_grubs) {
2408        return ('L');
2409    } else if (count_grubs == 1 && count_lilos == 1) {
2410        log_it("I'll bet you used to use LILO but switched to GRUB...");
2411        return ('G');
2412    } else if (count_boot0s == 1) {
2413        return ('B');
2414    } else if (count_dangerouslydedicated) {
2415        return ('D');
2416    } else {
2417        log_it("Unknown boot loader");
2418        return ('U');
2419    }
2420#else
2421    /*@ buffer ***************************************************** */
2422    char *list_drives_cmd;
2423    char *current_drive = NULL;
2424
2425    /*@ pointers *************************************************** */
2426    FILE *pdrives;
2427
2428    /*@ int ******************************************************** */
2429    int count_lilos = 0;
2430    int count_grubs = 0;
2431    size_t n = 0;
2432
2433    /*@ end vars *************************************************** */
2434
2435#ifdef __IA64__
2436    /* No choice for it */
2437    return ('E');
2438#endif
2439    assert(which_device != NULL);
2440    mr_asprintf(&list_drives_cmd,
2441            "parted2fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s",
2442            where_is_root_mounted());
2443    log_it("list_drives_cmd = %s", list_drives_cmd);
2444
2445    if (!(pdrives = popen(list_drives_cmd, "r"))) {
2446        log_OS_error("Unable to open list of drives");
2447        mr_free(list_drives_cmd);
2448        return ('\0');
2449    }
2450    mr_free(list_drives_cmd);
2451
2452    for (mr_getline(&current_drive, &n, pdrives); !feof(pdrives);
2453         mr_getline(&current_drive, &n, pdrives)) {
2454        mr_strip_spaces(current_drive);
2455        log_it("looking at drive %s's MBR", current_drive);
2456        if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
2457            count_grubs++;
2458            strcpy(which_device, current_drive);
2459            break;
2460        }
2461        if (does_string_exist_in_boot_block(current_drive, "LILO")) {
2462            count_lilos++;
2463            strcpy(which_device, current_drive);
2464            break;
2465        }
2466    }
2467    mr_free(current_drive);
2468
2469    if (pclose(pdrives)) {
2470        log_OS_error("Cannot pclose pdrives");
2471    }
2472    log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
2473    if (count_grubs && !count_lilos) {
2474        return ('G');
2475    } else if (count_lilos && !count_grubs) {
2476        return ('L');
2477    } else if (count_grubs == 1 && count_lilos == 1) {
2478        log_it("I'll bet you used to use LILO but switched to GRUB...");
2479        return ('G');
2480    } else {
2481        // We need to look on each partition then
2482        mr_asprintf(&list_drives_cmd,
2483            "parted2fdisk -l 2>/dev/null | grep -E \"^/dev/\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/");
2484        log_it("list_drives_cmd = %s", list_drives_cmd);
2485
2486        if (!(pdrives = popen(list_drives_cmd, "r"))) {
2487            log_OS_error("Unable to open list of drives");
2488            mr_free(list_drives_cmd);
2489            return ('\0');
2490        }
2491        mr_free(list_drives_cmd);
2492
2493        for (mr_getline(&current_drive, &n, pdrives); !feof(pdrives);
2494            mr_getline(&current_drive, &n, pdrives)) {
2495            mr_strip_spaces(current_drive);
2496            log_it("looking at partition %s's BR", current_drive);
2497            if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
2498                count_grubs++;
2499                strcpy(which_device, current_drive);
2500                break;
2501            }
2502            if (does_string_exist_in_boot_block(current_drive, "LILO")) {
2503                count_lilos++;
2504                strcpy(which_device, current_drive);
2505                break;
2506            }
2507        }
2508        mr_free(current_drive);
2509   
2510        if (pclose(pdrives)) {
2511            log_OS_error("Cannot pclose pdrives");
2512        }
2513        log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
2514        if (count_grubs && !count_lilos) {
2515            return ('G');
2516        } else if (count_lilos && !count_grubs) {
2517            return ('L');
2518        } else if (count_grubs == 1 && count_lilos == 1) {
2519            log_it("I'll bet you used to use LILO but switched to GRUB...");
2520            return ('G');
2521        } else {
2522            log_it("Unknown boot loader");
2523            return ('U');
2524        }
2525    }
2526#endif
2527}
2528
2529
2530/**
2531 * Write zeroes over the first 16K of @p device.
2532 * @param device The device to zero.
2533 * @return 0 for success, 1 for failure.
2534 */
2535int zero_out_a_device(char *device)
2536{
2537    FILE *fout;
2538    int i;
2539
2540    assert_string_is_neither_NULL_nor_zerolength(device);
2541
2542    log_it("Zeroing drive %s", device);
2543    if (!(fout = fopen(device, "w"))) {
2544        log_OS_error("Unable to open/write to device");
2545        return (1);
2546    }
2547    for (i = 0; i < 16384; i++) {
2548        fputc('\0', fout);
2549    }
2550    paranoid_fclose(fout);
2551    log_it("Device successfully zeroed.");
2552    return (0);
2553}
2554
2555
2556/**
2557 * Return the device pointed to by @p incoming.
2558 * @param incoming The device to resolve symlinks for.
2559 * @return The path to the real device file.
2560 * @note The returned string points to static storage that will be overwritten with each call.
2561 * @bug Won't work with file v4.0; needs to be written in C.
2562 */
2563char *resolve_softlinks_to_get_to_actual_device_file(char *incoming)
2564{
2565    static char output[MAX_STR_LEN];
2566    char *command = NULL;
2567    char *curr_fname = NULL;
2568    char *scratch = NULL;
2569    char *tmp = NULL;
2570    char *p = NULL;
2571
2572    struct stat statbuf;
2573    malloc_string(tmp);
2574    malloc_string(scratch);
2575    malloc_string(curr_fname);
2576    if (!does_file_exist(incoming)) {
2577        log_it
2578            ("resolve_softlinks_to_get_to_actual_device_file --- device not found");
2579        strcpy(output, incoming);
2580    } else {
2581        strcpy(curr_fname, incoming);
2582        lstat(curr_fname, &statbuf);
2583        while (S_ISLNK(statbuf.st_mode)) {
2584            mr_msg(1, "curr_fname = %s", curr_fname);
2585            mr_asprintf(&command, "file %s", curr_fname);
2586            strcpy(tmp, call_program_and_get_last_line_of_output(command));
2587            mr_free(command);
2588
2589            for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' ';
2590                 p--);
2591            p++;
2592            strcpy(scratch, p);
2593            for (p = scratch; *p != '\0' && *p != '\''; p++);
2594            *p = '\0';
2595            mr_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp,
2596                    scratch);
2597            if (scratch[0] == '/') {
2598                strcpy(curr_fname, scratch);    // copy whole thing because it's an absolute softlink
2599            } else {            // copy over the basename cos it's a relative softlink
2600                p = curr_fname + strlen(curr_fname);
2601                while (p != curr_fname && *p != '/') {
2602                    p--;
2603                }
2604                if (*p == '/') {
2605                    p++;
2606                }
2607                strcpy(p, scratch);
2608            }
2609            lstat(curr_fname, &statbuf);
2610        }
2611        strcpy(output, curr_fname);
2612        log_it("resolved %s to %s", incoming, output);
2613    }
2614    mr_free(curr_fname);
2615    mr_free(tmp);
2616    return (output);
2617}
2618
2619/* @} - end of deviceGroup */
2620
2621
2622/**
2623 * Return the type of partition format (GPT or MBR)
2624 */
2625char *which_partition_format(const char *drive)
2626{
2627    static char output[4];
2628    char *tmp = NULL;
2629    char *command = NULL;
2630    char *fdisk = NULL;
2631
2632    mr_msg(0, "Looking for partition table format type");
2633    mr_asprintf(&fdisk, "/sbin/parted2fdisk");
2634    mr_msg(1, "Using %s", fdisk);
2635    mr_asprintf(&command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
2636    mr_free(fdisk);
2637
2638    mr_asprintf(&tmp, call_program_and_get_last_line_of_output(command));
2639    mr_free(command);
2640
2641    if (strstr(tmp, "GPT") == NULL) {
2642        strcpy(output, "MBR");
2643    } else {
2644        strcpy(output, "GPT");
2645    }
2646    mr_free(tmp);
2647    mr_msg(0, "Found %s partition table format type", output);
2648    return(output);
2649}
2650/* @} - end of deviceGroup */
Note: See TracBrowser for help on using the repository browser.