source: MondoRescue/branches/2.2.8/mondo/src/common/libmondo-devices.c @ 2046

Last change on this file since 2046 was 1988, checked in by Bruno Cornec, 13 years ago

Fix for #261 nsspool and nssvol support (thanks sprobst for report and proposal of ptch)

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