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

Last change on this file since 1075 was 1075, checked in by bruno, 13 years ago

Improvements for USB support in mindi when called from mondo
Changelogs in C files removed from common

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