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

Last change on this file since 1977 was 1977, checked in by Bruno Cornec, 16 years ago

svn merge -r 1938:1976 $SVN_M/branches/2.2.6

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