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

Last change on this file since 2050 was 2050, checked in by Bruno Cornec, 12 years ago
  • Do not try to create the dummy file on the NFS share when in DR mode as now the NFS share is mounted ro !
  • Property svn:keywords set to Id
File size: 76.0 KB
Line 
1/* libmondo-devices.c                 Subroutines for handling devices
2   $Id: libmondo-devices.c 2050 2008-10-23 12:38:39Z 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 2050 2008-10-23 12:38:39Z 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        if (! bkpinfo->disaster_recovery) {
2013            asprintf(&tmp1,"%s/%s/.dummy.txt", bkpinfo->isodir,bkpinfo->nfs_remote_dir);
2014            sprintf(command, "echo hi > %s", tmp1);
2015            while (run_program_and_log_output(command, FALSE)) {
2016                strcpy(tmp, bkpinfo->nfs_remote_dir);
2017                sprintf(prompt,
2018                    "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.",
2019                    bkpinfo->nfs_remote_dir, bkpinfo->isodir);
2020                if (!popup_and_get_string
2021                    ("Directory", prompt, tmp, MAX_STR_LEN)) {
2022                    log_to_screen("User has chosen not to backup the PC");
2023                    finish(1);
2024                }
2025                strcpy(bkpinfo->nfs_remote_dir, tmp);
2026                // check whether writable - we better remove surrounding space s for this
2027                strip_spaces(bkpinfo->nfs_remote_dir);
2028                paranoid_free(tmp1);
2029                asprintf(&tmp1,"%s/%s/.dummy.txt", bkpinfo->isodir,bkpinfo->nfs_remote_dir);
2030                sprintf(command, "echo hi > %s", tmp1);
2031            }
2032            unlink(tmp1);
2033            paranoid_free(tmp1);
2034        }
2035
2036        if (!popup_and_get_string
2037            ("Prefix.",
2038             "Please enter the prefix that will be prepended to your ISO filename.  Example: machine1 to obtain machine1-[1-9]*.iso files",
2039            bkpinfo->prefix, MAX_STR_LEN / 4)) {
2040            log_to_screen("User has chosen not to backup the PC");
2041            finish(1);
2042        }
2043        log_msg(3, "prefix set to %s", bkpinfo->prefix);
2044
2045        for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2046            bkpinfo->media_size[i] = 650;
2047        }
2048        log_msg(3, "Just set nfs_remote_dir to %s",
2049                bkpinfo->nfs_remote_dir);
2050        log_msg(3, "isodir is still %s", bkpinfo->isodir);
2051        break;
2052
2053    case iso:
2054        if (!bkpinfo->disaster_recovery) {
2055            if (!popup_and_get_string
2056                ("Storage dir.",
2057                 "Please enter the full path name to the directory for your ISO images.  Example: /mnt/raid0_0",
2058                 bkpinfo->isodir, MAX_STR_LEN / 4)) {
2059                log_to_screen("User has chosen not to backup the PC");
2060                finish(1);
2061            }
2062            if (archiving_to_media) {
2063                if ((bkpinfo->compression_level =
2064                     which_compression_level()) == -1) {
2065                    log_to_screen("User has chosen not to backup the PC");
2066                    finish(1);
2067                }
2068                if (!popup_and_get_string
2069                    ("ISO size.",
2070                     "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.",
2071                     sz_size, 16)) {
2072                    log_to_screen("User has chosen not to backup the PC");
2073                    finish(1);
2074                }
2075                for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2076                    bkpinfo->media_size[i] = atoi(sz_size);
2077                }
2078            } else {
2079                for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2080                    bkpinfo->media_size[i] = 650;
2081                }
2082            }
2083        }
2084        if (!popup_and_get_string
2085            ("Prefix.",
2086             "Please enter the prefix that will be prepended to your ISO filename.  Example: machine1 to obtain machine1-[1-9]*.iso files",
2087             bkpinfo->prefix, MAX_STR_LEN / 4)) {
2088            log_to_screen("User has chosen not to backup the PC");
2089            finish(1);
2090        }
2091        log_msg(3, "prefix set to %s", bkpinfo->prefix);
2092        break;
2093    default:
2094        fatal_error
2095            ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
2096    }
2097
2098    if (archiving_to_media) {
2099
2100#ifdef __FreeBSD__
2101        strcpy(bkpinfo->boot_device,
2102               call_program_and_get_last_line_of_output
2103               ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
2104#else
2105        strcpy(bkpinfo->boot_device,
2106               call_program_and_get_last_line_of_output
2107               ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
2108#endif
2109        i = which_boot_loader(bkpinfo->boot_device);
2110        if (i == 'U')           // unknown
2111        {
2112
2113#ifdef __FreeBSD__
2114            if (!popup_and_get_string
2115                ("Boot device",
2116                 "What is your boot device? (e.g. /dev/ad0)",
2117                 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2118                log_to_screen("User has chosen not to backup the PC");
2119                finish(1);
2120            }
2121            i = which_boot_loader(bkpinfo->boot_device);
2122#else
2123            if (!popup_and_get_string
2124                ("Boot device",
2125                 "What is your boot device? (e.g. /dev/hda)",
2126                 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2127                log_to_screen("User has chosen not to backup the PC");
2128                finish(1);
2129            }
2130            if (does_string_exist_in_boot_block
2131                (bkpinfo->boot_device, "LILO")) {
2132                i = 'L';
2133            } else
2134                if (does_string_exist_in_boot_block
2135                    (bkpinfo->boot_device, "ELILO")) {
2136                i = 'E';
2137            } else
2138                if (does_string_exist_in_boot_block
2139                    (bkpinfo->boot_device, "GRUB")) {
2140                i = 'G';
2141            } else {
2142                i = 'U';
2143            }
2144#endif
2145            if (i == 'U') {
2146                if (ask_me_yes_or_no
2147                    ("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?"))
2148                {
2149                    i = 'R';    // raw
2150                } else {
2151                    log_to_screen
2152                        ("I cannot find your boot loader. Please run mondoarchive with parameters.");
2153                    finish(1);
2154                }
2155            }
2156        }
2157        bkpinfo->boot_loader = i;
2158        strcpy(bkpinfo->include_paths, "/");
2159        if (!popup_and_get_string
2160            ("Backup paths",
2161             "Please enter paths which you want me to backup. The default is '/' (i.e. everything).",
2162             bkpinfo->include_paths, MAX_STR_LEN)) {
2163            log_to_screen("User has chosen not to backup the PC");
2164            finish(1);
2165        }
2166        strcpy(tmp, list_of_NFS_mounts_only());
2167        if (strlen(tmp) > 2) {
2168            if (bkpinfo->exclude_paths[0]) {
2169                strcat(bkpinfo->exclude_paths, " ");
2170            }
2171            strncpy(bkpinfo->exclude_paths, tmp, MAX_STR_LEN);
2172        }
2173// NTFS
2174        strcpy(tmp,
2175               call_program_and_get_last_line_of_output
2176               ("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'"));
2177        if (strlen(tmp) > 2) {
2178            if (!popup_and_get_string
2179                ("NTFS partitions",
2180                 "Please enter/confirm the NTFS partitions you wish to backup as well.",
2181                 tmp, MAX_STR_LEN / 4)) {
2182                log_to_screen("User has chosen not to backup the PC");
2183                finish(1);
2184            }
2185            strncpy(bkpinfo->image_devs, tmp, MAX_STR_LEN / 4);
2186        }
2187
2188
2189        if (!popup_and_get_string
2190            ("Exclude paths",
2191             "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.",
2192             bkpinfo->exclude_paths, (4*MAX_STR_LEN)-1)) {
2193            log_to_screen("User has chosen not to backup the PC");
2194            finish(1);
2195        }
2196// Interactive mode:
2197#ifdef __IA64__
2198        bkpinfo->make_cd_use_lilo = TRUE;
2199#else
2200        bkpinfo->make_cd_use_lilo = FALSE;
2201#endif
2202        bkpinfo->backup_data = TRUE;
2203        bkpinfo->verify_data =
2204            ask_me_yes_or_no
2205            ("Will you want to verify your backups after Mondo has created them?");
2206
2207#ifndef __FreeBSD__
2208        if (!ask_me_yes_or_no
2209            ("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."))
2210#endif
2211        {
2212            strcpy(bkpinfo->kernel_path, "FAILSAFE");
2213        }
2214
2215        if (!ask_me_yes_or_no
2216            ("Are you sure you want to proceed? Hit 'no' to abort.")) {
2217            log_to_screen("User has chosen not to backup the PC");
2218            finish(1);
2219        }
2220    } else {
2221        bkpinfo->restore_data = TRUE;   // probably...
2222    }
2223
2224    if (bkpinfo->backup_media_type == iso
2225        || bkpinfo->backup_media_type == nfs) {
2226        g_ISO_restore_mode = TRUE;
2227    }
2228#ifdef __FreeSD__
2229// skip
2230#else
2231    if (bkpinfo->backup_media_type == nfs) {
2232        sprintf(tmp, "mount | grep \"%s\" | cut -d' ' -f3",
2233                bkpinfo->nfs_mount);
2234//      strcpy(bkpinfo->isodir, call_program_and_get_last_line_of_output(tmp));
2235        log_msg(3, "I think the NFS mount is mounted at %s",
2236                bkpinfo->isodir);
2237    }
2238    log_it("isodir = %s", bkpinfo->isodir);
2239    log_it("nfs_mount = '%s'", bkpinfo->nfs_mount);
2240#endif
2241
2242    log_it("media device = %s", bkpinfo->media_device);
2243    log_it("media size = %ld", bkpinfo->media_size[1]);
2244    log_it("media type = %s",
2245           bkptype_to_string(bkpinfo->backup_media_type));
2246    log_it("prefix = %s", bkpinfo->prefix);
2247    log_it("compression = %ld", bkpinfo->compression_level);
2248    log_it("include_paths = '%s'", bkpinfo->include_paths);
2249    log_it("exclude_paths = '%s'", bkpinfo->exclude_paths);
2250    log_it("scratchdir = '%s'", bkpinfo->scratchdir);
2251    log_it("tmpdir = '%s'", bkpinfo->tmpdir);
2252    log_it("image_devs = '%s'", bkpinfo->image_devs);
2253    log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device,
2254           bkpinfo->boot_loader);
2255    if (bkpinfo->media_size[0] < 0) {
2256        if (archiving_to_media) {
2257            fatal_error("Media size is less than zero.");
2258        } else {
2259            log_msg(2, "Warning - media size is less than zero.");
2260            bkpinfo->media_size[0] = 0;
2261        }
2262    }
2263    paranoid_free(tmp);
2264    paranoid_free(sz_size);
2265    paranoid_free(command);
2266    paranoid_free(comment);
2267    paranoid_free(prompt);
2268    return (0);
2269}
2270
2271
2272
2273
2274/**
2275 * @addtogroup utilityGroup
2276 * @{
2277 */
2278/**
2279 * Get a space-separated list of NFS devices and mounts.
2280 * @return The list created.
2281 * @note The return value points to static data that will be overwritten with each call.
2282 */
2283char *list_of_NFS_devices_and_mounts(void)
2284{
2285    char *exclude_these_devices;
2286    char *exclude_these_directories;
2287    static char result_sz[512];
2288
2289    malloc_string(exclude_these_devices);
2290    malloc_string(exclude_these_directories);
2291    strcpy(exclude_these_directories,
2292           call_program_and_get_last_line_of_output
2293           ("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;}'"));
2294    strcpy(exclude_these_devices,
2295           call_program_and_get_last_line_of_output
2296           ("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;}'"));
2297    sprintf(result_sz, "%s %s", exclude_these_directories,
2298            exclude_these_devices);
2299    paranoid_free(exclude_these_devices);
2300    paranoid_free(exclude_these_directories);
2301    return (result_sz);
2302}
2303
2304
2305
2306
2307/**
2308 * Get a space-separated list of NFS mounts.
2309 * @return The list created.
2310 * @note The return value points to static data that will be overwritten with each call.
2311 * @bug Even though we only want the mounts, the devices are still checked.
2312 */
2313char *list_of_NFS_mounts_only(void)
2314{
2315    char *exclude_these_devices;
2316    char *exclude_these_directories;
2317    static char result_sz[512];
2318
2319    malloc_string(exclude_these_devices);
2320    malloc_string(exclude_these_directories);
2321    strcpy(exclude_these_directories,
2322           call_program_and_get_last_line_of_output
2323           ("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;}'"));
2324    strcpy(exclude_these_devices,
2325           call_program_and_get_last_line_of_output
2326           ("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;}'"));
2327    sprintf(result_sz, "%s", exclude_these_directories);
2328    paranoid_free(exclude_these_devices);
2329    paranoid_free(exclude_these_directories);
2330    return (result_sz);
2331}
2332
2333/* @} - end of utilityGroup */
2334
2335
2336
2337
2338
2339/**
2340 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
2341 * [random] is a random number between 1 and 32767.
2342 * @param store_name_here Where to store the new filename.
2343 * @param stub A random number will be appended to this to make the FIFO's name.
2344 * @ingroup deviceGroup
2345 */
2346void make_fifo(char *store_name_here, char *stub)
2347{
2348    char *tmp;
2349
2350    malloc_string(tmp);
2351    assert_string_is_neither_NULL_nor_zerolength(stub);
2352
2353    sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
2354            (int) (random() % 32768));
2355    make_hole_for_file(store_name_here);
2356    mkfifo(store_name_here, S_IRWXU | S_IRWXG);
2357    sprintf(tmp, "chmod 770 %s", store_name_here);
2358    paranoid_system(tmp);
2359    paranoid_free(tmp);
2360}
2361
2362
2363
2364
2365
2366
2367/**
2368 * Set the tmpdir and scratchdir to reside on the partition with the most free space.
2369 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
2370 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set.
2371 * @ingroup utilityGroup
2372 */
2373void sensibly_set_tmpdir_and_scratchdir()
2374{
2375    char *tmp, *command, *sz;
2376
2377    malloc_string(tmp);
2378    malloc_string(command);
2379    malloc_string(sz);
2380    assert(bkpinfo != NULL);
2381
2382#ifdef __FreeBSD__
2383    strcpy(tmp,
2384           call_program_and_get_last_line_of_output
2385           ("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;}'"));
2386#else
2387    strcpy(tmp,
2388           call_program_and_get_last_line_of_output
2389           ("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;}'"));
2390#endif
2391
2392    if (tmp[0] != '/') {
2393        strcpy(sz, tmp);
2394        strcpy(tmp, "/");
2395        strcat(tmp, sz);
2396    }
2397    if (!tmp[0]) {
2398        fatal_error("I couldn't figure out the tempdir!");
2399    }
2400    setup_tmpdir(tmp);
2401    log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir);
2402
2403    sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%d", tmp,
2404            (int) (random() % 32768));
2405    log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
2406
2407    sprintf(command, "rm -Rf %s/tmp.mondo.* %s/mondo.scratch.*", tmp, tmp);
2408    paranoid_system(command);
2409    paranoid_free(tmp);
2410    paranoid_free(command);
2411    paranoid_free(sz);
2412}
2413
2414
2415
2416
2417
2418
2419/**
2420 * @addtogroup deviceGroup
2421 * @{
2422 */
2423/**
2424 * If we can read @p dev, set @p output to it.
2425 * If @p dev cannot be read, set @p output to "".
2426 * @param dev The device to check for.
2427 * @param output Set to @p dev if @p dev exists, "" otherwise.
2428 * @return TRUE if @p dev exists, FALSE if it doesn't.
2429 */
2430bool set_dev_to_this_if_rx_OK(char *output, char *dev)
2431{
2432    char *command;
2433
2434    malloc_string(command);
2435    if (!dev || dev[0] == '\0') {
2436        output[0] = '\0';
2437        return (FALSE);
2438    }
2439//  assert_string_is_neither_NULL_nor_zerolength(dev);
2440    log_msg(10, "Injecting %s", dev);
2441    inject_device(dev);
2442    if (!does_file_exist(dev)) {
2443        log_msg(10, "%s doesn't exist. Returning FALSE.", dev);
2444        return (FALSE);
2445    }
2446    sprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null",
2447            512L, dev);
2448    if (!run_program_and_log_output(command, FALSE)
2449        && !run_program_and_log_output(command, FALSE)) {
2450        strcpy(output, dev);
2451        log_msg(4, "Found it - %s", dev);
2452        return (TRUE);
2453    } else {
2454        output[0] = '\0';
2455        log_msg(4, "It's not %s", dev);
2456        return (FALSE);
2457    }
2458}
2459
2460
2461
2462
2463
2464/**
2465 * Find out what number CD is in the drive.
2466 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
2467 * @return The current CD number, or -1 if it could not be found.
2468 * @note If the CD is not mounted, it will be mounted
2469 * (and remain mounted after this function returns).
2470 */
2471int what_number_cd_is_this()
2472{
2473    int cd_number = -1;
2474    char *mountdev;
2475    char *tmp;
2476
2477    malloc_string(mountdev);
2478    malloc_string(tmp);
2479    assert(bkpinfo != NULL);
2480//  log_it("Asking what_number_cd_is_this");
2481    if (g_ISO_restore_mode) {
2482        sprintf(tmp, "mount | grep iso9660 | awk '{print $3;}'");
2483//      log_it("tmp = %s", tmp);
2484
2485        strcpy(mountdev, call_program_and_get_last_line_of_output(tmp));
2486        strcat(mountdev, "/archives/THIS-CD-NUMBER");
2487//      log_it("mountdev = %s", mountdev);
2488        cd_number = atoi(last_line_of_file(mountdev));
2489//      log_it("cd_number = %d", cd_number);
2490        paranoid_free(mountdev);
2491        paranoid_free(tmp);
2492        return (cd_number);
2493    }
2494
2495    strcpy(mountdev, bkpinfo->media_device);
2496    if (!mountdev[0]) {
2497        log_it
2498            ("(what_number_cd_is_this) Warning - media_device unknown. Finding out...");
2499        find_cdrom_device(bkpinfo->media_device, FALSE);
2500    }
2501    if (!is_this_device_mounted(MNT_CDROM)) {
2502        if (bkpinfo->backup_media_type == usb) {
2503            mount_USB_here(mountdev, MNT_CDROM);
2504        } else {
2505            mount_CDROM_here(mountdev, MNT_CDROM);
2506        }
2507    }
2508    cd_number =
2509        atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
2510//  log_it("cd_number..later.. = %d", cd_number);
2511    paranoid_free(mountdev);
2512    paranoid_free(tmp);
2513    return (cd_number);
2514}
2515
2516
2517
2518
2519
2520
2521
2522/**
2523 * Find out what device is mounted as root (/).
2524 * @return Root device.
2525 * @note The returned string points to static storage and will be overwritten with every call.
2526 * @bug A bit of a misnomer; it's actually finding out the root device.
2527 * The mountpoint (where it's mounted) will obviously be '/'.
2528 */
2529char *where_is_root_mounted()
2530{
2531    /*@ buffers **************** */
2532    static char tmp[MAX_STR_LEN];
2533
2534
2535#ifdef __FreeBSD__
2536    strcpy(tmp, call_program_and_get_last_line_of_output
2537           ("mount | grep \" on / \" | cut -d' ' -f1"));
2538#else
2539    strcpy(tmp, call_program_and_get_last_line_of_output
2540           ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"));
2541    if (strstr(tmp, "/dev/cciss/")) {
2542        strcpy(tmp, call_program_and_get_last_line_of_output
2543               ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"));
2544    }
2545    if (strstr(tmp, "/dev/md")) {
2546        strcpy(tmp,
2547               call_program_and_get_last_line_of_output
2548               ("mount | grep \" on / \" | cut -d' ' -f1"));
2549    }
2550#endif
2551
2552    return (tmp);
2553}
2554
2555
2556/**
2557 * Find out which boot loader is in use.
2558 * @param which_device Device to look for the boot loader on.
2559 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
2560 * @note Under Linux, all drives are examined, not just @p which_device.
2561 */
2562#ifdef __FreeBSD__
2563char which_boot_loader(char *which_device)
2564{
2565    int count_lilos = 0;
2566    int count_grubs = 0;
2567    int count_boot0s = 0;
2568    int count_dangerouslydedicated = 0;
2569
2570    log_it("looking at drive %s's MBR", which_device);
2571    if (does_string_exist_in_boot_block(which_device, "GRUB")) {
2572        count_grubs++;
2573    }
2574    if (does_string_exist_in_boot_block(which_device, "LILO")) {
2575        count_lilos++;
2576    }
2577    if (does_string_exist_in_boot_block(which_device, "Drive")) {
2578        count_boot0s++;
2579    }
2580    if (does_string_exist_in_first_N_blocks
2581        (which_device, "FreeBSD/i386", 17)) {
2582        count_dangerouslydedicated++;
2583    }
2584    log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
2585           count_grubs, count_lilos, count_elilos, count_boot0s,
2586           count_dangerouslydedicated);
2587
2588    if (count_grubs && !count_lilos) {
2589        return ('G');
2590    } else if (count_lilos && !count_grubs) {
2591        return ('L');
2592    } else if (count_grubs == 1 && count_lilos == 1) {
2593        log_it("I'll bet you used to use LILO but switched to GRUB...");
2594        return ('G');
2595    } else if (count_boot0s == 1) {
2596        return ('B');
2597    } else if (count_dangerouslydedicated) {
2598        return ('D');
2599    } else {
2600        log_it("Unknown boot loader");
2601        return ('U');
2602    }
2603}
2604
2605#else
2606
2607char which_boot_loader(char *which_device)
2608{
2609    /*@ buffer ***************************************************** */
2610    char *list_drives_cmd;
2611    char *current_drive;
2612
2613    /*@ pointers *************************************************** */
2614    FILE *pdrives;
2615
2616    /*@ int ******************************************************** */
2617    int count_lilos = 0;
2618    int count_grubs = 0;
2619
2620    /*@ end vars *************************************************** */
2621
2622    malloc_string(list_drives_cmd);
2623    malloc_string(current_drive);
2624
2625#ifdef __IA64__
2626    /* No choice for it */
2627    return ('E');
2628#endif
2629    assert(which_device != NULL);
2630    //  sprintf (list_drives_cmd,
2631    //       "fdisk -l | grep /dev | grep cyl | tr ':' ' ' | cut -d' ' -f2");
2632
2633    sprintf(list_drives_cmd,
2634            "parted2fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s",
2635            where_is_root_mounted());
2636    log_it("list_drives_cmd = %s", list_drives_cmd);
2637
2638    if (!(pdrives = popen(list_drives_cmd, "r"))) {
2639        log_OS_error("Unable to open list of drives");
2640        paranoid_free(list_drives_cmd);
2641        paranoid_free(current_drive);
2642        return ('\0');
2643    }
2644    for (fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
2645         fgets(current_drive, MAX_STR_LEN, pdrives)) {
2646        strip_spaces(current_drive);
2647        log_it("looking at drive %s's MBR", current_drive);
2648        if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
2649            count_grubs++;
2650            strcpy(which_device, current_drive);
2651            break;
2652        }
2653        if (does_string_exist_in_boot_block(current_drive, "LILO")) {
2654            count_lilos++;
2655            strcpy(which_device, current_drive);
2656            break;
2657        }
2658    }
2659    if (pclose(pdrives)) {
2660        log_OS_error("Cannot pclose pdrives");
2661    }
2662    log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
2663    if (count_grubs && !count_lilos) {
2664        return ('G');
2665    } else if (count_lilos && !count_grubs) {
2666        return ('L');
2667    } else if (count_grubs == 1 && count_lilos == 1) {
2668        log_it("I'll bet you used to use LILO but switched to GRUB...");
2669        return ('G');
2670    } else {
2671        // We need to look on each partition then
2672        sprintf(list_drives_cmd,
2673            "parted2fdisk -l 2>/dev/null | grep -E \"^/dev/\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/");
2674        log_it("list_drives_cmd = %s", list_drives_cmd);
2675
2676        if (!(pdrives = popen(list_drives_cmd, "r"))) {
2677            log_OS_error("Unable to open list of drives");
2678            paranoid_free(list_drives_cmd);
2679            paranoid_free(current_drive);
2680            return ('\0');
2681        }
2682        for (fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
2683            fgets(current_drive, MAX_STR_LEN, pdrives)) {
2684            strip_spaces(current_drive);
2685            log_it("looking at partition %s's BR", current_drive);
2686            if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
2687                count_grubs++;
2688                strcpy(which_device, current_drive);
2689                break;
2690            }
2691            if (does_string_exist_in_boot_block(current_drive, "LILO")) {
2692                count_lilos++;
2693                strcpy(which_device, current_drive);
2694                break;
2695            }
2696        }
2697        if (pclose(pdrives)) {
2698            log_OS_error("Cannot pclose pdrives");
2699        }
2700        log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
2701        paranoid_free(list_drives_cmd);
2702        paranoid_free(current_drive);
2703        if (count_grubs && !count_lilos) {
2704            return ('G');
2705        } else if (count_lilos && !count_grubs) {
2706            return ('L');
2707        } else if (count_grubs == 1 && count_lilos == 1) {
2708            log_it("I'll bet you used to use LILO but switched to GRUB...");
2709            return ('G');
2710        } else {
2711            log_it("Unknown boot loader");
2712            return ('U');
2713        }
2714    }
2715}
2716#endif
2717
2718
2719
2720
2721/**
2722 * Write zeroes over the first 16K of @p device.
2723 * @param device The device to zero.
2724 * @return 0 for success, 1 for failure.
2725 */
2726int zero_out_a_device(char *device)
2727{
2728    FILE *fout;
2729    int i;
2730
2731    assert_string_is_neither_NULL_nor_zerolength(device);
2732
2733    log_it("Zeroing drive %s", device);
2734    if (!(fout = fopen(device, "w"))) {
2735        log_OS_error("Unable to open/write to device");
2736        return (1);
2737    }
2738    for (i = 0; i < 16384; i++) {
2739        fputc('\0', fout);
2740    }
2741    paranoid_fclose(fout);
2742    log_it("Device successfully zeroed.");
2743    return (0);
2744}
2745
2746/**
2747 * Return the device pointed to by @p incoming.
2748 * @param incoming The device to resolve symlinks for.
2749 * @return The path to the real device file.
2750 * @note The returned string points to static storage that will be overwritten with each call.
2751 * @bug Won't work with file v4.0; needs to be written in C.
2752 */
2753char *resolve_softlinks_to_get_to_actual_device_file(char *incoming)
2754{
2755    static char output[MAX_STR_LEN];
2756    char *command;
2757    char *curr_fname;
2758    char *scratch;
2759    char *tmp;
2760    char *p;
2761
2762    struct stat statbuf;
2763    command = malloc(1000);
2764    malloc_string(tmp);
2765    malloc_string(scratch);
2766    malloc_string(curr_fname);
2767    if (!does_file_exist(incoming)) {
2768        log_it
2769            ("resolve_softlinks_to_get_to_actual_device_file --- device not found");
2770        strcpy(output, incoming);
2771    } else {
2772        strcpy(curr_fname, incoming);
2773        lstat(curr_fname, &statbuf);
2774        while (S_ISLNK(statbuf.st_mode)) {
2775            log_msg(1, "curr_fname = %s", curr_fname);
2776            sprintf(command, "file %s", curr_fname);
2777            strcpy(tmp, call_program_and_get_last_line_of_output(command));
2778            for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' ';
2779                 p--);
2780            p++;
2781            strcpy(scratch, p);
2782            for (p = scratch; *p != '\0' && *p != '\''; p++);
2783            *p = '\0';
2784            log_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp,
2785                    scratch);
2786            if (scratch[0] == '/') {
2787                strcpy(curr_fname, scratch);    // copy whole thing because it's an absolute softlink
2788            } else {            // copy over the basename cos it's a relative softlink
2789                p = curr_fname + strlen(curr_fname);
2790                while (p != curr_fname && *p != '/') {
2791                    p--;
2792                }
2793                if (*p == '/') {
2794                    p++;
2795                }
2796                strcpy(p, scratch);
2797            }
2798            lstat(curr_fname, &statbuf);
2799        }
2800        strcpy(output, curr_fname);
2801        log_it("resolved %s to %s", incoming, output);
2802    }
2803    paranoid_free(command);
2804    paranoid_free(curr_fname);
2805    paranoid_free(tmp);
2806    return (output);
2807}
2808
2809/* @} - end of deviceGroup */
2810
2811
2812/**
2813 * Return the type of partition format (GPT or MBR)
2814 */
2815char *which_partition_format(const char *drive)
2816{
2817    static char output[4];
2818    char *tmp;
2819    char *command;
2820    char *fdisk;
2821#ifdef __IA64__
2822    struct stat buf;
2823#endif
2824    malloc_string(tmp);
2825    malloc_string(command);
2826    malloc_string(fdisk);
2827    log_msg(0, "Looking for partition table format type");
2828    sprintf(fdisk, "/sbin/parted2fdisk");
2829    log_msg(1, "Using %s", fdisk);
2830    sprintf(command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
2831    strcpy(tmp, call_program_and_get_last_line_of_output(command));
2832    if (strstr(tmp, "GPT") == NULL) {
2833        strcpy(output, "MBR");
2834    } else {
2835        strcpy(output, "GPT");
2836    }
2837    log_msg(0, "Found %s partition table format type", output);
2838    paranoid_free(command);
2839    paranoid_free(tmp);
2840    paranoid_free(fdisk);
2841    return (output);
2842}
2843
2844/* @} - end of deviceGroup */
Note: See TracBrowser for help on using the repository browser.