source: branches/3.0/mondo/src/common/libmondo-devices.c @ 2934

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