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

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

Fix a linker error

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