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

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

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

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