source: trunk/mondo/mondo/common/libmondo-devices.c @ 127

Last change on this file since 127 was 127, checked in by bcornec, 14 years ago

merge -r 125:126 $SVN_M/branches/2.05

  • Property svn:keywords set to Id
File size: 71.3 KB
Line 
1/* libmondo-devices.c                 Subroutines for handling devices
2   $Id: libmondo-devices.c 127 2005-11-19 01:27:31Z bcornec $
3*/
4
5/**
6 * @file
7 * Functions to handle interactions with backup devices.
8 */
9
10#include "my-stuff.h"
11#include "mondostructures.h"
12#include "libmondo-files-EXT.h"
13#include "libmondo-devices.h"
14#include "lib-common-externs.h"
15#include "libmondo-string-EXT.h"
16#include "libmondo-tools-EXT.h"
17#include "libmondo-gui-EXT.h"
18#include "libmondo-fork-EXT.h"
19#include "libmondo-stream-EXT.h"
20
21#include <sys/types.h>
22#ifdef __FreeBSD__
23#define DKTYPENAMES
24#define FSTYPENAMES
25#include <sys/disklabel.h>
26#include <sys/disk.h>
27#elif linux
28#define u64 unsigned long long
29#include <linux/fs.h>           /* for BLKGETSIZE64 */
30#include <linux/hdreg.h>
31#endif
32
33/*@unused@*/
34//static char cvsid[] = "$Id: libmondo-devices.c 127 2005-11-19 01:27:31Z bcornec $";
35
36extern int g_current_media_number;
37extern double g_kernel_version;
38
39extern bool g_ISO_restore_mode;
40extern struct s_bkpinfo *g_bkpinfo_DONTUSETHIS;
41extern char *g_erase_tmpdir_and_scratchdir;
42extern char *g_selfmounted_isodir;
43
44static char g_cdrw_drive_is_here[MAX_STR_LEN / 4] = "";
45static char g_cdrom_drive_is_here[MAX_STR_LEN / 4] = "";
46static char g_dvd_drive_is_here[MAX_STR_LEN / 4] = "";
47
48
49/**
50 * ????? @bug ?????
51 * @ingroup globalGroup
52 */
53bool g_restoring_live_from_cd = FALSE;
54
55extern t_bkptype g_backup_media_type;   // set by main()
56
57
58
59
60void set_g_cdrom_and_g_dvd_to_bkpinfo_value(struct s_bkpinfo *bkpinfo)
61{
62    strcpy(g_cdrom_drive_is_here, bkpinfo->media_device);   // just in case
63    strcpy(g_dvd_drive_is_here, bkpinfo->media_device); // just in case
64}
65
66
67
68/**
69 * Retract all CD trays and wait for autorun to complete.
70 * @ingroup deviceGroup
71 */
72void retract_CD_tray_and_defeat_autorun(void)
73{
74//  log_it("rctada: Retracting all CD trays", __LINE__);
75    if (strlen(g_cdrom_drive_is_here) > 0) {
76        inject_device(g_cdrom_drive_is_here);
77    }
78    if (strlen(g_dvd_drive_is_here) > 0) {
79        inject_device(g_dvd_drive_is_here);
80    }
81    if (strlen(g_cdrw_drive_is_here) > 0) {
82        inject_device(g_cdrw_drive_is_here);
83    }
84//  log_it("rctada: killing autorun");
85//  run_program_and_log_output("killall autorun", TRUE);
86    if (!run_program_and_log_output("ps | grep autorun | grep -v grep", 5)) {
87        log_it("autorun detected; sleeping for 2 seconds");
88        sleep(2);
89    }
90    log_it("rctada: Unmounting all CD drives", __LINE__);
91    run_program_and_log_output("umount /dev/cdr* /dev/dvd*", 5);
92}
93
94
95
96/**
97 * Determine whether we're booted off a ramdisk.
98 * @return @c TRUE (we are) or @c FALSE (we aren't).
99 * @ingroup utilityGroup
100 */
101bool am_I_in_disaster_recovery_mode(void)
102{
103    char *tmp, *comment;
104    bool is_this_a_ramdisk = FALSE;
105
106    malloc_string(tmp);
107    malloc_string(comment);
108    strcpy(tmp, where_is_root_mounted());
109    sprintf(comment, "root is mounted at %s\n", tmp);
110    log_msg(0, comment);
111    log_msg(0,
112            "No, Schlomo, that doesn't mean %s is the root partition. It's just a debugging message. Relax. It's part of am_I_in_disaster_recovery_mode().",
113            tmp);
114
115#ifdef __FreeBSD__
116    if (strstr(tmp, "/dev/md")) {
117        is_this_a_ramdisk = TRUE;
118    }
119#else
120    if (!strncmp(tmp, "/dev/ram", 8)
121        || (!strncmp(tmp, "/dev/rd", 7) && !strcmp(tmp, "/dev/rd/")
122            && strncmp(tmp, "/dev/rd/cd", 10)) || strstr(tmp, "rootfs")
123        || !strcmp(tmp, "/dev/root")) {
124        is_this_a_ramdisk = TRUE;
125    } else {
126        is_this_a_ramdisk = FALSE;
127    }
128#endif
129
130    if (is_this_a_ramdisk) {
131        if (!does_file_exist("/THIS-IS-A-RAMDISK")
132            && !does_file_exist("/tmp/mountlist.txt.sample")) {
133            log_to_screen
134                ("Using /dev/root is stupid of you but I'll forgive you.");
135            is_this_a_ramdisk = FALSE;
136        }
137    }
138    if (does_file_exist("/THIS-IS-A-RAMDISK")) {
139        is_this_a_ramdisk = TRUE;
140    }
141    paranoid_free(tmp);
142    paranoid_free(comment);
143    log_msg(1, "Is this a ramdisk? result = %d", is_this_a_ramdisk);
144    return (is_this_a_ramdisk);
145}
146
147
148
149
150
151/**
152 * Turn @c bkpinfo->backup_media_type into a human-readable string.
153 * @return The human readable string (e.g. @c cdr becomes <tt>"cdr"</tt>).
154 * @note The returned string points to static storage that will be overwritten with each call.
155 * @ingroup stringGroup
156 */
157static char *bkptype_to_string(t_bkptype bt)
158{
159    static char output[MAX_STR_LEN / 4];
160    switch (bt) {
161    case none:
162        strcpy(output, "none");
163        break;
164    case iso:
165        strcpy(output, "iso");
166        break;
167    case cdr:
168        strcpy(output, "cdr");
169        break;
170    case cdrw:
171        strcpy(output, "cdrw");
172        break;
173    case cdstream:
174        strcpy(output, "cdstream");
175        break;
176    case nfs:
177        strcpy(output, "nfs");
178        break;
179    case tape:
180        strcpy(output, "tape");
181        break;
182    case udev:
183        strcpy(output, "udev");
184        break;
185    default:
186        strcpy(output, "default");
187    }
188    return (output);
189}
190
191
192
193/**
194 * @addtogroup deviceGroup
195 * @{
196 */
197/**
198 * Eject the tray of the specified CD device.
199 * @param dev The device to eject.
200 * @return the return value of the @c eject command. (0=success, nonzero=failure)
201 */
202int eject_device(char *dev)
203{
204    char *command;
205    int res1 = 0, res2 = 0;
206
207    malloc_string(command);
208
209    if (IS_THIS_A_STREAMING_BACKUP(g_backup_media_type)
210        && g_backup_media_type != udev) {
211        sprintf(command, "mt -f %s offline", dev);
212        res1 = run_program_and_log_output(command, 1);
213    } else {
214        res1 = 0;
215    }
216
217#ifdef __FreeBSD__
218    if (strstr(dev, "acd")) {
219        sprintf(command, "cdcontrol -f %s eject", dev);
220    } else {
221        sprintf(command, "camcontrol eject `echo %s | sed 's|/dev/||'`",
222                dev);
223    }
224#else
225    sprintf(command, "eject %s", dev);
226#endif
227
228    log_msg(3, "Ejecting %s", dev);
229    res2 = run_program_and_log_output(command, 1);
230    paranoid_free(command);
231    if (res1 && res2) {
232        return (1);
233    } else {
234        return (0);
235    }
236}
237
238/**
239 * Load (inject) the tray of the specified CD device.
240 * @param dev The device to load/inject.
241 * @return 0 for success, nonzero for failure.
242 */
243int inject_device(char *dev)
244{
245    char *command;
246    int i;
247
248    malloc_string(command);
249
250
251#ifdef __FreeBSD__
252    if (strstr(dev, "acd")) {
253        sprintf(command, "cdcontrol -f %s close", dev);
254    } else {
255        sprintf(command, "camcontrol load `echo %s | sed 's|/dev/||'`",
256                dev);
257    }
258#else
259    sprintf(command, "eject -t %s", dev);
260#endif
261    i = run_program_and_log_output(command, FALSE);
262    paranoid_free(command);
263    return (i);
264}
265
266
267/**
268 * Determine whether the specified @p device (really, you can use any file)
269 * exists.
270 * @return TRUE if it exists, FALSE if it doesn't.
271 */
272bool does_device_exist(char *device)
273{
274
275    /*@ buffers *********************************************************** */
276    char *tmp;
277
278    malloc_string(tmp);
279    assert_string_is_neither_NULL_nor_zerolength(device);
280
281    sprintf(tmp, "ls %s > /dev/null 2> /dev/null", device);
282
283    paranoid_free(tmp);
284    if (system(tmp)) {
285        return (FALSE);
286    } else {
287        return (TRUE);
288    }
289}
290
291
292/**
293 * Determine whether a non-Microsoft partition exists on any connected hard drive.
294 * @return TRUE (there's a Linux/FreeBSD partition) or FALSE (Microsoft has taken over yet another innocent PC).
295 */
296bool does_nonMS_partition_exist(void)
297{
298#if __FreeBSD__
299    return
300        !system
301        ("for drive in /dev/ad? /dev/da?; do fdisk $drive | grep -q FreeBSD && exit 0; done; false");
302#else
303    return
304        !system
305        ("parted2fdisk -l 2>/dev/null | grep '^/dev/' | egrep -qv '(MS|DOS|FAT|NTFS)'");
306#endif
307}
308
309/**
310 * Determine whether the specified @p partno exists on the specified @p drive.
311 * @param drive The drive to search for the partition in.
312 * @param partno The partition number to look for.
313 * @return 0 if it exists, nonzero otherwise.
314 */
315int does_partition_exist(const char *drive, int partno)
316{
317    /*@ buffers **************************************************** */
318    char *program;
319    char *incoming;
320    char *searchstr;
321    char *tmp;
322
323    /*@ ints ******************************************************* */
324    int res = 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(program);
335    malloc_string(incoming);
336    malloc_string(searchstr);
337    malloc_string(tmp);
338
339#ifdef __FreeBSD__
340    // We assume here that this is running from mondorestore. (It is.)
341    sprintf(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    paranoid_free(program);
366    paranoid_free(incoming);
367    paranoid_free(searchstr);
368    paranoid_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    paranoid_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    paranoid_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        log_msg(1, "mount failed");
484    } else {
485        log_msg(1, "mount succeeded with %s", dev);
486    }
487    paranoid_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        log_msg(3, "Been there, done that. Returning %s", cdrw_device);
522        paranoid_free(comment);
523        paranoid_free(tmp);
524        paranoid_free(cdr_exe);
525        paranoid_free(command);
526        return (0);
527    }
528    if (g_backup_media_type == dvd) {
529        log_msg(1,
530                "This is dumb. You're calling find_cdrw_device() but you're backing up to DVD. WTF?");
531        paranoid_free(comment);
532        paranoid_free(tmp);
533        paranoid_free(cdr_exe);
534        paranoid_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        paranoid_free(comment);
552        paranoid_free(tmp);
553        paranoid_free(cdr_exe);
554        paranoid_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        paranoid_free(comment);
562        paranoid_free(tmp);
563        paranoid_free(cdr_exe);
564        paranoid_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        log_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        log_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        log_msg(4, "Can't find cdrecord; assuming %s", output);
646        if (!does_device_exist(output)) {
647            log_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        log_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        log_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            log_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                log_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                            log_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        log_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        log_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            log_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        log_msg(4, "(find_cdrom_device) --> '%s'", output);
778        if (!does_device_exist(output)) {
779            found_it = FALSE;
780            log_msg(4, "OK, I was wrong, I haven't found it... yet.");
781        }
782    }
783
784    if (!found_it) {
785        log_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            log_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                log_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                log_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            log_msg(3, "I still haven't found it.");
847            return (1);
848        }
849        log_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    log_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        log_msg(4, "Finally found it at %s", output);
864        retval = 0;
865        goto end_of_find_cdrom_device;
866    } else {
867        log_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    paranoid_free(tmp);
873    paranoid_free(cdr_exe);
874    paranoid_free(phrase_one);
875    paranoid_free(phrase_two);
876    paranoid_free(command);
877    paranoid_free(dvd_last_resort);
878    paranoid_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        log_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    log_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        log_msg(2, "I think DVD is at %s", output);
917    } else {
918        log_msg(2, "I cannot find DVD");
919        retval = 1;
920    }
921
922    if (try_to_mount) {
923        log_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        log_msg(1, "Error getting size of %s: %s", drive, strerror(errno));
989    }
990#if linux
991    fileid = open(drive, O_RDONLY);
992    if (fileid) {
993        if (ioctl(fileid, HDIO_GETGEO, &hdgeo) != -1) {
994            if (hdgeo.cylinders && hdgeo.heads && hdgeo.sectors) {
995                cylindersleft = cylinders = hdgeo.cylinders;
996                cylindersize = hdgeo.heads * hdgeo.sectors / 2;
997                outvalA = cylindersize * cylinders / 1024;
998                log_msg(2, "Got Harddisk geometry, C:%d, H:%d, S:%d",
999                        hdgeo.cylinders, hdgeo.heads, hdgeo.sectors);
1000                gotgeo = 1;
1001            } else {
1002                log_msg(1, "Harddisk geometry wrong");
1003            }
1004        } else {
1005            log_msg(1,
1006                    "Error in ioctl() getting new hard disk geometry (%s), resizing in unsafe mode",
1007                    strerror(errno));
1008        }
1009        close(fileid);
1010    } else {
1011        log_msg(1, "Failed to open %s for reading: %s", drive,
1012                strerror(errno));
1013    }
1014    if (!gotgeo) {
1015        log_msg(1, "Failed to get harddisk geometry, using old mode");
1016    }
1017/* 
1018  if ((fd = open (drive, O_RDONLY)) != -1) {
1019      if (ioctl (fd, HDIO_GETGEO, &hdgeo) != -1)  {
1020      close (fd);
1021      log_msg (2, "Geometry of drive %s is C:%d, H:%d, S%d, its size is %d MB", drive, hdgeo.cylinders, hdgeo.heads, hdgeo.sectors, (hdgeo.cylinders * hdgeo.heads * hdgeo.sectors / 2 / 1024));
1022      if ( hdgeo.cylinders && hdgeo.heads && hdgeo.sectors ) {
1023          outvalB = ((long) (hdgeo.cylinders * hdgeo.heads * hdgeo.sectors / 2 / 1024));
1024      }
1025      }
1026      close (fd);
1027 */
1028#endif
1029
1030// OLDER DISKS will give ridiculously low value for outvalB (so outvalA is returned) :)
1031// NEWER DISKS will give sane value for outvalB (close to outvalA, in other words) :)
1032
1033    outvalC = (outvalA > outvalB) ? outvalA : outvalB;
1034
1035//  log_msg (5, "drive = %s, error = %s", drive, strerror (errno));
1036//  fatal_error ("GPSOD: Unable to get size of drive");
1037    log_msg(1, "%s --> %ld or %ld --> %ld", drive, outvalA, outvalB,
1038            outvalC);
1039
1040    return (outvalC);
1041}
1042
1043/* The old version */
1044#if 0
1045long get_phys_size_of_drive(char *drive)
1046{
1047    /*@ pointers **************************************************** */
1048#if linux
1049    FILE *fin;
1050    char *p;
1051    char *q;
1052    char *r;
1053    /*@ buffers ***************************************************** */
1054    char *tmp;
1055    char *command;
1056
1057    /*@ long ******************************************************** */
1058    long outL;
1059    long tempLa;
1060    long tempLb;
1061    long tempLc;
1062
1063#endif
1064
1065    struct hd_geometry hdgeo;
1066    int fd;
1067
1068#ifdef __FreeBSD__
1069    off_t o;
1070
1071    if ((fd = open(drive, O_RDONLY)) != -1) {
1072        if (ioctl(fd, DIOCGMEDIASIZE, &o) != -1) {
1073            close(fd);
1074            return (long) (o / (off_t) (1024 * 1024));
1075        }
1076        close(fd);
1077    }
1078    log_msg(4, "drive = %s, error = %s", drive, strerror(errno));
1079    fatal_error("GPSOD: Unable to get size of drive");
1080#else
1081
1082    malloc_string(tmp);
1083    malloc_string(command);
1084
1085    if ((fd = open(drive, O_RDONLY)) != -1) {
1086        if (ioctl(fd, HDIO_GETGEO, &hdgeo) != -1) {
1087            close(fd);
1088            log_msg(2,
1089                    "Geometry of drive %s is C:%d, H:%d, S%d, its size is %d MB",
1090                    drive, hdgeo.cylinders, hdgeo.heads, hdgeo.sectors,
1091                    (hdgeo.cylinders * hdgeo.heads * hdgeo.sectors / 2 /
1092                     1024));
1093            if (hdgeo.cylinders && hdgeo.heads && hdgeo.sectors) {
1094                return ((long)
1095                        (hdgeo.cylinders * hdgeo.heads * hdgeo.sectors /
1096                         2 / 1024));
1097            }
1098        }
1099        close(fd);
1100    }
1101
1102    assert_string_is_neither_NULL_nor_zerolength(drive);
1103
1104    sprintf(command,
1105            "parted2fdisk -l %s | head -n4 | tr -s '\n' '\t' | tr -s ' ' '\t' | cut -f8,14,16",
1106            drive);
1107    strcpy(tmp, call_program_and_get_last_line_of_output(command));
1108    if (tmp[0]) {
1109        p = tmp;
1110        q = strchr(p, ' ');
1111        if (q) {
1112            *(q++) = '\0';
1113            r = strchr(q, ' ');
1114            if (r) {
1115                *(r++) = '\0';
1116                tempLa = atol(p);
1117                tempLb = atol(q);
1118                tempLc = atol(r);
1119                outL = tempLa * tempLb / 1024 * tempLc / 1024;
1120                if (outL > 100) {
1121                    paranoid_free(tmp);
1122                    paranoid_free(command);
1123                    return (outL);
1124                }
1125            }
1126        }
1127    }
1128
1129    /* try to grep for 'Drive xxxx: yyy MB' */
1130    sprintf(command,
1131            "parted2fdisk -l %s | grep MB | tr -s ' ' '\t' | cut -f3",
1132            drive);
1133    strcpy(tmp, call_program_and_get_last_line_of_output(command));
1134    if (atol(tmp) > 0) {
1135        paranoid_free(tmp);
1136        paranoid_free(command);
1137        return (atol(tmp));
1138    }
1139
1140    /* else, do it the old-fashioned way */
1141    p = strrchr(drive, (int) '/');
1142    if (p) {
1143        strcpy(tmp, p + 1);
1144    } else {
1145        paranoid_free(tmp);
1146        paranoid_free(command);
1147        return (-1);
1148    }
1149    sprintf(command, "dmesg | grep %s 2> /dev/null", tmp);
1150    if (!(fin = popen(command, "r"))) {
1151        log_OS_error("Cannot popen dmesg command");
1152    } else {
1153        fgets(tmp, MAX_STR_LEN - 1, fin);
1154        while (!feof(fin) && !strstr(tmp, "GB") && !strstr(tmp, "MB")) {
1155            fgets(tmp, MAX_STR_LEN - 1, fin);
1156        }
1157        if (pclose(fin)) {
1158            log_OS_error("Cannot pclose dmesg fin");
1159        }
1160    }
1161    if (!(p = strstr(tmp, "GB")) && !(p = strstr(tmp, "MB"))) {
1162        log_msg(3, "Cannot find %s's size: dmesg isn't helping either.",
1163                drive);
1164        paranoid_free(tmp);
1165        paranoid_free(command);
1166        return (-1);
1167    }
1168    for (; !isdigit(*(p - 1)); p--);
1169    *p = '\0';
1170    for (p--; isdigit(*(p - 1)); p--);
1171    outL = atol(p);
1172    if (outL <= 0) {
1173        paranoid_free(tmp);
1174        paranoid_free(command);
1175        return (-1);
1176    }
1177    if (strstr(tmp, "GB")) {
1178        outL = outL * 1024;
1179    }
1180    paranoid_free(tmp);
1181    paranoid_free(command);
1182    return (outL * 19 / 20);
1183#endif
1184}
1185#endif                          /* 0 */
1186
1187
1188
1189
1190
1191/**
1192 * Determine whether @p format is supported by the kernel. Uses /proc/filesystems
1193 * under Linux and @c lsvfs under FreeBSD.
1194 * @param format The format to test.
1195 * @return TRUE if the format is supported, FALSE if not.
1196 */
1197bool is_this_a_valid_disk_format(char *format)
1198{
1199    char *good_formats;
1200    char *command;
1201    char *format_sz;
1202
1203    FILE *pin;
1204    int retval;
1205    malloc_string(good_formats);
1206    malloc_string(command);
1207    malloc_string(format_sz);
1208
1209    assert_string_is_neither_NULL_nor_zerolength(format);
1210
1211    sprintf(format_sz, "%s ", format);
1212
1213#ifdef __FreeBSD__
1214    sprintf(command,
1215            "lsvfs | tr -s '\t' ' ' | grep -v Filesys | grep -v -- -- | cut -d' ' -f1 | tr -s '\n' ' '");
1216#else
1217    sprintf(command,
1218            "cat /proc/filesystems | grep -v nodev | tr -s '\t' ' ' | cut -d' ' -f2 | tr -s '\n' ' '");
1219#endif
1220
1221    pin = popen(command, "r");
1222    if (!pin) {
1223        log_OS_error("Unable to read good formats");
1224        retval = 0;
1225    } else {
1226        strcpy(good_formats, " ");
1227        (void) fgets(good_formats + 1, MAX_STR_LEN, pin);
1228        if (pclose(pin)) {
1229            log_OS_error("Cannot pclose good formats");
1230        }
1231        strip_spaces(good_formats);
1232        strcat(good_formats, " swap lvm raid ntfs 7 "); // " ntfs 7 " -- um, cheating much? :)
1233        if (strstr(good_formats, format_sz)) {
1234            retval = 1;
1235        } else {
1236            retval = 0;
1237        }
1238    }
1239    paranoid_free(good_formats);
1240    paranoid_free(command);
1241    paranoid_free(format_sz);
1242    return (retval);
1243}
1244
1245
1246/** @def SWAPLIST_COMMAND The command to list the swap files/partitions in use. */
1247
1248/**
1249 * Determine whether @p device_raw is currently mounted.
1250 * @param device_raw The device to check.
1251 * @return TRUE if it's mounted, FALSE if not.
1252 */
1253bool is_this_device_mounted(char *device_raw)
1254{
1255
1256    /*@ pointers **************************************************** */
1257    FILE *fin;
1258
1259    /*@ buffers ***************************************************** */
1260    char *incoming;
1261    char *device_with_tab;
1262    char *device_with_space;
1263    char *tmp;
1264    int retval = 0;
1265
1266#ifdef __FreeBSD__
1267#define SWAPLIST_COMMAND "swapinfo"
1268#else
1269#define SWAPLIST_COMMAND "cat /proc/swaps"
1270#endif
1271
1272    /*@ end vars **************************************************** */
1273
1274    malloc_string(incoming);
1275    malloc_string(device_with_tab);
1276    malloc_string(device_with_space);
1277    malloc_string(tmp);
1278    assert(device_raw != NULL);
1279//  assert_string_is_neither_NULL_nor_zerolength(device_raw);
1280    if (device_raw[0] != '/' && !strstr(device_raw, ":/")) {
1281        log_msg(1, "%s needs to have a '/' prefixed - I'll do it",
1282                device_raw);
1283        sprintf(tmp, "/%s", device_raw);
1284    } else {
1285        strcpy(tmp, device_raw);
1286    }
1287    log_msg(1, "Is %s mounted?", tmp);
1288    if (!strcmp(tmp, "/proc") || !strcmp(tmp, "proc")) {
1289        log_msg(1,
1290                "I don't know how the heck /proc made it into the mountlist. I'll ignore it.");
1291        return (0);
1292    }
1293    sprintf(device_with_tab, "%s\t", tmp);
1294    sprintf(device_with_space, "%s ", tmp);
1295
1296    if (!(fin = popen("mount", "r"))) {
1297        log_OS_error("Cannot popen 'mount'");
1298        return (FALSE);
1299    }
1300    for (fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin);
1301         fgets(incoming, MAX_STR_LEN - 1, fin)) {
1302        if (strstr(incoming, device_with_space) //> incoming
1303            || strstr(incoming, device_with_tab))   // > incoming)
1304        {
1305            paranoid_pclose(fin);
1306            retval = 1;
1307            goto end_of_func;
1308        }
1309    }
1310    paranoid_pclose(fin);
1311    sprintf(tmp, "%s | grep -w \"%s\" > /dev/null 2> /dev/null",
1312            SWAPLIST_COMMAND, device_with_space);
1313    log_msg(4, "tmp (command) = '%s'", tmp);
1314    if (!system(tmp)) {
1315        retval = 1;
1316        goto end_of_func;
1317    }
1318  end_of_func:
1319    paranoid_free(incoming);
1320    paranoid_free(device_with_tab);
1321    paranoid_free(device_with_space);
1322    paranoid_free(tmp);
1323    return (retval);
1324}
1325
1326#ifdef __FreeBSD__
1327//                       CODE IS FREEBSD-SPECIFIC
1328/**
1329 * Create a loopback device for specified @p fname.
1330 * @param fname The file to associate with a device.
1331 * @return /dev entry for the device, or NULL if it couldn't be allocated.
1332 */
1333char *make_vn(char *fname)
1334{
1335    char *device = (char *) malloc(MAX_STR_LEN);
1336    char *mddevice = (char *) malloc(32);
1337    char command[MAX_STR_LEN];
1338    int vndev = 2;
1339    if (atoi
1340        (call_program_and_get_last_line_of_output
1341         ("/sbin/sysctl -n kern.osreldate")) < 500000) {
1342        do {
1343            sprintf(mddevice, "vn%ic", vndev++);
1344            sprintf(command, "vnconfig %s %s", mddevice, fname);
1345            if (vndev > 10) {
1346                return NULL;
1347            }
1348        }
1349        while (system(command));
1350    } else {
1351        sprintf(command, "mdconfig -a -t vnode -f %s", fname);
1352        mddevice = call_program_and_get_last_line_of_output(command);
1353        if (!strstr(mddevice, "md")) {
1354            return NULL;
1355        }
1356    }
1357    sprintf(device, "/dev/%s", mddevice);
1358    return device;
1359}
1360
1361
1362
1363//                       CODE IS FREEBSD-SPECIFIC
1364/**
1365 * Deallocate specified @p dname.
1366 * This should be called when you are done with the device created by make_vn(),
1367 * so the system does not run out of @c vn devices.
1368 * @param dname The device to deallocate.
1369 * @return 0 for success, nonzero for failure.
1370 */
1371int kick_vn(char *dname)
1372{
1373    char command[MAX_STR_LEN];
1374
1375    if (strncmp(dname, "/dev/", 5) == 0) {
1376        dname += 5;
1377    }
1378
1379    if (atoi
1380        (call_program_and_get_last_line_of_output
1381         ("/sbin/sysctl -n kern.osreldate")) < 500000) {
1382        sprintf(command, "vnconfig -d %s", dname);
1383        return system(command);
1384    } else {
1385        sprintf(command, "mdconfig -d -u %s", dname);
1386        return system(command);
1387    }
1388     /*NOTREACHED*/ return 255;
1389}
1390#endif
1391
1392
1393/**
1394 * Mount the CD-ROM at @p mountpoint.
1395 * @param device The device (or file if g_ISO_restore_mode) to mount.
1396 * @param mountpoint The place to mount it.
1397 * @return 0 for success, nonzero for failure.
1398 */
1399int mount_CDROM_here(char *device, char *mountpoint)
1400{
1401    /*@ buffer ****************************************************** */
1402    char *command;
1403    char *dev;
1404    char *options;
1405    int retval;
1406
1407    malloc_string(command);
1408    malloc_string(dev);
1409    malloc_string(options);
1410    assert_string_is_neither_NULL_nor_zerolength(device);
1411    assert_string_is_neither_NULL_nor_zerolength(mountpoint);
1412
1413    make_hole_for_dir(mountpoint);
1414    strcpy(options, "ro");
1415    if (isdigit(device[0])) {
1416        find_cdrom_device(device, FALSE);
1417    } else {
1418        strcpy(dev, device);
1419    }
1420    if (g_ISO_restore_mode) {
1421
1422#ifdef __FreeBSD__
1423        strcpy(dev, make_vn(device));
1424        if (!dev) {
1425            sprintf(command, "Unable to mount ISO (make_vn(%s) failed)",
1426                    device);
1427            fatal_error(command);
1428        }
1429        strcpy(device, dev);
1430#else
1431        strcat(options, ",loop");
1432#endif
1433
1434    }
1435    log_msg(4, "(mount_CDROM_here --- device=%s, mountpoint=%s", device,
1436            mountpoint);
1437    /*@ end vars *************************************************** */
1438
1439#ifdef __FreeBSD__
1440    sprintf(command, "mount_cd9660 -r %s %s 2>> %s",
1441            device, mountpoint, MONDO_LOGFILE);
1442
1443#else
1444    sprintf(command, "mount %s -o %s -t iso9660 %s 2>> %s",
1445            device, options, mountpoint, MONDO_LOGFILE);
1446#endif
1447
1448    log_msg(4, command);
1449    if (strncmp(device, "/dev/", 5) == 0) {
1450        retract_CD_tray_and_defeat_autorun();
1451    }
1452    retval = system(command);
1453    log_msg(1, "system(%s) returned %d", command, retval);
1454
1455    paranoid_free(command);
1456    paranoid_free(dev);
1457    paranoid_free(options);
1458    return (retval);
1459}
1460
1461
1462
1463
1464
1465
1466/**
1467 * Ask the user for CD number @p cd_number_i_want.
1468 * Sets g_current_media_number once the correct CD is inserted.
1469 * @param bkpinfo The backup information structure. Fields used:
1470 * - @c bkpinfo->backup_media_type
1471 * - @c bkpinfo->prefix
1472 * - @c bkpinfo->isodir
1473 * - @c bkpinfo->media_device
1474 * - @c bkpinfo->please_dont_eject_when_restoring
1475 * @param cd_number_i_want The CD number to ask for.
1476 */
1477void
1478insist_on_this_cd_number(struct s_bkpinfo *bkpinfo, int cd_number_i_want)
1479{
1480
1481    /*@ int ************************************************************* */
1482    int res = 0;
1483
1484
1485    /*@ buffers ********************************************************* */
1486    char *tmp;
1487    char *request;
1488
1489    assert(bkpinfo != NULL);
1490    assert(cd_number_i_want > 0);
1491
1492//  log_msg(3, "Insisting on CD number %d", cd_number_i_want);
1493
1494    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1495        log_msg(3,
1496                "No need to insist_on_this_cd_number when the backup type isn't CD-R(W) or NFS or ISO");
1497        return;
1498    }
1499    malloc_string(tmp);
1500    malloc_string(request);
1501    sprintf(tmp, "mkdir -p " MNT_CDROM);
1502    run_program_and_log_output(tmp, 5);
1503    if (g_ISO_restore_mode || bkpinfo->backup_media_type == iso
1504        || bkpinfo->backup_media_type == nfs) {
1505        log_msg(3, "Remounting CD");
1506        g_ISO_restore_mode = TRUE;
1507// FIXME --- I'm tempted to do something about this...
1508// Why unmount and remount again and again?
1509        if (is_this_device_mounted(MNT_CDROM)) {
1510            run_program_and_log_output("umount " MNT_CDROM, 5);
1511        }
1512        system("mkdir -p /tmp/isodir &> /dev/null");
1513        sprintf(tmp, "%s/%s/%s-%d.iso", bkpinfo->isodir,
1514                bkpinfo->nfs_remote_dir, bkpinfo->prefix,
1515                cd_number_i_want);
1516        if (!does_file_exist(tmp)) {
1517            sprintf(tmp, "/tmp/isodir/%s/%s-%d.iso",
1518                    bkpinfo->nfs_remote_dir, bkpinfo->prefix,
1519                    cd_number_i_want);
1520            if (does_file_exist(tmp)) {
1521                log_msg(1,
1522                        "FIXME - hacking bkpinfo->isodir from '%s' to /tmp/isodir",
1523                        bkpinfo->isodir);
1524                strcpy(bkpinfo->isodir, "/tmp/isodir");
1525            }
1526        }
1527        log_msg(3, "Mounting %s at %s", tmp, MNT_CDROM);
1528        if (mount_CDROM_here(tmp, MNT_CDROM)) {
1529            fatal_error("Mommy!");
1530        }
1531//    g_current_media_number = cd_number_i_want;
1532//    return;
1533    }
1534    if ((res = what_number_cd_is_this(bkpinfo)) != cd_number_i_want) {
1535        log_msg(3, "Currently, we hold %d but we want %d", res,
1536                cd_number_i_want);
1537        sprintf(tmp, "Insisting on %s #%d",
1538                media_descriptor_string(bkpinfo->backup_media_type),
1539                cd_number_i_want);
1540        sprintf(request, "Please insert %s #%d and press Enter.",
1541                media_descriptor_string(bkpinfo->backup_media_type),
1542                cd_number_i_want);
1543        log_msg(3, tmp);
1544        while (what_number_cd_is_this(bkpinfo) != cd_number_i_want) {
1545            paranoid_system("sync");
1546            if (is_this_device_mounted(MNT_CDROM)) {
1547                res =
1548                    run_program_and_log_output("umount " MNT_CDROM, FALSE);
1549            } else {
1550                res = 0;
1551            }
1552            if (res) {
1553                log_to_screen("WARNING - failed to unmount CD-ROM drive");
1554            }
1555            if (!bkpinfo->please_dont_eject) {
1556                res = eject_device(bkpinfo->media_device);
1557            } else {
1558                res = 0;
1559            }
1560            if (res) {
1561                log_to_screen("WARNING - failed to eject CD-ROM disk");
1562            }
1563            popup_and_OK(request);
1564            if (!bkpinfo->please_dont_eject) {
1565                inject_device(bkpinfo->media_device);
1566            }
1567            paranoid_system("sync");
1568        }
1569        log_msg(1, "Thankyou. Proceeding...");
1570        g_current_media_number = cd_number_i_want;
1571    }
1572    paranoid_free(tmp);
1573    paranoid_free(request);
1574}
1575
1576/* @} - end of deviceGroup */
1577
1578
1579
1580
1581
1582
1583/**
1584 * Ask user for details of backup/restore information.
1585 * Called when @c mondoarchive doesn't get any parameters.
1586 * @param bkpinfo The backup information structure to fill out with the user's data.
1587 * @param archiving_to_media TRUE if archiving, FALSE if restoring.
1588 * @return 0, always.
1589 * @bug No point of `int' return value.
1590 * @ingroup archiveGroup
1591 */
1592int interactively_obtain_media_parameters_from_user(struct s_bkpinfo
1593                                                    *bkpinfo,
1594                                                    bool
1595                                                    archiving_to_media)
1596// archiving_to_media is TRUE if I'm being called by mondoarchive
1597// archiving_to_media is FALSE if I'm being called by mondorestore
1598{
1599    char *tmp;
1600    char *sz_size;
1601    char *command;
1602    char *comment;
1603    char *prompt;
1604    int i;
1605    FILE *fin;
1606
1607    malloc_string(tmp);
1608    malloc_string(sz_size);
1609    malloc_string(command);
1610    malloc_string(comment);
1611    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    log_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
1638/*
1639  if (find_home_of_exe("star") && (!find_home_of_exe("afio") || find_home_of_exe("selinuxenabled")))
1640    {
1641      bkpinfo->use_star = FALSE;   
1642      bkpinfo->use_lzo = FALSE;
1643      log_to_screen("Using star, not afio");
1644      if (!find_home_of_exe("afio"))
1645    { log_to_screen("...because afio not found"); }
1646      if (find_home_of_exe("selinuxenabled"))
1647    { log_to_screen("...because SELINUX found"); }
1648    }
1649*/
1650
1651    mvaddstr_and_log_it(2, 0, " ");
1652
1653// Find device's /dev (or SCSI) entry
1654    switch (bkpinfo->backup_media_type) {
1655    case cdr:
1656    case cdrw:
1657    case dvd:
1658        if (archiving_to_media) {
1659            if (ask_me_yes_or_no
1660                ("Is your computer a laptop, or does the CD writer incorporate BurnProof technology?"))
1661            {
1662                bkpinfo->manual_cd_tray = TRUE;
1663            }
1664            if ((bkpinfo->compression_level =
1665                 which_compression_level()) == -1) {
1666                log_to_screen("User has chosen not to backup the PC");
1667                finish(1);
1668            }
1669            sprintf(comment, "What speed is your %s (re)writer?",
1670                    media_descriptor_string(bkpinfo->backup_media_type));
1671            if (bkpinfo->backup_media_type == dvd) {
1672                find_dvd_device(bkpinfo->media_device, FALSE);
1673                strcpy(tmp, "1");
1674                sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE);  // 4.7 salesman's GB = 4.482 real GB = 4582 MB
1675                log_msg(1, "Setting to DVD defaults");
1676            } else {
1677                strcpy(bkpinfo->media_device, VANILLA_SCSI_CDROM);
1678                strcpy(tmp, "4");
1679                strcpy(sz_size, "650");
1680                log_msg(1, "Setting to CD defaults");
1681            }
1682            if (bkpinfo->backup_media_type != dvd) {
1683                if (!popup_and_get_string("Speed", comment, tmp, 4)) {
1684                    log_to_screen("User has chosen not to backup the PC");
1685                    finish(1);
1686                }
1687            }
1688            bkpinfo->cdrw_speed = atoi(tmp);    // if DVD then this shouldn't ever be used anyway :)
1689            sprintf(comment,
1690                    "How much data (in Megabytes) will each %s store?",
1691                    media_descriptor_string(bkpinfo->backup_media_type));
1692            if (!popup_and_get_string("Size", comment, sz_size, 5)) {
1693                log_to_screen("User has chosen not to backup the PC");
1694                finish(1);
1695            }
1696            for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1697                bkpinfo->media_size[i] = atoi(sz_size);
1698            }
1699            if (bkpinfo->media_size[0] <= 0) {
1700                log_to_screen("User has chosen not to backup the PC");
1701                finish(1);
1702            }
1703        }
1704    case cdstream:
1705        if (bkpinfo->disaster_recovery) {
1706            strcpy(bkpinfo->media_device, "/dev/cdrom");
1707            log_msg(2, "CD-ROM device assumed to be at %s",
1708                    bkpinfo->media_device);
1709        } else if (bkpinfo->restore_data
1710                   || bkpinfo->backup_media_type == dvd) {
1711            if (!bkpinfo->media_device[0]) {
1712                strcpy(bkpinfo->media_device, "/dev/cdrom");
1713            }                   // just for the heck of it :)
1714            log_msg(1, "bkpinfo->media_device = %s",
1715                    bkpinfo->media_device);
1716            if (bkpinfo->backup_media_type == dvd
1717                || find_cdrom_device(bkpinfo->media_device, FALSE)) {
1718                log_msg(1, "bkpinfo->media_device = %s",
1719                        bkpinfo->media_device);
1720                sprintf(comment,
1721                        "Please specify your %s drive's /dev entry",
1722                        media_descriptor_string(bkpinfo->
1723                                                backup_media_type));
1724                if (!popup_and_get_string
1725                    ("Device?", comment, bkpinfo->media_device,
1726                     MAX_STR_LEN / 4)) {
1727                    log_to_screen("User has chosen not to backup the PC");
1728                    finish(1);
1729                }
1730            }
1731            log_msg(2, "%s device found at %s",
1732                    media_descriptor_string(bkpinfo->backup_media_type),
1733                    bkpinfo->media_device);
1734        } else {
1735            if (find_cdrw_device(bkpinfo->media_device)) {
1736                bkpinfo->media_device[0] = '\0';
1737            }
1738            if (bkpinfo->media_device[0]) {
1739                sprintf(tmp,
1740                        "I think I've found your %s burner at SCSI node %s; am I right on the money?",
1741                        media_descriptor_string(bkpinfo->
1742                                                backup_media_type),
1743                        bkpinfo->media_device);
1744                if (!ask_me_yes_or_no(tmp)) {
1745                    bkpinfo->media_device[0] = '\0';
1746                }
1747            }
1748            if (!bkpinfo->media_device[0]) {
1749                if (g_kernel_version < 2.6) {
1750                    i = popup_and_get_string("Device node?",
1751                                             "What is the SCSI node of your CD (re)writer, please?",
1752                                             bkpinfo->media_device,
1753                                             MAX_STR_LEN / 4);
1754                } else {
1755                    i = popup_and_get_string("/dev entry?",
1756                                             "What is the /dev entry of your CD (re)writer, please?",
1757                                             bkpinfo->media_device,
1758                                             MAX_STR_LEN / 4);
1759                }
1760                if (!i) {
1761                    log_to_screen("User has chosen not to backup the PC");
1762                    finish(1);
1763                }
1764            }
1765        }
1766        if (bkpinfo->backup_media_type == cdstream) {
1767            for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1768                bkpinfo->media_size[i] = 650;
1769            }
1770        }
1771        break;
1772    case udev:
1773        if (!ask_me_yes_or_no
1774            ("This option is for advanced users only. Are you sure?")) {
1775            log_to_screen("User has chosen not to backup the PC");
1776            finish(1);
1777        }
1778    case tape:
1779
1780        if (find_tape_device_and_size(bkpinfo->media_device, sz_size)) {
1781            log_msg(3, "Ok, using vanilla scsi tape.");
1782            strcpy(bkpinfo->media_device, VANILLA_SCSI_TAPE);
1783            if ((fin = fopen(bkpinfo->media_device, "r"))) {
1784                paranoid_fclose(fin);
1785            } else {
1786                strcpy(bkpinfo->media_device, "/dev/osst0");
1787            }
1788        }
1789        if (bkpinfo->media_device[0]) {
1790            if ((fin = fopen(bkpinfo->media_device, "r"))) {
1791                paranoid_fclose(fin);
1792            } else {
1793                if (does_file_exist("/tmp/mondo-restore.cfg")) {
1794                    read_cfg_var("/tmp/mondo-restore.cfg", "media-dev",
1795                                 bkpinfo->media_device);
1796                }
1797            }
1798            sprintf(tmp,
1799                    "I think I've found your tape streamer at %s; am I right on the money?",
1800                    bkpinfo->media_device);
1801        }
1802        if (bkpinfo->media_device[0]) {
1803            sprintf(tmp,
1804                    "I think I've found your tape streamer at %s; am I right on the money?",
1805                    bkpinfo->media_device);
1806            if (!ask_me_yes_or_no(tmp)) {
1807                bkpinfo->media_device[0] = '\0';
1808            }
1809        }
1810        if (!bkpinfo->media_device[0]) {
1811            if (!popup_and_get_string
1812                ("Device name?",
1813                 "What is the /dev entry of your tape streamer?",
1814                 bkpinfo->media_device, MAX_STR_LEN / 4)) {
1815                log_to_screen("User has chosen not to backup the PC");
1816                finish(1);
1817            }
1818        }
1819        sprintf(tmp, "ls -l %s", bkpinfo->media_device);
1820        if (run_program_and_log_output(tmp, FALSE)) {
1821            log_to_screen("User has not specified a valid /dev entry");
1822            finish(1);
1823        }
1824        log_msg(4, "sz_size = %s", sz_size);
1825        sz_size[0] = '\0';
1826/*
1827    if ((size_sz[0]=='\0' || atol(size_sz)==0) && archiving_to_media)
1828      {
1829        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))
1830          { log_to_screen("User has chosen not to backup the PC"); finish(1); }
1831      }
1832*/
1833        if (sz_size[0] == '\0') {
1834            bkpinfo->media_size[0] = 0;
1835        } else {
1836            bkpinfo->media_size[0] =
1837                friendly_sizestr_to_sizelong(sz_size) / 2 - 50;
1838        }
1839        log_msg(4, "media_size[0] = %ld", bkpinfo->media_size[0]);
1840        if (bkpinfo->media_size[0] <= 0) {
1841            bkpinfo->media_size[0] = 0;
1842        }
1843        for (i = 1; i <= MAX_NOOF_MEDIA; i++) {
1844            bkpinfo->media_size[i] = bkpinfo->media_size[0];
1845        }
1846        if (archiving_to_media) {
1847            if ((bkpinfo->compression_level =
1848                 which_compression_level()) == -1) {
1849                log_to_screen("User has chosen not to backup the PC");
1850                finish(1);
1851            }
1852        }
1853        break;
1854
1855
1856
1857    case nfs:
1858        if (!bkpinfo->nfs_mount[0]) {
1859            strcpy(bkpinfo->nfs_mount,
1860                   call_program_and_get_last_line_of_output
1861                   ("mount | grep \":\" | cut -d' ' -f1 | head -n1"));
1862        }
1863#ifdef __FreeBSD__
1864        if (TRUE)
1865#else
1866        if (!bkpinfo->disaster_recovery)
1867#endif
1868        {
1869            if (!popup_and_get_string
1870                ("NFS dir.",
1871                 "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.)",
1872                 bkpinfo->nfs_mount, MAX_STR_LEN / 4)) {
1873                log_to_screen("User has chosen not to backup the PC");
1874                finish(1);
1875            }
1876            if (!bkpinfo->restore_data) {
1877                if ((bkpinfo->compression_level =
1878                     which_compression_level()) == -1) {
1879                    log_to_screen("User has chosen not to backup the PC");
1880                    finish(1);
1881                }
1882            }
1883            // check whether already mounted - we better remove
1884            // surrounding spaces and trailing '/' for this
1885            strip_spaces(bkpinfo->nfs_mount);
1886            if (bkpinfo->nfs_mount[strlen(bkpinfo->nfs_mount) - 1] == '/')
1887                bkpinfo->nfs_mount[strlen(bkpinfo->nfs_mount) - 1] = '\0';
1888            sprintf(command, "mount | grep \"%s \" | cut -d' ' -f3",
1889                    bkpinfo->nfs_mount);
1890            strcpy(bkpinfo->isodir,
1891                   call_program_and_get_last_line_of_output(command));
1892        }
1893        if (bkpinfo->disaster_recovery) {
1894            system("umount /tmp/isodir 2> /dev/null");
1895            if (!popup_and_get_string
1896                ("NFS share", "Which remote NFS share should I mount?",
1897                 bkpinfo->nfs_mount, MAX_STR_LEN)) {
1898                log_to_screen("User has chosen not to backup the PC");
1899                finish(1);
1900            }
1901        }
1902        if (!is_this_device_mounted(bkpinfo->nfs_mount)) {
1903            sprintf(bkpinfo->isodir, "/tmp/isodir.mondo.%d",
1904                    (int) (random() % 32768));
1905            sprintf(command, "mkdir -p %s", bkpinfo->isodir);
1906            run_program_and_log_output(command, 5);
1907            sprintf(tmp, "mount %s -t nfs %s", bkpinfo->nfs_mount,
1908                    bkpinfo->isodir);
1909            run_program_and_log_output(tmp, 5);
1910            malloc_string(g_selfmounted_isodir);
1911            strcpy(g_selfmounted_isodir, bkpinfo->isodir);
1912        }
1913        if (!is_this_device_mounted(bkpinfo->nfs_mount)) {
1914            popup_and_OK
1915                ("Please mount that partition before you try to backup to or restore from it.");
1916            finish(1);
1917        }
1918        strcpy(tmp, bkpinfo->nfs_remote_dir);
1919        if (!popup_and_get_string
1920            ("Directory", "Which directory within that mountpoint?", tmp,
1921             MAX_STR_LEN)) {
1922            log_to_screen("User has chosen not to backup the PC");
1923            finish(1);
1924        }
1925        strcpy(bkpinfo->nfs_remote_dir, tmp);
1926        // check whether writable - we better remove surrounding spaces for this
1927        strip_spaces(bkpinfo->nfs_remote_dir);
1928        sprintf(command, "echo hi > %s/%s/.dummy.txt", bkpinfo->isodir,
1929                bkpinfo->nfs_remote_dir);
1930        while (run_program_and_log_output(command, FALSE)) {
1931            strcpy(tmp, bkpinfo->nfs_remote_dir);
1932            asprintf(&prompt,
1933                     "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.",
1934                     bkpinfo->nfs_remote_dir, bkpinfo->isodir);
1935            if (!popup_and_get_string
1936                ("Directory", prompt, tmp, MAX_STR_LEN)) {
1937                log_to_screen("User has chosen not to backup the PC");
1938                finish(1);
1939            }
1940            strcpy(bkpinfo->nfs_remote_dir, tmp);
1941            // check whether writable - we better remove surrounding spaces for this */
1942            strip_spaces(bkpinfo->nfs_remote_dir);
1943            asprintf(&command, "echo hi > %s/%s/.dummy.txt",
1944                     bkpinfo->isodir, bkpinfo->nfs_remote_dir);
1945        }
1946        for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1947            bkpinfo->media_size[i] = 650;
1948        }
1949        log_msg(3, "Just set nfs_remote_dir to %s",
1950                bkpinfo->nfs_remote_dir);
1951        log_msg(3, "isodir is still %s", bkpinfo->isodir);
1952        break;
1953
1954    case iso:
1955        if (!bkpinfo->disaster_recovery) {
1956            if (!popup_and_get_string
1957                ("Storage dir.",
1958                 "Please enter the full path that contains your ISO images.  Example: /mnt/raid0_0",
1959                 bkpinfo->isodir, MAX_STR_LEN / 4)) {
1960                log_to_screen("User has chosen not to backup the PC");
1961                finish(1);
1962            }
1963            if (archiving_to_media) {
1964                if ((bkpinfo->compression_level =
1965                     which_compression_level()) == -1) {
1966                    log_to_screen("User has chosen not to backup the PC");
1967                    finish(1);
1968                }
1969                if (!popup_and_get_string
1970                    ("ISO size.",
1971                     "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.",
1972                     sz_size, 16)) {
1973                    log_to_screen("User has chosen not to backup the PC");
1974                    finish(1);
1975                }
1976                for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1977                    bkpinfo->media_size[i] = atoi(sz_size);
1978                }
1979                if (!popup_and_get_string
1980                    ("Prefix.",
1981                     "Please enter the prefix that will be prepended to your ISO filename.  Example: machine1 to obtain machine1-[1-9]*.iso files",
1982                     bkpinfo->prefix, MAX_STR_LEN / 4)) {
1983                    log_to_screen("User has chosen not to backup the PC");
1984                    finish(1);
1985                }
1986            } else {
1987                for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1988                    bkpinfo->media_size[i] = 650;
1989                }
1990            }
1991        }
1992        break;
1993    default:
1994        fatal_error
1995            ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
1996    }
1997    if (archiving_to_media) {
1998
1999#ifdef __FreeBSD__
2000        strcpy(bkpinfo->boot_device,
2001               call_program_and_get_last_line_of_output
2002               ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
2003#else
2004        strcpy(bkpinfo->boot_device,
2005               call_program_and_get_last_line_of_output
2006               ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
2007#endif
2008        i = which_boot_loader(bkpinfo->boot_device);
2009        if (i == 'U')           // unknown
2010        {
2011
2012#ifdef __FreeBSD__
2013            if (!popup_and_get_string
2014                ("Boot device",
2015                 "What is your boot device? (e.g. /dev/ad0)",
2016                 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2017                log_to_screen("User has chosen not to backup the PC");
2018                finish(1);
2019            }
2020            i = which_boot_loader(bkpinfo->boot_device);
2021#else
2022            if (!popup_and_get_string
2023                ("Boot device",
2024                 "What is your boot device? (e.g. /dev/hda)",
2025                 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2026                log_to_screen("User has chosen not to backup the PC");
2027                finish(1);
2028            }
2029            if (does_string_exist_in_boot_block
2030                (bkpinfo->boot_device, "LILO")) {
2031                i = 'L';
2032            } else
2033                if (does_string_exist_in_boot_block
2034                    (bkpinfo->boot_device, "ELILO")) {
2035                i = 'E';
2036            } else
2037                if (does_string_exist_in_boot_block
2038                    (bkpinfo->boot_device, "GRUB")) {
2039                i = 'G';
2040            } else {
2041                i = 'U';
2042            }
2043#endif
2044            if (i == 'U') {
2045                if (ask_me_yes_or_no
2046                    ("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?"))
2047                {
2048                    i = 'R';    // raw
2049                } else {
2050                    log_to_screen
2051                        ("I cannot find your boot loader. Please run mondoarchive with parameters.");
2052                    finish(1);
2053                }
2054            }
2055        }
2056        bkpinfo->boot_loader = i;
2057        strcpy(bkpinfo->include_paths, "/");
2058        if (!popup_and_get_string
2059            ("Backup paths",
2060             "Please enter paths which you want me to backup. The default is '/' (i.e. everything).",
2061             bkpinfo->include_paths, MAX_STR_LEN)) {
2062            log_to_screen("User has chosen not to backup the PC");
2063            finish(1);
2064        }
2065        strcpy(tmp, list_of_NFS_mounts_only());
2066        if (strlen(tmp) > 2) {
2067            if (bkpinfo->exclude_paths[0]) {
2068                strcat(bkpinfo->exclude_paths, " ");
2069            }
2070            strncpy(bkpinfo->exclude_paths, tmp, MAX_STR_LEN);
2071        }
2072// NTFS
2073        strcpy(tmp,
2074               call_program_and_get_last_line_of_output
2075               ("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'"));
2076        if (strlen(tmp) > 2) {
2077            if (!popup_and_get_string
2078                ("NTFS partitions",
2079                 "Please enter/confirm the NTFS partitions you wish to backup as well.",
2080                 tmp, MAX_STR_LEN / 4)) {
2081                log_to_screen("User has chosen not to backup the PC");
2082                finish(1);
2083            }
2084            strncpy(bkpinfo->image_devs, tmp, MAX_STR_LEN / 4);
2085        }
2086
2087
2088        if (!popup_and_get_string
2089            ("Exclude paths",
2090             "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.",
2091             bkpinfo->exclude_paths, MAX_STR_LEN)) {
2092            log_to_screen("User has chosen not to backup the PC");
2093            finish(1);
2094        }
2095        bkpinfo->make_cd_use_lilo = FALSE;
2096        bkpinfo->backup_data = TRUE;
2097        bkpinfo->verify_data =
2098            ask_me_yes_or_no
2099            ("Will you want to verify your backups after Mondo has created them?");
2100
2101#ifndef __FreeBSD__
2102        if (!ask_me_yes_or_no
2103            ("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."))
2104#endif
2105        {
2106            strcpy(bkpinfo->kernel_path, "FAILSAFE");
2107        }
2108
2109        if (!ask_me_yes_or_no
2110            ("Are you sure you want to proceed? Hit 'no' to abort.")) {
2111            log_to_screen("User has chosen not to backup the PC");
2112            finish(1);
2113        }
2114    } else {
2115        bkpinfo->restore_data = TRUE;   // probably...
2116    }
2117
2118    if (bkpinfo->backup_media_type == iso
2119        || bkpinfo->backup_media_type == nfs) {
2120        g_ISO_restore_mode = TRUE;
2121    }
2122#ifdef __FreeSD__
2123// skip
2124#else
2125    if (bkpinfo->backup_media_type == nfs) {
2126        sprintf(tmp, "mount | grep \"%s\" | cut -d' ' -f3",
2127                bkpinfo->nfs_mount);
2128//      strcpy(bkpinfo->isodir, call_program_and_get_last_line_of_output(tmp));
2129        log_msg(3, "I think the NFS mount is mounted at %s",
2130                bkpinfo->isodir);
2131    }
2132    log_it("isodir = %s", bkpinfo->isodir);
2133    log_it("nfs_mount = '%s'", bkpinfo->nfs_mount);
2134#endif
2135
2136    log_it("media device = %s", bkpinfo->media_device);
2137    log_it("media size = %ld", bkpinfo->media_size[1]);
2138    log_it("media type = %s",
2139           bkptype_to_string(bkpinfo->backup_media_type));
2140    log_it("compression = %ld", bkpinfo->compression_level);
2141    log_it("include_paths = '%s'", bkpinfo->include_paths);
2142    log_it("exclude_paths = '%s'", bkpinfo->exclude_paths);
2143    log_it("scratchdir = '%s'", bkpinfo->scratchdir);
2144    log_it("tmpdir = '%s'", bkpinfo->tmpdir);
2145    log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device,
2146           bkpinfo->boot_loader);
2147    log_it("prefix = %s", bkpinfo->prefix);
2148    if (bkpinfo->media_size[0] < 0) {
2149        if (archiving_to_media) {
2150            fatal_error("Media size is less than zero.");
2151        } else {
2152            log_msg(2, "Warning - media size is less than zero.");
2153            bkpinfo->media_size[0] = 0;
2154        }
2155    }
2156    paranoid_free(tmp);
2157    paranoid_free(sz_size);
2158    paranoid_free(command);
2159    paranoid_free(comment);
2160    paranoid_free(prompt);
2161    return (0);
2162}
2163
2164
2165
2166
2167/**
2168 * @addtogroup utilityGroup
2169 * @{
2170 */
2171/**
2172 * Get a space-separated list of NFS devices and mounts.
2173 * @return The list created.
2174 * @note The return value points to static data that will be overwritten with each call.
2175 */
2176char *list_of_NFS_devices_and_mounts(void)
2177{
2178    char *exclude_these_devices;
2179    char *exclude_these_directories;
2180    static char result_sz[512];
2181
2182    malloc_string(exclude_these_devices);
2183    malloc_string(exclude_these_directories);
2184    strcpy(exclude_these_directories,
2185           call_program_and_get_last_line_of_output
2186           ("mount -t coda,ncpfs,nfs,smbfs | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' ' ' | awk '{print $0;}'"));
2187    strcpy(exclude_these_devices,
2188           call_program_and_get_last_line_of_output
2189           ("cat /etc/fstab | tr -s '\t' ' ' | grep -E '( (coda|ncpfs|nfs|smbfs) )' | cut -d' ' -f1 | tr -s '\n' ' ' | awk '{print $0;}'"));
2190    sprintf(result_sz, "%s %s", exclude_these_directories,
2191            exclude_these_devices);
2192    paranoid_free(exclude_these_devices);
2193    paranoid_free(exclude_these_directories);
2194    return (result_sz);
2195}
2196
2197
2198
2199
2200/**
2201 * Get a space-separated list of NFS mounts.
2202 * @return The list created.
2203 * @note The return value points to static data that will be overwritten with each call.
2204 * @bug Even though we only want the mounts, the devices are still checked.
2205 */
2206char *list_of_NFS_mounts_only(void)
2207{
2208    char *exclude_these_devices;
2209    char *exclude_these_directories;
2210    static char result_sz[512];
2211
2212    malloc_string(exclude_these_devices);
2213    malloc_string(exclude_these_directories);
2214    strcpy(exclude_these_directories,
2215           call_program_and_get_last_line_of_output
2216           ("mount -t coda,ncpfs,nfs,smbfs | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' ' ' | awk '{print $0;}'"));
2217    strcpy(exclude_these_devices,
2218           call_program_and_get_last_line_of_output
2219           ("cat /etc/fstab | tr -s '\t' ' ' | grep -E '( (coda|ncpfs|nfs|smbfs) )' | cut -d' ' -f1 | tr -s '\n' ' ' | awk '{print $0;}'"));
2220    sprintf(result_sz, "%s", exclude_these_directories);
2221    paranoid_free(exclude_these_devices);
2222    paranoid_free(exclude_these_directories);
2223    return (result_sz);
2224}
2225
2226/* @} - end of utilityGroup */
2227
2228
2229
2230
2231
2232/**
2233 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
2234 * [random] is a random number between 1 and 32767.
2235 * @param store_name_here Where to store the new filename.
2236 * @param stub A random number will be appended to this to make the FIFO's name.
2237 * @ingroup deviceGroup
2238 */
2239void make_fifo(char *store_name_here, char *stub)
2240{
2241    char *tmp;
2242
2243    malloc_string(tmp);
2244    assert_string_is_neither_NULL_nor_zerolength(stub);
2245
2246    sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
2247            (int) (random() % 32768));
2248    make_hole_for_file(store_name_here);
2249    mkfifo(store_name_here, S_IRWXU | S_IRWXG);
2250    sprintf(tmp, "chmod 770 %s", store_name_here);
2251    paranoid_system(tmp);
2252    paranoid_free(tmp);
2253}
2254
2255
2256
2257
2258
2259
2260/**
2261 * Set the tmpdir and scratchdir to reside on the partition with the most free space.
2262 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
2263 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set.
2264 * @ingroup utilityGroup
2265 */
2266void sensibly_set_tmpdir_and_scratchdir(struct s_bkpinfo *bkpinfo)
2267{
2268    char *tmp, *command, *sz;
2269
2270    malloc_string(tmp);
2271    malloc_string(command);
2272    malloc_string(sz);
2273    assert(bkpinfo != NULL);
2274
2275#ifdef __FreeBSD__
2276    strcpy(tmp,
2277           call_program_and_get_last_line_of_output
2278           ("df -m -t nonfs,msdosfs,ntfs,smbfs,smb,cifs | tr -s '\t' ' ' | grep -v none | grep -v Filesystem | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -n | tail -n1 | awk '{print $NF;}'"));
2279#else
2280    strcpy(tmp,
2281           call_program_and_get_last_line_of_output
2282           ("df -m -x nfs -x vfat -x ntfs -x smbfs -x smb -x cifs | sed 's/                  /devdev/' | tr -s '\t' ' ' | grep -v none | grep -v Filesystem | grep -v /dev/shm | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -n | tail -n1 | awk '{print $NF;}'"));
2283#endif
2284
2285    if (tmp[0] != '/') {
2286        strcpy(sz, tmp);
2287        strcpy(tmp, "/");
2288        strcat(tmp, sz);
2289    }
2290    if (!tmp[0]) {
2291        fatal_error("I couldn't figure out the tempdir!");
2292    }
2293    sprintf(bkpinfo->tmpdir, "%s/tmp.mondo.%d", tmp,
2294            (int) (random() % 32768));
2295    log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir);
2296
2297    sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%d", tmp,
2298            (int) (random() % 32768));
2299    log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
2300
2301    sprintf(g_erase_tmpdir_and_scratchdir, "rm -Rf %s %s", bkpinfo->tmpdir,
2302            bkpinfo->scratchdir);
2303
2304    sprintf(command, "rm -Rf %s/tmp.mondo.* %s/mondo.scratch.*", tmp, tmp);
2305    paranoid_system(command);
2306    paranoid_free(tmp);
2307    paranoid_free(command);
2308    paranoid_free(sz);
2309}
2310
2311
2312
2313
2314
2315
2316/**
2317 * @addtogroup deviceGroup
2318 * @{
2319 */
2320/**
2321 * If we can read @p dev, set @p output to it.
2322 * If @p dev cannot be read, set @p output to "".
2323 * @param dev The device to check for.
2324 * @param output Set to @p dev if @p dev exists, "" otherwise.
2325 * @return TRUE if @p dev exists, FALSE if it doesn't.
2326 */
2327bool set_dev_to_this_if_rx_OK(char *output, char *dev)
2328{
2329    char *command;
2330
2331    malloc_string(command);
2332    if (!dev || dev[0] == '\0') {
2333        output[0] = '\0';
2334        return (FALSE);
2335    }
2336//  assert_string_is_neither_NULL_nor_zerolength(dev);
2337    log_msg(10, "Injecting %s", dev);
2338    inject_device(dev);
2339    if (!does_file_exist(dev)) {
2340        log_msg(10, "%s doesn't exist. Returning FALSE.", dev);
2341        return (FALSE);
2342    }
2343    sprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null",
2344            512L, dev);
2345    if (!run_program_and_log_output(command, FALSE)
2346        && !run_program_and_log_output(command, FALSE)) {
2347        strcpy(output, dev);
2348        log_msg(4, "Found it - %s", dev);
2349        return (TRUE);
2350    } else {
2351        output[0] = '\0';
2352        log_msg(4, "It's not %s", dev);
2353        return (FALSE);
2354    }
2355}
2356
2357
2358
2359
2360
2361/**
2362 * Find out what number CD is in the drive.
2363 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
2364 * @return The current CD number, or -1 if it could not be found.
2365 * @note If the CD is not mounted, it will be mounted
2366 * (and remain mounted after this function returns).
2367 */
2368int what_number_cd_is_this(struct s_bkpinfo *bkpinfo)
2369{
2370    int cd_number = -1;
2371    char *mountdev;
2372    char *tmp;
2373
2374    malloc_string(mountdev);
2375    malloc_string(tmp);
2376    assert(bkpinfo != NULL);
2377//  log_it("Asking what_number_cd_is_this");
2378    if (g_ISO_restore_mode) {
2379        sprintf(tmp, "mount | grep iso9660 | awk '{print $3;}'");
2380//      log_it("tmp = %s", tmp);
2381
2382        strcpy(mountdev, call_program_and_get_last_line_of_output(tmp));
2383        strcat(mountdev, "/archives/THIS-CD-NUMBER");
2384//      log_it("mountdev = %s", mountdev);
2385        cd_number = atoi(last_line_of_file(mountdev));
2386//      log_it("cd_number = %d", cd_number);
2387        paranoid_free(mountdev);
2388        paranoid_free(tmp);
2389        return (cd_number);
2390    }
2391
2392    strcpy(mountdev, bkpinfo->media_device);
2393    if (!mountdev[0]) {
2394        log_it
2395            ("(what_number_cd_is_this) Warning - media_device unknown. Finding out...");
2396        find_cdrom_device(bkpinfo->media_device, FALSE);
2397    }
2398    if (!is_this_device_mounted(MNT_CDROM)) {
2399        mount_CDROM_here(mountdev, MNT_CDROM);
2400    }
2401    cd_number =
2402        atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
2403//  log_it("cd_number..later.. = %d", cd_number);
2404    paranoid_free(mountdev);
2405    paranoid_free(tmp);
2406    return (cd_number);
2407}
2408
2409
2410
2411
2412
2413
2414
2415/**
2416 * Find out what device is mounted as root (/).
2417 * @return Root device.
2418 * @note The returned string points to static storage and will be overwritten with every call.
2419 * @bug A bit of a misnomer; it's actually finding out the root device.
2420 * The mountpoint (where it's mounted) will obviously be '/'.
2421 */
2422char *where_is_root_mounted()
2423{
2424    /*@ buffers **************** */
2425    static char tmp[MAX_STR_LEN];
2426
2427
2428#ifdef __FreeBSD__
2429    strcpy(tmp, call_program_and_get_last_line_of_output
2430           ("mount | grep \" on / \" | cut -d' ' -f1"));
2431#else
2432    strcpy(tmp, call_program_and_get_last_line_of_output
2433           ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"));
2434    if (strstr(tmp, "/dev/cciss/")) {
2435        strcpy(tmp, call_program_and_get_last_line_of_output
2436               ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"));
2437    }
2438    if (strstr(tmp, "/dev/md")) {
2439        strcpy(tmp,
2440               call_program_and_get_last_line_of_output
2441               ("mount | grep \" on / \" | cut -d' ' -f1"));
2442    }
2443#endif
2444
2445    return (tmp);
2446}
2447
2448
2449/**
2450 * Find out which boot loader is in use.
2451 * @param which_device Device to look for the boot loader on.
2452 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
2453 * @note Under Linux, all drives are examined, not just @p which_device.
2454 */
2455#ifdef __FreeBSD__
2456char which_boot_loader(char *which_device)
2457{
2458    int count_lilos = 0;
2459    int count_grubs = 0;
2460    int count_boot0s = 0;
2461    int count_dangerouslydedicated = 0;
2462
2463    log_it("looking at drive %s's MBR", which_device);
2464    if (does_string_exist_in_boot_block(which_device, "GRUB")) {
2465        count_grubs++;
2466    }
2467    if (does_string_exist_in_boot_block(which_device, "LILO")) {
2468        count_lilos++;
2469    }
2470    if (does_string_exist_in_boot_block(which_device, "Drive")) {
2471        count_boot0s++;
2472    }
2473    if (does_string_exist_in_first_N_blocks
2474        (which_device, "FreeBSD/i386", 17)) {
2475        count_dangerouslydedicated++;
2476    }
2477    log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
2478           count_grubs, count_lilos, count_elilos, count_boot0s,
2479           count_dangerouslydedicated);
2480
2481    if (count_grubs && !count_lilos) {
2482        return ('G');
2483    } else if (count_lilos && !count_grubs) {
2484        return ('L');
2485    } else if (count_grubs == 1 && count_lilos == 1) {
2486        log_it("I'll bet you used to use LILO but switched to GRUB...");
2487        return ('G');
2488    } else if (count_boot0s == 1) {
2489        return ('B');
2490    } else if (count_dangerouslydedicated) {
2491        return ('D');
2492    } else {
2493        log_it("Unknown boot loader");
2494        return ('U');
2495    }
2496}
2497
2498#else
2499
2500char which_boot_loader(char *which_device)
2501{
2502    /*@ buffer ***************************************************** */
2503    char *list_drives_cmd;
2504    char *current_drive;
2505
2506    /*@ pointers *************************************************** */
2507    FILE *pdrives;
2508
2509    /*@ int ******************************************************** */
2510    int count_lilos = 0;
2511    int count_grubs = 0;
2512
2513    /*@ end vars *************************************************** */
2514
2515    malloc_string(list_drives_cmd);
2516    malloc_string(current_drive);
2517
2518#ifdef __IA64__
2519    /* No choice for it */
2520    return ('E');
2521#endif
2522    assert(which_device != NULL);
2523    //  sprintf (list_drives_cmd,
2524    //       "fdisk -l | grep /dev | grep cyl | tr ':' ' ' | cut -d' ' -f2");
2525
2526    sprintf(list_drives_cmd,
2527            // "parted2fdisk
2528            "fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s",
2529            where_is_root_mounted());
2530    log_it("list_drives_cmd = %s", list_drives_cmd);
2531
2532    if (!(pdrives = popen(list_drives_cmd, "r"))) {
2533        log_OS_error("Unable to open list of drives");
2534        paranoid_free(list_drives_cmd);
2535        paranoid_free(current_drive);
2536        return ('\0');
2537    }
2538    for (fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
2539         fgets(current_drive, MAX_STR_LEN, pdrives)) {
2540        strip_spaces(current_drive);
2541        log_it("looking at drive %s's MBR", current_drive);
2542        if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
2543            count_grubs++;
2544            strcpy(which_device, current_drive);
2545            break;
2546        }
2547        if (does_string_exist_in_boot_block(current_drive, "LILO")) {
2548            count_lilos++;
2549            strcpy(which_device, current_drive);
2550            break;
2551        }
2552    }
2553    if (pclose(pdrives)) {
2554        log_OS_error("Cannot pclose pdrives");
2555    }
2556    log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
2557    paranoid_free(list_drives_cmd);
2558    paranoid_free(current_drive);
2559    if (count_grubs && !count_lilos) {
2560        return ('G');
2561    } else if (count_lilos && !count_grubs) {
2562        return ('L');
2563    } else if (count_grubs == 1 && count_lilos == 1) {
2564        log_it("I'll bet you used to use LILO but switched to GRUB...");
2565        return ('G');
2566    } else {
2567        log_it("Unknown boot loader");
2568        return ('U');
2569    }
2570}
2571#endif
2572
2573
2574
2575
2576/**
2577 * Write zeroes over the first 16K of @p device.
2578 * @param device The device to zero.
2579 * @return 0 for success, 1 for failure.
2580 */
2581int zero_out_a_device(char *device)
2582{
2583    FILE *fout;
2584    int i;
2585
2586    assert_string_is_neither_NULL_nor_zerolength(device);
2587
2588    log_it("Zeroing drive %s", device);
2589    if (!(fout = fopen(device, "w"))) {
2590        log_OS_error("Unable to open/write to device");
2591        return (1);
2592    }
2593    for (i = 0; i < 16384; i++) {
2594        fputc('\0', fout);
2595    }
2596    paranoid_fclose(fout);
2597    log_it("Device successfully zeroed.");
2598    return (0);
2599}
2600
2601/**
2602 * Return the device pointed to by @p incoming.
2603 * @param incoming The device to resolve symlinks for.
2604 * @return The path to the real device file.
2605 * @note The returned string points to static storage that will be overwritten with each call.
2606 * @bug Won't work with file v4.0; needs to be written in C.
2607 */
2608char *resolve_softlinks_to_get_to_actual_device_file(char *incoming)
2609{
2610    static char output[MAX_STR_LEN];
2611    char *command;
2612    char *curr_fname;
2613    char *scratch;
2614    char *tmp;
2615    char *p;
2616
2617    struct stat statbuf;
2618    command = malloc(1000);
2619    malloc_string(tmp);
2620    malloc_string(scratch);
2621    malloc_string(curr_fname);
2622    if (!does_file_exist(incoming)) {
2623        log_it
2624            ("resolve_softlinks_to_get_to_actual_device_file --- device not found");
2625        strcpy(output, incoming);
2626    } else {
2627        strcpy(curr_fname, incoming);
2628        lstat(curr_fname, &statbuf);
2629        while (S_ISLNK(statbuf.st_mode)) {
2630            log_msg(1, "curr_fname = %s", curr_fname);
2631            sprintf(command, "file %s", curr_fname);
2632            strcpy(tmp, call_program_and_get_last_line_of_output(command));
2633            for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' ';
2634                 p--);
2635            p++;
2636            strcpy(scratch, p);
2637            for (p = scratch; *p != '\0' && *p != '\''; p++);
2638            *p = '\0';
2639            log_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp,
2640                    scratch);
2641            if (scratch[0] == '/') {
2642                strcpy(curr_fname, scratch);    // copy whole thing because it's an absolute softlink
2643            } else {            // copy over the basename cos it's a relative softlink
2644                p = curr_fname + strlen(curr_fname);
2645                while (p != curr_fname && *p != '/') {
2646                    p--;
2647                }
2648                if (*p == '/') {
2649                    p++;
2650                }
2651                strcpy(p, scratch);
2652            }
2653            lstat(curr_fname, &statbuf);
2654        }
2655        strcpy(output, curr_fname);
2656        log_it("resolved %s to %s", incoming, output);
2657    }
2658    paranoid_free(command);
2659    paranoid_free(curr_fname);
2660    paranoid_free(tmp);
2661    return (output);
2662}
2663
2664/* @} - end of deviceGroup */
2665
2666
2667/**
2668 * Return the type of partition format (GPT or MBR)
2669 */
2670char *which_partition_format(const char *drive)
2671{
2672    static char output[4];
2673    char *tmp;
2674    char *command;
2675    char *fdisk;
2676
2677    malloc_string(tmp);
2678    malloc_string(command);
2679    malloc_string(fdisk);
2680    log_msg(0, "Looking for partition table format type");
2681// BERLIOS: Do that temporarily: we need to put back parted2fdisk everywhere
2682#ifdef __IA64__
2683    struct stat buf;
2684
2685    sprintf(fdisk, "/usr/local/bin/fdisk");
2686    if (stat(fdisk, &buf) != 0) {
2687#endif
2688        sprintf(fdisk, "/sbin/fdisk");
2689#ifdef __IA64__
2690    }
2691#endif
2692    log_msg(1, "Using %s", fdisk);
2693    sprintf(command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
2694    strcpy(tmp, call_program_and_get_last_line_of_output(command));
2695    if (strstr(tmp, "GPT") == NULL) {
2696        strcpy(output, "MBR");
2697    } else {
2698        strcpy(output, "GPT");
2699    }
2700    log_msg(0, "Found %s partition table format type", output);
2701    paranoid_free(command);
2702    paranoid_free(tmp);
2703    paranoid_free(fdisk);
2704    return (output);
2705}
2706
2707/* @} - end of deviceGroup */
Note: See TracBrowser for help on using the repository browser.