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

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

fix linker errors
begining of rewrite for libmondo-devices.c

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