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

Last change on this file since 2772 was 2772, checked in by Bruno Cornec, 9 years ago
  • Adds support of ext attr through the GUI. Fix second part of #468
  • Property svn:keywords set to Id
File size: 96.6 KB
Line 
1/* libmondo-devices.c                 Subroutines for handling devices
2   $Id: libmondo-devices.c 2772 2011-04-22 00:00:07Z bruno $
3*/
4
5/**
6 * @file
7 * Functions to handle interactions with backup devices.
8 */
9
10#include "my-stuff.h"
11#include "mr_mem.h"
12#include "mr_str.h"
13#include "mondostructures.h"
14#include "libmondo-files-EXT.h"
15#include "libmondo-devices.h"
16#include "lib-common-externs.h"
17#include "libmondo-string-EXT.h"
18#include "libmondo-tools-EXT.h"
19#include "libmondo-gui-EXT.h"
20#include "libmondo-fork-EXT.h"
21#include "libmondo-stream-EXT.h"
22
23#include <sys/types.h>
24#ifdef __FreeBSD__
25#define DKTYPENAMES
26#define FSTYPENAMES
27#include <sys/disklabel.h>
28#include <sys/disk.h>
29#elif linux
30#define u64 unsigned long long
31#include <linux/fs.h>           /* for BLKGETSIZE64 */
32#include <linux/hdreg.h>
33#endif
34
35/*@unused@*/
36//static char cvsid[] = "$Id: libmondo-devices.c 2772 2011-04-22 00:00:07Z bruno $";
37//
38
39extern char *which_compression_type();
40/* Do we use extended attributes and acl ?  */
41extern char *g_getfacl;
42extern char *g_getfattr;
43
44extern int g_current_media_number;
45extern double g_kernel_version;
46
47extern bool g_ISO_restore_mode;
48extern char *g_selfmounted_isodir;
49extern char *MONDO_LOGFILE;
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_netfs = 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/* Stuff that handles the -I and -E option when a whole disk DSF is used */
71typedef struct mounted_fs_struct {
72    char device[MAX_STR_LEN];       /* The name of the device */
73    char mount_point[MAX_STR_LEN];  /* The devices mount point */
74    unsigned char check;            /* 1 == included on DSF */
75    struct mounted_fs_struct *next;
76} MOUNTED_FS_STRUCT;
77
78static MOUNTED_FS_STRUCT *DSF_Head = NULL;      /* Points to the first entry of mounted_fs_struct list */
79static MOUNTED_FS_STRUCT *DSF_Tail = NULL;      /* Points to the last entry of mounted_fs_struct list */
80
81
82void set_g_cdrom_and_g_dvd_to_bkpinfo_value()
83{
84    strcpy(g_cdrom_drive_is_here, bkpinfo->media_device);   // just in case
85    strcpy(g_dvd_drive_is_here, bkpinfo->media_device); // just in case
86}
87
88
89
90/**
91 * Retract all CD trays and wait for autorun to complete.
92 * @ingroup deviceGroup
93 */
94void retract_CD_tray_and_defeat_autorun(void)
95{
96//  log_it("rctada: Retracting all CD trays", __LINE__);
97    if (strlen(g_cdrom_drive_is_here) > 0) {
98        inject_device(g_cdrom_drive_is_here);
99    }
100    if (strlen(g_dvd_drive_is_here) > 0) {
101        inject_device(g_dvd_drive_is_here);
102    }
103    if (strlen(g_cdrw_drive_is_here) > 0) {
104        inject_device(g_cdrw_drive_is_here);
105    }
106//  log_it("rctada: killing autorun");
107//  run_program_and_log_output("killall autorun", TRUE);
108    if (!run_program_and_log_output("ps | grep autorun | grep -v grep", 5)) {
109        log_it("autorun detected; sleeping for 2 seconds");
110        sleep(2);
111    }
112    log_it("rctada: Unmounting all CD drives", __LINE__);
113    run_program_and_log_output("umount /dev/cdr* /dev/dvd*", 5);
114}
115
116
117
118/**
119 * Determine whether we're booted off a ramdisk.
120 * @return @c TRUE (we are) or @c FALSE (we aren't).
121 * @ingroup utilityGroup
122 */
123bool am_I_in_disaster_recovery_mode(void)
124{
125    char *tmp = NULL;
126    char *comment;
127    bool is_this_a_ramdisk = FALSE;
128
129    malloc_string(comment);
130    mr_asprintf(&tmp, "%s", where_is_root_mounted());
131    sprintf(comment, "root is mounted at %s\n", tmp);
132    log_msg(0, comment);
133    log_msg(0,
134            "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().",
135            tmp);
136
137#ifdef __FreeBSD__
138    if (strstr(tmp, "/dev/md")) {
139        is_this_a_ramdisk = TRUE;
140    }
141#else
142    if (!strncmp(tmp, "/dev/ram", 8)
143        || (!strncmp(tmp, "/dev/rd", 7) && !strcmp(tmp, "/dev/rd/")
144            && strncmp(tmp, "/dev/rd/cd", 10)) || strstr(tmp, "rootfs")
145        || !strcmp(tmp, "/dev/root")) {
146        is_this_a_ramdisk = TRUE;
147    } else {
148        is_this_a_ramdisk = FALSE;
149    }
150#endif
151    mr_free(tmp);
152
153    if (is_this_a_ramdisk) {
154        if (!does_file_exist("/THIS-IS-A-RAMDISK")) {
155            log_to_screen
156                ("Using /dev/root is stupid of you but I'll forgive you.");
157            is_this_a_ramdisk = FALSE;
158        }
159    }
160    if (does_file_exist("/THIS-IS-A-RAMDISK")) {
161        is_this_a_ramdisk = TRUE;
162    }
163    paranoid_free(comment);
164    log_msg(1, "Is this a ramdisk? result = %d", is_this_a_ramdisk);
165    return (is_this_a_ramdisk);
166}
167
168
169
170
171
172/**
173 * Turn @c bkpinfo->backup_media_type into a human-readable string.
174 * @return The human readable string (e.g. @c cdr becomes <tt>"cdr"</tt>).
175 * @note The returned string points to static storage that will be overwritten with each call.
176 * @ingroup stringGroup
177 */
178static char *bkptype_to_string(t_bkptype bt)
179{
180    static char output[MAX_STR_LEN / 4];
181    switch (bt) {
182    case none:
183        strcpy(output, "none");
184        break;
185    case iso:
186        strcpy(output, "iso");
187        break;
188    case cdr:
189        strcpy(output, "cdr");
190        break;
191    case cdrw:
192        strcpy(output, "cdrw");
193        break;
194    case cdstream:
195        strcpy(output, "cdstream");
196        break;
197    case netfs:
198        strcpy(output, "netfs");
199        break;
200    case tape:
201        strcpy(output, "tape");
202        break;
203    case udev:
204        strcpy(output, "udev");
205        break;
206    case usb:
207        strcpy(output, "usb");
208        break;
209    default:
210        strcpy(output, "default");
211    }
212    return (output);
213}
214
215
216
217/**
218 * @addtogroup deviceGroup
219 * @{
220 */
221/**
222 * Eject the tray of the specified CD device.
223 * @param dev The device to eject.
224 * @return the return value of the @c eject command. (0=success, nonzero=failure)
225 */
226int eject_device(char *dev)
227{
228    char *command;
229    int res1 = 0, res2 = 0;
230
231    malloc_string(command);
232
233    if (IS_THIS_A_STREAMING_BACKUP(g_backup_media_type)
234        && g_backup_media_type != udev) {
235        sprintf(command, "mt -f %s offline", dev);
236        res1 = run_program_and_log_output(command, 1);
237    } else {
238        res1 = 0;
239    }
240
241#ifdef __FreeBSD__
242    if (strstr(dev, "acd")) {
243        sprintf(command, "cdcontrol -f %s eject", dev);
244    } else {
245        sprintf(command, "camcontrol eject `echo %s | sed 's|/dev/||'`",
246                dev);
247    }
248#else
249    sprintf(command, "eject %s", dev);
250#endif
251
252    log_msg(3, "Ejecting %s", dev);
253    res2 = run_program_and_log_output(command, 1);
254    paranoid_free(command);
255    if (res1 && res2) {
256        return (1);
257    } else {
258        return (0);
259    }
260}
261
262/**
263 * Load (inject) the tray of the specified CD device.
264 * @param dev The device to load/inject.
265 * @return 0 for success, nonzero for failure.
266 */
267int inject_device(char *dev)
268{
269    char *command;
270    int i;
271
272    malloc_string(command);
273
274
275#ifdef __FreeBSD__
276    if (strstr(dev, "acd")) {
277        sprintf(command, "cdcontrol -f %s close", dev);
278    } else {
279        sprintf(command, "camcontrol load `echo %s | sed 's|/dev/||'`",
280                dev);
281    }
282#else
283    sprintf(command, "eject -t %s", dev);
284#endif
285    i = run_program_and_log_output(command, FALSE);
286    paranoid_free(command);
287    return (i);
288}
289
290
291/**
292 * Determine whether the specified @p device (really, you can use any file)
293 * exists.
294 * @return TRUE if it exists, FALSE if it doesn't.
295 */
296bool does_device_exist(char *device)
297{
298
299    /*@ buffers *********************************************************** */
300    char *tmp;
301    bool ret;
302
303    malloc_string(tmp);
304    assert_string_is_neither_NULL_nor_zerolength(device);
305
306    sprintf(tmp, "ls %s > /dev/null 2> /dev/null", device);
307
308    if (system(tmp)) {
309        ret = FALSE;
310    } else {
311        ret = TRUE;
312    }
313    paranoid_free(tmp);
314    return (ret);
315}
316
317
318/**
319 * Determine whether a non-Microsoft partition exists on any connected hard drive.
320 * @return TRUE (there's a Linux/FreeBSD partition) or FALSE (Microsoft has taken over yet another innocent PC).
321 */
322bool does_nonMS_partition_exist(void)
323{
324#if __FreeBSD__
325    return
326        !system
327        ("for drive in /dev/ad? /dev/da?; do fdisk $drive | grep -q FreeBSD && exit 0; done; false");
328#else
329    return
330        !system
331        ("parted2fdisk -l 2>/dev/null | grep '^/dev/' | grep -Eqv '(MS|DOS|FAT|NTFS)'");
332#endif
333}
334
335/**
336 * Determine whether the specified @p partno exists on the specified @p drive.
337 * @param drive The drive to search for the partition in.
338 * @param partno The partition number to look for.
339 * @return 0 if it exists, nonzero otherwise.
340 */
341int does_partition_exist(const char *drive, int partno)
342{
343    /*@ buffers **************************************************** */
344    char *program;
345    char *incoming;
346    char *searchstr = NULL;
347    char *tmp;
348
349    /*@ ints ******************************************************* */
350    int res = 0;
351
352    /*@ pointers *************************************************** */
353    FILE *fin;
354
355
356    /*@ end vars *************************************************** */
357    assert_string_is_neither_NULL_nor_zerolength(drive);
358    assert(partno >= 0 && partno < 999);
359
360    malloc_string(program);
361    malloc_string(incoming);
362    malloc_string(searchstr);
363    malloc_string(tmp);
364
365#ifdef __FreeBSD__
366    // We assume here that this is running from mondorestore. (It is.)
367    sprintf(program, "ls %s %s >/dev/null 2>&1", drive,
368            build_partition_name(tmp, drive, partno));
369    return system(program);
370#else
371    tmp[0] = '\0';
372#endif
373
374    sprintf(program, "parted2fdisk -l %s 2> /dev/null", drive);
375    fin = popen(program, "r");
376    if (!fin) {
377        log_it("program=%s", program);
378        log_OS_error("Cannot popen-in program");
379        return (0);
380    }
381    (void) build_partition_name(searchstr, drive, partno);
382    strcat(searchstr, " ");
383    for (res = 0; !res && fgets(incoming, MAX_STR_LEN - 1, fin);) {
384        if (strstr(incoming, searchstr)) {
385            res = 1;
386        }
387    }
388    if (pclose(fin)) {
389        log_OS_error("Cannot pclose fin");
390    }
391    paranoid_free(program);
392    paranoid_free(incoming);
393    paranoid_free(searchstr);
394    paranoid_free(tmp);
395    return (res);
396}
397
398
399
400
401
402/**
403 * Determine whether given NULL-terminated @p str exists in the MBR of @p dev.
404 * @param dev The device to look in.
405 * @param str The string to look for.
406 * @return TRUE if it exists, FALSE if it doesn't.
407 */
408bool does_string_exist_in_boot_block(char *dev, char *str)
409{
410    /*@ buffers **************************************************** */
411    char *command;
412
413    /*@ end vars *************************************************** */
414    int i;
415
416    assert_string_is_neither_NULL_nor_zerolength(dev);
417    assert_string_is_neither_NULL_nor_zerolength(str);
418
419    malloc_string(command);
420    sprintf(command,
421            "dd if=%s bs=446 count=1 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null",
422            dev, str);
423    i = system(command);
424    paranoid_free(command);
425    if (i) {
426        return (FALSE);
427    } else {
428        return (TRUE);
429    }
430}
431
432/**
433 * Determine whether specified @p str exists in the first @p n sectors of
434 * @p dev.
435 * @param dev The device to look in.
436 * @param str The string to look for.
437 * @param n The number of 512-byte sectors to search.
438 */
439bool does_string_exist_in_first_N_blocks(char *dev, char *str, int n)
440{
441    /*@ buffers **************************************************** */
442    char *command;
443    /*@ end vars *************************************************** */
444    int i;
445
446    malloc_string(command);
447    sprintf(command,
448            "dd if=%s bs=512 count=%i 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null",
449            dev, n, str);
450    i = system(command);
451    paranoid_free(command);
452    if (i) {
453        return (FALSE);
454    } else {
455        return (TRUE);
456    }
457}
458
459
460
461/**
462 * Try to mount CD-ROM at @p mountpoint. If the CD-ROM is not found or has
463 * not been specified, call find_cdrom_device() to find it.
464 * @param bkpinfo The backup information structure. The only field used is @c bkpinfo->media_device.
465 * @param mountpoint Where to mount the CD-ROM.
466 * @return 0 for success, nonzero for failure.
467 * @see mount_CDROM_here
468 */
469int find_and_mount_actual_cd(char *mountpoint)
470{
471    /*@ buffers ***************************************************** */
472
473    /*@ int's  ****************************************************** */
474    int res;
475    char *dev;
476
477    /*@ end vars **************************************************** */
478
479    malloc_string(dev);
480    assert(bkpinfo != NULL);
481    assert_string_is_neither_NULL_nor_zerolength(mountpoint);
482
483    if (g_backup_media_type == dvd) {
484        strcpy(dev, g_dvd_drive_is_here);
485        if (!dev[0]) {
486            find_dvd_device(dev, FALSE);
487        }
488    } else {
489        strcpy(dev, g_cdrom_drive_is_here);
490        if (!dev[0]) {
491            find_cdrom_device(dev, FALSE);
492        }
493    }
494
495    if (bkpinfo->backup_media_type != iso) {
496        retract_CD_tray_and_defeat_autorun();
497    }
498
499    if (!dev[0] || (res = mount_CDROM_here(dev, mountpoint))) {
500        if (!popup_and_get_string
501            ("CD-ROM device", "Please enter your CD-ROM's /dev device",
502             dev, MAX_STR_LEN / 4)) {
503            res = 1;
504        } else {
505            res = mount_CDROM_here(dev, mountpoint);
506        }
507    }
508    if (res) {
509        log_msg(1, "mount failed");
510    } else {
511        log_msg(1, "mount succeeded with %s", dev);
512    }
513    paranoid_free(dev);
514    return (res);
515}
516
517
518
519
520
521
522/**
523 * Locate a CD-R/W writer's SCSI node.
524 * @param cdrw_device SCSI node will be placed here.
525 * @return 0 for success, nonzero for failure.
526 */
527int find_cdrw_device(char *cdrw_device)
528{
529    /*@ buffers ************************ */
530    char *comment;
531    char *tmp = NULL;
532    char *cdr_exe = NULL;
533    char *command;
534
535    malloc_string(comment);
536    malloc_string(command);
537    if (g_cdrw_drive_is_here[0]) {
538        strcpy(cdrw_device, g_cdrw_drive_is_here);
539        log_msg(3, "Been there, done that. Returning %s", cdrw_device);
540        paranoid_free(comment);
541        paranoid_free(command);
542        return (0);
543    }
544    if (g_backup_media_type == dvd) {
545        log_msg(1,
546                "This is dumb. You're calling find_cdrw_device() but you're backing up to DVD. WTF?");
547        paranoid_free(comment);
548        paranoid_free(command);
549        return (1);
550    }
551    run_program_and_log_output("insmod ide-scsi", -1);
552    if (find_home_of_exe("cdrecord")) {
553        mr_asprintf(&cdr_exe, "cdrecord");
554    } else {
555        mr_asprintf(&cdr_exe, "dvdrecord");
556    }
557    if (find_home_of_exe(cdr_exe)) {
558        sprintf(command,
559                "%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",
560                cdr_exe);
561        mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
562    }
563    if ((tmp == NULL) || (strlen(tmp) < 2)) {
564        paranoid_free(comment);
565        mr_free(tmp);
566        mr_free(cdr_exe);
567        paranoid_free(command);
568        return 1;
569    } else {
570        strcpy(cdrw_device, tmp);
571        sprintf(comment, "Found CDRW device - %s", cdrw_device);
572        log_it(comment);
573        strcpy(g_cdrw_drive_is_here, cdrw_device);
574        paranoid_free(comment);
575        mr_free(tmp);
576        mr_free(cdr_exe);
577        paranoid_free(command);
578        return (0);
579    }
580}
581
582
583
584
585/**
586 * Attempt to locate a CD-ROM device's /dev entry.
587 * Several different methods may be used to find the device, including
588 * calling @c cdrecord, searching @c dmesg, and trial-and-error.
589 * @param output Where to put the located /dev entry.
590 * @param try_to_mount Whether to mount the CD as part of the test; if mount
591 * fails then return failure.
592 * @return 0 for success, nonzero for failure.
593 */
594int find_cdrom_device(char *output, bool try_to_mount)
595{
596    /*@ pointers **************************************************** */
597    FILE *fin;
598    char *p;
599    char *q;
600    char *r;
601    int retval = 0;
602
603    /*@ bool's ****************************************************** */
604    bool found_it = FALSE;
605
606    /*@ buffers ***************************************************** */
607    char *tmp;
608    char *tmp1 = NULL;
609    char *cdr_exe = NULL;
610    char *phrase_one;
611    char *phrase_two;
612    char *command;
613    char *dvd_last_resort;
614    char *mountpoint;
615    static char the_last_place_i_found_it[MAX_STR_LEN] = "";
616
617    /*@ intialize *************************************************** */
618    malloc_string(tmp);
619    malloc_string(phrase_one);
620    malloc_string(phrase_two);
621    malloc_string(command);
622    malloc_string(dvd_last_resort);
623    malloc_string(mountpoint);
624
625    output[0] = '\0';
626    phrase_one[0] = '\0';
627    phrase_two[0] = '\0';
628    dvd_last_resort[0] = '\0';
629
630    /*@ end vars **************************************************** */
631
632    if (g_cdrom_drive_is_here[0] && !isdigit(g_cdrom_drive_is_here[0])) {
633        strcpy(output, g_cdrom_drive_is_here);
634        log_msg(3, "Been there, done that. Returning %s", output);
635        retval = 0;
636        goto end_of_find_cdrom_device;
637    }
638    if (the_last_place_i_found_it[0] != '\0' && !try_to_mount) {
639        strcpy(output, the_last_place_i_found_it);
640        log_msg(3,
641                "find_cdrom_device() --- returning last found location - '%s'",
642                output);
643        retval = 0;
644        goto end_of_find_cdrom_device;
645    }
646
647    sprintf(mountpoint, "%s/cd.mnt", bkpinfo->tmpdir);
648    make_hole_for_dir(mountpoint);
649
650    if (find_home_of_exe("cdrecord")) {
651        mr_asprintf(&cdr_exe, "cdrecord");
652    } else {
653        mr_asprintf(&cdr_exe, "dvdrecord");
654    }
655    tmp[0] = '\0';
656    if (!find_home_of_exe(cdr_exe)) {
657        strcpy(output, "/dev/cdrom");
658        log_msg(4, "Can't find cdrecord; assuming %s", output);
659        if (!does_device_exist(output)) {
660            log_msg(4, "That didn't work. Sorry.");
661            retval = 1;
662            goto end_of_find_cdrom_device;
663        } else {
664            retval = 0;
665            goto end_of_find_cdrom_device;
666        }
667    }
668
669    sprintf(command, "%s -scanbus 2> /dev/null", cdr_exe);
670    fin = popen(command, "r");
671    if (!fin) {
672        log_msg(4, "command=%s", command);
673        log_OS_error("Cannot popen command");
674        mr_free(cdr_exe);
675        return (1);
676    }
677    for ((void)fgets(tmp, MAX_STR_LEN, fin); !feof(fin);
678         (void)fgets(tmp, MAX_STR_LEN, fin)) {
679        p = strchr(tmp, '\'');
680        if (p) {
681            q = strchr(++p, '\'');
682            if (q) {
683                for (r = q; *(r - 1) == ' '; r--);
684                *r = '\0';
685                strcpy(phrase_one, p);
686                p = strchr(++q, '\'');
687                if (p) {
688                    q = strchr(++p, '\'');
689                    if (q) {
690                        while (*(q - 1) == ' ') {
691                            q--;
692                        }
693                        *q = '\0';
694                        strcpy(phrase_two, p);
695                    }
696                }
697            }
698        }
699    }
700    paranoid_pclose(fin);
701
702#ifndef __FreeBSD__
703    if (strlen(phrase_two) == 0) {
704        log_msg(4, "Not running phase two. String is empty.");
705    } else {
706        sprintf(command, "dmesg | grep \"%s\" 2> /dev/null", phrase_two);
707        fin = popen(command, "r");
708        if (!fin) {
709            log_msg(4, "Cannot run 2nd command - non-fatal, fortunately");
710        } else {
711            for ((void)fgets(tmp, MAX_STR_LEN, fin); !feof(fin);
712                 (void)fgets(tmp, MAX_STR_LEN, fin)) {
713                log_msg(5, "--> '%s'", tmp);
714                if (tmp[0] != ' ' && tmp[1] != ' ') {
715                    p = strchr(tmp, ':');
716                    if (p) {
717                        *p = '\0';
718                        if (strstr(tmp, "DVD")) {
719                            sprintf(dvd_last_resort, "/dev/%s", tmp);
720                            log_msg(4,
721                                    "Ignoring '%s' because it's a DVD drive",
722                                    tmp);
723                        } else {
724                            sprintf(output, "/dev/%s", tmp);
725                            found_it = TRUE;
726                        }
727                    }
728                }
729            }
730            paranoid_pclose(fin);
731        }
732    }
733
734#endif
735#ifdef __FreeBSD__
736    if (!found_it) {
737        log_msg(4, "OK, approach 2");
738        if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/cdrom"))) {
739            if (!
740                (found_it =
741                 set_dev_to_this_if_rx_OK(output, "/dev/cdrom1"))) {
742                if (!
743                    (found_it =
744                     set_dev_to_this_if_rx_OK(output, "/dev/dvd"))) {
745                    if (!
746                        (found_it =
747                         set_dev_to_this_if_rx_OK(output, "/dev/acd0"))) {
748                        if (!
749                            (found_it =
750                             set_dev_to_this_if_rx_OK(output,
751                                                      "/dev/cd01"))) {
752                            if (!
753                                (found_it =
754                                 set_dev_to_this_if_rx_OK(output,
755                                                          "/dev/acd1"))) {
756                                if (!
757                                    (found_it =
758                                     set_dev_to_this_if_rx_OK(output,
759                                                              "/dev/cd1")))
760                                {
761                                    retval = 1;
762                                    goto end_of_find_cdrom_device;
763                                }
764                            }
765                        }
766                    }
767                }
768            }
769        }
770    }
771#else
772    if (!found_it && strlen(dvd_last_resort) > 0) {
773        log_msg(4, "Well, I'll use the DVD - %s - as a last resort",
774                dvd_last_resort);
775        strcpy(output, dvd_last_resort);
776        found_it = TRUE;
777    }
778    if (found_it) {
779        sprintf(tmp, "grep \"%s=ide-scsi\" /proc/cmdline &> /dev/null",
780                strrchr(output, '/') + 1);
781        if (system(tmp) == 0) {
782            log_msg(4,
783                    "%s is not right. It's being SCSI-emulated. Continuing.",
784                    output);
785            found_it = FALSE;
786            output[0] = '\0';
787        }
788    }
789
790    if (found_it) {
791        log_msg(4, "(find_cdrom_device) --> '%s'", output);
792        if (!does_device_exist(output)) {
793            found_it = FALSE;
794            log_msg(4, "OK, I was wrong, I haven't found it... yet.");
795        }
796    }
797
798    if (!found_it) {
799        log_msg(4, "OK, approach 2");
800        if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/scd0"))) {
801            if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/sr0"))) {
802                if (!
803                    (found_it =
804                     set_dev_to_this_if_rx_OK(output, "/dev/cdrom"))) {
805                    if (!
806                        (found_it =
807                         set_dev_to_this_if_rx_OK(output,
808                                                  "/dev/cdrom0"))) {
809                        if (!
810                            (found_it =
811                             set_dev_to_this_if_rx_OK(output,
812                                                      "/dev/cdrom1"))) {
813                            if (!
814                                (found_it =
815                                 set_dev_to_this_if_rx_OK(output,
816                                                          "/dev/sr1"))) {
817                                if (!
818                                    (found_it =
819                                     set_dev_to_this_if_rx_OK(output,
820                                                              "/dev/dvd")))
821                                {
822                                    if (!
823                                        (found_it =
824                                         set_dev_to_this_if_rx_OK(output,
825                                                                  g_cdrw_drive_is_here)))
826                                    {
827                                        retval = 1;
828                                        goto end_of_find_cdrom_device;
829                                    }
830                                }
831                            }
832                        }
833                    }
834                }
835            }
836        }
837    }
838#endif
839
840    if (found_it && try_to_mount) {
841        if (mount_CDROM_here(output, mountpoint)) {
842            log_msg(4, "[Cardigans] I've changed my mind");
843            found_it = FALSE;
844        } else {
845            sprintf(tmp, "%s/archives", mountpoint);
846            if (!does_file_exist(tmp)) {
847                log_msg(4, "[Cardigans] I'll take it back");
848                found_it = FALSE;
849            } else {
850                sprintf(command, "umount %s", output);
851                paranoid_system(command);
852                log_msg(4, "I'm confident the Mondo CD is in %s", output);
853            }
854        }
855    }
856    unlink(mountpoint);
857
858    if (found_it) {
859        if (!does_file_exist(output)) {
860            log_msg(3, "I still haven't found it.");
861            return (1);
862        }
863        log_msg(3, "(find_cdrom_device) --> '%s'", output);
864        strcpy(the_last_place_i_found_it, output);
865        strcpy(g_cdrom_drive_is_here, output);
866        retval = 0;
867        goto end_of_find_cdrom_device;
868    }
869
870    sprintf(command,
871            "%s -scanbus | grep \"[0-9],[0-9],[0-9]\" | grep \"[D|C][V|D]\" | grep -n \"\" | grep \"%s\" | cut -d':' -f2",
872            cdr_exe, g_cdrw_drive_is_here);
873    log_msg(1, "command=%s", command);
874    mr_asprintf(&tmp1, "%s", call_program_and_get_last_line_of_output(command));
875    if (strlen(tmp1) > 0) {
876        strcpy(output, tmp1);
877        log_msg(4, "Finally found it at %s", output);
878        retval = 0;
879    } else {
880        log_msg(4, "Still couldn't find it.");
881        retval = 1;
882    }
883    mr_free(tmp1);
884
885  end_of_find_cdrom_device:
886    paranoid_free(tmp);
887    mr_free(cdr_exe);
888    paranoid_free(phrase_one);
889    paranoid_free(phrase_two);
890    paranoid_free(command);
891    paranoid_free(dvd_last_resort);
892    paranoid_free(mountpoint);
893    return (retval);
894}
895
896
897
898
899
900int find_dvd_device(char *output, bool try_to_mount)
901{
902    char *command;
903    char *tmp;
904    int retval = 0, devno = -1;
905
906    malloc_string(command);
907    malloc_string(tmp);
908
909    if (g_dvd_drive_is_here[0]) {
910        strcpy(output, g_dvd_drive_is_here);
911        log_msg(3, "Been there, done that. Returning %s", output);
912        return (0);
913    }
914
915    sprintf(tmp, "%s", call_program_and_get_last_line_of_output
916            ("dvdrecord -scanbus 2> /dev/null | grep \") '\" | grep -n \"\" | grep DVD | cut -d':' -f1")
917        );
918    log_msg(5, "tmp = '%s'", tmp);
919    if (!tmp[0])
920        sprintf(tmp, "%s", call_program_and_get_last_line_of_output
921                ("cdrecord -scanbus 2> /dev/null | grep \") '\" | grep -n \"\" | grep DVD | cut -d':' -f1")
922            );
923    if (tmp[0]) {
924        devno = atoi(tmp) - 1;
925    }
926    if (devno >= 0) {
927        retval = 0;
928        sprintf(output, "/dev/scd%d", devno);
929        strcpy(g_dvd_drive_is_here, output);
930        log_msg(2, "I think DVD is at %s", output);
931    } else {
932        log_msg(2, "I cannot find DVD");
933        retval = 1;
934    }
935
936    if (try_to_mount) {
937        log_msg(1, "Ignoring the fact that try_to_mount==TRUE");
938    }
939    return (retval);
940}
941
942
943
944
945
946#include <sys/ioctl.h>
947
948/**
949 * Find the size of the specified @p drive, in megabytes. Uses @c ioctl calls
950 * and @c dmesg.
951 * @param drive The device to find the size of.
952 * @return size in megabytes.
953 */
954long get_phys_size_of_drive(char *drive)
955{
956    int fd;
957#if linux
958    unsigned long long s = 0;
959    int fileid, cylinders = 0, cylindersleft = 0;
960    int cylindersize = 0;
961    int gotgeo = 0;
962
963
964    struct hd_geometry hdgeo;
965#elif __FreeBSD__
966    off_t s;
967#endif
968
969    long outvalA = -1;
970    long outvalB = -1;
971    long outvalC = -1;
972
973    if ((fd = open(drive, O_RDONLY)) != -1) {
974        if (ioctl(fd,
975#if linux
976#ifdef BLKGETSIZE64
977                  BLKGETSIZE64,
978#else
979                  BLKGETSIZE,
980#endif
981#elif __FreeBSD__
982                  DIOCGMEDIASIZE,
983#endif
984                  &s) != -1) {
985            close(fd);
986            // s>>11 works for older disks but not for newer ones
987            outvalB =
988#if linux
989#ifdef BLKGETSIZE64
990                s >> 20
991#else
992                s >> 11
993#endif
994#else
995                s >> 20
996#endif
997                ;
998        }
999    }
1000
1001    if (outvalB <= 0) {
1002        log_msg(1, "Error getting size of %s: %s", drive, strerror(errno));
1003#if linux
1004        fileid = open(drive, O_RDONLY);
1005        if (fileid != -1) {
1006            if (ioctl(fileid, HDIO_GETGEO, &hdgeo) != -1) {
1007                if (hdgeo.cylinders && hdgeo.heads && hdgeo.sectors) {
1008                    cylindersleft = cylinders = hdgeo.cylinders;
1009                    cylindersize = hdgeo.heads * hdgeo.sectors / 2;
1010                    outvalA = cylindersize * cylinders / 1024;
1011                    log_msg(2, "Got Harddisk geometry, C:%d, H:%d, S:%d",
1012                            hdgeo.cylinders, hdgeo.heads, hdgeo.sectors);
1013                    gotgeo = 1;
1014                } else {
1015                    log_msg(1, "Harddisk geometry wrong");
1016                }
1017            } else {
1018                log_msg(1,
1019                        "Error in ioctl() getting new hard disk geometry (%s), resizing in unsafe mode",
1020                        strerror(errno));
1021            }
1022            close(fileid);
1023        } else {
1024            log_msg(1, "Failed to open %s for reading: %s", drive,
1025                    strerror(errno));
1026        }
1027        if (!gotgeo) {
1028            log_msg(1, "Failed to get harddisk geometry, using old mode");
1029        }
1030#endif
1031    }
1032// OLDER DISKS will give ridiculously low value for outvalB (so outvalA is returned) :)
1033// NEWER DISKS will give sane value for outvalB (close to outvalA, in other words) :)
1034
1035    outvalC = (outvalA > outvalB) ? outvalA : outvalB;
1036
1037//  log_msg (5, "drive = %s, error = %s", drive, strerror (errno));
1038//  fatal_error ("GPSOD: Unable to get size of drive");
1039    log_msg(1, "%s --> %ld or %ld --> %ld", drive, outvalA, outvalB,
1040            outvalC);
1041
1042    return (outvalC);
1043}
1044
1045/**
1046 * Determine whether @p format is supported by the kernel. Uses /proc/filesystems
1047 * under Linux and @c lsvfs under FreeBSD.
1048 * @param format The format to test.
1049 * @return TRUE if the format is supported, FALSE if not.
1050 */
1051bool is_this_a_valid_disk_format(char *format)
1052{
1053    char *good_formats = NULL;
1054    char *command;
1055    char *format_sz;
1056
1057    FILE *pin;
1058    int retval;
1059    malloc_string(good_formats);
1060    malloc_string(command);
1061    malloc_string(format_sz);
1062
1063    assert_string_is_neither_NULL_nor_zerolength(format);
1064
1065    sprintf(format_sz, "%s ", format);
1066
1067#ifdef __FreeBSD__
1068    sprintf(command,
1069            "lsvfs | tr -s '\t' ' ' | grep -v Filesys | grep -v -- -- | cut -d' ' -f1 | tr -s '\n' ' '");
1070#else
1071    sprintf(command,
1072            "grep -v nodev /proc/filesystems | tr -s '\t' ' ' | cut -d' ' -f2 | tr -s '\n' ' '");
1073#endif
1074
1075    pin = popen(command, "r");
1076    if (!pin) {
1077        log_OS_error("Unable to read good formats");
1078        retval = 0;
1079    } else {
1080        strcpy(good_formats, " ");
1081        (void) fgets(good_formats + 1, MAX_STR_LEN - 1, pin);
1082        if (pclose(pin)) {
1083            log_OS_error("Cannot pclose good formats");
1084        }
1085        strip_spaces(good_formats);
1086        strcat(good_formats, " swap lvm raid ntfs-3g ntfs 7 "); // " ntfs 7 " -- um, cheating much? :)
1087        if (strstr(good_formats, format_sz)) {
1088            retval = 1;
1089        } else {
1090            retval = 0;
1091        }
1092    }
1093    paranoid_free(good_formats);
1094    paranoid_free(command);
1095    paranoid_free(format_sz);
1096    return (retval);
1097}
1098
1099
1100/** @def SWAPLIST_COMMAND The command to list the swap files/partitions in use. */
1101
1102/**
1103 * Determine whether @p device_raw is currently mounted.
1104 * @param device_raw The device to check.
1105 * @return TRUE if it's mounted, FALSE if not.
1106 */
1107bool is_this_device_mounted(char *device_raw)
1108{
1109
1110    /*@ pointers **************************************************** */
1111    FILE *fin;
1112
1113    /*@ buffers ***************************************************** */
1114    char *incoming;
1115    char *device_with_tab = NULL;
1116    char *device_with_space = NULL;
1117    char *tmp = NULL;
1118    bool retval = FALSE;
1119
1120#ifdef __FreeBSD__
1121#define SWAPLIST_COMMAND "swapinfo"
1122#else
1123#define SWAPLIST_COMMAND "cat /proc/swaps"
1124#endif
1125
1126    /*@ end vars **************************************************** */
1127
1128    malloc_string(incoming);
1129    assert(device_raw != NULL);
1130//  assert_string_is_neither_NULL_nor_zerolength(device_raw);
1131    if (device_raw[0] != '/' && !strstr(device_raw, ":/")) {
1132        log_msg(1, "%s needs to have a '/' prefixed - I'll do it",
1133                device_raw);
1134        mr_asprintf(&tmp, "/%s", device_raw);
1135    } else {
1136        mr_asprintf(&tmp, "%s", device_raw);
1137    }
1138    log_msg(1, "Is %s mounted?", tmp);
1139    if (!strcmp(tmp, "/proc") || !strcmp(tmp, "proc")) {
1140        log_msg(1,
1141                "I don't know how the heck /proc made it into the mountlist. I'll ignore it.");
1142        mr_free(tmp);
1143        return(FALSE);
1144    }
1145    mr_asprintf(&device_with_tab, "%s\t", tmp);
1146    mr_asprintf(&device_with_space, "%s ", tmp);
1147    mr_free(tmp);
1148
1149    if (!(fin = popen("mount", "r"))) {
1150        log_OS_error("Cannot popen 'mount'");
1151        return(FALSE);
1152    }
1153    for ((void)fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin);
1154         (void)fgets(incoming, MAX_STR_LEN - 1, fin)) {
1155        if (strstr(incoming, device_with_space) //> incoming
1156            || strstr(incoming, device_with_tab))   // > incoming)
1157        {
1158            paranoid_pclose(fin);
1159            paranoid_free(incoming);
1160            return(TRUE);
1161        }
1162    }
1163    mr_free(device_with_tab);
1164    paranoid_pclose(fin);
1165    mr_asprintf(&tmp, "%s | grep -E \"^%s\" > /dev/null 2> /dev/null", SWAPLIST_COMMAND, device_with_space);
1166    mr_free(device_with_space);
1167    log_msg(4, "tmp (command) = '%s'", tmp);
1168    if (!system(tmp)) {
1169        retval = TRUE;
1170    }
1171    mr_free(tmp);
1172    paranoid_free(incoming);
1173    return(retval);
1174}
1175
1176#ifdef __FreeBSD__
1177//                       CODE IS FREEBSD-SPECIFIC
1178/**
1179 * Create a loopback device for specified @p fname.
1180 * @param fname The file to associate with a device.
1181 * @return /dev entry for the device, or NULL if it couldn't be allocated.
1182 */
1183char *make_vn(char *fname)
1184{
1185    char *device = (char *) malloc(MAX_STR_LEN);
1186    char *mddevice = (char *) malloc(32);
1187    char command[MAX_STR_LEN];
1188    int vndev = 2;
1189    if (atoi
1190        (call_program_and_get_last_line_of_output
1191         ("/sbin/sysctl -n kern.osreldate")) < 500000) {
1192        do {
1193            sprintf(mddevice, "vn%ic", vndev++);
1194            sprintf(command, "vnconfig %s %s", mddevice, fname);
1195            if (vndev > 10) {
1196                return NULL;
1197            }
1198        }
1199        while (system(command));
1200    } else {
1201        sprintf(command, "mdconfig -a -t vnode -f %s", fname);
1202        mddevice = call_program_and_get_last_line_of_output(command);
1203        if (!strstr(mddevice, "md")) {
1204            return NULL;
1205        }
1206    }
1207    sprintf(device, "/dev/%s", mddevice);
1208    return device;
1209}
1210
1211
1212
1213//                       CODE IS FREEBSD-SPECIFIC
1214/**
1215 * Deallocate specified @p dname.
1216 * This should be called when you are done with the device created by make_vn(),
1217 * so the system does not run out of @c vn devices.
1218 * @param dname The device to deallocate.
1219 * @return 0 for success, nonzero for failure.
1220 */
1221int kick_vn(char *dname)
1222{
1223    char command[MAX_STR_LEN];
1224
1225    if (strncmp(dname, "/dev/", 5) == 0) {
1226        dname += 5;
1227    }
1228
1229    if (atoi
1230        (call_program_and_get_last_line_of_output
1231         ("/sbin/sysctl -n kern.osreldate")) < 500000) {
1232        sprintf(command, "vnconfig -d %s", dname);
1233        return system(command);
1234    } else {
1235        sprintf(command, "mdconfig -d -u %s", dname);
1236        return system(command);
1237    }
1238     /*NOTREACHED*/ return 255;
1239}
1240#endif
1241
1242
1243/**
1244 * Mount the CD-ROM at @p mountpoint.
1245 * @param device The device (or file if g_ISO_restore_mode) to mount.
1246 * @param mountpoint The place to mount it.
1247 * @return 0 for success, nonzero for failure.
1248 */
1249int mount_USB_here(char *device, char *mountpoint)
1250{
1251    /*@ buffer ****************************************************** */
1252    char *command;
1253    int retval;
1254
1255    malloc_string(command);
1256    assert_string_is_neither_NULL_nor_zerolength(device);
1257    assert_string_is_neither_NULL_nor_zerolength(mountpoint);
1258
1259    make_hole_for_dir(mountpoint);
1260    if (isdigit(device[0])) {
1261        return(1);
1262    }
1263    log_msg(4, "(mount_USB_here --- device=%s, mountpoint=%s", device,
1264            mountpoint);
1265
1266#ifdef __FreeBSD__
1267    sprintf(command, "mount_vfat %s %s 2>> %s",
1268            device, mountpoint, MONDO_LOGFILE);
1269
1270#else
1271    sprintf(command, "mount %s -t vfat %s 2>> %s",
1272            device, mountpoint, MONDO_LOGFILE);
1273#endif
1274
1275    log_msg(4, command);
1276    retval = system(command);
1277    log_msg(1, "system(%s) returned %d", command, retval);
1278
1279    paranoid_free(command);
1280    return (retval);
1281}
1282
1283/**
1284 * Mount the CD-ROM at @p mountpoint.
1285 * @param device The device (or file if g_ISO_restore_mode) to mount.
1286 * @param mountpoint The place to mount it.
1287 * @return 0 for success, nonzero for failure.
1288 */
1289int mount_CDROM_here(char *device, char *mountpoint)
1290{
1291    /*@ buffer ****************************************************** */
1292    char *command = NULL;
1293    int retval;
1294#ifdef __FreeBSD__
1295    char *dev = NULL;
1296#else
1297    char *options = NULL;
1298#endif
1299
1300    assert_string_is_neither_NULL_nor_zerolength(device);
1301    assert_string_is_neither_NULL_nor_zerolength(mountpoint);
1302
1303    make_hole_for_dir(mountpoint);
1304
1305    if (isdigit(device[0])) {
1306        find_cdrom_device(device, FALSE);
1307    }
1308#ifndef __FreeBSD__
1309    mr_asprintf(&options, "ro");
1310#endif
1311
1312    if (g_ISO_restore_mode) {
1313
1314#ifdef __FreeBSD__
1315        mr_asprintf(&dev, "%s", make_vn(device));
1316        if (!dev) {
1317            mr_asprintf(&command, "Unable to mount ISO (make_vn(%s) failed)", device);
1318            fatal_error(command);
1319        }
1320        strcpy(device, dev);
1321        paranoid_free(dev);
1322#else
1323        mr_strcat(options, ",loop");
1324#endif
1325
1326    }
1327    log_msg(4, "(mount_CDROM_here --- device=%s, mountpoint=%s", device,
1328            mountpoint);
1329    /*@ end vars *************************************************** */
1330
1331#ifdef __FreeBSD__
1332    mr_asprintf(&command, "mount_cd9660 -r %s %s 2>> %s", device, mountpoint, MONDO_LOGFILE);
1333
1334#else
1335    mr_asprintf(&command, "mount %s -o %s -t iso9660 %s 2>> %s", device, options, mountpoint, MONDO_LOGFILE);
1336    paranoid_free(options);
1337#endif
1338
1339    log_msg(4, command);
1340    if (strncmp(device, "/dev/", 5) == 0) {
1341        retract_CD_tray_and_defeat_autorun();
1342    }
1343    retval = system(command);
1344    log_msg(1, "system(%s) returned %d", command, retval);
1345    paranoid_free(command);
1346
1347    return (retval);
1348}
1349
1350
1351/**
1352* Mount the CD-ROM or USB device at /mnt/cdrom.
1353* @param bkpinfo The backup information structure. Fields used:
1354* - @c bkpinfo->backup_media_type
1355* - @c bkpinfo->disaster_recovery
1356* - @c bkpinfo->isodir
1357* - @c bkpinfo->media_device
1358* @return 0 for success, nonzero for failure.
1359*/
1360int mount_media()
1361{
1362char *mount_cmd;
1363char *mountdir = NULL;
1364int i, res;
1365#ifdef __FreeBSD__
1366char mdd[32];
1367char *mddev = mdd;
1368#endif
1369
1370malloc_string(mount_cmd);
1371assert(bkpinfo != NULL);
1372
1373    if (bkpinfo->backup_media_type == tape
1374        || bkpinfo->backup_media_type == udev) {
1375        log_msg(8, "Tape/udev. Therefore, no need to mount a media.");
1376        paranoid_free(mount_cmd);
1377        return 0;
1378    }
1379
1380    if (!run_program_and_log_output("mount | grep -F " MNT_CDROM, FALSE)) {
1381        log_msg(2, "mount_media() - media already mounted. Fair enough.");
1382        paranoid_free(mount_cmd);
1383        return (0);
1384    }
1385
1386    if (bkpinfo->backup_media_type == netfs) {
1387        log_msg(2, "Mounting for Network thingy");
1388        log_msg(2, "isodir = %s", bkpinfo->isodir);
1389        if ((!bkpinfo->isodir[0] || !strcmp(bkpinfo->isodir, "/"))
1390            && am_I_in_disaster_recovery_mode()) {
1391            strcpy(bkpinfo->isodir, "/tmp/isodir");
1392            log_msg(1, "isodir is being set to %s", bkpinfo->isodir);
1393        }
1394#ifdef __FreeBSD__
1395        sprintf(mount_cmd, "/mnt/isodir/%s/%s/%s-%d.iso", bkpinfo->isodir,
1396            bkpinfo->netfs_remote_dir, bkpinfo->prefix, g_current_media_number);
1397        mddev = make_vn(mount_cmd);
1398        sprintf(mount_cmd, "mount_cd9660 -r %s " MNT_CDROM, mddev);
1399#else
1400        sprintf(mount_cmd, "mount %s/%s/%s-%d.iso -t iso9660 -o loop,ro %s",
1401            bkpinfo->isodir, bkpinfo->netfs_remote_dir,
1402            bkpinfo->prefix, g_current_media_number, MNT_CDROM);
1403#endif
1404
1405    } else if (bkpinfo->backup_media_type == iso) {
1406        if (bkpinfo->subdir) {
1407            mr_asprintf(&mountdir, "%s/%s", bkpinfo->isodir, bkpinfo->subdir);
1408        } else {
1409            mr_asprintf(&mountdir, "%s", bkpinfo->isodir);
1410        }
1411#ifdef __FreeBSD__
1412        sprintf(mount_cmd, "%s/%s-%d.iso", mountdir,
1413            bkpinfo->prefix, g_current_media_number);
1414        mddev = make_vn(mount_cmd);
1415        sprintf(mount_cmd, "mount_cd9660 -r %s %s", mddev, MNT_CDROM);
1416#else
1417        sprintf(mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s",
1418            mountdir, bkpinfo->prefix, g_current_media_number, MNT_CDROM);
1419#endif
1420    } else if (bkpinfo->backup_media_type == usb) {
1421        sprintf(mount_cmd, "mount -t vfat %s %s", bkpinfo->media_device, MNT_CDROM);
1422    } else if (strstr(bkpinfo->media_device, "/dev/")) {
1423#ifdef __FreeBSD__
1424        sprintf(mount_cmd, "mount_cd9660 -r %s %s", bkpinfo->media_device,
1425        MNT_CDROM);
1426#else
1427        sprintf(mount_cmd, "mount %s -t iso9660 -o ro %s",
1428        bkpinfo->media_device, MNT_CDROM);
1429#endif
1430    } else {
1431        if (bkpinfo->disaster_recovery
1432            && does_file_exist("/tmp/CDROM-LIVES-HERE")) {
1433            strcpy(bkpinfo->media_device,
1434                last_line_of_file("/tmp/CDROM-LIVES-HERE"));
1435        } else {
1436            find_cdrom_device(bkpinfo->media_device, TRUE);
1437        }
1438
1439#ifdef __FreeBSD__
1440    sprintf(mount_cmd, "mount_cd9660 -r %s %s", bkpinfo->media_device,
1441        MNT_CDROM);
1442#else
1443    sprintf(mount_cmd, "mount %s -t iso9660 -o ro %s",
1444        bkpinfo->media_device, MNT_CDROM);
1445#endif
1446    }
1447
1448    log_msg(2, "(mount_media) --- command = %s", mount_cmd);
1449    for (i = 0; i < 2; i++) {
1450        res = run_program_and_log_output(mount_cmd, FALSE);
1451        if (!res) {
1452            break;
1453        } else {
1454            log_msg(2, "Failed to mount device.");
1455            sleep(5);
1456            run_program_and_log_output("sync", FALSE);
1457        }
1458    }
1459
1460    if (res) {
1461        log_msg(2, "Failed, despite %d attempts", i);
1462    } else {
1463        log_msg(2, "Mounted media drive OK");
1464    }
1465    paranoid_free(mount_cmd);
1466    return (res);
1467}
1468/**************************************************************************
1469*END_MOUNT_CDROM                                                         *
1470**************************************************************************/
1471
1472
1473
1474
1475/**
1476 * Ask the user for CD number @p cd_number_i_want.
1477 * Sets g_current_media_number once the correct CD is inserted.
1478 * @param bkpinfo The backup information structure. Fields used:
1479 * - @c bkpinfo->backup_media_type
1480 * - @c bkpinfo->prefix
1481 * - @c bkpinfo->isodir
1482 * - @c bkpinfo->media_device
1483 * - @c bkpinfo->please_dont_eject_when_restoring
1484 * @param cd_number_i_want The CD number to ask for.
1485 */
1486void
1487insist_on_this_cd_number(int cd_number_i_want)
1488{
1489
1490    /*@ int ************************************************************* */
1491    int res = 0;
1492
1493
1494    /*@ buffers ********************************************************* */
1495    char *tmp;
1496    char *mds = NULL;
1497    char *request;
1498
1499    assert(bkpinfo != NULL);
1500    assert(cd_number_i_want > 0);
1501
1502//  log_msg(3, "Insisting on CD number %d", cd_number_i_want);
1503
1504    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1505        log_msg(3,
1506                "No need to insist_on_this_cd_number when the backup type isn't CD-R(W) or NFS or ISO");
1507        return;
1508    }
1509    malloc_string(tmp);
1510    malloc_string(request);
1511    sprintf(tmp, "mkdir -p " MNT_CDROM);
1512    run_program_and_log_output(tmp, 5);
1513    if (g_ISO_restore_mode || bkpinfo->backup_media_type == iso
1514        || bkpinfo->backup_media_type == netfs) {
1515        g_ISO_restore_mode = TRUE;
1516        if (!is_this_device_mounted(MNT_CDROM)) {
1517            log_msg(3, "Mounting media");
1518            g_current_media_number = cd_number_i_want;
1519            mount_media();
1520        }
1521    }
1522    if ((res = what_number_cd_is_this()) != cd_number_i_want) {
1523        log_msg(3, "Currently, we hold %d but we want %d", res,
1524                cd_number_i_want);
1525        mds = media_descriptor_string(bkpinfo->backup_media_type);
1526        sprintf(tmp, "Insisting on %s #%d", mds, cd_number_i_want);
1527        sprintf(request, "Please insert %s #%d and press Enter.", mds, cd_number_i_want);
1528        mr_free(mds);
1529        log_msg(3, tmp);
1530        while (what_number_cd_is_this() != cd_number_i_want) {
1531            paranoid_system("sync");
1532            if (is_this_device_mounted(MNT_CDROM)) {
1533                res =
1534                    run_program_and_log_output("umount " MNT_CDROM, FALSE);
1535            } else {
1536                res = 0;
1537            }
1538            if (res) {
1539                log_to_screen("WARNING - failed to unmount CD-ROM drive");
1540            }
1541            if (!bkpinfo->please_dont_eject) {
1542                res = eject_device(bkpinfo->media_device);
1543            } else {
1544                res = 0;
1545            }
1546            if (res) {
1547                log_to_screen("WARNING - failed to eject CD-ROM disk");
1548            }
1549            popup_and_OK(request);
1550            if (!bkpinfo->please_dont_eject) {
1551                inject_device(bkpinfo->media_device);
1552            }
1553            paranoid_system("sync");
1554        }
1555        log_msg(1, "Thankyou. Proceeding...");
1556        g_current_media_number = cd_number_i_want;
1557    }
1558    paranoid_free(tmp);
1559    paranoid_free(request);
1560}
1561
1562/* @} - end of deviceGroup */
1563
1564
1565
1566/**
1567 * Creates a singly linked list of all of the non-NETFS mounted file systems.
1568 * @param DSFptr A pointer  to the structure MOUNTED_FS_STRUCT used to hold
1569 * the list of mounted file systems.
1570 * @return None.
1571 */
1572static void add_mounted_fs_struct (MOUNTED_FS_STRUCT *DSFptr)
1573{
1574    assert (DSFptr);
1575    if (DSF_Head == NULL) {
1576        DSF_Head = DSFptr;
1577    } else {
1578        DSF_Tail->next = DSFptr;
1579    }
1580    DSFptr->next = NULL;
1581    DSF_Tail = DSFptr;
1582}
1583
1584/**
1585 * Find the structure, in the singly linked list of all of the non-NETFS
1586 * mounted file systems, that contains the specified device.
1587 * @param device The device to find
1588 * @return NULL if it didn't find the device, a pointer to the
1589 * structure if it did.
1590 */
1591static MOUNTED_FS_STRUCT *find_device_in_list (char *device)
1592{
1593    MOUNTED_FS_STRUCT *DSFptr = NULL;
1594
1595    DSFptr = DSF_Head;
1596    while (DSFptr != NULL) {
1597        if (!strcmp(DSFptr->device, device)) {
1598            break;
1599        }
1600        DSFptr = DSFptr->next;
1601    }
1602    return (DSFptr);
1603}
1604
1605/**
1606 * Find the structure, in the singly linked list of all of the non-NETFS
1607 * mounted file systems, that contains the specified mount point.
1608 * @param mount_point The mount point to find
1609 * @return NULL is it didn't find the mount point, a pointer to the
1610 * structure if it did.
1611 */
1612static MOUNTED_FS_STRUCT *find_mount_point_in_list (char *mount_point)
1613{
1614    MOUNTED_FS_STRUCT *DSFptr = NULL;
1615
1616    DSFptr = DSF_Head;
1617    while (DSFptr != NULL) {
1618        if (!strcmp(DSFptr->mount_point, mount_point)) {
1619            break;
1620        }
1621        DSFptr = DSFptr->next;
1622    }
1623    return (DSFptr);
1624}
1625
1626/**
1627 * Frees the memory for all of the structures on the linked list of
1628 * all of the non-NETFS mounted file systems.
1629 */
1630static void free_mounted_fs_list (void) {
1631    MOUNTED_FS_STRUCT *DSFptr = NULL;
1632    MOUNTED_FS_STRUCT *DSFnext = NULL;
1633 
1634    DSFptr = DSF_Head;
1635    while (DSFptr != NULL) {
1636        DSFnext = DSFptr->next;
1637        paranoid_free(DSFptr);
1638        DSFptr = DSFnext;
1639    }
1640    DSF_Head = NULL;
1641    DSF_Tail = NULL;
1642}
1643
1644
1645/**
1646 * Creates a linked list of all of the non-NETFS mounted file systems.
1647 * We use a linked list because we don't know how many  mounted file
1648 * there are (and there can be a lot).
1649 * @return 0 on success and greated than 0 on failure.
1650 */
1651static int create_list_of_non_NETFS_mounted_file_systems (void)
1652{
1653    int i = 0;
1654    int mount_cnt = 0;
1655    int lastpos = 0;
1656    char *mounted_file_system = NULL;
1657    char *command = NULL;
1658    char *token = NULL;
1659    char token_chars[] =" :\t\r\f\a\0";
1660    MOUNTED_FS_STRUCT *DSFptr = NULL;
1661
1662    free_mounted_fs_list();
1663    /********
1664    * Find the number of mounted file system entries and their respective mount points.
1665    * I can't return all of the entries as one string because it's length can be longer
1666    * than MAX_STR_LEN which is used in call_program_and_get_last_line_of_output().
1667    * So start looping and get the number of  mounted file systems and query them one by one.
1668    ********/
1669    /* Get the number of mounted file systems ((those that start with "/dev/" */
1670    mr_asprintf(&command, "mount 2>/dev/null | awk '{if($1 ~ \"^/dev/\"){print $0}}'|wc -l");
1671    log_msg(5, "Running: %s", command);
1672    mr_asprintf(&mounted_file_system, "%s", call_program_and_get_last_line_of_output(command));
1673    paranoid_free(command);
1674
1675    mount_cnt = atoi(mounted_file_system);
1676    log_msg (5, "mount_cnt: %d", mount_cnt);
1677    paranoid_free(mounted_file_system);
1678
1679    for (i=mount_cnt; i > 0; i--) {
1680        mr_asprintf(&command, "mount 2>/dev/null | awk '{if($1 ~ \"^/dev/\"){print $1,$3}}'|head -n %d", i);
1681        log_msg(5, "Running: %s", command);
1682        mr_asprintf(&mounted_file_system, "%s", call_program_and_get_last_line_of_output(command));
1683        paranoid_free(command);
1684
1685        log_msg (5, "mounted_file_system: %s", mounted_file_system);
1686        if ((token = mr_strtok(mounted_file_system, token_chars, &lastpos)) == NULL) {
1687            log_msg (4, "Could not get the list of mounted file systems");
1688            paranoid_free(mounted_file_system);
1689            mr_free(token);
1690            return (1);
1691        }
1692        if (token) {
1693            log_msg (5, "token: %s", token);
1694        }
1695        while (token != NULL) {
1696            log_msg (5, "token: %s", token);
1697            if ((DSFptr = (MOUNTED_FS_STRUCT *) calloc(1, sizeof(MOUNTED_FS_STRUCT))) == NULL) {
1698                fatal_error ("Cannot allocate memory");
1699            }
1700            add_mounted_fs_struct(DSFptr);
1701            strcpy(DSFptr->device, token);
1702            mr_free(token);
1703            if ((token = mr_strtok(mounted_file_system, token_chars, &lastpos)) == NULL) {
1704                log_msg (5, "Ran out of entries on the mounted file systems list");
1705                mr_free(mounted_file_system);
1706                mr_free(token);
1707                return (1);
1708            }
1709            log_msg (5, "token: %s", token);
1710            strcpy(DSFptr->mount_point, token);
1711            mr_free(token);
1712            token = mr_strtok(mounted_file_system, token_chars, &lastpos); 
1713        }
1714        mr_free(mounted_file_system);
1715    }
1716    /********
1717    * DSFptr = DSF_Head;
1718    * while (DSFptr != NULL) {
1719    * printf ("Dev: %s  MP: %s  Check: %d\n", DSFptr->device, DSFptr->mount_point, DSFptr->check);
1720    * DSFptr = DSFptr->next;
1721    * }
1722    ********/
1723    return (0);
1724}
1725
1726
1727
1728/**
1729 * Given a whole disk device special file, determine which mounted file systems
1730 * are on the dsf's partitions and which mounted file systems are not.
1731 * @param dsf The whole disk device special file.
1732 * @param included_dsf_list A char pointer used to hold the list of mount points
1733 * that are on the dsf. Memory for the array will be allocated within the function.
1734 * @param excluded_dsf_list A char pointer used to hold the list of mount points
1735 * that are not on the dsf. Memory for the array will be allocated within the function.
1736 * @return 0 on success, -1 if no device special file was passed in, -2 if a device
1737 * special file was passed in but it has no partitions on it, or 1 on failure
1738 */
1739static int get_dsf_mount_list (const char *dsf, char **included_dsf_list, char **excluded_dsf_list) {
1740    int i = 0;
1741    int c = 0;
1742    int lastpos = 0;
1743    char VG[MAX_STR_LEN];
1744    char *tmp = NULL;
1745    char *command = NULL;
1746    char *partition_list = NULL;
1747    char partitions[64][MAX_STR_LEN];
1748    char *mount_list = NULL;
1749    char *token = NULL;
1750    char *ndsf = NULL;
1751    char token_chars[] =" \t\r\f\a\0";
1752    MOUNTED_FS_STRUCT *DSFptr = NULL;
1753
1754    memset((char *)partitions, 0, sizeof(partitions));
1755
1756    log_msg(5, "dsf: %s", dsf);
1757
1758    /********
1759    * See if a device special file was passed in (i.e. it must start with /dev/
1760    ********/
1761    if (strncmp(dsf, "/dev/", 5)) {
1762        log_msg (4, "%s does not start with /dev/ and (probably) is not a  device special file", dsf);
1763        return (-1);
1764    }
1765    log_msg(4, "  %s looks like a device special file", dsf);
1766    /* Verify that the dsf exists */ 
1767    mr_asprintf(&command, "ls -al %s 2>/dev/null | wc -l", dsf);
1768    log_msg(5, "  Executing: %s", command);
1769    mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1770    paranoid_free(command);
1771
1772    log_msg(5, "  Return value: %s", tmp);
1773    c = atoi(tmp);
1774    paranoid_free(tmp);
1775
1776    if (!c) {
1777        log_to_screen("Cannot find device special file %s", dsf);
1778        return (1);
1779    }
1780    log_msg(4, "  %s device special file exists", dsf);
1781
1782    /* Get a list of the mounted file systems */
1783    if (create_list_of_non_NETFS_mounted_file_systems()) {
1784        log_to_screen ("Could not get the list of mounted file systems");
1785        return (1);
1786    }
1787    log_msg (5, "Processing dsf: %s", dsf);
1788    /********
1789    * Get a list of the dsf's partitions. There could be no partitions on the disk
1790    * or a dsf of a partition was passed in (e.g. /dev/sda1 instead of /dev/sda).
1791    * Either way, it's an error.
1792    ********/
1793    mr_asprintf(&command, "parted2fdisk -l %s 2>/dev/null|grep -E \"^/dev/\"|awk '{printf(\"%%s \", $1)}END{print \"\"}'", dsf);
1794    log_msg(5, "Executing: %s", command);
1795    mr_asprintf(&partition_list, "%s", call_program_and_get_last_line_of_output(command));
1796    paranoid_free(command);
1797    log_msg(4, "Partition list for %s: %s", dsf, partition_list);
1798    if (!strlen(partition_list)) {
1799        /* There were no partitions on the disk */
1800        log_msg(4, "No partitions on device special file %s", dsf);
1801        log_msg(4, "I guess it's a partition itself");
1802        strcpy(partitions[0], dsf);
1803        ndsf = truncate_to_drive_name(dsf);
1804    } else {
1805        /* Fill the partition list */
1806        i = 0;
1807        lastpos = 0;
1808        while ((token = mr_strtok(partition_list, token_chars, &lastpos)) != NULL) {
1809            log_msg (4, "Found partition: %s", token);
1810            strcpy(partitions[i++], token);
1811            mr_free(token);
1812        }
1813        mr_asprintf(&ndsf, "%s", dsf);
1814    }
1815    mr_free(partition_list);
1816
1817    /* In any case we want to exclude the dsf itself from all MondRescue activities
1818     * at restore time (LVM, fdisk, ...) so we want it in our exclude_dev list */
1819    if ((DSFptr = (MOUNTED_FS_STRUCT *) calloc(1, sizeof(MOUNTED_FS_STRUCT))) == NULL) {
1820        fatal_error ("Cannot allocate memory");
1821    }
1822    add_mounted_fs_struct(DSFptr);
1823    strcpy(DSFptr->device, dsf);
1824    DSFptr->check = 1;
1825
1826    /*  For the rest ndsf is the new dsf to deal with */
1827    /********
1828     * At this point, we have a list of all of the partitions on the dsf. Now try to
1829     * see which partitions have a file system on them.
1830     *
1831     * Loop through each partition on the disk and:
1832     *
1833     * - If the partition is swap, it ignores it.
1834     *
1835     * - If the partition is mounted (e.g. /dev/sda1 is mounted on /boot), it adds an entry
1836     *  to the linked list, copies to it the device name and mount point, and sets check == 1.
1837     *
1838     * - If the partition is part of a Volume Group that has Logical Volumes mounted, it adds
1839     *  an entry to the linked list for each mounted Logical Volume in that Volume Group, copying
1840     *  to it the device name and mount point, and sets check == 1. Note that if the Volume Group
1841     *  contains more than one disk, it will still add the entry even if the Logical Volume's
1842     *  extents are not on the dsf that was passed in to the function. For example, Volume Group
1843     *  VolGroup00 contains the disks /dev/sda1 and /dev/sdb1, and the Logical Volumes LogVol01,
1844     *  which is mounted on /var and has all of its extents on /dev/sda1, and LogVol02, which is
1845     *  mounted as /usr and has all of its extents on /dev/sdb1. If you pass /dev/sda into the
1846     *  function, both /var and /usr will be archived even though /usr is actually on/dev/sdb.
1847     *
1848     * - If the partition is part of a Volume Group that has Logical Volumes used in a mounted
1849     *  software raid device, it adds an entry to the linked list, copies to it the software raid
1850     *  device name and mount point, and sets check == 1.
1851     *
1852     * - If the partition is part of a mounted software raid device, it adds an entry to the linked
1853     *  list, copies to it the software raid device name and mount point, and sets check == 1.
1854     *
1855     ********/
1856    for (i=0; strlen(partitions[i]); i++) {
1857        log_msg(4, "Processing partition: %s", partitions[i]);
1858        /* See if it's swap. If it is, ignore it. */
1859        mr_asprintf(&command, "parted2fdisk -l %s 2>/dev/null | awk '{if(($1==\"%s\")&&(toupper($0) ~ \"SWAP\")){print $1;exit}}'", 
1860          ndsf, partitions[i]);
1861        log_msg(5, "  Running: %s", command);
1862        mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1863        paranoid_free(command);
1864        log_msg(5, "  Return value: %s", tmp);
1865        c = strlen(tmp);
1866        paranoid_free(tmp);
1867        if (c) {
1868            log_msg(4, "It's swap. Ignoring partition %s", partitions[i]); 
1869            continue;
1870        } 
1871        /* It's not swap. See if we can find the mount point from the mount command. */
1872        mr_asprintf(&command, "mount 2>/dev/null | awk '{if((NF>0)&&($1==\"%s\")){print $3}}'", partitions[i]);
1873        mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1874        paranoid_free(command);
1875        if (strlen(tmp)) {
1876            log_msg(4, "  %s is mounted: %s", partitions[i], tmp);
1877            if ((DSFptr = find_mount_point_in_list(tmp)) == NULL) {
1878                log_msg (4, "Can't find mount point %s in mounted file systems list", tmp);
1879                paranoid_free(tmp);
1880                return (1);
1881            }
1882            DSFptr->check = 1;
1883            paranoid_free(tmp);
1884            continue;
1885        }
1886        paranoid_free(tmp);
1887        /* It's not swap and it's not mounted. See if it's LVM */
1888        log_msg(4, "  It's not mounted. Checking to see if it's LVM...");
1889        /* Check for LVM */
1890        mr_asprintf(&command, "pvdisplay -c %s | grep '%s:' 2> /dev/null", partitions[i], partitions[i]);
1891        log_msg(5, "  Running: %s", command);
1892        mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1893        paranoid_free(command);
1894        if (strlen(tmp)) {
1895            log_msg(4, "Found an LVM partition at %s. Find the VG it's in...", partitions[i]);
1896            /* It's LVM: Find the VG it's in */
1897            mr_asprintf(&command, "pvdisplay -v %s 2>/dev/null|grep \"VG Name\"|awk '{print $NF}'", partitions[i]);
1898            log_msg(5, "  Running: %s", command);
1899            strcpy(VG, call_program_and_get_last_line_of_output(command));
1900            paranoid_free(command);
1901            log_msg(4, "  Volume Group: %s", VG);
1902            if (strlen(VG)) {
1903                /* Found the Volume Group. Now find all of the VG's mount points */
1904                log_msg(4, "  Found the Volume Group. Now find all of the VG's mount points");
1905                mr_asprintf(&command, "mount 2>/dev/null|grep -E \"/dev/mapper/%s-|/dev/%s/\"|awk '{printf(\"%%s \",$3)}END{print \"\"}'", VG, VG);
1906                log_msg(5, "  Running: %s", command);
1907                mr_asprintf(&mount_list, "%s", call_program_and_get_last_line_of_output(command));
1908                paranoid_free(command);
1909                log_msg(4, "  VG %s mount_list: %s", VG, mount_list);
1910                lastpos = 0;
1911                while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
1912                    log_msg (5, "mount point token: %s", token);
1913                    if ((DSFptr = find_mount_point_in_list(token)) == NULL) {
1914                        log_msg (4, "Can't find mount point %s in mounted file systems list", token);
1915                        paranoid_free(tmp);
1916                        mr_free(token);
1917                        return (1);
1918                    }
1919                    DSFptr->check = 1;
1920                    mr_free(token);
1921                }
1922                /********
1923                 * Now we want to see if there are any software raid devices using
1924                 * any of the Logical Volumes on the Volume Group.
1925                 *******/
1926                paranoid_free(mount_list);
1927
1928                mr_asprintf(&command, "%s", "cat /proc/mdstat|grep -iv Personal|awk '{if($0~\"^.*[ ]+:\"){printf(\"/dev/%s \", $1)}}END{print \"\"}'");
1929                log_msg (5, "Running: %s", command);
1930                mr_asprintf(&mount_list, "%s", call_program_and_get_last_line_of_output(command));
1931                paranoid_free(command);
1932                log_msg(4, "  Software raid device list: %s", mount_list);
1933                lastpos = 0;
1934                while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
1935                    mr_asprintf(&command, "mdadm --detail %s 2>/dev/null | grep -c %s", token, VG);
1936                    log_msg (5, "Running: %s", command);
1937                    paranoid_free(tmp);
1938                    mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1939                    paranoid_free(command);
1940                    log_msg(4, "Number of Software raid device: %s", tmp);
1941                    if (atoi(tmp)) {
1942                        /* This device is on our disk */
1943                        if ((DSFptr = find_device_in_list(token)) == NULL) {
1944                            log_msg (4, "Can't find device %s in mounted file systems list", token);
1945                            paranoid_free(tmp);
1946                            mr_free(token);
1947                            return (1);
1948                        }
1949                        DSFptr->check = 1;
1950                    }
1951                }
1952                mr_free(token);
1953                paranoid_free(mount_list);
1954            } else {
1955                log_msg (4, "Error finding Volume Group for partition %s", partitions[i]);
1956                paranoid_free(tmp);
1957                return (1);
1958            }
1959            paranoid_free(tmp);
1960            continue;
1961        } else {
1962            log_msg (4, "Error finding partition type for the partition %s", partitions[i]);
1963        }
1964        paranoid_free(tmp);
1965        /********
1966         * It's not swap, mounted, or LVM. See if it's used in a software raid device.
1967         ********/
1968        log_msg (5, "It's not swap, mounted, or LVM. See if it's used in a software raid device.");
1969        mr_asprintf(&command, "mdadm --examine %s 2>/dev/null | awk '{if($1 == \"UUID\"){print $3}}'", partitions[i]);
1970        log_msg(4, "  Running: %s", command);
1971        mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1972        paranoid_free(command);
1973        if (!strlen(tmp)) {
1974            log_msg(4, "  Partition %s is not used in a non-LVM software raid device", partitions[i]);
1975            paranoid_free(tmp);
1976            continue;
1977        }
1978        log_msg (5, "  UUID: %s", tmp);
1979        /* Get the Software raid device list */
1980        mr_asprintf(&command, "%s", "cat /proc/mdstat|grep -iv Personal|awk '{if($0~\"^.*[ ]+:\"){printf(\"/dev/%s \", $1)}}END{print \"\"}'");
1981        log_msg (5, "  Running: %s", command);
1982        mr_asprintf(&mount_list, "%s", call_program_and_get_last_line_of_output(command));
1983        paranoid_free(command);
1984        log_msg(4, "  Software raid device list: %s", mount_list);
1985        /* Loop through the software raid device list to see if we can find the partition */
1986        lastpos = 0;
1987        while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
1988            mr_asprintf(&command, "mdadm --detail %s 2>/dev/null | grep -c %s", token, tmp);
1989            log_msg(4, "  Running: %s", command);
1990            paranoid_free(tmp);
1991            mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1992            paranoid_free(command);
1993            if (!atoi(tmp)) {
1994                log_msg (4,"  Didn't find partition %s in software raid device %s", partitions[i], token);
1995            } else {
1996                if ((DSFptr = find_device_in_list(token)) == NULL) {
1997                    log_msg (4, "Can't find device %s in mounted file systems list", token);
1998                    paranoid_free(tmp);
1999                    mr_free(token);
2000                    return (1);
2001                }
2002                DSFptr->check = 1;
2003                break;
2004            }
2005            mr_free(token);
2006        }
2007        paranoid_free(tmp);
2008        paranoid_free(mount_list);
2009    }
2010
2011    /* Determine how much memory to allocate for included_dsf_list and excluded_dsf_list */
2012    i = 0;
2013    DSFptr= DSF_Head;
2014    while (DSFptr != NULL) {
2015        i += strlen(DSFptr->mount_point) + 1;
2016        DSFptr = DSFptr->next;
2017    }
2018    log_msg (5, "i: %d", i);
2019    if ((*included_dsf_list = (char *) calloc(i+100, sizeof(char))) == NULL) {
2020        fatal_error ("Cannot allocate memory");
2021    }
2022    if ((*excluded_dsf_list = (char *) calloc(i+100, sizeof(char))) == NULL) {
2023        fatal_error ("Cannot allocate memory");
2024    }
2025    DSFptr= DSF_Head;
2026    while (DSFptr != NULL) {
2027        if (DSFptr->check) {
2028            log_msg (4, "%s is mounted on %s and is on disk %s", DSFptr->device, DSFptr->mount_point, ndsf);
2029            strcat(*included_dsf_list, DSFptr->mount_point);
2030            strcat(*included_dsf_list, "|");
2031        } else {
2032            log_msg (4, "%s is mounted on %s and is NOT on disk %s", DSFptr->device, DSFptr->mount_point, ndsf);
2033            strcat(*excluded_dsf_list, DSFptr->mount_point);
2034            strcat(*excluded_dsf_list, "|");
2035        }
2036        DSFptr = DSFptr->next;
2037    }
2038    mr_free(ndsf);
2039
2040    log_msg (5, "included_dsf_list: %s", *included_dsf_list);
2041    log_msg (5, "excluded_dsf_list: %s", *excluded_dsf_list);
2042    return (0);
2043}
2044
2045
2046
2047
2048
2049/* Update the bkpinfo structure for exclude & include paths
2050 * in order to handle correctly paths corresponding to devices */
2051void mr_make_devlist_from_pathlist(char *pathlist, char mode) {
2052
2053char *token = NULL;
2054int lastpos = 0;
2055char *mounted_on_dsf = NULL;
2056char *not_mounted_on_dsf = NULL;
2057char token_chars[] ="|\t\r\f\a\0\n";
2058char *tmp = NULL;
2059char *tmp1 = NULL;
2060
2061if (pathlist == NULL) {
2062    return;
2063}
2064while ((token = mr_strtok(pathlist, token_chars, &lastpos)) != NULL) {
2065    switch (get_dsf_mount_list(token, &mounted_on_dsf, &not_mounted_on_dsf)) {
2066    case 1: 
2067        if (mode == 'E') {
2068            log_msg(1, "WARNING ! %s doesn't exist in -E option", token);
2069        } else {
2070            log_msg(1, "ERROR ! %s doesn't exist in -I option", token);
2071            fatal_error("Error processing -I option");
2072        }
2073        break;
2074    /* Everything is OK; proceed to archive data */
2075    case 0:
2076        if (mode == 'E') {
2077            if (strlen(mounted_on_dsf)) {
2078                log_to_screen("Excluding the following file systems on %s:", token);
2079                log_to_screen("==> %s", mounted_on_dsf);
2080                log_msg (5, "Adding to bkpinfo->exclude_paths due to -E option: %s", mounted_on_dsf);
2081                if (bkpinfo->exclude_paths) {
2082                    mr_strcat(bkpinfo->exclude_paths,"|%s",mounted_on_dsf);
2083                } else {
2084                    mr_asprintf(bkpinfo->exclude_paths,"%s",mounted_on_dsf);
2085                }
2086                if (bkpinfo->exclude_devs) {
2087                    mr_strcat(bkpinfo->exclude_devs,"|%s",token);
2088                } else {
2089                    mr_asprintf(bkpinfo->exclude_devs,"%s",token);
2090                }
2091            }
2092        } else {
2093            log_to_screen("Archiving only the following file systems on %s:", token);
2094            log_to_screen("==> %s", mounted_on_dsf);
2095            strcpy(bkpinfo->include_paths, "/");
2096            if (strlen(not_mounted_on_dsf)) {
2097                log_msg (5, "Adding to bkpinfo->exclude_paths due to -I option: %s", not_mounted_on_dsf);
2098                log_to_screen("Not archiving the following file systems:");
2099                log_to_screen("==> %s", not_mounted_on_dsf);
2100                if (bkpinfo->exclude_paths) {
2101                    mr_strcat(bkpinfo->exclude_paths, "|%s",not_mounted_on_dsf);
2102                } else {
2103                    mr_asprintf(bkpinfo->exclude_paths,"%s",not_mounted_on_dsf);
2104                }
2105            }
2106        }
2107        break;
2108    /* It's a dsf but not a whole disk dsf */
2109    case -2:
2110        log_to_screen("Could %s be a partition instead of a whole disk device special file?\nIgnored.", token);
2111        break;
2112    /* A device special file was not passed in. Process it as a path. */
2113    case -1:
2114        /*  Adds a | to ensure correct detection even at both ends */
2115        mr_asprintf(&tmp1,"|%s",token);
2116        if (mode == 'E') {
2117            /*  Add the token if not already in the list */
2118            mr_asprintf(&tmp,"|%s|",bkpinfo->exclude_paths);
2119            if (strstr(tmp,tmp1) == NULL) {
2120                if (bkpinfo->exclude_paths) {
2121                    mr_strcat(bkpinfo->exclude_paths,tmp1);
2122                    mr_free(tmp1);
2123                } else {
2124                    bkpinfo->exclude_paths = tmp1;
2125                }
2126            }
2127        } else {
2128            /*  Add the token if not already in the list */
2129            mr_asprintf(&tmp,"|%s|",bkpinfo->include_paths);
2130            if (strstr(tmp,tmp1) == NULL) {
2131                strcat(bkpinfo->include_paths,tmp1);
2132            }
2133            mr_free(tmp1);
2134        }
2135        mr_free(tmp);
2136        break;
2137    }
2138    mr_free(token);
2139
2140    if (bkpinfo->include_paths != NULL) {
2141        log_msg(1, "include_paths is now '%s'", bkpinfo->include_paths);
2142    }
2143    if (bkpinfo->exclude_paths != NULL) {
2144        log_msg(1, "exclude_paths is now '%s'", bkpinfo->exclude_paths);
2145    }
2146    if (bkpinfo->exclude_devs != NULL) {
2147        log_msg(1, "exclude_devs is now '%s'", bkpinfo->exclude_devs);
2148    }
2149}
2150}
2151
2152
2153
2154
2155/**
2156 * Ask user for details of backup/restore information.
2157 * Called when @c mondoarchive doesn't get any parameters.
2158 * @param bkpinfo The backup information structure to fill out with the user's data.
2159 * @param archiving_to_media TRUE if archiving, FALSE if restoring.
2160 * @return 0, always.
2161 * @bug No point of `int' return value.
2162 * @ingroup archiveGroup
2163 */
2164int interactively_obtain_media_parameters_from_user(bool archiving_to_media)
2165// archiving_to_media is TRUE if I'm being called by mondoarchive
2166// archiving_to_media is FALSE if I'm being called by mondorestore
2167{
2168    char *tmp = NULL;
2169    char *tmp1 = NULL;
2170    char *mds = NULL;
2171    char p[8*MAX_STR_LEN];
2172    char *sz_size;
2173    char *command;
2174    char *compression_type = NULL;
2175    char *comment;
2176    char *prompt;
2177    int i;
2178    FILE *fin;
2179
2180    malloc_string(sz_size);
2181    malloc_string(command);
2182    malloc_string(comment);
2183    malloc_string(prompt);
2184    malloc_string(tmp1);
2185    assert(bkpinfo != NULL);
2186    sz_size[0] = '\0';
2187    bkpinfo->nonbootable_backup = FALSE;
2188
2189    // Tape, CD, NETFS, ...?
2190    srandom(getpid());
2191    bkpinfo->backup_media_type =
2192        (g_restoring_live_from_cd) ? cdr :
2193        which_backup_media_type(bkpinfo->restore_data);
2194    if (bkpinfo->backup_media_type == none) {
2195        log_to_screen("User has chosen not to backup the PC");
2196        finish(1);
2197    }
2198    /* Why asking to remove the media with tape ?
2199    if (bkpinfo->backup_media_type == tape && bkpinfo->restore_data) {
2200        popup_and_OK("Please remove media from drive(s)");
2201    }
2202    */
2203    log_msg(3, "media type = %s",
2204            bkptype_to_string(bkpinfo->backup_media_type));
2205    if (archiving_to_media) {
2206        sensibly_set_tmpdir_and_scratchdir();
2207    }
2208    bkpinfo->cdrw_speed = (bkpinfo->backup_media_type == cdstream) ? 2 : 4;
2209    bkpinfo->compression_level =
2210        (bkpinfo->backup_media_type == cdstream) ? 1 : 5;
2211    bkpinfo->use_lzo =
2212        (bkpinfo->backup_media_type == cdstream) ? TRUE : FALSE;
2213    mvaddstr_and_log_it(2, 0, " ");
2214
2215    // Find device's /dev (or SCSI) entry
2216    switch (bkpinfo->backup_media_type) {
2217    case cdr:
2218    case cdrw:
2219    case dvd:
2220    case usb:
2221        /* Never try to eject a USB device */
2222        if (bkpinfo->backup_media_type == usb) {
2223            bkpinfo->please_dont_eject = TRUE;
2224        }
2225        if (archiving_to_media) {
2226            if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
2227                if (ask_me_yes_or_no
2228                    ("Is your computer a laptop, or does the CD writer incorporate BurnProof technology?"))
2229                {
2230                    bkpinfo->manual_cd_tray = TRUE;
2231                }
2232            }
2233            if ((compression_type = which_compression_type()) == NULL) {
2234                log_to_screen("User has chosen not to backup the PC");
2235                finish(1);
2236            }
2237            if ((bkpinfo->compression_level =
2238                 which_compression_level()) == -1) {
2239                log_to_screen("User has chosen not to backup the PC");
2240                finish(1);
2241            }
2242            mds = media_descriptor_string(bkpinfo->backup_media_type);
2243            sprintf(comment, "What speed is your %s (re)writer?", mds);
2244            if (bkpinfo->backup_media_type == dvd) {
2245                find_dvd_device(bkpinfo->media_device, FALSE);
2246                strcpy(tmp1, "1");
2247                sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE);  // 4.7 salesman's GB = 4.482 real GB = 4482 MB
2248                log_msg(1, "Setting to DVD defaults");
2249            } else {
2250                strcpy(bkpinfo->media_device, VANILLA_SCSI_CDROM);
2251                strcpy(tmp1, "4");
2252                strcpy(sz_size, "650");
2253                log_msg(1, "Setting to CD defaults");
2254            }
2255            if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
2256                if (!popup_and_get_string("Speed", comment, tmp1, 4)) {
2257                    log_to_screen("User has chosen not to backup the PC");
2258                    finish(1);
2259                }
2260            }
2261            bkpinfo->cdrw_speed = atoi(tmp1);   // if DVD then this shouldn't ever be used anyway :)
2262
2263            sprintf(comment,
2264                    "How much data (in Megabytes) will each %s store?", mds);
2265            mr_free(mds);
2266            if (!popup_and_get_string("Size", comment, sz_size, 5)) {
2267                log_to_screen("User has chosen not to backup the PC");
2268                finish(1);
2269            }
2270            for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2271                bkpinfo->media_size[i] = atoi(sz_size);
2272            }
2273            if (bkpinfo->media_size[0] <= 0) {
2274                log_to_screen("User has chosen not to backup the PC");
2275                finish(1);
2276            }
2277        }
2278        /* No break because we continue even for usb */
2279    case cdstream:
2280        mds = media_descriptor_string(bkpinfo->backup_media_type);
2281
2282        if ((bkpinfo->disaster_recovery) && (bkpinfo->backup_media_type != usb)) {
2283            strcpy(bkpinfo->media_device, "/dev/cdrom");
2284            log_msg(2, "CD-ROM device assumed to be at %s",
2285                    bkpinfo->media_device);
2286        } else if ((bkpinfo->restore_data && (bkpinfo->backup_media_type != usb))
2287                   || bkpinfo->backup_media_type == dvd) {
2288            if (!bkpinfo->media_device[0]) {
2289                strcpy(bkpinfo->media_device, "/dev/cdrom");
2290            }                   // just for the heck of it :)
2291            log_msg(1, "bkpinfo->media_device = %s",
2292                    bkpinfo->media_device);
2293            if (bkpinfo->backup_media_type == dvd
2294                || find_cdrom_device(bkpinfo->media_device, FALSE)) {
2295                log_msg(1, "bkpinfo->media_device = %s",
2296                        bkpinfo->media_device);
2297                sprintf(comment,
2298                        "Please specify your %s drive's /dev entry", mds);
2299                if (!popup_and_get_string
2300                    ("Device?", comment, bkpinfo->media_device,
2301                     MAX_STR_LEN / 4)) {
2302                    log_to_screen("User has chosen not to backup the PC");
2303                    finish(1);
2304                }
2305            }
2306            log_msg(2, "%s device found at %s", mds, bkpinfo->media_device);
2307        } else {
2308            if ((find_cdrw_device(bkpinfo->media_device)) && (bkpinfo->backup_media_type != usb)) {
2309                bkpinfo->media_device[0] = '\0';
2310            }
2311            if (bkpinfo->media_device[0]) {
2312                if (bkpinfo->backup_media_type == usb) {
2313                    mr_asprintf(&tmp, "I think your %s media corresponds to %s. Is this correct?", mds, bkpinfo->media_device);
2314                } else {
2315                    mr_asprintf(&tmp, "I think I've found your %s burner at SCSI node %s. Is this correct? (Say no if you have an IDE burner and you are running a 2.6 kernel. You will then be prompted for further details.)", mds, bkpinfo->media_device);
2316                }
2317                if (!ask_me_yes_or_no(tmp)) {
2318                    bkpinfo->media_device[0] = '\0';
2319                }
2320                mr_free(tmp);
2321            }
2322            if (!bkpinfo->media_device[0]) {
2323                if (bkpinfo->backup_media_type == usb) {
2324                    i = popup_and_get_string("/dev entry?",
2325                                         "What is the /dev entry of your USB Disk/Key, please?",
2326                                         bkpinfo->media_device,
2327                                         MAX_STR_LEN / 4);
2328                } else {
2329                    if (g_kernel_version < 2.6) {
2330                        i = popup_and_get_string("Device node?",
2331                                             "What is the SCSI node of your CD (re)writer, please?",
2332                                             bkpinfo->media_device,
2333                                             MAX_STR_LEN / 4);
2334                    } else {
2335                        i = popup_and_get_string("/dev entry?",
2336                                             "What is the /dev entry of your CD (re)writer, please?",
2337                                             bkpinfo->media_device,
2338                                             MAX_STR_LEN / 4);
2339                    }
2340                }
2341                if (!i) {
2342                    log_to_screen("User has chosen not to backup the PC");
2343                    finish(1);
2344                }
2345            }
2346        }
2347        mr_free(mds);
2348
2349        if (bkpinfo->backup_media_type == cdstream) {
2350            for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2351                bkpinfo->media_size[i] = 650;
2352            }
2353        }
2354        break;
2355    case udev:
2356        if (!ask_me_yes_or_no
2357            ("This option is for advanced users only. Are you sure?")) {
2358            log_to_screen("User has chosen not to backup the PC");
2359            finish(1);
2360        }
2361    case tape:
2362
2363        if ((!bkpinfo->restore_mode) && (find_tape_device_and_size(bkpinfo->media_device, sz_size))) {
2364            log_msg(3, "Ok, using vanilla scsi tape.");
2365            strcpy(bkpinfo->media_device, VANILLA_SCSI_TAPE);
2366            if ((fin = fopen(bkpinfo->media_device, "r"))) {
2367                paranoid_fclose(fin);
2368            } else {
2369                strcpy(bkpinfo->media_device, "/dev/osst0");
2370            }
2371        }
2372        if (bkpinfo->media_device[0]) {
2373            if ((fin = fopen(bkpinfo->media_device, "r"))) {
2374                paranoid_fclose(fin);
2375            } else {
2376                if (does_file_exist("/tmp/mondo-restore.cfg")) {
2377                    read_cfg_var("/tmp/mondo-restore.cfg", "media-dev",
2378                                 bkpinfo->media_device);
2379                }
2380            }
2381        }
2382        if (bkpinfo->media_device[0]) {
2383            mr_asprintf(&tmp, "I think I've found your tape streamer at %s; am I right on the money?", bkpinfo->media_device);
2384            if (!ask_me_yes_or_no(tmp)) {
2385                bkpinfo->media_device[0] = '\0';
2386            }
2387            mr_free(tmp);
2388        }
2389        if (!bkpinfo->media_device[0]) {
2390            if (!popup_and_get_string
2391                ("Device name?",
2392                 "What is the /dev entry of your tape streamer?",
2393                 bkpinfo->media_device, MAX_STR_LEN / 4)) {
2394                log_to_screen("User has chosen not to backup the PC");
2395                finish(1);
2396            }
2397        }
2398        mr_asprintf(&tmp, "ls -l %s", bkpinfo->media_device);
2399        if (run_program_and_log_output(tmp, FALSE)) {
2400            log_to_screen("User has not specified a valid /dev entry");
2401            finish(1);
2402        }
2403        mr_free(tmp);
2404        log_msg(4, "sz_size = %s", sz_size);
2405        sz_size[0] = '\0';
2406
2407        bkpinfo->use_obdr = ask_me_yes_or_no
2408            ("Do you want to activate OBDR support for your tapes ?");
2409        if (sz_size[0] == '\0') {
2410            bkpinfo->media_size[0] = 0;
2411        } else {
2412            bkpinfo->media_size[0] =
2413                friendly_sizestr_to_sizelong(sz_size) / 2 - 50;
2414        }
2415        log_msg(4, "media_size[0] = %ld", bkpinfo->media_size[0]);
2416        if (bkpinfo->media_size[0] <= 0) {
2417            bkpinfo->media_size[0] = 0;
2418        }
2419        for (i = 1; i <= MAX_NOOF_MEDIA; i++) {
2420            bkpinfo->media_size[i] = bkpinfo->media_size[0];
2421        }
2422        if (archiving_to_media) {
2423            if ((compression_type = which_compression_type()) == NULL) {
2424                log_to_screen("User has chosen not to backup the PC");
2425                finish(1);
2426            }
2427            if ((bkpinfo->compression_level =
2428                 which_compression_level()) == -1) {
2429                log_to_screen("User has chosen not to backup the PC");
2430                finish(1);
2431            }
2432        }
2433        break;
2434
2435
2436
2437    case netfs:
2438        /* Never try to eject a NETFS device */
2439        bkpinfo->please_dont_eject = TRUE;
2440
2441        /* Initiate bkpinfo netfs_mount path from running environment if not already done */
2442        if (!bkpinfo->netfs_mount[0]) {
2443            strcpy(bkpinfo->netfs_mount,
2444                   call_program_and_get_last_line_of_output
2445                   ("mount | grep \":\" | cut -d' ' -f1 | head -n1"));
2446        }
2447#ifdef __FreeBSD__
2448        if (TRUE)
2449#else
2450        if (!bkpinfo->disaster_recovery)
2451#endif
2452        {
2453            if (!popup_and_get_string
2454                ("Network shared dir.",
2455                 "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.)",
2456                 bkpinfo->netfs_mount, MAX_STR_LEN / 4)) {
2457                log_to_screen("User has chosen not to backup the PC");
2458                finish(1);
2459            }
2460            if (!bkpinfo->restore_data) {
2461                if ((compression_type = which_compression_type()) == NULL) {
2462                    log_to_screen("User has chosen not to backup the PC");
2463                    finish(1);
2464                }
2465                if ((bkpinfo->compression_level =
2466                     which_compression_level()) == -1) {
2467                    log_to_screen("User has chosen not to backup the PC");
2468                    finish(1);
2469                }
2470            }
2471            // check whether already mounted - we better remove
2472            // surrounding spaces and trailing '/' for this
2473            strip_spaces(bkpinfo->netfs_mount);
2474            if (bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] == '/')
2475                bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] = '\0';
2476            sprintf(command, "mount | grep \"%s \" | cut -d' ' -f3",
2477                    bkpinfo->netfs_mount);
2478            strcpy(bkpinfo->isodir,
2479                   call_program_and_get_last_line_of_output(command));
2480
2481            if (!bkpinfo->restore_data) {
2482                sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE);  // 4.7 salesman's GB = 4.482 real GB = 4482 MB
2483                sprintf(comment,
2484                    "How much data (in Megabytes) will each media store?");
2485                if (!popup_and_get_string("Size", comment, sz_size, 5)) {
2486                    log_to_screen("User has chosen not to backup the PC");
2487                    finish(1);
2488                }
2489            } else {
2490                strcpy(sz_size, "0");
2491            }
2492            for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2493                bkpinfo->media_size[i] = atoi(sz_size);
2494            }
2495            if (bkpinfo->media_size[0] < 0) {
2496                log_to_screen("User has chosen not to backup the PC");
2497                finish(1);
2498            }
2499        }
2500        /*  Force NFS to be the protocol by default */
2501        if (bkpinfo->netfs_proto == NULL) {
2502            mr_asprintf(&(bkpinfo->netfs_proto), "nfs");
2503        }
2504        if (bkpinfo->disaster_recovery) {
2505            sprintf(command ,"umount %s/isodir 2> /dev/null", bkpinfo->tmpdir);
2506            (void)system(command);
2507        }
2508        strcpy(tmp1, bkpinfo->netfs_proto);
2509        if (!popup_and_get_string
2510            ("Network protocol", "Which protocol should I use (nfs/sshfs) ?",
2511             tmp1, MAX_STR_LEN)) {
2512            log_to_screen("User has chosen not to backup the PC");
2513            finish(1);
2514        }
2515        mr_free(bkpinfo->netfs_proto);
2516        mr_asprintf(&(bkpinfo->netfs_proto), "%s", tmp1);
2517        if (!popup_and_get_string
2518            ("Network share", "Which remote share should I mount?",
2519             bkpinfo->netfs_mount, MAX_STR_LEN)) {
2520            log_to_screen("User has chosen not to backup the PC");
2521            finish(1);
2522        }
2523
2524        /* Initiate bkpinfo isodir path from running environment if mount already done */
2525        if (is_this_device_mounted(bkpinfo->netfs_mount)) {
2526            strcpy(bkpinfo->isodir,
2527                   call_program_and_get_last_line_of_output
2528                   ("mount | grep \":\" | cut -d' ' -f3 | head -n1"));
2529        } else {
2530            sprintf(bkpinfo->isodir, "%s/netfsdir", bkpinfo->tmpdir);
2531            sprintf(command, "mkdir -p %s", bkpinfo->isodir);
2532            run_program_and_log_output(command, 5);
2533            if (bkpinfo->restore_data) {
2534                if (strstr(bkpinfo->netfs_proto, "sshfs")) {
2535                    mr_asprintf(&tmp, "sshfs -o ro %s %s", bkpinfo->netfs_mount, bkpinfo->isodir);
2536                } else {
2537                    mr_asprintf(&tmp, "mount -t %s -o nolock,ro %s %s", bkpinfo->netfs_proto, bkpinfo->netfs_mount, bkpinfo->isodir);
2538                }
2539            } else {
2540                if (strstr(bkpinfo->netfs_proto, "sshfs")) {
2541                    mr_asprintf(&tmp, "sshfs %s %s", bkpinfo->netfs_mount, bkpinfo->isodir);
2542                } else {
2543                    mr_asprintf(&tmp, "mount -t %s -o nolock %s %s", bkpinfo->netfs_proto, bkpinfo->netfs_mount, bkpinfo->isodir);
2544                }
2545            }
2546            run_program_and_log_output(tmp, 3);
2547            mr_free(tmp);
2548
2549            malloc_string(g_selfmounted_isodir);
2550            strcpy(g_selfmounted_isodir, bkpinfo->isodir);
2551        }
2552        if (!is_this_device_mounted(bkpinfo->netfs_mount)) {
2553            popup_and_OK
2554                ("Please mount that partition before you try to backup to or restore from it.");
2555            finish(1);
2556        }
2557        strcpy(tmp1, bkpinfo->netfs_remote_dir);
2558        if (!popup_and_get_string
2559            ("Directory", "Which directory within that mountpoint?", tmp1,
2560             MAX_STR_LEN)) {
2561            log_to_screen("User has chosen not to backup the PC");
2562            finish(1);
2563        }
2564        strcpy(bkpinfo->netfs_remote_dir, tmp1);
2565
2566        // check whether writable - we better remove surrounding spaces for this
2567        strip_spaces(bkpinfo->netfs_remote_dir);
2568
2569        if (!popup_and_get_string
2570            ("Prefix.",
2571             "Please enter the prefix that will be prepended to your ISO filename.  Example: machine1 to obtain machine1-[1-9]*.iso files",
2572            bkpinfo->prefix, MAX_STR_LEN / 4)) {
2573            log_to_screen("User has chosen not to backup the PC");
2574            finish(1);
2575        }
2576        log_msg(3, "prefix set to %s", bkpinfo->prefix);
2577
2578        for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2579            bkpinfo->media_size[i] = 650;
2580        }
2581        log_msg(3, "Just set netfs_remote_dir to %s",
2582                bkpinfo->netfs_remote_dir);
2583        log_msg(3, "isodir is still %s", bkpinfo->isodir);
2584        break;
2585
2586    case iso:
2587        if (!bkpinfo->disaster_recovery) {
2588            if (!popup_and_get_string
2589                ("Storage dir.",
2590                 "Please enter the full path name to the directory for your ISO images.  Example: /mnt/raid0_0",
2591                 bkpinfo->isodir, MAX_STR_LEN / 4)) {
2592                log_to_screen("User has chosen not to backup the PC");
2593                finish(1);
2594            }
2595            if (archiving_to_media) {
2596                if ((compression_type = which_compression_type()) == NULL) {
2597                    log_to_screen("User has chosen not to backup the PC");
2598                    finish(1);
2599                }
2600                if ((bkpinfo->compression_level =
2601                     which_compression_level()) == -1) {
2602                    log_to_screen("User has chosen not to backup the PC");
2603                    finish(1);
2604                }
2605                sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE);  // 4.7 salesman's GB = 4.482 real GB = 4482 MB
2606                if (!popup_and_get_string
2607                    ("ISO size.",
2608                     "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 (700) or DVD's (4480) you plan to backup to.",
2609                     sz_size, 16)) {
2610                    log_to_screen("User has chosen not to backup the PC");
2611                    finish(1);
2612                }
2613                for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2614                    bkpinfo->media_size[i] = atoi(sz_size);
2615                }
2616            } else {
2617                for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2618                    bkpinfo->media_size[i] = 650;
2619                }
2620            }
2621        }
2622        if (!popup_and_get_string
2623            ("Prefix.",
2624             "Please enter the prefix that will be prepended to your ISO filename.  Example: machine1 to obtain machine1-[1-9]*.iso files",
2625             bkpinfo->prefix, MAX_STR_LEN / 4)) {
2626            log_to_screen("User has chosen not to backup the PC");
2627            finish(1);
2628        }
2629        log_msg(3, "prefix set to %s", bkpinfo->prefix);
2630        break;
2631    default:
2632        fatal_error
2633            ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
2634    }
2635
2636    if (archiving_to_media) {
2637
2638#ifdef __FreeBSD__
2639        strcpy(bkpinfo->boot_device,
2640               call_program_and_get_last_line_of_output
2641               ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
2642#else
2643        strcpy(bkpinfo->boot_device,
2644               call_program_and_get_last_line_of_output
2645               ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
2646#endif
2647        i = which_boot_loader(bkpinfo->boot_device);
2648        if (i == 'U')           // unknown
2649        {
2650
2651#ifdef __FreeBSD__
2652            if (!popup_and_get_string
2653                ("Boot device",
2654                 "What is your boot device? (e.g. /dev/ad0)",
2655                 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2656                log_to_screen("User has chosen not to backup the PC");
2657                finish(1);
2658            }
2659            i = which_boot_loader(bkpinfo->boot_device);
2660#else
2661            if (!popup_and_get_string
2662                ("Boot device",
2663                 "What is your boot device? (e.g. /dev/hda)",
2664                 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2665                log_to_screen("User has chosen not to backup the PC");
2666                finish(1);
2667            }
2668            if (does_string_exist_in_boot_block
2669                (bkpinfo->boot_device, "LILO")) {
2670                i = 'L';
2671            } else
2672                if (does_string_exist_in_boot_block
2673                    (bkpinfo->boot_device, "ELILO")) {
2674                i = 'E';
2675            } else
2676                if (does_string_exist_in_boot_block
2677                    (bkpinfo->boot_device, "GRUB")) {
2678                i = 'G';
2679            } else {
2680                i = 'U';
2681            }
2682#endif
2683            if (i == 'U') {
2684                if (ask_me_yes_or_no
2685                    ("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?"))
2686                {
2687                    i = 'R';    // raw
2688                } else {
2689                    log_to_screen
2690                        ("I cannot find your boot loader. Please run mondoarchive with parameters.");
2691                    finish(1);
2692                }
2693            }
2694        }
2695        bkpinfo->boot_loader = i;
2696        strcpy(bkpinfo->include_paths, "/");
2697        if (!popup_and_get_string
2698            ("Backup paths",
2699             "Please enter paths (separated by '|') which you want me to backup. The default is '/' (i.e. everything).",
2700             bkpinfo->include_paths, MAX_STR_LEN)) {
2701            log_to_screen("User has chosen not to backup the PC");
2702            finish(1);
2703        }
2704        tmp = list_of_NETFS_mounts_only();
2705        if (strlen(tmp) > 2) {
2706            mr_strcat(bkpinfo->exclude_paths, "|%s",tmp);
2707        }
2708        mr_free(tmp);
2709// NTFS
2710        strcpy(tmp1, call_program_and_get_last_line_of_output("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'"));
2711        if (strlen(tmp1) > 2) {
2712            if (!popup_and_get_string
2713                ("NTFS partitions",
2714                 "Please enter/confirm the NTFS partitions you wish to backup as well.",
2715                 tmp1, MAX_STR_LEN / 4)) {
2716                log_to_screen("User has chosen not to backup the PC");
2717                finish(1);
2718            }
2719            strncpy(bkpinfo->image_devs, tmp1, MAX_STR_LEN / 4);
2720        }
2721
2722        if (bkpinfo->exclude_paths != NULL ) {
2723            strncpy(p,bkpinfo->exclude_paths,(8*MAX_STR_LEN)-1);
2724        } else {
2725            p[0] = '\0';
2726        }
2727        popup_and_get_string("Exclude paths", "Please enter paths which you do NOT want to backup. Separate them with '|'. NB: /tmp and /proc are always excluded. :-) Just hit 'Enter' if you want to do a full system backup.", p, (8*MAX_STR_LEN)-1);
2728        if (p == NULL) {
2729            log_to_screen("User has chosen not to backup the PC");
2730            finish(1);
2731        }
2732        mr_free(bkpinfo->exclude_paths);
2733        mr_asprintf(&tmp, "%s", p);
2734        bkpinfo->exclude_paths = tmp;
2735
2736        if (!popup_and_get_string
2737            ("Temporary directory",
2738             "Please enter your temporary directory.",
2739             bkpinfo->tmpdir, (4*MAX_STR_LEN)-1)) {
2740            log_to_screen("User has chosen not to backup the PC");
2741            finish(1);
2742        }
2743        if (!popup_and_get_string
2744            ("Scratch directory",
2745             "Please enter your scratch directory.",
2746             bkpinfo->scratchdir, (4*MAX_STR_LEN)-1)) {
2747            log_to_screen("User has chosen not to backup the PC");
2748            finish(1);
2749        }
2750        if (ask_me_yes_or_no("Do you want to backup extended attributes?")) {
2751            if (find_home_of_exe("getfattr")) {
2752                mr_asprintf(&g_getfattr,"getfattr");
2753            }
2754            if (find_home_of_exe("getfacl")) {
2755                mr_asprintf(&g_getfacl,"getfacl");
2756            }
2757        }
2758// Interactive mode:
2759#ifdef __IA64__
2760        bkpinfo->make_cd_use_lilo = TRUE;
2761#else
2762        bkpinfo->make_cd_use_lilo = FALSE;
2763#endif
2764        bkpinfo->backup_data = TRUE;
2765        if (strcmp(compression_type,"lzo") == 0) {
2766            strcpy(bkpinfo->zip_exe, "lzop");
2767            strcpy(bkpinfo->zip_suffix, "lzo");
2768        } else if (strcmp(compression_type,"gzip") == 0) {
2769            strcpy(bkpinfo->zip_exe, "gzip");
2770            strcpy(bkpinfo->zip_suffix, "gz");
2771        //} else if (strcmp(compression_type,"lzma") == 0) {
2772            //strcpy(bkpinfo->zip_exe, "xy");
2773            //strcpy(bkpinfo->zip_suffix, "xy");
2774        } else if (strcmp(compression_type,"bzip2") == 0) {
2775            strcpy(bkpinfo->zip_exe, "bzip2");
2776            strcpy(bkpinfo->zip_suffix, "bz2");
2777        } else {
2778            bkpinfo->zip_exe[0] = bkpinfo->zip_suffix[0] = '\0';
2779        }
2780        bkpinfo->verify_data =
2781            ask_me_yes_or_no
2782            ("Will you want to verify your backups after Mondo has created them?");
2783
2784#ifndef __FreeBSD__
2785        if (!ask_me_yes_or_no
2786            ("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."))
2787#endif
2788        {
2789            strcpy(bkpinfo->kernel_path, "FAILSAFE");
2790        }
2791
2792        if (!ask_me_yes_or_no
2793            ("Are you sure you want to proceed? Hit 'no' to abort.")) {
2794            log_to_screen("User has chosen not to backup the PC");
2795            finish(1);
2796        }
2797    } else {
2798        bkpinfo->restore_data = TRUE;   // probably...
2799    }
2800
2801    if (bkpinfo->backup_media_type == iso
2802        || bkpinfo->backup_media_type == netfs) {
2803        g_ISO_restore_mode = TRUE;
2804    }
2805#ifdef __FreeSD__
2806// skip
2807#else
2808    if (bkpinfo->backup_media_type == netfs) {
2809        log_msg(3, "I think the Remote mount is mounted at %s",
2810                bkpinfo->isodir);
2811    }
2812    log_it("isodir = %s", bkpinfo->isodir);
2813    log_it("netfs_mount = '%s'", bkpinfo->netfs_mount);
2814    if (bkpinfo->netfs_proto) {
2815        log_it("netfs_proto = '%s'", bkpinfo->netfs_proto);
2816    }
2817    if (bkpinfo->netfs_user) {
2818        log_it("netfs_user = '%s'", bkpinfo->netfs_user);
2819    }
2820#endif
2821
2822    log_it("media device = %s", bkpinfo->media_device);
2823    log_it("media size = %ld", bkpinfo->media_size[1]);
2824    log_it("media type = %s",
2825           bkptype_to_string(bkpinfo->backup_media_type));
2826    log_it("prefix = %s", bkpinfo->prefix);
2827    log_it("compression = %ld", bkpinfo->compression_level);
2828    log_it("exclude_path = %s", bkpinfo->exclude_paths);
2829    log_it("include_path = %s", bkpinfo->include_paths);
2830
2831    /* Handle devices passed in bkpinfo and print result */
2832    /*  the mr_make_devlist_from_pathlist function appends
2833     *  to the *_paths variables so copy before */
2834    mr_make_devlist_from_pathlist(bkpinfo->exclude_paths, 'E');
2835    mr_make_devlist_from_pathlist(bkpinfo->include_paths, 'I');
2836
2837    log_it("scratchdir = '%s'", bkpinfo->scratchdir);
2838    log_it("tmpdir = '%s'", bkpinfo->tmpdir);
2839    log_it("image_devs = '%s'", bkpinfo->image_devs);
2840    log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device,
2841           bkpinfo->boot_loader);
2842    if (bkpinfo->media_size[0] < 0) {
2843        if (archiving_to_media) {
2844            fatal_error("Media size is less than zero.");
2845        } else {
2846            log_msg(2, "Warning - media size is less than zero.");
2847            bkpinfo->media_size[0] = 0;
2848        }
2849    }
2850    paranoid_free(sz_size);
2851    paranoid_free(tmp1);
2852    paranoid_free(command);
2853    paranoid_free(comment);
2854    paranoid_free(prompt);
2855    return (0);
2856}
2857
2858
2859/**
2860 * Get a |-separated list of NETFS mounts.
2861 * @return The list created.
2862 * @note The return value points to allocated string that needs to be freed
2863 * @bug Even though we only want the mounts, the devices are still checked.
2864 */
2865char *list_of_NETFS_mounts_only(void)
2866{
2867    char *exclude_these_directories = NULL;
2868
2869    mr_asprintf(&exclude_these_directories,"%s", call_program_and_get_last_line_of_output("mount -t coda,ncpfs,fuse.sshfs,nfs,nfs4,vmhgfs,smbfs,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' '|' | awk '{print $0;}'"));
2870    log_msg(9,"list_of_NETFS_mounts_only returns %s\n",exclude_these_directories);
2871    return(exclude_these_directories);
2872}
2873
2874/* @} - end of utilityGroup */
2875
2876
2877
2878
2879
2880/**
2881 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
2882 * [random] is a random number between 1 and 32767.
2883 * @param store_name_here Where to store the new filename.
2884 * @param stub A random number will be appended to this to make the FIFO's name.
2885 * @ingroup deviceGroup
2886 */
2887void make_fifo(char *store_name_here, char *stub)
2888{
2889    char *tmp;
2890
2891    malloc_string(tmp);
2892    assert_string_is_neither_NULL_nor_zerolength(stub);
2893
2894    sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
2895            (int) (random() % 32768));
2896    make_hole_for_file(store_name_here);
2897    mkfifo(store_name_here, S_IRWXU | S_IRWXG);
2898    sprintf(tmp, "chmod 770 %s", store_name_here);
2899    paranoid_system(tmp);
2900    paranoid_free(tmp);
2901}
2902
2903
2904
2905
2906
2907
2908/**
2909 * Set the tmpdir and scratchdir to reside on the partition with the most free space.
2910 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
2911 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set.
2912 * @ingroup utilityGroup
2913 */
2914void sensibly_set_tmpdir_and_scratchdir()
2915{
2916    char *tmp = NULL; 
2917    char *command = NULL;
2918    char *sz = NULL;
2919
2920    assert(bkpinfo != NULL);
2921
2922#ifdef __FreeBSD__
2923    mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output("LANGUAGE=C df -m -P -t nonfs,msdosfs,ntfs,ntfs-3g,vmhgfs,smbfs,smb,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol | grep -vE \"none|Filesystem\" | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -nr | awk '{print $NF;}' | while read x ; do test -w $x && echo $x && break ; done"));
2924#else
2925    mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output("LANGUAGE=C df -m -P -x nfs -x nfs4 -x fuse.sshfs -x fuse -x vfat -x ntfs -x ntfs-3g -x vmhgfs -x smbfs -x smb -x cifs -x afs -x gfs -x ocfs -x ocfs2 -x mvfs -x nsspool -x nssvol -x iso9660 | grep -vE \"none|Filesystem|/dev/shm\" | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -nr | awk '{print $NF;}' | while read x ; do test -w $x && echo $x && break ; done"));
2926#endif
2927
2928    if (tmp[0] != '/') {
2929        mr_asprintf(&sz, "%s", tmp);
2930        paranoid_free(tmp);
2931        mr_asprintf(&tmp, "/%s", sz);
2932        mr_free(sz);
2933    }
2934    if (!tmp[0]) {
2935        fatal_error("I couldn't figure out the tempdir!");
2936    }
2937    setup_tmpdir(tmp);
2938    log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir);
2939
2940    sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%d", tmp,
2941            (int) (random() % 32768));
2942    log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
2943
2944    mr_asprintf(&command, "rm -Rf %s/tmp.mondo.* %s/mondo.scratch.*", tmp, tmp);
2945    paranoid_free(tmp);
2946
2947    paranoid_system(command);
2948    mr_free(command);
2949}
2950
2951
2952
2953
2954
2955
2956/**
2957 * @addtogroup deviceGroup
2958 * @{
2959 */
2960/**
2961 * If we can read @p dev, set @p output to it.
2962 * If @p dev cannot be read, set @p output to "".
2963 * @param dev The device to check for.
2964 * @param output Set to @p dev if @p dev exists, "" otherwise.
2965 * @return TRUE if @p dev exists, FALSE if it doesn't.
2966 */
2967bool set_dev_to_this_if_rx_OK(char *output, char *dev)
2968{
2969    char *command;
2970
2971    malloc_string(command);
2972    if (!dev || dev[0] == '\0') {
2973        output[0] = '\0';
2974        return (FALSE);
2975    }
2976//  assert_string_is_neither_NULL_nor_zerolength(dev);
2977    log_msg(10, "Injecting %s", dev);
2978    inject_device(dev);
2979    if (!does_file_exist(dev)) {
2980        log_msg(10, "%s doesn't exist. Returning FALSE.", dev);
2981        return (FALSE);
2982    }
2983    sprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null",
2984            512L, dev);
2985    if (!run_program_and_log_output(command, FALSE)
2986        && !run_program_and_log_output(command, FALSE)) {
2987        strcpy(output, dev);
2988        log_msg(4, "Found it - %s", dev);
2989        return (TRUE);
2990    } else {
2991        output[0] = '\0';
2992        log_msg(4, "It's not %s", dev);
2993        return (FALSE);
2994    }
2995}
2996
2997
2998
2999
3000
3001/**
3002 * Find out what number CD is in the drive.
3003 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
3004 * @return The current CD number, or -1 if it could not be found.
3005 * @note If the CD is not mounted, it will be mounted
3006 * (and remain mounted after this function returns).
3007 */
3008int what_number_cd_is_this()
3009{
3010    int cd_number = -1;
3011    char *mountdev = NULL;
3012    char *tmp = NULL;
3013
3014    assert(bkpinfo != NULL);
3015//  log_it("Asking what_number_cd_is_this");
3016    if (g_ISO_restore_mode) {
3017        mr_asprintf(&tmp, "mount | grep iso9660 | awk '{print $3;}'");
3018
3019        mr_asprintf(&mountdev, "%s%s", call_program_and_get_last_line_of_output(tmp), "/archives/THIS-CD-NUMBER");
3020        cd_number = atoi(last_line_of_file(mountdev));
3021        paranoid_free(mountdev);
3022        paranoid_free(tmp);
3023
3024        return (cd_number);
3025    }
3026
3027    mr_asprintf(&mountdev, "%s", bkpinfo->media_device);
3028    if (!mountdev[0]) {
3029        log_it
3030            ("(what_number_cd_is_this) Warning - media_device unknown. Finding out...");
3031        find_cdrom_device(bkpinfo->media_device, FALSE);
3032    }
3033    if (!is_this_device_mounted(MNT_CDROM)) {
3034        if (bkpinfo->backup_media_type == usb) {
3035            mount_USB_here(mountdev, MNT_CDROM);
3036        } else {
3037            mount_CDROM_here(mountdev, MNT_CDROM);
3038        }
3039    }
3040    paranoid_free(mountdev);
3041
3042    cd_number = atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
3043    return (cd_number);
3044}
3045
3046
3047
3048
3049
3050
3051
3052/**
3053 * Find out what device is mounted as root (/).
3054 * @return Root device.
3055 * @note The returned string points to static storage and will be overwritten with every call.
3056 * @bug A bit of a misnomer; it's actually finding out the root device.
3057 * The mountpoint (where it's mounted) will obviously be '/'.
3058 */
3059char *where_is_root_mounted()
3060{
3061    /*@ buffers **************** */
3062    static char tmp[MAX_STR_LEN];
3063
3064
3065#ifdef __FreeBSD__
3066    strcpy(tmp, call_program_and_get_last_line_of_output
3067           ("mount | grep \" on / \" | cut -d' ' -f1"));
3068#else
3069    strcpy(tmp, call_program_and_get_last_line_of_output
3070           ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"));
3071    if (strstr(tmp, "/dev/cciss/")) {
3072        strcpy(tmp, call_program_and_get_last_line_of_output
3073               ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"));
3074    }
3075    if (strstr(tmp, "/dev/md")) {
3076        strcpy(tmp,
3077               call_program_and_get_last_line_of_output
3078               ("mount | grep \" on / \" | cut -d' ' -f1"));
3079    }
3080#endif
3081
3082    return (tmp);
3083}
3084
3085
3086/**
3087 * Find out which boot loader is in use.
3088 * @param which_device Device to look for the boot loader on.
3089 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
3090 * @note Under Linux, all drives are examined, not just @p which_device.
3091 */
3092#ifdef __FreeBSD__
3093char which_boot_loader(char *which_device)
3094{
3095    int count_lilos = 0;
3096    int count_grubs = 0;
3097    int count_boot0s = 0;
3098    int count_dangerouslydedicated = 0;
3099
3100    log_it("looking at drive %s's MBR", which_device);
3101    if (does_string_exist_in_boot_block(which_device, "GRUB")) {
3102        count_grubs++;
3103    }
3104    if (does_string_exist_in_boot_block(which_device, "LILO")) {
3105        count_lilos++;
3106    }
3107    if (does_string_exist_in_boot_block(which_device, "Drive")) {
3108        count_boot0s++;
3109    }
3110    if (does_string_exist_in_first_N_blocks
3111        (which_device, "FreeBSD/i386", 17)) {
3112        count_dangerouslydedicated++;
3113    }
3114    log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
3115           count_grubs, count_lilos, count_elilos, count_boot0s,
3116           count_dangerouslydedicated);
3117
3118    if (count_grubs && !count_lilos) {
3119        return ('G');
3120    } else if (count_lilos && !count_grubs) {
3121        return ('L');
3122    } else if (count_grubs == 1 && count_lilos == 1) {
3123        log_it("I'll bet you used to use LILO but switched to GRUB...");
3124        return ('G');
3125    } else if (count_boot0s == 1) {
3126        return ('B');
3127    } else if (count_dangerouslydedicated) {
3128        return ('D');
3129    } else {
3130        log_it("Unknown boot loader");
3131        return ('U');
3132    }
3133}
3134
3135#else
3136
3137char which_boot_loader(char *which_device)
3138{
3139    /*@ buffer ***************************************************** */
3140    char *list_drives_cmd = NULL;
3141    char *current_drive;
3142
3143    /*@ pointers *************************************************** */
3144    FILE *pdrives;
3145
3146    /*@ int ******************************************************** */
3147    int count_lilos = 0;
3148    int count_grubs = 0;
3149
3150    /*@ end vars *************************************************** */
3151
3152    malloc_string(current_drive);
3153
3154#ifdef __IA64__
3155    /* No choice for it */
3156    return ('E');
3157#endif
3158    assert(which_device != NULL);
3159
3160    mr_asprintf(&list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s", where_is_root_mounted());
3161    log_it("list_drives_cmd = %s", list_drives_cmd);
3162
3163    if (!(pdrives = popen(list_drives_cmd, "r"))) {
3164        log_OS_error("Unable to open list of drives");
3165        mr_free(list_drives_cmd);
3166        paranoid_free(current_drive);
3167        return ('\0');
3168    }
3169    mr_free(list_drives_cmd);
3170
3171    for ((void)fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
3172         (void)fgets(current_drive, MAX_STR_LEN, pdrives)) {
3173        strip_spaces(current_drive);
3174        log_it("looking at drive %s's MBR", current_drive);
3175        if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
3176            count_grubs++;
3177            strcpy(which_device, current_drive);
3178            break;
3179        }
3180        if (does_string_exist_in_boot_block(current_drive, "LILO")) {
3181            count_lilos++;
3182            strcpy(which_device, current_drive);
3183            break;
3184        }
3185    }
3186    if (pclose(pdrives)) {
3187        log_OS_error("Cannot pclose pdrives");
3188    }
3189    log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
3190    if (count_grubs && !count_lilos) {
3191        paranoid_free(current_drive);
3192        return ('G');
3193    } else if (count_lilos && !count_grubs) {
3194        paranoid_free(current_drive);
3195        return ('L');
3196    } else if (count_grubs == 1 && count_lilos == 1) {
3197        log_it("I'll bet you used to use LILO but switched to GRUB...");
3198        paranoid_free(current_drive);
3199        return ('G');
3200    } else {
3201        // We need to look on each partition then
3202        mr_asprintf(&list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep -E \"^/dev/\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/");
3203        log_it("list_drives_cmd = %s", list_drives_cmd);
3204
3205        if (!(pdrives = popen(list_drives_cmd, "r"))) {
3206            log_OS_error("Unable to open list of drives");
3207            mr_free(list_drives_cmd);
3208            paranoid_free(current_drive);
3209            return ('\0');
3210        }
3211        mr_free(list_drives_cmd);
3212
3213        for ((void)fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
3214            (void)fgets(current_drive, MAX_STR_LEN, pdrives)) {
3215            strip_spaces(current_drive);
3216            log_it("looking at partition %s's BR", current_drive);
3217            if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
3218                count_grubs++;
3219                strcpy(which_device, current_drive);
3220                break;
3221            }
3222            if (does_string_exist_in_boot_block(current_drive, "LILO")) {
3223                count_lilos++;
3224                strcpy(which_device, current_drive);
3225                break;
3226            }
3227        }
3228        if (pclose(pdrives)) {
3229            log_OS_error("Cannot pclose pdrives");
3230        }
3231        log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
3232        paranoid_free(current_drive);
3233        if (count_grubs && !count_lilos) {
3234            return ('G');
3235        } else if (count_lilos && !count_grubs) {
3236            return ('L');
3237        } else if (count_grubs == 1 && count_lilos == 1) {
3238            log_it("I'll bet you used to use LILO but switched to GRUB...");
3239            return ('G');
3240        } else {
3241            log_it("Unknown boot loader");
3242            return ('U');
3243        }
3244    }
3245}
3246#endif
3247
3248
3249
3250
3251/**
3252 * Write zeroes over the first 16K of @p device.
3253 * @param device The device to zero.
3254 * @return 0 for success, 1 for failure.
3255 */
3256int zero_out_a_device(char *device)
3257{
3258    FILE *fout;
3259    int i;
3260
3261    assert_string_is_neither_NULL_nor_zerolength(device);
3262
3263    log_it("Zeroing drive %s", device);
3264    if (!(fout = fopen(device, "w"))) {
3265        log_OS_error("Unable to open/write to device");
3266        return (1);
3267    }
3268    for (i = 0; i < 16384; i++) {
3269        fputc('\0', fout);
3270    }
3271    paranoid_fclose(fout);
3272    log_it("Device successfully zeroed.");
3273    return (0);
3274}
3275
3276/**
3277 * Return the device pointed to by @p incoming.
3278 * @param incoming The device to resolve symlinks for.
3279 * @return The path to the real device file.
3280 * @note The returned string points to static storage that will be overwritten with each call.
3281 * @bug Won't work with file v4.0; needs to be written in C.
3282 */
3283char *resolve_softlinks_to_get_to_actual_device_file(char *incoming)
3284{
3285    static char output[MAX_STR_LEN];
3286    char *command;
3287    char *curr_fname;
3288    char *scratch = NULL;
3289    char *tmp = NULL;
3290    char *p;
3291
3292    struct stat statbuf;
3293    command = malloc(1000);
3294    malloc_string(curr_fname);
3295    if (!does_file_exist(incoming)) {
3296        log_it
3297            ("resolve_softlinks_to_get_to_actual_device_file --- device not found");
3298        strcpy(output, incoming);
3299    } else {
3300        strcpy(curr_fname, incoming);
3301        lstat(curr_fname, &statbuf);
3302        while (S_ISLNK(statbuf.st_mode)) {
3303            log_msg(1, "curr_fname = %s", curr_fname);
3304            sprintf(command, "file %s", curr_fname);
3305            mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
3306            for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' ';
3307                 p--);
3308            p++;
3309            mr_asprintf(&scratch, "%s", p);
3310            for (p = scratch; *p != '\0' && *p != '\''; p++);
3311            *p = '\0';
3312            log_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp, scratch);
3313            mr_free(tmp);
3314
3315            if (scratch[0] == '/') {
3316                strcpy(curr_fname, scratch);    // copy whole thing because it's an absolute softlink
3317            } else {            // copy over the basename cos it's a relative softlink
3318                p = curr_fname + strlen(curr_fname);
3319                while (p != curr_fname && *p != '/') {
3320                    p--;
3321                }
3322                if (*p == '/') {
3323                    p++;
3324                }
3325                strcpy(p, scratch);
3326            }
3327            mr_free(scratch);
3328            lstat(curr_fname, &statbuf);
3329        }
3330        strcpy(output, curr_fname);
3331        log_it("resolved %s to %s", incoming, output);
3332    }
3333    paranoid_free(command);
3334    paranoid_free(curr_fname);
3335    return (output);
3336}
3337
3338/* @} - end of deviceGroup */
3339
3340/**
3341 * Return the type of partition format (GPT or MBR)
3342 */
3343char *which_partition_format(const char *drive)
3344{
3345    static char output[4];
3346    char *tmp = NULL;
3347    char *command;
3348    char *fdisk;
3349#ifdef __IA64__
3350    struct stat buf;
3351#endif
3352    malloc_string(command);
3353    malloc_string(fdisk);
3354    sprintf(fdisk, "/sbin/parted2fdisk");
3355    sprintf(command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
3356    mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
3357    if (strstr(tmp, "GPT") == NULL) {
3358        strcpy(output, "MBR");
3359    } else {
3360        strcpy(output, "GPT");
3361    }
3362    mr_free(tmp);
3363
3364    log_msg(0, "Found %s partition table format type", output);
3365    paranoid_free(command);
3366    paranoid_free(fdisk);
3367    return (output);
3368}
3369/* @} - end of deviceGroup */
Note: See TracBrowser for help on using the repository browser.