source: MondoRescue/branches/2.2.9/mondo/src/common/libmondo-devices.c@ 2769

Last change on this file since 2769 was 2769, checked in by Bruno Cornec, 13 years ago
  • Introduce a new bkpinfo member (subdir) to support storing the subdir under which ISO images are stored on an external HDD. Should fix mostly #433.
  • Property svn:keywords set to Id
File size: 95.1 KB
Line 
1/* libmondo-devices.c Subroutines for handling devices
2 $Id: libmondo-devices.c 2769 2011-04-21 11:48:52Z bruno $
3*/
4
5/**
6 * @file
7 * Functions to handle interactions with backup devices.
8 */
9
10#include "my-stuff.h"
11#include "mr_mem.h"
12#include "mr_str.h"
13#include "mondostructures.h"
14#include "libmondo-files-EXT.h"
15#include "libmondo-devices.h"
16#include "lib-common-externs.h"
17#include "libmondo-string-EXT.h"
18#include "libmondo-tools-EXT.h"
19#include "libmondo-gui-EXT.h"
20#include "libmondo-fork-EXT.h"
21#include "libmondo-stream-EXT.h"
22
23#include <sys/types.h>
24#ifdef __FreeBSD__
25#define DKTYPENAMES
26#define FSTYPENAMES
27#include <sys/disklabel.h>
28#include <sys/disk.h>
29#elif linux
30#define u64 unsigned long long
31#include <linux/fs.h> /* for BLKGETSIZE64 */
32#include <linux/hdreg.h>
33#endif
34
35/*@unused@*/
36//static char cvsid[] = "$Id: libmondo-devices.c 2769 2011-04-21 11:48:52Z bruno $";
37
38extern int g_current_media_number;
39extern double g_kernel_version;
40
41extern bool g_ISO_restore_mode;
42extern char *g_selfmounted_isodir;
43extern char *MONDO_LOGFILE;
44
45extern void setup_tmpdir(char *path);
46
47static char g_cdrw_drive_is_here[MAX_STR_LEN / 4] = "";
48static char g_cdrom_drive_is_here[MAX_STR_LEN / 4] = "";
49static char g_dvd_drive_is_here[MAX_STR_LEN / 4] = "";
50
51
52/**
53 * ????? @bug ?????
54 * @ingroup globalGroup
55 */
56bool g_restoring_live_from_cd = FALSE;
57bool g_restoring_live_from_netfs = FALSE;
58
59extern t_bkptype g_backup_media_type; // set by main()
60
61/* Reference to global bkpinfo */
62extern struct s_bkpinfo *bkpinfo;
63
64/* Stuff that handles the -I and -E option when a whole disk DSF is used */
65typedef struct mounted_fs_struct {
66 char device[MAX_STR_LEN]; /* The name of the device */
67 char mount_point[MAX_STR_LEN]; /* The devices mount point */
68 unsigned char check; /* 1 == included on DSF */
69 struct mounted_fs_struct *next;
70} MOUNTED_FS_STRUCT;
71
72static MOUNTED_FS_STRUCT *DSF_Head = NULL; /* Points to the first entry of mounted_fs_struct list */
73static MOUNTED_FS_STRUCT *DSF_Tail = NULL; /* Points to the last entry of mounted_fs_struct list */
74
75
76void set_g_cdrom_and_g_dvd_to_bkpinfo_value()
77{
78 strcpy(g_cdrom_drive_is_here, bkpinfo->media_device); // just in case
79 strcpy(g_dvd_drive_is_here, bkpinfo->media_device); // just in case
80}
81
82
83
84/**
85 * Retract all CD trays and wait for autorun to complete.
86 * @ingroup deviceGroup
87 */
88void retract_CD_tray_and_defeat_autorun(void)
89{
90// log_it("rctada: Retracting all CD trays", __LINE__);
91 if (strlen(g_cdrom_drive_is_here) > 0) {
92 inject_device(g_cdrom_drive_is_here);
93 }
94 if (strlen(g_dvd_drive_is_here) > 0) {
95 inject_device(g_dvd_drive_is_here);
96 }
97 if (strlen(g_cdrw_drive_is_here) > 0) {
98 inject_device(g_cdrw_drive_is_here);
99 }
100// log_it("rctada: killing autorun");
101// run_program_and_log_output("killall autorun", TRUE);
102 if (!run_program_and_log_output("ps | grep autorun | grep -v grep", 5)) {
103 log_it("autorun detected; sleeping for 2 seconds");
104 sleep(2);
105 }
106 log_it("rctada: Unmounting all CD drives", __LINE__);
107 run_program_and_log_output("umount /dev/cdr* /dev/dvd*", 5);
108}
109
110
111
112/**
113 * Determine whether we're booted off a ramdisk.
114 * @return @c TRUE (we are) or @c FALSE (we aren't).
115 * @ingroup utilityGroup
116 */
117bool am_I_in_disaster_recovery_mode(void)
118{
119 char *tmp = NULL;
120 char *comment;
121 bool is_this_a_ramdisk = FALSE;
122
123 malloc_string(comment);
124 mr_asprintf(&tmp, "%s", where_is_root_mounted());
125 sprintf(comment, "root is mounted at %s\n", tmp);
126 log_msg(0, comment);
127 log_msg(0,
128 "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().",
129 tmp);
130
131#ifdef __FreeBSD__
132 if (strstr(tmp, "/dev/md")) {
133 is_this_a_ramdisk = TRUE;
134 }
135#else
136 if (!strncmp(tmp, "/dev/ram", 8)
137 || (!strncmp(tmp, "/dev/rd", 7) && !strcmp(tmp, "/dev/rd/")
138 && strncmp(tmp, "/dev/rd/cd", 10)) || strstr(tmp, "rootfs")
139 || !strcmp(tmp, "/dev/root")) {
140 is_this_a_ramdisk = TRUE;
141 } else {
142 is_this_a_ramdisk = FALSE;
143 }
144#endif
145 mr_free(tmp);
146
147 if (is_this_a_ramdisk) {
148 if (!does_file_exist("/THIS-IS-A-RAMDISK")) {
149 log_to_screen
150 ("Using /dev/root is stupid of you but I'll forgive you.");
151 is_this_a_ramdisk = FALSE;
152 }
153 }
154 if (does_file_exist("/THIS-IS-A-RAMDISK")) {
155 is_this_a_ramdisk = TRUE;
156 }
157 paranoid_free(comment);
158 log_msg(1, "Is this a ramdisk? result = %d", is_this_a_ramdisk);
159 return (is_this_a_ramdisk);
160}
161
162
163
164
165
166/**
167 * Turn @c bkpinfo->backup_media_type into a human-readable string.
168 * @return The human readable string (e.g. @c cdr becomes <tt>"cdr"</tt>).
169 * @note The returned string points to static storage that will be overwritten with each call.
170 * @ingroup stringGroup
171 */
172static char *bkptype_to_string(t_bkptype bt)
173{
174 static char output[MAX_STR_LEN / 4];
175 switch (bt) {
176 case none:
177 strcpy(output, "none");
178 break;
179 case iso:
180 strcpy(output, "iso");
181 break;
182 case cdr:
183 strcpy(output, "cdr");
184 break;
185 case cdrw:
186 strcpy(output, "cdrw");
187 break;
188 case cdstream:
189 strcpy(output, "cdstream");
190 break;
191 case netfs:
192 strcpy(output, "netfs");
193 break;
194 case tape:
195 strcpy(output, "tape");
196 break;
197 case udev:
198 strcpy(output, "udev");
199 break;
200 case usb:
201 strcpy(output, "usb");
202 break;
203 default:
204 strcpy(output, "default");
205 }
206 return (output);
207}
208
209
210
211/**
212 * @addtogroup deviceGroup
213 * @{
214 */
215/**
216 * Eject the tray of the specified CD device.
217 * @param dev The device to eject.
218 * @return the return value of the @c eject command. (0=success, nonzero=failure)
219 */
220int eject_device(char *dev)
221{
222 char *command;
223 int res1 = 0, res2 = 0;
224
225 malloc_string(command);
226
227 if (IS_THIS_A_STREAMING_BACKUP(g_backup_media_type)
228 && g_backup_media_type != udev) {
229 sprintf(command, "mt -f %s offline", dev);
230 res1 = run_program_and_log_output(command, 1);
231 } else {
232 res1 = 0;
233 }
234
235#ifdef __FreeBSD__
236 if (strstr(dev, "acd")) {
237 sprintf(command, "cdcontrol -f %s eject", dev);
238 } else {
239 sprintf(command, "camcontrol eject `echo %s | sed 's|/dev/||'`",
240 dev);
241 }
242#else
243 sprintf(command, "eject %s", dev);
244#endif
245
246 log_msg(3, "Ejecting %s", dev);
247 res2 = run_program_and_log_output(command, 1);
248 paranoid_free(command);
249 if (res1 && res2) {
250 return (1);
251 } else {
252 return (0);
253 }
254}
255
256/**
257 * Load (inject) the tray of the specified CD device.
258 * @param dev The device to load/inject.
259 * @return 0 for success, nonzero for failure.
260 */
261int inject_device(char *dev)
262{
263 char *command;
264 int i;
265
266 malloc_string(command);
267
268
269#ifdef __FreeBSD__
270 if (strstr(dev, "acd")) {
271 sprintf(command, "cdcontrol -f %s close", dev);
272 } else {
273 sprintf(command, "camcontrol load `echo %s | sed 's|/dev/||'`",
274 dev);
275 }
276#else
277 sprintf(command, "eject -t %s", dev);
278#endif
279 i = run_program_and_log_output(command, FALSE);
280 paranoid_free(command);
281 return (i);
282}
283
284
285/**
286 * Determine whether the specified @p device (really, you can use any file)
287 * exists.
288 * @return TRUE if it exists, FALSE if it doesn't.
289 */
290bool does_device_exist(char *device)
291{
292
293 /*@ buffers *********************************************************** */
294 char *tmp;
295 bool ret;
296
297 malloc_string(tmp);
298 assert_string_is_neither_NULL_nor_zerolength(device);
299
300 sprintf(tmp, "ls %s > /dev/null 2> /dev/null", device);
301
302 if (system(tmp)) {
303 ret = FALSE;
304 } else {
305 ret = TRUE;
306 }
307 paranoid_free(tmp);
308 return (ret);
309}
310
311
312/**
313 * Determine whether a non-Microsoft partition exists on any connected hard drive.
314 * @return TRUE (there's a Linux/FreeBSD partition) or FALSE (Microsoft has taken over yet another innocent PC).
315 */
316bool does_nonMS_partition_exist(void)
317{
318#if __FreeBSD__
319 return
320 !system
321 ("for drive in /dev/ad? /dev/da?; do fdisk $drive | grep -q FreeBSD && exit 0; done; false");
322#else
323 return
324 !system
325 ("parted2fdisk -l 2>/dev/null | grep '^/dev/' | grep -Eqv '(MS|DOS|FAT|NTFS)'");
326#endif
327}
328
329/**
330 * Determine whether the specified @p partno exists on the specified @p drive.
331 * @param drive The drive to search for the partition in.
332 * @param partno The partition number to look for.
333 * @return 0 if it exists, nonzero otherwise.
334 */
335int does_partition_exist(const char *drive, int partno)
336{
337 /*@ buffers **************************************************** */
338 char *program;
339 char *incoming;
340 char *searchstr = NULL;
341 char *tmp;
342
343 /*@ ints ******************************************************* */
344 int res = 0;
345
346 /*@ pointers *************************************************** */
347 FILE *fin;
348
349
350 /*@ end vars *************************************************** */
351 assert_string_is_neither_NULL_nor_zerolength(drive);
352 assert(partno >= 0 && partno < 999);
353
354 malloc_string(program);
355 malloc_string(incoming);
356 malloc_string(searchstr);
357 malloc_string(tmp);
358
359#ifdef __FreeBSD__
360 // We assume here that this is running from mondorestore. (It is.)
361 sprintf(program, "ls %s %s >/dev/null 2>&1", drive,
362 build_partition_name(tmp, drive, partno));
363 return system(program);
364#else
365 tmp[0] = '\0';
366#endif
367
368 sprintf(program, "parted2fdisk -l %s 2> /dev/null", drive);
369 fin = popen(program, "r");
370 if (!fin) {
371 log_it("program=%s", program);
372 log_OS_error("Cannot popen-in program");
373 return (0);
374 }
375 (void) build_partition_name(searchstr, drive, partno);
376 strcat(searchstr, " ");
377 for (res = 0; !res && fgets(incoming, MAX_STR_LEN - 1, fin);) {
378 if (strstr(incoming, searchstr)) {
379 res = 1;
380 }
381 }
382 if (pclose(fin)) {
383 log_OS_error("Cannot pclose fin");
384 }
385 paranoid_free(program);
386 paranoid_free(incoming);
387 paranoid_free(searchstr);
388 paranoid_free(tmp);
389 return (res);
390}
391
392
393
394
395
396/**
397 * Determine whether given NULL-terminated @p str exists in the MBR of @p dev.
398 * @param dev The device to look in.
399 * @param str The string to look for.
400 * @return TRUE if it exists, FALSE if it doesn't.
401 */
402bool does_string_exist_in_boot_block(char *dev, char *str)
403{
404 /*@ buffers **************************************************** */
405 char *command;
406
407 /*@ end vars *************************************************** */
408 int i;
409
410 assert_string_is_neither_NULL_nor_zerolength(dev);
411 assert_string_is_neither_NULL_nor_zerolength(str);
412
413 malloc_string(command);
414 sprintf(command,
415 "dd if=%s bs=446 count=1 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null",
416 dev, str);
417 i = system(command);
418 paranoid_free(command);
419 if (i) {
420 return (FALSE);
421 } else {
422 return (TRUE);
423 }
424}
425
426/**
427 * Determine whether specified @p str exists in the first @p n sectors of
428 * @p dev.
429 * @param dev The device to look in.
430 * @param str The string to look for.
431 * @param n The number of 512-byte sectors to search.
432 */
433bool does_string_exist_in_first_N_blocks(char *dev, char *str, int n)
434{
435 /*@ buffers **************************************************** */
436 char *command;
437 /*@ end vars *************************************************** */
438 int i;
439
440 malloc_string(command);
441 sprintf(command,
442 "dd if=%s bs=512 count=%i 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null",
443 dev, n, str);
444 i = system(command);
445 paranoid_free(command);
446 if (i) {
447 return (FALSE);
448 } else {
449 return (TRUE);
450 }
451}
452
453
454
455/**
456 * Try to mount CD-ROM at @p mountpoint. If the CD-ROM is not found or has
457 * not been specified, call find_cdrom_device() to find it.
458 * @param bkpinfo The backup information structure. The only field used is @c bkpinfo->media_device.
459 * @param mountpoint Where to mount the CD-ROM.
460 * @return 0 for success, nonzero for failure.
461 * @see mount_CDROM_here
462 */
463int find_and_mount_actual_cd(char *mountpoint)
464{
465 /*@ buffers ***************************************************** */
466
467 /*@ int's ****************************************************** */
468 int res;
469 char *dev;
470
471 /*@ end vars **************************************************** */
472
473 malloc_string(dev);
474 assert(bkpinfo != NULL);
475 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
476
477 if (g_backup_media_type == dvd) {
478 strcpy(dev, g_dvd_drive_is_here);
479 if (!dev[0]) {
480 find_dvd_device(dev, FALSE);
481 }
482 } else {
483 strcpy(dev, g_cdrom_drive_is_here);
484 if (!dev[0]) {
485 find_cdrom_device(dev, FALSE);
486 }
487 }
488
489 if (bkpinfo->backup_media_type != iso) {
490 retract_CD_tray_and_defeat_autorun();
491 }
492
493 if (!dev[0] || (res = mount_CDROM_here(dev, mountpoint))) {
494 if (!popup_and_get_string
495 ("CD-ROM device", "Please enter your CD-ROM's /dev device",
496 dev, MAX_STR_LEN / 4)) {
497 res = 1;
498 } else {
499 res = mount_CDROM_here(dev, mountpoint);
500 }
501 }
502 if (res) {
503 log_msg(1, "mount failed");
504 } else {
505 log_msg(1, "mount succeeded with %s", dev);
506 }
507 paranoid_free(dev);
508 return (res);
509}
510
511
512
513
514
515
516/**
517 * Locate a CD-R/W writer's SCSI node.
518 * @param cdrw_device SCSI node will be placed here.
519 * @return 0 for success, nonzero for failure.
520 */
521int find_cdrw_device(char *cdrw_device)
522{
523 /*@ buffers ************************ */
524 char *comment;
525 char *tmp = NULL;
526 char *cdr_exe = NULL;
527 char *command;
528
529 malloc_string(comment);
530 malloc_string(command);
531 if (g_cdrw_drive_is_here[0]) {
532 strcpy(cdrw_device, g_cdrw_drive_is_here);
533 log_msg(3, "Been there, done that. Returning %s", cdrw_device);
534 paranoid_free(comment);
535 paranoid_free(command);
536 return (0);
537 }
538 if (g_backup_media_type == dvd) {
539 log_msg(1,
540 "This is dumb. You're calling find_cdrw_device() but you're backing up to DVD. WTF?");
541 paranoid_free(comment);
542 paranoid_free(command);
543 return (1);
544 }
545 run_program_and_log_output("insmod ide-scsi", -1);
546 if (find_home_of_exe("cdrecord")) {
547 mr_asprintf(&cdr_exe, "cdrecord");
548 } else {
549 mr_asprintf(&cdr_exe, "dvdrecord");
550 }
551 if (find_home_of_exe(cdr_exe)) {
552 sprintf(command,
553 "%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",
554 cdr_exe);
555 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
556 }
557 if ((tmp == NULL) || (strlen(tmp) < 2)) {
558 paranoid_free(comment);
559 mr_free(tmp);
560 mr_free(cdr_exe);
561 paranoid_free(command);
562 return 1;
563 } else {
564 strcpy(cdrw_device, tmp);
565 sprintf(comment, "Found CDRW device - %s", cdrw_device);
566 log_it(comment);
567 strcpy(g_cdrw_drive_is_here, cdrw_device);
568 paranoid_free(comment);
569 mr_free(tmp);
570 mr_free(cdr_exe);
571 paranoid_free(command);
572 return (0);
573 }
574}
575
576
577
578
579/**
580 * Attempt to locate a CD-ROM device's /dev entry.
581 * Several different methods may be used to find the device, including
582 * calling @c cdrecord, searching @c dmesg, and trial-and-error.
583 * @param output Where to put the located /dev entry.
584 * @param try_to_mount Whether to mount the CD as part of the test; if mount
585 * fails then return failure.
586 * @return 0 for success, nonzero for failure.
587 */
588int find_cdrom_device(char *output, bool try_to_mount)
589{
590 /*@ pointers **************************************************** */
591 FILE *fin;
592 char *p;
593 char *q;
594 char *r;
595 int retval = 0;
596
597 /*@ bool's ****************************************************** */
598 bool found_it = FALSE;
599
600 /*@ buffers ***************************************************** */
601 char *tmp;
602 char *tmp1 = NULL;
603 char *cdr_exe = NULL;
604 char *phrase_one;
605 char *phrase_two;
606 char *command;
607 char *dvd_last_resort;
608 char *mountpoint;
609 static char the_last_place_i_found_it[MAX_STR_LEN] = "";
610
611 /*@ intialize *************************************************** */
612 malloc_string(tmp);
613 malloc_string(phrase_one);
614 malloc_string(phrase_two);
615 malloc_string(command);
616 malloc_string(dvd_last_resort);
617 malloc_string(mountpoint);
618
619 output[0] = '\0';
620 phrase_one[0] = '\0';
621 phrase_two[0] = '\0';
622 dvd_last_resort[0] = '\0';
623
624 /*@ end vars **************************************************** */
625
626 if (g_cdrom_drive_is_here[0] && !isdigit(g_cdrom_drive_is_here[0])) {
627 strcpy(output, g_cdrom_drive_is_here);
628 log_msg(3, "Been there, done that. Returning %s", output);
629 retval = 0;
630 goto end_of_find_cdrom_device;
631 }
632 if (the_last_place_i_found_it[0] != '\0' && !try_to_mount) {
633 strcpy(output, the_last_place_i_found_it);
634 log_msg(3,
635 "find_cdrom_device() --- returning last found location - '%s'",
636 output);
637 retval = 0;
638 goto end_of_find_cdrom_device;
639 }
640
641 sprintf(mountpoint, "%s/cd.mnt", bkpinfo->tmpdir);
642 make_hole_for_dir(mountpoint);
643
644 if (find_home_of_exe("cdrecord")) {
645 mr_asprintf(&cdr_exe, "cdrecord");
646 } else {
647 mr_asprintf(&cdr_exe, "dvdrecord");
648 }
649 tmp[0] = '\0';
650 if (!find_home_of_exe(cdr_exe)) {
651 strcpy(output, "/dev/cdrom");
652 log_msg(4, "Can't find cdrecord; assuming %s", output);
653 if (!does_device_exist(output)) {
654 log_msg(4, "That didn't work. Sorry.");
655 retval = 1;
656 goto end_of_find_cdrom_device;
657 } else {
658 retval = 0;
659 goto end_of_find_cdrom_device;
660 }
661 }
662
663 sprintf(command, "%s -scanbus 2> /dev/null", cdr_exe);
664 fin = popen(command, "r");
665 if (!fin) {
666 log_msg(4, "command=%s", command);
667 log_OS_error("Cannot popen command");
668 mr_free(cdr_exe);
669 return (1);
670 }
671 for ((void)fgets(tmp, MAX_STR_LEN, fin); !feof(fin);
672 (void)fgets(tmp, MAX_STR_LEN, fin)) {
673 p = strchr(tmp, '\'');
674 if (p) {
675 q = strchr(++p, '\'');
676 if (q) {
677 for (r = q; *(r - 1) == ' '; r--);
678 *r = '\0';
679 strcpy(phrase_one, p);
680 p = strchr(++q, '\'');
681 if (p) {
682 q = strchr(++p, '\'');
683 if (q) {
684 while (*(q - 1) == ' ') {
685 q--;
686 }
687 *q = '\0';
688 strcpy(phrase_two, p);
689 }
690 }
691 }
692 }
693 }
694 paranoid_pclose(fin);
695
696#ifndef __FreeBSD__
697 if (strlen(phrase_two) == 0) {
698 log_msg(4, "Not running phase two. String is empty.");
699 } else {
700 sprintf(command, "dmesg | grep \"%s\" 2> /dev/null", phrase_two);
701 fin = popen(command, "r");
702 if (!fin) {
703 log_msg(4, "Cannot run 2nd command - non-fatal, fortunately");
704 } else {
705 for ((void)fgets(tmp, MAX_STR_LEN, fin); !feof(fin);
706 (void)fgets(tmp, MAX_STR_LEN, fin)) {
707 log_msg(5, "--> '%s'", tmp);
708 if (tmp[0] != ' ' && tmp[1] != ' ') {
709 p = strchr(tmp, ':');
710 if (p) {
711 *p = '\0';
712 if (strstr(tmp, "DVD")) {
713 sprintf(dvd_last_resort, "/dev/%s", tmp);
714 log_msg(4,
715 "Ignoring '%s' because it's a DVD drive",
716 tmp);
717 } else {
718 sprintf(output, "/dev/%s", tmp);
719 found_it = TRUE;
720 }
721 }
722 }
723 }
724 paranoid_pclose(fin);
725 }
726 }
727
728#endif
729#ifdef __FreeBSD__
730 if (!found_it) {
731 log_msg(4, "OK, approach 2");
732 if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/cdrom"))) {
733 if (!
734 (found_it =
735 set_dev_to_this_if_rx_OK(output, "/dev/cdrom1"))) {
736 if (!
737 (found_it =
738 set_dev_to_this_if_rx_OK(output, "/dev/dvd"))) {
739 if (!
740 (found_it =
741 set_dev_to_this_if_rx_OK(output, "/dev/acd0"))) {
742 if (!
743 (found_it =
744 set_dev_to_this_if_rx_OK(output,
745 "/dev/cd01"))) {
746 if (!
747 (found_it =
748 set_dev_to_this_if_rx_OK(output,
749 "/dev/acd1"))) {
750 if (!
751 (found_it =
752 set_dev_to_this_if_rx_OK(output,
753 "/dev/cd1")))
754 {
755 retval = 1;
756 goto end_of_find_cdrom_device;
757 }
758 }
759 }
760 }
761 }
762 }
763 }
764 }
765#else
766 if (!found_it && strlen(dvd_last_resort) > 0) {
767 log_msg(4, "Well, I'll use the DVD - %s - as a last resort",
768 dvd_last_resort);
769 strcpy(output, dvd_last_resort);
770 found_it = TRUE;
771 }
772 if (found_it) {
773 sprintf(tmp, "grep \"%s=ide-scsi\" /proc/cmdline &> /dev/null",
774 strrchr(output, '/') + 1);
775 if (system(tmp) == 0) {
776 log_msg(4,
777 "%s is not right. It's being SCSI-emulated. Continuing.",
778 output);
779 found_it = FALSE;
780 output[0] = '\0';
781 }
782 }
783
784 if (found_it) {
785 log_msg(4, "(find_cdrom_device) --> '%s'", output);
786 if (!does_device_exist(output)) {
787 found_it = FALSE;
788 log_msg(4, "OK, I was wrong, I haven't found it... yet.");
789 }
790 }
791
792 if (!found_it) {
793 log_msg(4, "OK, approach 2");
794 if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/scd0"))) {
795 if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/sr0"))) {
796 if (!
797 (found_it =
798 set_dev_to_this_if_rx_OK(output, "/dev/cdrom"))) {
799 if (!
800 (found_it =
801 set_dev_to_this_if_rx_OK(output,
802 "/dev/cdrom0"))) {
803 if (!
804 (found_it =
805 set_dev_to_this_if_rx_OK(output,
806 "/dev/cdrom1"))) {
807 if (!
808 (found_it =
809 set_dev_to_this_if_rx_OK(output,
810 "/dev/sr1"))) {
811 if (!
812 (found_it =
813 set_dev_to_this_if_rx_OK(output,
814 "/dev/dvd")))
815 {
816 if (!
817 (found_it =
818 set_dev_to_this_if_rx_OK(output,
819 g_cdrw_drive_is_here)))
820 {
821 retval = 1;
822 goto end_of_find_cdrom_device;
823 }
824 }
825 }
826 }
827 }
828 }
829 }
830 }
831 }
832#endif
833
834 if (found_it && try_to_mount) {
835 if (mount_CDROM_here(output, mountpoint)) {
836 log_msg(4, "[Cardigans] I've changed my mind");
837 found_it = FALSE;
838 } else {
839 sprintf(tmp, "%s/archives", mountpoint);
840 if (!does_file_exist(tmp)) {
841 log_msg(4, "[Cardigans] I'll take it back");
842 found_it = FALSE;
843 } else {
844 sprintf(command, "umount %s", output);
845 paranoid_system(command);
846 log_msg(4, "I'm confident the Mondo CD is in %s", output);
847 }
848 }
849 }
850 unlink(mountpoint);
851
852 if (found_it) {
853 if (!does_file_exist(output)) {
854 log_msg(3, "I still haven't found it.");
855 return (1);
856 }
857 log_msg(3, "(find_cdrom_device) --> '%s'", output);
858 strcpy(the_last_place_i_found_it, output);
859 strcpy(g_cdrom_drive_is_here, output);
860 retval = 0;
861 goto end_of_find_cdrom_device;
862 }
863
864 sprintf(command,
865 "%s -scanbus | grep \"[0-9],[0-9],[0-9]\" | grep \"[D|C][V|D]\" | grep -n \"\" | grep \"%s\" | cut -d':' -f2",
866 cdr_exe, g_cdrw_drive_is_here);
867 log_msg(1, "command=%s", command);
868 mr_asprintf(&tmp1, "%s", call_program_and_get_last_line_of_output(command));
869 if (strlen(tmp1) > 0) {
870 strcpy(output, tmp1);
871 log_msg(4, "Finally found it at %s", output);
872 retval = 0;
873 } else {
874 log_msg(4, "Still couldn't find it.");
875 retval = 1;
876 }
877 mr_free(tmp1);
878
879 end_of_find_cdrom_device:
880 paranoid_free(tmp);
881 mr_free(cdr_exe);
882 paranoid_free(phrase_one);
883 paranoid_free(phrase_two);
884 paranoid_free(command);
885 paranoid_free(dvd_last_resort);
886 paranoid_free(mountpoint);
887 return (retval);
888}
889
890
891
892
893
894int find_dvd_device(char *output, bool try_to_mount)
895{
896 char *command;
897 char *tmp;
898 int retval = 0, devno = -1;
899
900 malloc_string(command);
901 malloc_string(tmp);
902
903 if (g_dvd_drive_is_here[0]) {
904 strcpy(output, g_dvd_drive_is_here);
905 log_msg(3, "Been there, done that. Returning %s", output);
906 return (0);
907 }
908
909 sprintf(tmp, "%s", call_program_and_get_last_line_of_output
910 ("dvdrecord -scanbus 2> /dev/null | grep \") '\" | grep -n \"\" | grep DVD | cut -d':' -f1")
911 );
912 log_msg(5, "tmp = '%s'", tmp);
913 if (!tmp[0])
914 sprintf(tmp, "%s", call_program_and_get_last_line_of_output
915 ("cdrecord -scanbus 2> /dev/null | grep \") '\" | grep -n \"\" | grep DVD | cut -d':' -f1")
916 );
917 if (tmp[0]) {
918 devno = atoi(tmp) - 1;
919 }
920 if (devno >= 0) {
921 retval = 0;
922 sprintf(output, "/dev/scd%d", devno);
923 strcpy(g_dvd_drive_is_here, output);
924 log_msg(2, "I think DVD is at %s", output);
925 } else {
926 log_msg(2, "I cannot find DVD");
927 retval = 1;
928 }
929
930 if (try_to_mount) {
931 log_msg(1, "Ignoring the fact that try_to_mount==TRUE");
932 }
933 return (retval);
934}
935
936
937
938
939
940#include <sys/ioctl.h>
941
942/**
943 * Find the size of the specified @p drive, in megabytes. Uses @c ioctl calls
944 * and @c dmesg.
945 * @param drive The device to find the size of.
946 * @return size in megabytes.
947 */
948long get_phys_size_of_drive(char *drive)
949{
950 int fd;
951#if linux
952 unsigned long long s = 0;
953 int fileid, cylinders = 0, cylindersleft = 0;
954 int cylindersize = 0;
955 int gotgeo = 0;
956
957
958 struct hd_geometry hdgeo;
959#elif __FreeBSD__
960 off_t s;
961#endif
962
963 long outvalA = -1;
964 long outvalB = -1;
965 long outvalC = -1;
966
967 if ((fd = open(drive, O_RDONLY)) != -1) {
968 if (ioctl(fd,
969#if linux
970#ifdef BLKGETSIZE64
971 BLKGETSIZE64,
972#else
973 BLKGETSIZE,
974#endif
975#elif __FreeBSD__
976 DIOCGMEDIASIZE,
977#endif
978 &s) != -1) {
979 close(fd);
980 // s>>11 works for older disks but not for newer ones
981 outvalB =
982#if linux
983#ifdef BLKGETSIZE64
984 s >> 20
985#else
986 s >> 11
987#endif
988#else
989 s >> 20
990#endif
991 ;
992 }
993 }
994
995 if (outvalB <= 0) {
996 log_msg(1, "Error getting size of %s: %s", drive, strerror(errno));
997#if linux
998 fileid = open(drive, O_RDONLY);
999 if (fileid != -1) {
1000 if (ioctl(fileid, HDIO_GETGEO, &hdgeo) != -1) {
1001 if (hdgeo.cylinders && hdgeo.heads && hdgeo.sectors) {
1002 cylindersleft = cylinders = hdgeo.cylinders;
1003 cylindersize = hdgeo.heads * hdgeo.sectors / 2;
1004 outvalA = cylindersize * cylinders / 1024;
1005 log_msg(2, "Got Harddisk geometry, C:%d, H:%d, S:%d",
1006 hdgeo.cylinders, hdgeo.heads, hdgeo.sectors);
1007 gotgeo = 1;
1008 } else {
1009 log_msg(1, "Harddisk geometry wrong");
1010 }
1011 } else {
1012 log_msg(1,
1013 "Error in ioctl() getting new hard disk geometry (%s), resizing in unsafe mode",
1014 strerror(errno));
1015 }
1016 close(fileid);
1017 } else {
1018 log_msg(1, "Failed to open %s for reading: %s", drive,
1019 strerror(errno));
1020 }
1021 if (!gotgeo) {
1022 log_msg(1, "Failed to get harddisk geometry, using old mode");
1023 }
1024#endif
1025 }
1026// OLDER DISKS will give ridiculously low value for outvalB (so outvalA is returned) :)
1027// NEWER DISKS will give sane value for outvalB (close to outvalA, in other words) :)
1028
1029 outvalC = (outvalA > outvalB) ? outvalA : outvalB;
1030
1031// log_msg (5, "drive = %s, error = %s", drive, strerror (errno));
1032// fatal_error ("GPSOD: Unable to get size of drive");
1033 log_msg(1, "%s --> %ld or %ld --> %ld", drive, outvalA, outvalB,
1034 outvalC);
1035
1036 return (outvalC);
1037}
1038
1039/**
1040 * Determine whether @p format is supported by the kernel. Uses /proc/filesystems
1041 * under Linux and @c lsvfs under FreeBSD.
1042 * @param format The format to test.
1043 * @return TRUE if the format is supported, FALSE if not.
1044 */
1045bool is_this_a_valid_disk_format(char *format)
1046{
1047 char *good_formats = NULL;
1048 char *command;
1049 char *format_sz;
1050
1051 FILE *pin;
1052 int retval;
1053 malloc_string(good_formats);
1054 malloc_string(command);
1055 malloc_string(format_sz);
1056
1057 assert_string_is_neither_NULL_nor_zerolength(format);
1058
1059 sprintf(format_sz, "%s ", format);
1060
1061#ifdef __FreeBSD__
1062 sprintf(command,
1063 "lsvfs | tr -s '\t' ' ' | grep -v Filesys | grep -v -- -- | cut -d' ' -f1 | tr -s '\n' ' '");
1064#else
1065 sprintf(command,
1066 "grep -v nodev /proc/filesystems | tr -s '\t' ' ' | cut -d' ' -f2 | tr -s '\n' ' '");
1067#endif
1068
1069 pin = popen(command, "r");
1070 if (!pin) {
1071 log_OS_error("Unable to read good formats");
1072 retval = 0;
1073 } else {
1074 strcpy(good_formats, " ");
1075 (void) fgets(good_formats + 1, MAX_STR_LEN - 1, pin);
1076 if (pclose(pin)) {
1077 log_OS_error("Cannot pclose good formats");
1078 }
1079 strip_spaces(good_formats);
1080 strcat(good_formats, " swap lvm raid ntfs-3g ntfs 7 "); // " ntfs 7 " -- um, cheating much? :)
1081 if (strstr(good_formats, format_sz)) {
1082 retval = 1;
1083 } else {
1084 retval = 0;
1085 }
1086 }
1087 paranoid_free(good_formats);
1088 paranoid_free(command);
1089 paranoid_free(format_sz);
1090 return (retval);
1091}
1092
1093
1094/** @def SWAPLIST_COMMAND The command to list the swap files/partitions in use. */
1095
1096/**
1097 * Determine whether @p device_raw is currently mounted.
1098 * @param device_raw The device to check.
1099 * @return TRUE if it's mounted, FALSE if not.
1100 */
1101bool is_this_device_mounted(char *device_raw)
1102{
1103
1104 /*@ pointers **************************************************** */
1105 FILE *fin;
1106
1107 /*@ buffers ***************************************************** */
1108 char *incoming;
1109 char *device_with_tab = NULL;
1110 char *device_with_space = NULL;
1111 char *tmp = NULL;
1112 bool retval = FALSE;
1113
1114#ifdef __FreeBSD__
1115#define SWAPLIST_COMMAND "swapinfo"
1116#else
1117#define SWAPLIST_COMMAND "cat /proc/swaps"
1118#endif
1119
1120 /*@ end vars **************************************************** */
1121
1122 malloc_string(incoming);
1123 assert(device_raw != NULL);
1124// assert_string_is_neither_NULL_nor_zerolength(device_raw);
1125 if (device_raw[0] != '/' && !strstr(device_raw, ":/")) {
1126 log_msg(1, "%s needs to have a '/' prefixed - I'll do it",
1127 device_raw);
1128 mr_asprintf(&tmp, "/%s", device_raw);
1129 } else {
1130 mr_asprintf(&tmp, "%s", device_raw);
1131 }
1132 log_msg(1, "Is %s mounted?", tmp);
1133 if (!strcmp(tmp, "/proc") || !strcmp(tmp, "proc")) {
1134 log_msg(1,
1135 "I don't know how the heck /proc made it into the mountlist. I'll ignore it.");
1136 mr_free(tmp);
1137 return(FALSE);
1138 }
1139 mr_asprintf(&device_with_tab, "%s\t", tmp);
1140 mr_asprintf(&device_with_space, "%s ", tmp);
1141 mr_free(tmp);
1142
1143 if (!(fin = popen("mount", "r"))) {
1144 log_OS_error("Cannot popen 'mount'");
1145 return(FALSE);
1146 }
1147 for ((void)fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin);
1148 (void)fgets(incoming, MAX_STR_LEN - 1, fin)) {
1149 if (strstr(incoming, device_with_space) //> incoming
1150 || strstr(incoming, device_with_tab)) // > incoming)
1151 {
1152 paranoid_pclose(fin);
1153 paranoid_free(incoming);
1154 return(TRUE);
1155 }
1156 }
1157 mr_free(device_with_tab);
1158 paranoid_pclose(fin);
1159 mr_asprintf(&tmp, "%s | grep -E \"^%s\" > /dev/null 2> /dev/null", SWAPLIST_COMMAND, device_with_space);
1160 mr_free(device_with_space);
1161 log_msg(4, "tmp (command) = '%s'", tmp);
1162 if (!system(tmp)) {
1163 retval = TRUE;
1164 }
1165 mr_free(tmp);
1166 paranoid_free(incoming);
1167 return(retval);
1168}
1169
1170#ifdef __FreeBSD__
1171// CODE IS FREEBSD-SPECIFIC
1172/**
1173 * Create a loopback device for specified @p fname.
1174 * @param fname The file to associate with a device.
1175 * @return /dev entry for the device, or NULL if it couldn't be allocated.
1176 */
1177char *make_vn(char *fname)
1178{
1179 char *device = (char *) malloc(MAX_STR_LEN);
1180 char *mddevice = (char *) malloc(32);
1181 char command[MAX_STR_LEN];
1182 int vndev = 2;
1183 if (atoi
1184 (call_program_and_get_last_line_of_output
1185 ("/sbin/sysctl -n kern.osreldate")) < 500000) {
1186 do {
1187 sprintf(mddevice, "vn%ic", vndev++);
1188 sprintf(command, "vnconfig %s %s", mddevice, fname);
1189 if (vndev > 10) {
1190 return NULL;
1191 }
1192 }
1193 while (system(command));
1194 } else {
1195 sprintf(command, "mdconfig -a -t vnode -f %s", fname);
1196 mddevice = call_program_and_get_last_line_of_output(command);
1197 if (!strstr(mddevice, "md")) {
1198 return NULL;
1199 }
1200 }
1201 sprintf(device, "/dev/%s", mddevice);
1202 return device;
1203}
1204
1205
1206
1207// CODE IS FREEBSD-SPECIFIC
1208/**
1209 * Deallocate specified @p dname.
1210 * This should be called when you are done with the device created by make_vn(),
1211 * so the system does not run out of @c vn devices.
1212 * @param dname The device to deallocate.
1213 * @return 0 for success, nonzero for failure.
1214 */
1215int kick_vn(char *dname)
1216{
1217 char command[MAX_STR_LEN];
1218
1219 if (strncmp(dname, "/dev/", 5) == 0) {
1220 dname += 5;
1221 }
1222
1223 if (atoi
1224 (call_program_and_get_last_line_of_output
1225 ("/sbin/sysctl -n kern.osreldate")) < 500000) {
1226 sprintf(command, "vnconfig -d %s", dname);
1227 return system(command);
1228 } else {
1229 sprintf(command, "mdconfig -d -u %s", dname);
1230 return system(command);
1231 }
1232 /*NOTREACHED*/ return 255;
1233}
1234#endif
1235
1236
1237/**
1238 * Mount the CD-ROM at @p mountpoint.
1239 * @param device The device (or file if g_ISO_restore_mode) to mount.
1240 * @param mountpoint The place to mount it.
1241 * @return 0 for success, nonzero for failure.
1242 */
1243int mount_USB_here(char *device, char *mountpoint)
1244{
1245 /*@ buffer ****************************************************** */
1246 char *command;
1247 int retval;
1248
1249 malloc_string(command);
1250 assert_string_is_neither_NULL_nor_zerolength(device);
1251 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
1252
1253 make_hole_for_dir(mountpoint);
1254 if (isdigit(device[0])) {
1255 return(1);
1256 }
1257 log_msg(4, "(mount_USB_here --- device=%s, mountpoint=%s", device,
1258 mountpoint);
1259
1260#ifdef __FreeBSD__
1261 sprintf(command, "mount_vfat %s %s 2>> %s",
1262 device, mountpoint, MONDO_LOGFILE);
1263
1264#else
1265 sprintf(command, "mount %s -t vfat %s 2>> %s",
1266 device, mountpoint, MONDO_LOGFILE);
1267#endif
1268
1269 log_msg(4, command);
1270 retval = system(command);
1271 log_msg(1, "system(%s) returned %d", command, retval);
1272
1273 paranoid_free(command);
1274 return (retval);
1275}
1276
1277/**
1278 * Mount the CD-ROM at @p mountpoint.
1279 * @param device The device (or file if g_ISO_restore_mode) to mount.
1280 * @param mountpoint The place to mount it.
1281 * @return 0 for success, nonzero for failure.
1282 */
1283int mount_CDROM_here(char *device, char *mountpoint)
1284{
1285 /*@ buffer ****************************************************** */
1286 char *command = NULL;
1287 int retval;
1288#ifdef __FreeBSD__
1289 char *dev = NULL;
1290#else
1291 char *options = NULL;
1292#endif
1293
1294 assert_string_is_neither_NULL_nor_zerolength(device);
1295 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
1296
1297 make_hole_for_dir(mountpoint);
1298
1299 if (isdigit(device[0])) {
1300 find_cdrom_device(device, FALSE);
1301 }
1302#ifndef __FreeBSD__
1303 mr_asprintf(&options, "ro");
1304#endif
1305
1306 if (g_ISO_restore_mode) {
1307
1308#ifdef __FreeBSD__
1309 mr_asprintf(&dev, "%s", make_vn(device));
1310 if (!dev) {
1311 mr_asprintf(&command, "Unable to mount ISO (make_vn(%s) failed)", device);
1312 fatal_error(command);
1313 }
1314 strcpy(device, dev);
1315 paranoid_free(dev);
1316#else
1317 mr_strcat(options, ",loop");
1318#endif
1319
1320 }
1321 log_msg(4, "(mount_CDROM_here --- device=%s, mountpoint=%s", device,
1322 mountpoint);
1323 /*@ end vars *************************************************** */
1324
1325#ifdef __FreeBSD__
1326 mr_asprintf(&command, "mount_cd9660 -r %s %s 2>> %s", device, mountpoint, MONDO_LOGFILE);
1327
1328#else
1329 mr_asprintf(&command, "mount %s -o %s -t iso9660 %s 2>> %s", device, options, mountpoint, MONDO_LOGFILE);
1330 paranoid_free(options);
1331#endif
1332
1333 log_msg(4, command);
1334 if (strncmp(device, "/dev/", 5) == 0) {
1335 retract_CD_tray_and_defeat_autorun();
1336 }
1337 retval = system(command);
1338 log_msg(1, "system(%s) returned %d", command, retval);
1339 paranoid_free(command);
1340
1341 return (retval);
1342}
1343
1344
1345/**
1346* Mount the CD-ROM or USB device at /mnt/cdrom.
1347* @param bkpinfo The backup information structure. Fields used:
1348* - @c bkpinfo->backup_media_type
1349* - @c bkpinfo->disaster_recovery
1350* - @c bkpinfo->isodir
1351* - @c bkpinfo->media_device
1352* @return 0 for success, nonzero for failure.
1353*/
1354int mount_media()
1355{
1356char *mount_cmd;
1357char *mountdir = NULL;
1358int i, res;
1359#ifdef __FreeBSD__
1360char mdd[32];
1361char *mddev = mdd;
1362#endif
1363
1364malloc_string(mount_cmd);
1365assert(bkpinfo != NULL);
1366
1367 if (bkpinfo->backup_media_type == tape
1368 || bkpinfo->backup_media_type == udev) {
1369 log_msg(8, "Tape/udev. Therefore, no need to mount a media.");
1370 paranoid_free(mount_cmd);
1371 return 0;
1372 }
1373
1374 if (!run_program_and_log_output("mount | grep -F " MNT_CDROM, FALSE)) {
1375 log_msg(2, "mount_media() - media already mounted. Fair enough.");
1376 paranoid_free(mount_cmd);
1377 return (0);
1378 }
1379
1380 if (bkpinfo->backup_media_type == netfs) {
1381 log_msg(2, "Mounting for Network thingy");
1382 log_msg(2, "isodir = %s", bkpinfo->isodir);
1383 if ((!bkpinfo->isodir[0] || !strcmp(bkpinfo->isodir, "/"))
1384 && am_I_in_disaster_recovery_mode()) {
1385 strcpy(bkpinfo->isodir, "/tmp/isodir");
1386 log_msg(1, "isodir is being set to %s", bkpinfo->isodir);
1387 }
1388#ifdef __FreeBSD__
1389 sprintf(mount_cmd, "/mnt/isodir/%s/%s/%s-%d.iso", bkpinfo->isodir,
1390 bkpinfo->netfs_remote_dir, bkpinfo->prefix, g_current_media_number);
1391 mddev = make_vn(mount_cmd);
1392 sprintf(mount_cmd, "mount_cd9660 -r %s " MNT_CDROM, mddev);
1393#else
1394 sprintf(mount_cmd, "mount %s/%s/%s-%d.iso -t iso9660 -o loop,ro %s",
1395 bkpinfo->isodir, bkpinfo->netfs_remote_dir,
1396 bkpinfo->prefix, g_current_media_number, MNT_CDROM);
1397#endif
1398
1399 } else if (bkpinfo->backup_media_type == iso) {
1400 if (bkpinfo->subdir) {
1401 mr_asprintf(&mountdir, "%s/%s", bkpinfo->isodir, bkpinfo->subdir);
1402 } else {
1403 mr_asprintf(&mountdir, "%s", bkpinfo->isodir);
1404 }
1405#ifdef __FreeBSD__
1406 sprintf(mount_cmd, "%s/%s-%d.iso", mountdir,
1407 bkpinfo->prefix, g_current_media_number);
1408 mddev = make_vn(mount_cmd);
1409 sprintf(mount_cmd, "mount_cd9660 -r %s %s", mddev, MNT_CDROM);
1410#else
1411 sprintf(mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s",
1412 mountdir, bkpinfo->prefix, g_current_media_number, MNT_CDROM);
1413#endif
1414 } else if (bkpinfo->backup_media_type == usb) {
1415 sprintf(mount_cmd, "mount -t vfat %s %s", bkpinfo->media_device, MNT_CDROM);
1416 } else if (strstr(bkpinfo->media_device, "/dev/")) {
1417#ifdef __FreeBSD__
1418 sprintf(mount_cmd, "mount_cd9660 -r %s %s", bkpinfo->media_device,
1419 MNT_CDROM);
1420#else
1421 sprintf(mount_cmd, "mount %s -t iso9660 -o ro %s",
1422 bkpinfo->media_device, MNT_CDROM);
1423#endif
1424 } else {
1425 if (bkpinfo->disaster_recovery
1426 && does_file_exist("/tmp/CDROM-LIVES-HERE")) {
1427 strcpy(bkpinfo->media_device,
1428 last_line_of_file("/tmp/CDROM-LIVES-HERE"));
1429 } else {
1430 find_cdrom_device(bkpinfo->media_device, TRUE);
1431 }
1432
1433#ifdef __FreeBSD__
1434 sprintf(mount_cmd, "mount_cd9660 -r %s %s", bkpinfo->media_device,
1435 MNT_CDROM);
1436#else
1437 sprintf(mount_cmd, "mount %s -t iso9660 -o ro %s",
1438 bkpinfo->media_device, MNT_CDROM);
1439#endif
1440 }
1441
1442 log_msg(2, "(mount_media) --- command = %s", mount_cmd);
1443 for (i = 0; i < 2; i++) {
1444 res = run_program_and_log_output(mount_cmd, FALSE);
1445 if (!res) {
1446 break;
1447 } else {
1448 log_msg(2, "Failed to mount device.");
1449 sleep(5);
1450 run_program_and_log_output("sync", FALSE);
1451 }
1452 }
1453
1454 if (res) {
1455 log_msg(2, "Failed, despite %d attempts", i);
1456 } else {
1457 log_msg(2, "Mounted media drive OK");
1458 }
1459 paranoid_free(mount_cmd);
1460 return (res);
1461}
1462/**************************************************************************
1463*END_MOUNT_CDROM *
1464**************************************************************************/
1465
1466
1467
1468
1469/**
1470 * Ask the user for CD number @p cd_number_i_want.
1471 * Sets g_current_media_number once the correct CD is inserted.
1472 * @param bkpinfo The backup information structure. Fields used:
1473 * - @c bkpinfo->backup_media_type
1474 * - @c bkpinfo->prefix
1475 * - @c bkpinfo->isodir
1476 * - @c bkpinfo->media_device
1477 * - @c bkpinfo->please_dont_eject_when_restoring
1478 * @param cd_number_i_want The CD number to ask for.
1479 */
1480void
1481insist_on_this_cd_number(int cd_number_i_want)
1482{
1483
1484 /*@ int ************************************************************* */
1485 int res = 0;
1486
1487
1488 /*@ buffers ********************************************************* */
1489 char *tmp;
1490 char *mds = NULL;
1491 char *request;
1492
1493 assert(bkpinfo != NULL);
1494 assert(cd_number_i_want > 0);
1495
1496// log_msg(3, "Insisting on CD number %d", cd_number_i_want);
1497
1498 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1499 log_msg(3,
1500 "No need to insist_on_this_cd_number when the backup type isn't CD-R(W) or NFS or ISO");
1501 return;
1502 }
1503 malloc_string(tmp);
1504 malloc_string(request);
1505 sprintf(tmp, "mkdir -p " MNT_CDROM);
1506 run_program_and_log_output(tmp, 5);
1507 if (g_ISO_restore_mode || bkpinfo->backup_media_type == iso
1508 || bkpinfo->backup_media_type == netfs) {
1509 g_ISO_restore_mode = TRUE;
1510 if (!is_this_device_mounted(MNT_CDROM)) {
1511 log_msg(3, "Mounting media");
1512 g_current_media_number = cd_number_i_want;
1513 mount_media();
1514 }
1515 }
1516 if ((res = what_number_cd_is_this()) != cd_number_i_want) {
1517 log_msg(3, "Currently, we hold %d but we want %d", res,
1518 cd_number_i_want);
1519 mds = media_descriptor_string(bkpinfo->backup_media_type);
1520 sprintf(tmp, "Insisting on %s #%d", mds, cd_number_i_want);
1521 sprintf(request, "Please insert %s #%d and press Enter.", mds, cd_number_i_want);
1522 mr_free(mds);
1523 log_msg(3, tmp);
1524 while (what_number_cd_is_this() != cd_number_i_want) {
1525 paranoid_system("sync");
1526 if (is_this_device_mounted(MNT_CDROM)) {
1527 res =
1528 run_program_and_log_output("umount " MNT_CDROM, FALSE);
1529 } else {
1530 res = 0;
1531 }
1532 if (res) {
1533 log_to_screen("WARNING - failed to unmount CD-ROM drive");
1534 }
1535 if (!bkpinfo->please_dont_eject) {
1536 res = eject_device(bkpinfo->media_device);
1537 } else {
1538 res = 0;
1539 }
1540 if (res) {
1541 log_to_screen("WARNING - failed to eject CD-ROM disk");
1542 }
1543 popup_and_OK(request);
1544 if (!bkpinfo->please_dont_eject) {
1545 inject_device(bkpinfo->media_device);
1546 }
1547 paranoid_system("sync");
1548 }
1549 log_msg(1, "Thankyou. Proceeding...");
1550 g_current_media_number = cd_number_i_want;
1551 }
1552 paranoid_free(tmp);
1553 paranoid_free(request);
1554}
1555
1556/* @} - end of deviceGroup */
1557
1558
1559
1560/**
1561 * Creates a singly linked list of all of the non-NETFS mounted file systems.
1562 * @param DSFptr A pointer to the structure MOUNTED_FS_STRUCT used to hold
1563 * the list of mounted file systems.
1564 * @return None.
1565 */
1566static void add_mounted_fs_struct (MOUNTED_FS_STRUCT *DSFptr)
1567{
1568 assert (DSFptr);
1569 if (DSF_Head == NULL) {
1570 DSF_Head = DSFptr;
1571 } else {
1572 DSF_Tail->next = DSFptr;
1573 }
1574 DSFptr->next = NULL;
1575 DSF_Tail = DSFptr;
1576}
1577
1578/**
1579 * Find the structure, in the singly linked list of all of the non-NETFS
1580 * mounted file systems, that contains the specified device.
1581 * @param device The device to find
1582 * @return NULL if it didn't find the device, a pointer to the
1583 * structure if it did.
1584 */
1585static MOUNTED_FS_STRUCT *find_device_in_list (char *device)
1586{
1587 MOUNTED_FS_STRUCT *DSFptr = NULL;
1588
1589 DSFptr = DSF_Head;
1590 while (DSFptr != NULL) {
1591 if (!strcmp(DSFptr->device, device)) {
1592 break;
1593 }
1594 DSFptr = DSFptr->next;
1595 }
1596 return (DSFptr);
1597}
1598
1599/**
1600 * Find the structure, in the singly linked list of all of the non-NETFS
1601 * mounted file systems, that contains the specified mount point.
1602 * @param mount_point The mount point to find
1603 * @return NULL is it didn't find the mount point, a pointer to the
1604 * structure if it did.
1605 */
1606static MOUNTED_FS_STRUCT *find_mount_point_in_list (char *mount_point)
1607{
1608 MOUNTED_FS_STRUCT *DSFptr = NULL;
1609
1610 DSFptr = DSF_Head;
1611 while (DSFptr != NULL) {
1612 if (!strcmp(DSFptr->mount_point, mount_point)) {
1613 break;
1614 }
1615 DSFptr = DSFptr->next;
1616 }
1617 return (DSFptr);
1618}
1619
1620/**
1621 * Frees the memory for all of the structures on the linked list of
1622 * all of the non-NETFS mounted file systems.
1623 */
1624static void free_mounted_fs_list (void) {
1625 MOUNTED_FS_STRUCT *DSFptr = NULL;
1626 MOUNTED_FS_STRUCT *DSFnext = NULL;
1627
1628 DSFptr = DSF_Head;
1629 while (DSFptr != NULL) {
1630 DSFnext = DSFptr->next;
1631 paranoid_free(DSFptr);
1632 DSFptr = DSFnext;
1633 }
1634 DSF_Head = NULL;
1635 DSF_Tail = NULL;
1636}
1637
1638
1639/**
1640 * Creates a linked list of all of the non-NETFS mounted file systems.
1641 * We use a linked list because we don't know how many mounted file
1642 * there are (and there can be a lot).
1643 * @return 0 on success and greated than 0 on failure.
1644 */
1645static int create_list_of_non_NETFS_mounted_file_systems (void)
1646{
1647 int i = 0;
1648 int mount_cnt = 0;
1649 int lastpos = 0;
1650 char *mounted_file_system = NULL;
1651 char *command = NULL;
1652 char *token = NULL;
1653 char token_chars[] =" :\t\r\f\a\0";
1654 MOUNTED_FS_STRUCT *DSFptr = NULL;
1655
1656 free_mounted_fs_list();
1657 /********
1658 * Find the number of mounted file system entries and their respective mount points.
1659 * I can't return all of the entries as one string because it's length can be longer
1660 * than MAX_STR_LEN which is used in call_program_and_get_last_line_of_output().
1661 * So start looping and get the number of mounted file systems and query them one by one.
1662 ********/
1663 /* Get the number of mounted file systems ((those that start with "/dev/" */
1664 mr_asprintf(&command, "mount 2>/dev/null | awk '{if($1 ~ \"^/dev/\"){print $0}}'|wc -l");
1665 log_msg(5, "Running: %s", command);
1666 mr_asprintf(&mounted_file_system, "%s", call_program_and_get_last_line_of_output(command));
1667 paranoid_free(command);
1668
1669 mount_cnt = atoi(mounted_file_system);
1670 log_msg (5, "mount_cnt: %d", mount_cnt);
1671 paranoid_free(mounted_file_system);
1672
1673 for (i=mount_cnt; i > 0; i--) {
1674 mr_asprintf(&command, "mount 2>/dev/null | awk '{if($1 ~ \"^/dev/\"){print $1,$3}}'|head -n %d", i);
1675 log_msg(5, "Running: %s", command);
1676 mr_asprintf(&mounted_file_system, "%s", call_program_and_get_last_line_of_output(command));
1677 paranoid_free(command);
1678
1679 log_msg (5, "mounted_file_system: %s", mounted_file_system);
1680 if ((token = mr_strtok(mounted_file_system, token_chars, &lastpos)) == NULL) {
1681 log_msg (4, "Could not get the list of mounted file systems");
1682 paranoid_free(mounted_file_system);
1683 mr_free(token);
1684 return (1);
1685 }
1686 if (token) {
1687 log_msg (5, "token: %s", token);
1688 }
1689 while (token != NULL) {
1690 log_msg (5, "token: %s", token);
1691 if ((DSFptr = (MOUNTED_FS_STRUCT *) calloc(1, sizeof(MOUNTED_FS_STRUCT))) == NULL) {
1692 fatal_error ("Cannot allocate memory");
1693 }
1694 add_mounted_fs_struct(DSFptr);
1695 strcpy(DSFptr->device, token);
1696 mr_free(token);
1697 if ((token = mr_strtok(mounted_file_system, token_chars, &lastpos)) == NULL) {
1698 log_msg (5, "Ran out of entries on the mounted file systems list");
1699 mr_free(mounted_file_system);
1700 mr_free(token);
1701 return (1);
1702 }
1703 log_msg (5, "token: %s", token);
1704 strcpy(DSFptr->mount_point, token);
1705 mr_free(token);
1706 token = mr_strtok(mounted_file_system, token_chars, &lastpos);
1707 }
1708 mr_free(mounted_file_system);
1709 }
1710 /********
1711 * DSFptr = DSF_Head;
1712 * while (DSFptr != NULL) {
1713 * printf ("Dev: %s MP: %s Check: %d\n", DSFptr->device, DSFptr->mount_point, DSFptr->check);
1714 * DSFptr = DSFptr->next;
1715 * }
1716 ********/
1717 return (0);
1718}
1719
1720
1721
1722/**
1723 * Given a whole disk device special file, determine which mounted file systems
1724 * are on the dsf's partitions and which mounted file systems are not.
1725 * @param dsf The whole disk device special file.
1726 * @param included_dsf_list A char pointer used to hold the list of mount points
1727 * that are on the dsf. Memory for the array will be allocated within the function.
1728 * @param excluded_dsf_list A char pointer used to hold the list of mount points
1729 * that are not on the dsf. Memory for the array will be allocated within the function.
1730 * @return 0 on success, -1 if no device special file was passed in, -2 if a device
1731 * special file was passed in but it has no partitions on it, or 1 on failure
1732 */
1733static int get_dsf_mount_list (const char *dsf, char **included_dsf_list, char **excluded_dsf_list) {
1734 int i = 0;
1735 int c = 0;
1736 int lastpos = 0;
1737 char VG[MAX_STR_LEN];
1738 char *tmp = NULL;
1739 char *command = NULL;
1740 char *partition_list = NULL;
1741 char partitions[64][MAX_STR_LEN];
1742 char *mount_list = NULL;
1743 char *token = NULL;
1744 char *ndsf = NULL;
1745 char token_chars[] =" \t\r\f\a\0";
1746 MOUNTED_FS_STRUCT *DSFptr = NULL;
1747
1748 memset((char *)partitions, 0, sizeof(partitions));
1749
1750 log_msg(5, "dsf: %s", dsf);
1751
1752 /********
1753 * See if a device special file was passed in (i.e. it must start with /dev/
1754 ********/
1755 if (strncmp(dsf, "/dev/", 5)) {
1756 log_msg (4, "%s does not start with /dev/ and (probably) is not a device special file", dsf);
1757 return (-1);
1758 }
1759 log_msg(4, " %s looks like a device special file", dsf);
1760 /* Verify that the dsf exists */
1761 mr_asprintf(&command, "ls -al %s 2>/dev/null | wc -l", dsf);
1762 log_msg(5, " Executing: %s", command);
1763 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1764 paranoid_free(command);
1765
1766 log_msg(5, " Return value: %s", tmp);
1767 c = atoi(tmp);
1768 paranoid_free(tmp);
1769
1770 if (!c) {
1771 log_to_screen("Cannot find device special file %s", dsf);
1772 return (1);
1773 }
1774 log_msg(4, " %s device special file exists", dsf);
1775
1776 /* Get a list of the mounted file systems */
1777 if (create_list_of_non_NETFS_mounted_file_systems()) {
1778 log_to_screen ("Could not get the list of mounted file systems");
1779 return (1);
1780 }
1781 log_msg (5, "Processing dsf: %s", dsf);
1782 /********
1783 * Get a list of the dsf's partitions. There could be no partitions on the disk
1784 * or a dsf of a partition was passed in (e.g. /dev/sda1 instead of /dev/sda).
1785 * Either way, it's an error.
1786 ********/
1787 mr_asprintf(&command, "parted2fdisk -l %s 2>/dev/null|grep -E \"^/dev/\"|awk '{printf(\"%%s \", $1)}END{print \"\"}'", dsf);
1788 log_msg(5, "Executing: %s", command);
1789 mr_asprintf(&partition_list, "%s", call_program_and_get_last_line_of_output(command));
1790 paranoid_free(command);
1791 log_msg(4, "Partition list for %s: %s", dsf, partition_list);
1792 if (!strlen(partition_list)) {
1793 /* There were no partitions on the disk */
1794 log_msg(4, "No partitions on device special file %s", dsf);
1795 log_msg(4, "I guess it's a partition itself");
1796 strcpy(partitions[0], dsf);
1797 ndsf = truncate_to_drive_name(dsf);
1798 } else {
1799 /* Fill the partition list */
1800 i = 0;
1801 lastpos = 0;
1802 while ((token = mr_strtok(partition_list, token_chars, &lastpos)) != NULL) {
1803 log_msg (4, "Found partition: %s", token);
1804 strcpy(partitions[i++], token);
1805 mr_free(token);
1806 }
1807 mr_asprintf(&ndsf, "%s", dsf);
1808 }
1809 mr_free(partition_list);
1810
1811 /* In any case we want to exclude the dsf itself from all MondRescue activities
1812 * at restore time (LVM, fdisk, ...) so we want it in our exclude_dev list */
1813 if ((DSFptr = (MOUNTED_FS_STRUCT *) calloc(1, sizeof(MOUNTED_FS_STRUCT))) == NULL) {
1814 fatal_error ("Cannot allocate memory");
1815 }
1816 add_mounted_fs_struct(DSFptr);
1817 strcpy(DSFptr->device, dsf);
1818 DSFptr->check = 1;
1819
1820 /* For the rest ndsf is the new dsf to deal with */
1821 /********
1822 * At this point, we have a list of all of the partitions on the dsf. Now try to
1823 * see which partitions have a file system on them.
1824 *
1825 * Loop through each partition on the disk and:
1826 *
1827 * - If the partition is swap, it ignores it.
1828 *
1829 * - If the partition is mounted (e.g. /dev/sda1 is mounted on /boot), it adds an entry
1830 * to the linked list, copies to it the device name and mount point, and sets check == 1.
1831 *
1832 * - If the partition is part of a Volume Group that has Logical Volumes mounted, it adds
1833 * an entry to the linked list for each mounted Logical Volume in that Volume Group, copying
1834 * to it the device name and mount point, and sets check == 1. Note that if the Volume Group
1835 * contains more than one disk, it will still add the entry even if the Logical Volume's
1836 * extents are not on the dsf that was passed in to the function. For example, Volume Group
1837 * VolGroup00 contains the disks /dev/sda1 and /dev/sdb1, and the Logical Volumes LogVol01,
1838 * which is mounted on /var and has all of its extents on /dev/sda1, and LogVol02, which is
1839 * mounted as /usr and has all of its extents on /dev/sdb1. If you pass /dev/sda into the
1840 * function, both /var and /usr will be archived even though /usr is actually on/dev/sdb.
1841 *
1842 * - If the partition is part of a Volume Group that has Logical Volumes used in a mounted
1843 * software raid device, it adds an entry to the linked list, copies to it the software raid
1844 * device name and mount point, and sets check == 1.
1845 *
1846 * - If the partition is part of a mounted software raid device, it adds an entry to the linked
1847 * list, copies to it the software raid device name and mount point, and sets check == 1.
1848 *
1849 ********/
1850 for (i=0; strlen(partitions[i]); i++) {
1851 log_msg(4, "Processing partition: %s", partitions[i]);
1852 /* See if it's swap. If it is, ignore it. */
1853 mr_asprintf(&command, "parted2fdisk -l %s 2>/dev/null | awk '{if(($1==\"%s\")&&(toupper($0) ~ \"SWAP\")){print $1;exit}}'",
1854 ndsf, partitions[i]);
1855 log_msg(5, " Running: %s", command);
1856 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1857 paranoid_free(command);
1858 log_msg(5, " Return value: %s", tmp);
1859 c = strlen(tmp);
1860 paranoid_free(tmp);
1861 if (c) {
1862 log_msg(4, "It's swap. Ignoring partition %s", partitions[i]);
1863 continue;
1864 }
1865 /* It's not swap. See if we can find the mount point from the mount command. */
1866 mr_asprintf(&command, "mount 2>/dev/null | awk '{if((NF>0)&&($1==\"%s\")){print $3}}'", partitions[i]);
1867 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1868 paranoid_free(command);
1869 if (strlen(tmp)) {
1870 log_msg(4, " %s is mounted: %s", partitions[i], tmp);
1871 if ((DSFptr = find_mount_point_in_list(tmp)) == NULL) {
1872 log_msg (4, "Can't find mount point %s in mounted file systems list", tmp);
1873 paranoid_free(tmp);
1874 return (1);
1875 }
1876 DSFptr->check = 1;
1877 paranoid_free(tmp);
1878 continue;
1879 }
1880 paranoid_free(tmp);
1881 /* It's not swap and it's not mounted. See if it's LVM */
1882 log_msg(4, " It's not mounted. Checking to see if it's LVM...");
1883 /* Check for LVM */
1884 mr_asprintf(&command, "pvdisplay -c %s | grep '%s:' 2> /dev/null", partitions[i], partitions[i]);
1885 log_msg(5, " Running: %s", command);
1886 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1887 paranoid_free(command);
1888 if (strlen(tmp)) {
1889 log_msg(4, "Found an LVM partition at %s. Find the VG it's in...", partitions[i]);
1890 /* It's LVM: Find the VG it's in */
1891 mr_asprintf(&command, "pvdisplay -v %s 2>/dev/null|grep \"VG Name\"|awk '{print $NF}'", partitions[i]);
1892 log_msg(5, " Running: %s", command);
1893 strcpy(VG, call_program_and_get_last_line_of_output(command));
1894 paranoid_free(command);
1895 log_msg(4, " Volume Group: %s", VG);
1896 if (strlen(VG)) {
1897 /* Found the Volume Group. Now find all of the VG's mount points */
1898 log_msg(4, " Found the Volume Group. Now find all of the VG's mount points");
1899 mr_asprintf(&command, "mount 2>/dev/null|grep -E \"/dev/mapper/%s-|/dev/%s/\"|awk '{printf(\"%%s \",$3)}END{print \"\"}'", VG, VG);
1900 log_msg(5, " Running: %s", command);
1901 mr_asprintf(&mount_list, "%s", call_program_and_get_last_line_of_output(command));
1902 paranoid_free(command);
1903 log_msg(4, " VG %s mount_list: %s", VG, mount_list);
1904 lastpos = 0;
1905 while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
1906 log_msg (5, "mount point token: %s", token);
1907 if ((DSFptr = find_mount_point_in_list(token)) == NULL) {
1908 log_msg (4, "Can't find mount point %s in mounted file systems list", token);
1909 paranoid_free(tmp);
1910 mr_free(token);
1911 return (1);
1912 }
1913 DSFptr->check = 1;
1914 mr_free(token);
1915 }
1916 /********
1917 * Now we want to see if there are any software raid devices using
1918 * any of the Logical Volumes on the Volume Group.
1919 *******/
1920 paranoid_free(mount_list);
1921
1922 mr_asprintf(&command, "%s", "cat /proc/mdstat|grep -iv Personal|awk '{if($0~\"^.*[ ]+:\"){printf(\"/dev/%s \", $1)}}END{print \"\"}'");
1923 log_msg (5, "Running: %s", command);
1924 mr_asprintf(&mount_list, "%s", call_program_and_get_last_line_of_output(command));
1925 paranoid_free(command);
1926 log_msg(4, " Software raid device list: %s", mount_list);
1927 lastpos = 0;
1928 while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
1929 mr_asprintf(&command, "mdadm --detail %s 2>/dev/null | grep -c %s", token, VG);
1930 log_msg (5, "Running: %s", command);
1931 paranoid_free(tmp);
1932 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1933 paranoid_free(command);
1934 log_msg(4, "Number of Software raid device: %s", tmp);
1935 if (atoi(tmp)) {
1936 /* This device is on our disk */
1937 if ((DSFptr = find_device_in_list(token)) == NULL) {
1938 log_msg (4, "Can't find device %s in mounted file systems list", token);
1939 paranoid_free(tmp);
1940 mr_free(token);
1941 return (1);
1942 }
1943 DSFptr->check = 1;
1944 }
1945 }
1946 mr_free(token);
1947 paranoid_free(mount_list);
1948 } else {
1949 log_msg (4, "Error finding Volume Group for partition %s", partitions[i]);
1950 paranoid_free(tmp);
1951 return (1);
1952 }
1953 paranoid_free(tmp);
1954 continue;
1955 } else {
1956 log_msg (4, "Error finding partition type for the partition %s", partitions[i]);
1957 }
1958 paranoid_free(tmp);
1959 /********
1960 * It's not swap, mounted, or LVM. See if it's used in a software raid device.
1961 ********/
1962 log_msg (5, "It's not swap, mounted, or LVM. See if it's used in a software raid device.");
1963 mr_asprintf(&command, "mdadm --examine %s 2>/dev/null | awk '{if($1 == \"UUID\"){print $3}}'", partitions[i]);
1964 log_msg(4, " Running: %s", command);
1965 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1966 paranoid_free(command);
1967 if (!strlen(tmp)) {
1968 log_msg(4, " Partition %s is not used in a non-LVM software raid device", partitions[i]);
1969 paranoid_free(tmp);
1970 continue;
1971 }
1972 log_msg (5, " UUID: %s", tmp);
1973 /* Get the Software raid device list */
1974 mr_asprintf(&command, "%s", "cat /proc/mdstat|grep -iv Personal|awk '{if($0~\"^.*[ ]+:\"){printf(\"/dev/%s \", $1)}}END{print \"\"}'");
1975 log_msg (5, " Running: %s", command);
1976 mr_asprintf(&mount_list, "%s", call_program_and_get_last_line_of_output(command));
1977 paranoid_free(command);
1978 log_msg(4, " Software raid device list: %s", mount_list);
1979 /* Loop through the software raid device list to see if we can find the partition */
1980 lastpos = 0;
1981 while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
1982 mr_asprintf(&command, "mdadm --detail %s 2>/dev/null | grep -c %s", token, tmp);
1983 log_msg(4, " Running: %s", command);
1984 paranoid_free(tmp);
1985 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1986 paranoid_free(command);
1987 if (!atoi(tmp)) {
1988 log_msg (4," Didn't find partition %s in software raid device %s", partitions[i], token);
1989 } else {
1990 if ((DSFptr = find_device_in_list(token)) == NULL) {
1991 log_msg (4, "Can't find device %s in mounted file systems list", token);
1992 paranoid_free(tmp);
1993 mr_free(token);
1994 return (1);
1995 }
1996 DSFptr->check = 1;
1997 break;
1998 }
1999 mr_free(token);
2000 }
2001 paranoid_free(tmp);
2002 paranoid_free(mount_list);
2003 }
2004
2005 /* Determine how much memory to allocate for included_dsf_list and excluded_dsf_list */
2006 i = 0;
2007 DSFptr= DSF_Head;
2008 while (DSFptr != NULL) {
2009 i += strlen(DSFptr->mount_point) + 1;
2010 DSFptr = DSFptr->next;
2011 }
2012 log_msg (5, "i: %d", i);
2013 if ((*included_dsf_list = (char *) calloc(i+100, sizeof(char))) == NULL) {
2014 fatal_error ("Cannot allocate memory");
2015 }
2016 if ((*excluded_dsf_list = (char *) calloc(i+100, sizeof(char))) == NULL) {
2017 fatal_error ("Cannot allocate memory");
2018 }
2019 DSFptr= DSF_Head;
2020 while (DSFptr != NULL) {
2021 if (DSFptr->check) {
2022 log_msg (4, "%s is mounted on %s and is on disk %s", DSFptr->device, DSFptr->mount_point, ndsf);
2023 strcat(*included_dsf_list, DSFptr->mount_point);
2024 strcat(*included_dsf_list, "|");
2025 } else {
2026 log_msg (4, "%s is mounted on %s and is NOT on disk %s", DSFptr->device, DSFptr->mount_point, ndsf);
2027 strcat(*excluded_dsf_list, DSFptr->mount_point);
2028 strcat(*excluded_dsf_list, "|");
2029 }
2030 DSFptr = DSFptr->next;
2031 }
2032 mr_free(ndsf);
2033
2034 log_msg (5, "included_dsf_list: %s", *included_dsf_list);
2035 log_msg (5, "excluded_dsf_list: %s", *excluded_dsf_list);
2036 return (0);
2037}
2038
2039
2040
2041
2042
2043/* Update the bkpinfo structure for exclude & include paths
2044 * in order to handle correctly paths corresponding to devices */
2045void mr_make_devlist_from_pathlist(char *pathlist, char mode) {
2046
2047char *token = NULL;
2048int lastpos = 0;
2049char *mounted_on_dsf = NULL;
2050char *not_mounted_on_dsf = NULL;
2051char token_chars[] ="|\t\r\f\a\0\n";
2052char *tmp = NULL;
2053char *tmp1 = NULL;
2054
2055if (pathlist == NULL) {
2056 return;
2057}
2058while ((token = mr_strtok(pathlist, token_chars, &lastpos)) != NULL) {
2059 switch (get_dsf_mount_list(token, &mounted_on_dsf, &not_mounted_on_dsf)) {
2060 case 1:
2061 if (mode == 'E') {
2062 log_msg(1, "WARNING ! %s doesn't exist in -E option", token);
2063 } else {
2064 log_msg(1, "ERROR ! %s doesn't exist in -I option", token);
2065 fatal_error("Error processing -I option");
2066 }
2067 break;
2068 /* Everything is OK; proceed to archive data */
2069 case 0:
2070 if (mode == 'E') {
2071 if (strlen(mounted_on_dsf)) {
2072 log_to_screen("Excluding the following file systems on %s:", token);
2073 log_to_screen("==> %s", mounted_on_dsf);
2074 log_msg (5, "Adding to bkpinfo->exclude_paths due to -E option: %s", mounted_on_dsf);
2075 if (bkpinfo->exclude_paths) {
2076 mr_strcat(bkpinfo->exclude_paths,"|%s",mounted_on_dsf);
2077 } else {
2078 mr_asprintf(bkpinfo->exclude_paths,"%s",mounted_on_dsf);
2079 }
2080 if (bkpinfo->exclude_devs) {
2081 mr_strcat(bkpinfo->exclude_devs,"|%s",token);
2082 } else {
2083 mr_asprintf(bkpinfo->exclude_devs,"%s",token);
2084 }
2085 }
2086 } else {
2087 log_to_screen("Archiving only the following file systems on %s:", token);
2088 log_to_screen("==> %s", mounted_on_dsf);
2089 strcpy(bkpinfo->include_paths, "/");
2090 if (strlen(not_mounted_on_dsf)) {
2091 log_msg (5, "Adding to bkpinfo->exclude_paths due to -I option: %s", not_mounted_on_dsf);
2092 log_to_screen("Not archiving the following file systems:");
2093 log_to_screen("==> %s", not_mounted_on_dsf);
2094 if (bkpinfo->exclude_paths) {
2095 mr_strcat(bkpinfo->exclude_paths, "|%s",not_mounted_on_dsf);
2096 } else {
2097 mr_asprintf(bkpinfo->exclude_paths,"%s",not_mounted_on_dsf);
2098 }
2099 }
2100 }
2101 break;
2102 /* It's a dsf but not a whole disk dsf */
2103 case -2:
2104 log_to_screen("Could %s be a partition instead of a whole disk device special file?\nIgnored.", token);
2105 break;
2106 /* A device special file was not passed in. Process it as a path. */
2107 case -1:
2108 /* Adds a | to ensure correct detection even at both ends */
2109 mr_asprintf(&tmp1,"|%s",token);
2110 if (mode == 'E') {
2111 /* Add the token if not already in the list */
2112 mr_asprintf(&tmp,"|%s|",bkpinfo->exclude_paths);
2113 if (strstr(tmp,tmp1) == NULL) {
2114 if (bkpinfo->exclude_paths) {
2115 mr_strcat(bkpinfo->exclude_paths,tmp1);
2116 mr_free(tmp1);
2117 } else {
2118 bkpinfo->exclude_paths = tmp1;
2119 }
2120 }
2121 } else {
2122 /* Add the token if not already in the list */
2123 mr_asprintf(&tmp,"|%s|",bkpinfo->include_paths);
2124 if (strstr(tmp,tmp1) == NULL) {
2125 strcat(bkpinfo->include_paths,tmp1);
2126 }
2127 mr_free(tmp1);
2128 }
2129 mr_free(tmp);
2130 break;
2131 }
2132 mr_free(token);
2133
2134 if (bkpinfo->include_paths != NULL) {
2135 log_msg(1, "include_paths is now '%s'", bkpinfo->include_paths);
2136 }
2137 if (bkpinfo->exclude_paths != NULL) {
2138 log_msg(1, "exclude_paths is now '%s'", bkpinfo->exclude_paths);
2139 }
2140 if (bkpinfo->exclude_devs != NULL) {
2141 log_msg(1, "exclude_devs is now '%s'", bkpinfo->exclude_devs);
2142 }
2143}
2144}
2145
2146
2147
2148
2149/**
2150 * Ask user for details of backup/restore information.
2151 * Called when @c mondoarchive doesn't get any parameters.
2152 * @param bkpinfo The backup information structure to fill out with the user's data.
2153 * @param archiving_to_media TRUE if archiving, FALSE if restoring.
2154 * @return 0, always.
2155 * @bug No point of `int' return value.
2156 * @ingroup archiveGroup
2157 */
2158int interactively_obtain_media_parameters_from_user(bool archiving_to_media)
2159// archiving_to_media is TRUE if I'm being called by mondoarchive
2160// archiving_to_media is FALSE if I'm being called by mondorestore
2161{
2162 char *tmp = NULL;
2163 char *tmp1 = NULL;
2164 char *mds = NULL;
2165 char p[8*MAX_STR_LEN];
2166 char *sz_size;
2167 char *command;
2168 char *comment;
2169 char *prompt;
2170 int i;
2171 FILE *fin;
2172
2173 malloc_string(sz_size);
2174 malloc_string(command);
2175 malloc_string(comment);
2176 malloc_string(prompt);
2177 malloc_string(tmp1);
2178 assert(bkpinfo != NULL);
2179 sz_size[0] = '\0';
2180 bkpinfo->nonbootable_backup = FALSE;
2181
2182 // Tape, CD, NETFS, ...?
2183 srandom(getpid());
2184 bkpinfo->backup_media_type =
2185 (g_restoring_live_from_cd) ? cdr :
2186 which_backup_media_type(bkpinfo->restore_data);
2187 if (bkpinfo->backup_media_type == none) {
2188 log_to_screen("User has chosen not to backup the PC");
2189 finish(1);
2190 }
2191 /* Why asking to remove the media with tape ?
2192 if (bkpinfo->backup_media_type == tape && bkpinfo->restore_data) {
2193 popup_and_OK("Please remove media from drive(s)");
2194 }
2195 */
2196 log_msg(3, "media type = %s",
2197 bkptype_to_string(bkpinfo->backup_media_type));
2198 if (archiving_to_media) {
2199 sensibly_set_tmpdir_and_scratchdir();
2200 }
2201 bkpinfo->cdrw_speed = (bkpinfo->backup_media_type == cdstream) ? 2 : 4;
2202 bkpinfo->compression_level =
2203 (bkpinfo->backup_media_type == cdstream) ? 1 : 5;
2204 bkpinfo->use_lzo =
2205 (bkpinfo->backup_media_type == cdstream) ? TRUE : FALSE;
2206 mvaddstr_and_log_it(2, 0, " ");
2207
2208 // Find device's /dev (or SCSI) entry
2209 switch (bkpinfo->backup_media_type) {
2210 case cdr:
2211 case cdrw:
2212 case dvd:
2213 case usb:
2214 /* Never try to eject a USB device */
2215 if (bkpinfo->backup_media_type == usb) {
2216 bkpinfo->please_dont_eject = TRUE;
2217 }
2218 if (archiving_to_media) {
2219 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
2220 if (ask_me_yes_or_no
2221 ("Is your computer a laptop, or does the CD writer incorporate BurnProof technology?"))
2222 {
2223 bkpinfo->manual_cd_tray = TRUE;
2224 }
2225 }
2226 if ((bkpinfo->compression_level =
2227 which_compression_level()) == -1) {
2228 log_to_screen("User has chosen not to backup the PC");
2229 finish(1);
2230 }
2231 mds = media_descriptor_string(bkpinfo->backup_media_type);
2232 sprintf(comment, "What speed is your %s (re)writer?", mds);
2233 if (bkpinfo->backup_media_type == dvd) {
2234 find_dvd_device(bkpinfo->media_device, FALSE);
2235 strcpy(tmp1, "1");
2236 sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB
2237 log_msg(1, "Setting to DVD defaults");
2238 } else {
2239 strcpy(bkpinfo->media_device, VANILLA_SCSI_CDROM);
2240 strcpy(tmp1, "4");
2241 strcpy(sz_size, "650");
2242 log_msg(1, "Setting to CD defaults");
2243 }
2244 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
2245 if (!popup_and_get_string("Speed", comment, tmp1, 4)) {
2246 log_to_screen("User has chosen not to backup the PC");
2247 finish(1);
2248 }
2249 }
2250 bkpinfo->cdrw_speed = atoi(tmp1); // if DVD then this shouldn't ever be used anyway :)
2251
2252 sprintf(comment,
2253 "How much data (in Megabytes) will each %s store?", mds);
2254 mr_free(mds);
2255 if (!popup_and_get_string("Size", comment, sz_size, 5)) {
2256 log_to_screen("User has chosen not to backup the PC");
2257 finish(1);
2258 }
2259 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2260 bkpinfo->media_size[i] = atoi(sz_size);
2261 }
2262 if (bkpinfo->media_size[0] <= 0) {
2263 log_to_screen("User has chosen not to backup the PC");
2264 finish(1);
2265 }
2266 }
2267 /* No break because we continue even for usb */
2268 case cdstream:
2269 mds = media_descriptor_string(bkpinfo->backup_media_type);
2270
2271 if ((bkpinfo->disaster_recovery) && (bkpinfo->backup_media_type != usb)) {
2272 strcpy(bkpinfo->media_device, "/dev/cdrom");
2273 log_msg(2, "CD-ROM device assumed to be at %s",
2274 bkpinfo->media_device);
2275 } else if ((bkpinfo->restore_data && (bkpinfo->backup_media_type != usb))
2276 || bkpinfo->backup_media_type == dvd) {
2277 if (!bkpinfo->media_device[0]) {
2278 strcpy(bkpinfo->media_device, "/dev/cdrom");
2279 } // just for the heck of it :)
2280 log_msg(1, "bkpinfo->media_device = %s",
2281 bkpinfo->media_device);
2282 if (bkpinfo->backup_media_type == dvd
2283 || find_cdrom_device(bkpinfo->media_device, FALSE)) {
2284 log_msg(1, "bkpinfo->media_device = %s",
2285 bkpinfo->media_device);
2286 sprintf(comment,
2287 "Please specify your %s drive's /dev entry", mds);
2288 if (!popup_and_get_string
2289 ("Device?", comment, bkpinfo->media_device,
2290 MAX_STR_LEN / 4)) {
2291 log_to_screen("User has chosen not to backup the PC");
2292 finish(1);
2293 }
2294 }
2295 log_msg(2, "%s device found at %s", mds, bkpinfo->media_device);
2296 } else {
2297 if ((find_cdrw_device(bkpinfo->media_device)) && (bkpinfo->backup_media_type != usb)) {
2298 bkpinfo->media_device[0] = '\0';
2299 }
2300 if (bkpinfo->media_device[0]) {
2301 if (bkpinfo->backup_media_type == usb) {
2302 mr_asprintf(&tmp, "I think your %s media corresponds to %s. Is this correct?", mds, bkpinfo->media_device);
2303 } else {
2304 mr_asprintf(&tmp, "I think I've found your %s burner at SCSI node %s. Is this correct? (Say no if you have an IDE burner and you are running a 2.6 kernel. You will then be prompted for further details.)", mds, bkpinfo->media_device);
2305 }
2306 if (!ask_me_yes_or_no(tmp)) {
2307 bkpinfo->media_device[0] = '\0';
2308 }
2309 mr_free(tmp);
2310 }
2311 if (!bkpinfo->media_device[0]) {
2312 if (bkpinfo->backup_media_type == usb) {
2313 i = popup_and_get_string("/dev entry?",
2314 "What is the /dev entry of your USB Disk/Key, please?",
2315 bkpinfo->media_device,
2316 MAX_STR_LEN / 4);
2317 } else {
2318 if (g_kernel_version < 2.6) {
2319 i = popup_and_get_string("Device node?",
2320 "What is the SCSI node of your CD (re)writer, please?",
2321 bkpinfo->media_device,
2322 MAX_STR_LEN / 4);
2323 } else {
2324 i = popup_and_get_string("/dev entry?",
2325 "What is the /dev entry of your CD (re)writer, please?",
2326 bkpinfo->media_device,
2327 MAX_STR_LEN / 4);
2328 }
2329 }
2330 if (!i) {
2331 log_to_screen("User has chosen not to backup the PC");
2332 finish(1);
2333 }
2334 }
2335 }
2336 mr_free(mds);
2337
2338 if (bkpinfo->backup_media_type == cdstream) {
2339 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2340 bkpinfo->media_size[i] = 650;
2341 }
2342 }
2343 break;
2344 case udev:
2345 if (!ask_me_yes_or_no
2346 ("This option is for advanced users only. Are you sure?")) {
2347 log_to_screen("User has chosen not to backup the PC");
2348 finish(1);
2349 }
2350 case tape:
2351
2352 if ((!bkpinfo->restore_mode) && (find_tape_device_and_size(bkpinfo->media_device, sz_size))) {
2353 log_msg(3, "Ok, using vanilla scsi tape.");
2354 strcpy(bkpinfo->media_device, VANILLA_SCSI_TAPE);
2355 if ((fin = fopen(bkpinfo->media_device, "r"))) {
2356 paranoid_fclose(fin);
2357 } else {
2358 strcpy(bkpinfo->media_device, "/dev/osst0");
2359 }
2360 }
2361 if (bkpinfo->media_device[0]) {
2362 if ((fin = fopen(bkpinfo->media_device, "r"))) {
2363 paranoid_fclose(fin);
2364 } else {
2365 if (does_file_exist("/tmp/mondo-restore.cfg")) {
2366 read_cfg_var("/tmp/mondo-restore.cfg", "media-dev",
2367 bkpinfo->media_device);
2368 }
2369 }
2370 }
2371 if (bkpinfo->media_device[0]) {
2372 mr_asprintf(&tmp, "I think I've found your tape streamer at %s; am I right on the money?", bkpinfo->media_device);
2373 if (!ask_me_yes_or_no(tmp)) {
2374 bkpinfo->media_device[0] = '\0';
2375 }
2376 mr_free(tmp);
2377 }
2378 if (!bkpinfo->media_device[0]) {
2379 if (!popup_and_get_string
2380 ("Device name?",
2381 "What is the /dev entry of your tape streamer?",
2382 bkpinfo->media_device, MAX_STR_LEN / 4)) {
2383 log_to_screen("User has chosen not to backup the PC");
2384 finish(1);
2385 }
2386 }
2387 mr_asprintf(&tmp, "ls -l %s", bkpinfo->media_device);
2388 if (run_program_and_log_output(tmp, FALSE)) {
2389 log_to_screen("User has not specified a valid /dev entry");
2390 finish(1);
2391 }
2392 mr_free(tmp);
2393 log_msg(4, "sz_size = %s", sz_size);
2394 sz_size[0] = '\0';
2395
2396 bkpinfo->use_obdr = ask_me_yes_or_no
2397 ("Do you want to activate OBDR support for your tapes ?");
2398 if (sz_size[0] == '\0') {
2399 bkpinfo->media_size[0] = 0;
2400 } else {
2401 bkpinfo->media_size[0] =
2402 friendly_sizestr_to_sizelong(sz_size) / 2 - 50;
2403 }
2404 log_msg(4, "media_size[0] = %ld", bkpinfo->media_size[0]);
2405 if (bkpinfo->media_size[0] <= 0) {
2406 bkpinfo->media_size[0] = 0;
2407 }
2408 for (i = 1; i <= MAX_NOOF_MEDIA; i++) {
2409 bkpinfo->media_size[i] = bkpinfo->media_size[0];
2410 }
2411 if (archiving_to_media) {
2412 if ((bkpinfo->compression_level =
2413 which_compression_level()) == -1) {
2414 log_to_screen("User has chosen not to backup the PC");
2415 finish(1);
2416 }
2417 }
2418 break;
2419
2420
2421
2422 case netfs:
2423 /* Never try to eject a NETFS device */
2424 bkpinfo->please_dont_eject = TRUE;
2425
2426 /* Initiate bkpinfo netfs_mount path from running environment if not already done */
2427 if (!bkpinfo->netfs_mount[0]) {
2428 strcpy(bkpinfo->netfs_mount,
2429 call_program_and_get_last_line_of_output
2430 ("mount | grep \":\" | cut -d' ' -f1 | head -n1"));
2431 }
2432#ifdef __FreeBSD__
2433 if (TRUE)
2434#else
2435 if (!bkpinfo->disaster_recovery)
2436#endif
2437 {
2438 if (!popup_and_get_string
2439 ("Network shared dir.",
2440 "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.)",
2441 bkpinfo->netfs_mount, MAX_STR_LEN / 4)) {
2442 log_to_screen("User has chosen not to backup the PC");
2443 finish(1);
2444 }
2445 if (!bkpinfo->restore_data) {
2446 if ((bkpinfo->compression_level =
2447 which_compression_level()) == -1) {
2448 log_to_screen("User has chosen not to backup the PC");
2449 finish(1);
2450 }
2451 }
2452 // check whether already mounted - we better remove
2453 // surrounding spaces and trailing '/' for this
2454 strip_spaces(bkpinfo->netfs_mount);
2455 if (bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] == '/')
2456 bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] = '\0';
2457 sprintf(command, "mount | grep \"%s \" | cut -d' ' -f3",
2458 bkpinfo->netfs_mount);
2459 strcpy(bkpinfo->isodir,
2460 call_program_and_get_last_line_of_output(command));
2461
2462 if (!bkpinfo->restore_data) {
2463 sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB
2464 sprintf(comment,
2465 "How much data (in Megabytes) will each media store?");
2466 if (!popup_and_get_string("Size", comment, sz_size, 5)) {
2467 log_to_screen("User has chosen not to backup the PC");
2468 finish(1);
2469 }
2470 } else {
2471 strcpy(sz_size, "0");
2472 }
2473 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2474 bkpinfo->media_size[i] = atoi(sz_size);
2475 }
2476 if (bkpinfo->media_size[0] < 0) {
2477 log_to_screen("User has chosen not to backup the PC");
2478 finish(1);
2479 }
2480 }
2481 /* Force NFS to be the protocol by default */
2482 if (bkpinfo->netfs_proto == NULL) {
2483 mr_asprintf(&(bkpinfo->netfs_proto), "nfs");
2484 }
2485 if (bkpinfo->disaster_recovery) {
2486 sprintf(command ,"umount %s/isodir 2> /dev/null", bkpinfo->tmpdir);
2487 (void)system(command);
2488 }
2489 strcpy(tmp1, bkpinfo->netfs_proto);
2490 if (!popup_and_get_string
2491 ("Network protocol", "Which protocol should I use (nfs/sshfs) ?",
2492 tmp1, MAX_STR_LEN)) {
2493 log_to_screen("User has chosen not to backup the PC");
2494 finish(1);
2495 }
2496 mr_free(bkpinfo->netfs_proto);
2497 mr_asprintf(&(bkpinfo->netfs_proto), "%s", tmp1);
2498 if (!popup_and_get_string
2499 ("Network share", "Which remote share should I mount?",
2500 bkpinfo->netfs_mount, MAX_STR_LEN)) {
2501 log_to_screen("User has chosen not to backup the PC");
2502 finish(1);
2503 }
2504
2505 /* Initiate bkpinfo isodir path from running environment if mount already done */
2506 if (is_this_device_mounted(bkpinfo->netfs_mount)) {
2507 strcpy(bkpinfo->isodir,
2508 call_program_and_get_last_line_of_output
2509 ("mount | grep \":\" | cut -d' ' -f3 | head -n1"));
2510 } else {
2511 sprintf(bkpinfo->isodir, "%s/netfsdir", bkpinfo->tmpdir);
2512 sprintf(command, "mkdir -p %s", bkpinfo->isodir);
2513 run_program_and_log_output(command, 5);
2514 if (bkpinfo->restore_data) {
2515 if (strstr(bkpinfo->netfs_proto, "sshfs")) {
2516 mr_asprintf(&tmp, "sshfs -o ro %s %s", bkpinfo->netfs_mount, bkpinfo->isodir);
2517 } else {
2518 mr_asprintf(&tmp, "mount -t %s -o nolock,ro %s %s", bkpinfo->netfs_proto, bkpinfo->netfs_mount, bkpinfo->isodir);
2519 }
2520 } else {
2521 if (strstr(bkpinfo->netfs_proto, "sshfs")) {
2522 mr_asprintf(&tmp, "sshfs %s %s", bkpinfo->netfs_mount, bkpinfo->isodir);
2523 } else {
2524 mr_asprintf(&tmp, "mount -t %s -o nolock %s %s", bkpinfo->netfs_proto, bkpinfo->netfs_mount, bkpinfo->isodir);
2525 }
2526 }
2527 run_program_and_log_output(tmp, 3);
2528 mr_free(tmp);
2529
2530 malloc_string(g_selfmounted_isodir);
2531 strcpy(g_selfmounted_isodir, bkpinfo->isodir);
2532 }
2533 if (!is_this_device_mounted(bkpinfo->netfs_mount)) {
2534 popup_and_OK
2535 ("Please mount that partition before you try to backup to or restore from it.");
2536 finish(1);
2537 }
2538 strcpy(tmp1, bkpinfo->netfs_remote_dir);
2539 if (!popup_and_get_string
2540 ("Directory", "Which directory within that mountpoint?", tmp1,
2541 MAX_STR_LEN)) {
2542 log_to_screen("User has chosen not to backup the PC");
2543 finish(1);
2544 }
2545 strcpy(bkpinfo->netfs_remote_dir, tmp1);
2546
2547 // check whether writable - we better remove surrounding spaces for this
2548 strip_spaces(bkpinfo->netfs_remote_dir);
2549
2550 if (!popup_and_get_string
2551 ("Prefix.",
2552 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
2553 bkpinfo->prefix, MAX_STR_LEN / 4)) {
2554 log_to_screen("User has chosen not to backup the PC");
2555 finish(1);
2556 }
2557 log_msg(3, "prefix set to %s", bkpinfo->prefix);
2558
2559 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2560 bkpinfo->media_size[i] = 650;
2561 }
2562 log_msg(3, "Just set netfs_remote_dir to %s",
2563 bkpinfo->netfs_remote_dir);
2564 log_msg(3, "isodir is still %s", bkpinfo->isodir);
2565 break;
2566
2567 case iso:
2568 if (!bkpinfo->disaster_recovery) {
2569 if (!popup_and_get_string
2570 ("Storage dir.",
2571 "Please enter the full path name to the directory for your ISO images. Example: /mnt/raid0_0",
2572 bkpinfo->isodir, MAX_STR_LEN / 4)) {
2573 log_to_screen("User has chosen not to backup the PC");
2574 finish(1);
2575 }
2576 if (archiving_to_media) {
2577 if ((bkpinfo->compression_level =
2578 which_compression_level()) == -1) {
2579 log_to_screen("User has chosen not to backup the PC");
2580 finish(1);
2581 }
2582 sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB
2583 if (!popup_and_get_string
2584 ("ISO size.",
2585 "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 (700) or DVD's (4480) you plan to backup to.",
2586 sz_size, 16)) {
2587 log_to_screen("User has chosen not to backup the PC");
2588 finish(1);
2589 }
2590 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2591 bkpinfo->media_size[i] = atoi(sz_size);
2592 }
2593 } else {
2594 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2595 bkpinfo->media_size[i] = 650;
2596 }
2597 }
2598 }
2599 if (!popup_and_get_string
2600 ("Prefix.",
2601 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
2602 bkpinfo->prefix, MAX_STR_LEN / 4)) {
2603 log_to_screen("User has chosen not to backup the PC");
2604 finish(1);
2605 }
2606 log_msg(3, "prefix set to %s", bkpinfo->prefix);
2607 break;
2608 default:
2609 fatal_error
2610 ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
2611 }
2612
2613 if (archiving_to_media) {
2614
2615#ifdef __FreeBSD__
2616 strcpy(bkpinfo->boot_device,
2617 call_program_and_get_last_line_of_output
2618 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
2619#else
2620 strcpy(bkpinfo->boot_device,
2621 call_program_and_get_last_line_of_output
2622 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
2623#endif
2624 i = which_boot_loader(bkpinfo->boot_device);
2625 if (i == 'U') // unknown
2626 {
2627
2628#ifdef __FreeBSD__
2629 if (!popup_and_get_string
2630 ("Boot device",
2631 "What is your boot device? (e.g. /dev/ad0)",
2632 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2633 log_to_screen("User has chosen not to backup the PC");
2634 finish(1);
2635 }
2636 i = which_boot_loader(bkpinfo->boot_device);
2637#else
2638 if (!popup_and_get_string
2639 ("Boot device",
2640 "What is your boot device? (e.g. /dev/hda)",
2641 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2642 log_to_screen("User has chosen not to backup the PC");
2643 finish(1);
2644 }
2645 if (does_string_exist_in_boot_block
2646 (bkpinfo->boot_device, "LILO")) {
2647 i = 'L';
2648 } else
2649 if (does_string_exist_in_boot_block
2650 (bkpinfo->boot_device, "ELILO")) {
2651 i = 'E';
2652 } else
2653 if (does_string_exist_in_boot_block
2654 (bkpinfo->boot_device, "GRUB")) {
2655 i = 'G';
2656 } else {
2657 i = 'U';
2658 }
2659#endif
2660 if (i == 'U') {
2661 if (ask_me_yes_or_no
2662 ("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?"))
2663 {
2664 i = 'R'; // raw
2665 } else {
2666 log_to_screen
2667 ("I cannot find your boot loader. Please run mondoarchive with parameters.");
2668 finish(1);
2669 }
2670 }
2671 }
2672 bkpinfo->boot_loader = i;
2673 strcpy(bkpinfo->include_paths, "/");
2674 if (!popup_and_get_string
2675 ("Backup paths",
2676 "Please enter paths (separated by '|') which you want me to backup. The default is '/' (i.e. everything).",
2677 bkpinfo->include_paths, MAX_STR_LEN)) {
2678 log_to_screen("User has chosen not to backup the PC");
2679 finish(1);
2680 }
2681 tmp = list_of_NETFS_mounts_only();
2682 if (strlen(tmp) > 2) {
2683 mr_strcat(bkpinfo->exclude_paths, "|%s",tmp);
2684 }
2685 mr_free(tmp);
2686// NTFS
2687 strcpy(tmp1, call_program_and_get_last_line_of_output("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'"));
2688 if (strlen(tmp1) > 2) {
2689 if (!popup_and_get_string
2690 ("NTFS partitions",
2691 "Please enter/confirm the NTFS partitions you wish to backup as well.",
2692 tmp1, MAX_STR_LEN / 4)) {
2693 log_to_screen("User has chosen not to backup the PC");
2694 finish(1);
2695 }
2696 strncpy(bkpinfo->image_devs, tmp1, MAX_STR_LEN / 4);
2697 }
2698
2699 if (bkpinfo->exclude_paths != NULL ) {
2700 strncpy(p,bkpinfo->exclude_paths,(8*MAX_STR_LEN)-1);
2701 } else {
2702 p[0] = '\0';
2703 }
2704 popup_and_get_string("Exclude paths", "Please enter paths which you do NOT want to backup. Separate them with '|'. NB: /tmp and /proc are always excluded. :-) Just hit 'Enter' if you want to do a full system backup.", p, (8*MAX_STR_LEN)-1);
2705 if (p == NULL) {
2706 log_to_screen("User has chosen not to backup the PC");
2707 finish(1);
2708 }
2709 mr_free(bkpinfo->exclude_paths);
2710 mr_asprintf(&tmp, "%s", p);
2711 bkpinfo->exclude_paths = tmp;
2712
2713 if (!popup_and_get_string
2714 ("Temporary directory",
2715 "Please enter your temporary directory.",
2716 bkpinfo->tmpdir, (4*MAX_STR_LEN)-1)) {
2717 log_to_screen("User has chosen not to backup the PC");
2718 finish(1);
2719 }
2720 if (!popup_and_get_string
2721 ("Scratch directory",
2722 "Please enter your scratch directory.",
2723 bkpinfo->scratchdir, (4*MAX_STR_LEN)-1)) {
2724 log_to_screen("User has chosen not to backup the PC");
2725 finish(1);
2726 }
2727// Interactive mode:
2728#ifdef __IA64__
2729 bkpinfo->make_cd_use_lilo = TRUE;
2730#else
2731 bkpinfo->make_cd_use_lilo = FALSE;
2732#endif
2733 bkpinfo->backup_data = TRUE;
2734 bkpinfo->verify_data =
2735 ask_me_yes_or_no
2736 ("Will you want to verify your backups after Mondo has created them?");
2737
2738#ifndef __FreeBSD__
2739 if (!ask_me_yes_or_no
2740 ("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."))
2741#endif
2742 {
2743 strcpy(bkpinfo->kernel_path, "FAILSAFE");
2744 }
2745
2746 if (!ask_me_yes_or_no
2747 ("Are you sure you want to proceed? Hit 'no' to abort.")) {
2748 log_to_screen("User has chosen not to backup the PC");
2749 finish(1);
2750 }
2751 } else {
2752 bkpinfo->restore_data = TRUE; // probably...
2753 }
2754
2755 if (bkpinfo->backup_media_type == iso
2756 || bkpinfo->backup_media_type == netfs) {
2757 g_ISO_restore_mode = TRUE;
2758 }
2759#ifdef __FreeSD__
2760// skip
2761#else
2762 if (bkpinfo->backup_media_type == netfs) {
2763 log_msg(3, "I think the Remote mount is mounted at %s",
2764 bkpinfo->isodir);
2765 }
2766 log_it("isodir = %s", bkpinfo->isodir);
2767 log_it("netfs_mount = '%s'", bkpinfo->netfs_mount);
2768 if (bkpinfo->netfs_proto) {
2769 log_it("netfs_proto = '%s'", bkpinfo->netfs_proto);
2770 }
2771 if (bkpinfo->netfs_user) {
2772 log_it("netfs_user = '%s'", bkpinfo->netfs_user);
2773 }
2774#endif
2775
2776 log_it("media device = %s", bkpinfo->media_device);
2777 log_it("media size = %ld", bkpinfo->media_size[1]);
2778 log_it("media type = %s",
2779 bkptype_to_string(bkpinfo->backup_media_type));
2780 log_it("prefix = %s", bkpinfo->prefix);
2781 log_it("compression = %ld", bkpinfo->compression_level);
2782 log_it("exclude_path = %s", bkpinfo->exclude_paths);
2783 log_it("include_path = %s", bkpinfo->include_paths);
2784
2785 /* Handle devices passed in bkpinfo and print result */
2786 /* the mr_make_devlist_from_pathlist function appends
2787 * to the *_paths variables so copy before */
2788 mr_make_devlist_from_pathlist(bkpinfo->exclude_paths, 'E');
2789 mr_make_devlist_from_pathlist(bkpinfo->include_paths, 'I');
2790
2791 log_it("scratchdir = '%s'", bkpinfo->scratchdir);
2792 log_it("tmpdir = '%s'", bkpinfo->tmpdir);
2793 log_it("image_devs = '%s'", bkpinfo->image_devs);
2794 log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device,
2795 bkpinfo->boot_loader);
2796 if (bkpinfo->media_size[0] < 0) {
2797 if (archiving_to_media) {
2798 fatal_error("Media size is less than zero.");
2799 } else {
2800 log_msg(2, "Warning - media size is less than zero.");
2801 bkpinfo->media_size[0] = 0;
2802 }
2803 }
2804 paranoid_free(sz_size);
2805 paranoid_free(tmp1);
2806 paranoid_free(command);
2807 paranoid_free(comment);
2808 paranoid_free(prompt);
2809 return (0);
2810}
2811
2812
2813/**
2814 * Get a |-separated list of NETFS mounts.
2815 * @return The list created.
2816 * @note The return value points to allocated string that needs to be freed
2817 * @bug Even though we only want the mounts, the devices are still checked.
2818 */
2819char *list_of_NETFS_mounts_only(void)
2820{
2821 char *exclude_these_directories = NULL;
2822
2823 mr_asprintf(&exclude_these_directories,"%s", call_program_and_get_last_line_of_output("mount -t coda,ncpfs,fuse.sshfs,nfs,nfs4,vmhgfs,smbfs,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' '|' | awk '{print $0;}'"));
2824 log_msg(9,"list_of_NETFS_mounts_only returns %s\n",exclude_these_directories);
2825 return(exclude_these_directories);
2826}
2827
2828/* @} - end of utilityGroup */
2829
2830
2831
2832
2833
2834/**
2835 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
2836 * [random] is a random number between 1 and 32767.
2837 * @param store_name_here Where to store the new filename.
2838 * @param stub A random number will be appended to this to make the FIFO's name.
2839 * @ingroup deviceGroup
2840 */
2841void make_fifo(char *store_name_here, char *stub)
2842{
2843 char *tmp;
2844
2845 malloc_string(tmp);
2846 assert_string_is_neither_NULL_nor_zerolength(stub);
2847
2848 sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
2849 (int) (random() % 32768));
2850 make_hole_for_file(store_name_here);
2851 mkfifo(store_name_here, S_IRWXU | S_IRWXG);
2852 sprintf(tmp, "chmod 770 %s", store_name_here);
2853 paranoid_system(tmp);
2854 paranoid_free(tmp);
2855}
2856
2857
2858
2859
2860
2861
2862/**
2863 * Set the tmpdir and scratchdir to reside on the partition with the most free space.
2864 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
2865 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set.
2866 * @ingroup utilityGroup
2867 */
2868void sensibly_set_tmpdir_and_scratchdir()
2869{
2870 char *tmp = NULL;
2871 char *command = NULL;
2872 char *sz = NULL;
2873
2874 assert(bkpinfo != NULL);
2875
2876#ifdef __FreeBSD__
2877 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output("LANGUAGE=C df -m -P -t nonfs,msdosfs,ntfs,ntfs-3g,vmhgfs,smbfs,smb,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol | grep -vE \"none|Filesystem\" | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -nr | awk '{print $NF;}' | while read x ; do test -w $x && echo $x && break ; done"));
2878#else
2879 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output("LANGUAGE=C df -m -P -x nfs -x nfs4 -x fuse.sshfs -x fuse -x vfat -x ntfs -x ntfs-3g -x vmhgfs -x smbfs -x smb -x cifs -x afs -x gfs -x ocfs -x ocfs2 -x mvfs -x nsspool -x nssvol -x iso9660 | grep -vE \"none|Filesystem|/dev/shm\" | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -nr | awk '{print $NF;}' | while read x ; do test -w $x && echo $x && break ; done"));
2880#endif
2881
2882 if (tmp[0] != '/') {
2883 mr_asprintf(&sz, "%s", tmp);
2884 paranoid_free(tmp);
2885 mr_asprintf(&tmp, "/%s", sz);
2886 mr_free(sz);
2887 }
2888 if (!tmp[0]) {
2889 fatal_error("I couldn't figure out the tempdir!");
2890 }
2891 setup_tmpdir(tmp);
2892 log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir);
2893
2894 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%d", tmp,
2895 (int) (random() % 32768));
2896 log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
2897
2898 mr_asprintf(&command, "rm -Rf %s/tmp.mondo.* %s/mondo.scratch.*", tmp, tmp);
2899 paranoid_free(tmp);
2900
2901 paranoid_system(command);
2902 mr_free(command);
2903}
2904
2905
2906
2907
2908
2909
2910/**
2911 * @addtogroup deviceGroup
2912 * @{
2913 */
2914/**
2915 * If we can read @p dev, set @p output to it.
2916 * If @p dev cannot be read, set @p output to "".
2917 * @param dev The device to check for.
2918 * @param output Set to @p dev if @p dev exists, "" otherwise.
2919 * @return TRUE if @p dev exists, FALSE if it doesn't.
2920 */
2921bool set_dev_to_this_if_rx_OK(char *output, char *dev)
2922{
2923 char *command;
2924
2925 malloc_string(command);
2926 if (!dev || dev[0] == '\0') {
2927 output[0] = '\0';
2928 return (FALSE);
2929 }
2930// assert_string_is_neither_NULL_nor_zerolength(dev);
2931 log_msg(10, "Injecting %s", dev);
2932 inject_device(dev);
2933 if (!does_file_exist(dev)) {
2934 log_msg(10, "%s doesn't exist. Returning FALSE.", dev);
2935 return (FALSE);
2936 }
2937 sprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null",
2938 512L, dev);
2939 if (!run_program_and_log_output(command, FALSE)
2940 && !run_program_and_log_output(command, FALSE)) {
2941 strcpy(output, dev);
2942 log_msg(4, "Found it - %s", dev);
2943 return (TRUE);
2944 } else {
2945 output[0] = '\0';
2946 log_msg(4, "It's not %s", dev);
2947 return (FALSE);
2948 }
2949}
2950
2951
2952
2953
2954
2955/**
2956 * Find out what number CD is in the drive.
2957 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
2958 * @return The current CD number, or -1 if it could not be found.
2959 * @note If the CD is not mounted, it will be mounted
2960 * (and remain mounted after this function returns).
2961 */
2962int what_number_cd_is_this()
2963{
2964 int cd_number = -1;
2965 char *mountdev = NULL;
2966 char *tmp = NULL;
2967
2968 assert(bkpinfo != NULL);
2969// log_it("Asking what_number_cd_is_this");
2970 if (g_ISO_restore_mode) {
2971 mr_asprintf(&tmp, "mount | grep iso9660 | awk '{print $3;}'");
2972
2973 mr_asprintf(&mountdev, "%s%s", call_program_and_get_last_line_of_output(tmp), "/archives/THIS-CD-NUMBER");
2974 cd_number = atoi(last_line_of_file(mountdev));
2975 paranoid_free(mountdev);
2976 paranoid_free(tmp);
2977
2978 return (cd_number);
2979 }
2980
2981 mr_asprintf(&mountdev, "%s", bkpinfo->media_device);
2982 if (!mountdev[0]) {
2983 log_it
2984 ("(what_number_cd_is_this) Warning - media_device unknown. Finding out...");
2985 find_cdrom_device(bkpinfo->media_device, FALSE);
2986 }
2987 if (!is_this_device_mounted(MNT_CDROM)) {
2988 if (bkpinfo->backup_media_type == usb) {
2989 mount_USB_here(mountdev, MNT_CDROM);
2990 } else {
2991 mount_CDROM_here(mountdev, MNT_CDROM);
2992 }
2993 }
2994 paranoid_free(mountdev);
2995
2996 cd_number = atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
2997 return (cd_number);
2998}
2999
3000
3001
3002
3003
3004
3005
3006/**
3007 * Find out what device is mounted as root (/).
3008 * @return Root device.
3009 * @note The returned string points to static storage and will be overwritten with every call.
3010 * @bug A bit of a misnomer; it's actually finding out the root device.
3011 * The mountpoint (where it's mounted) will obviously be '/'.
3012 */
3013char *where_is_root_mounted()
3014{
3015 /*@ buffers **************** */
3016 static char tmp[MAX_STR_LEN];
3017
3018
3019#ifdef __FreeBSD__
3020 strcpy(tmp, call_program_and_get_last_line_of_output
3021 ("mount | grep \" on / \" | cut -d' ' -f1"));
3022#else
3023 strcpy(tmp, call_program_and_get_last_line_of_output
3024 ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"));
3025 if (strstr(tmp, "/dev/cciss/")) {
3026 strcpy(tmp, call_program_and_get_last_line_of_output
3027 ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"));
3028 }
3029 if (strstr(tmp, "/dev/md")) {
3030 strcpy(tmp,
3031 call_program_and_get_last_line_of_output
3032 ("mount | grep \" on / \" | cut -d' ' -f1"));
3033 }
3034#endif
3035
3036 return (tmp);
3037}
3038
3039
3040/**
3041 * Find out which boot loader is in use.
3042 * @param which_device Device to look for the boot loader on.
3043 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
3044 * @note Under Linux, all drives are examined, not just @p which_device.
3045 */
3046#ifdef __FreeBSD__
3047char which_boot_loader(char *which_device)
3048{
3049 int count_lilos = 0;
3050 int count_grubs = 0;
3051 int count_boot0s = 0;
3052 int count_dangerouslydedicated = 0;
3053
3054 log_it("looking at drive %s's MBR", which_device);
3055 if (does_string_exist_in_boot_block(which_device, "GRUB")) {
3056 count_grubs++;
3057 }
3058 if (does_string_exist_in_boot_block(which_device, "LILO")) {
3059 count_lilos++;
3060 }
3061 if (does_string_exist_in_boot_block(which_device, "Drive")) {
3062 count_boot0s++;
3063 }
3064 if (does_string_exist_in_first_N_blocks
3065 (which_device, "FreeBSD/i386", 17)) {
3066 count_dangerouslydedicated++;
3067 }
3068 log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
3069 count_grubs, count_lilos, count_elilos, count_boot0s,
3070 count_dangerouslydedicated);
3071
3072 if (count_grubs && !count_lilos) {
3073 return ('G');
3074 } else if (count_lilos && !count_grubs) {
3075 return ('L');
3076 } else if (count_grubs == 1 && count_lilos == 1) {
3077 log_it("I'll bet you used to use LILO but switched to GRUB...");
3078 return ('G');
3079 } else if (count_boot0s == 1) {
3080 return ('B');
3081 } else if (count_dangerouslydedicated) {
3082 return ('D');
3083 } else {
3084 log_it("Unknown boot loader");
3085 return ('U');
3086 }
3087}
3088
3089#else
3090
3091char which_boot_loader(char *which_device)
3092{
3093 /*@ buffer ***************************************************** */
3094 char *list_drives_cmd = NULL;
3095 char *current_drive;
3096
3097 /*@ pointers *************************************************** */
3098 FILE *pdrives;
3099
3100 /*@ int ******************************************************** */
3101 int count_lilos = 0;
3102 int count_grubs = 0;
3103
3104 /*@ end vars *************************************************** */
3105
3106 malloc_string(current_drive);
3107
3108#ifdef __IA64__
3109 /* No choice for it */
3110 return ('E');
3111#endif
3112 assert(which_device != NULL);
3113
3114 mr_asprintf(&list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s", where_is_root_mounted());
3115 log_it("list_drives_cmd = %s", list_drives_cmd);
3116
3117 if (!(pdrives = popen(list_drives_cmd, "r"))) {
3118 log_OS_error("Unable to open list of drives");
3119 mr_free(list_drives_cmd);
3120 paranoid_free(current_drive);
3121 return ('\0');
3122 }
3123 mr_free(list_drives_cmd);
3124
3125 for ((void)fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
3126 (void)fgets(current_drive, MAX_STR_LEN, pdrives)) {
3127 strip_spaces(current_drive);
3128 log_it("looking at drive %s's MBR", current_drive);
3129 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
3130 count_grubs++;
3131 strcpy(which_device, current_drive);
3132 break;
3133 }
3134 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
3135 count_lilos++;
3136 strcpy(which_device, current_drive);
3137 break;
3138 }
3139 }
3140 if (pclose(pdrives)) {
3141 log_OS_error("Cannot pclose pdrives");
3142 }
3143 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
3144 if (count_grubs && !count_lilos) {
3145 paranoid_free(current_drive);
3146 return ('G');
3147 } else if (count_lilos && !count_grubs) {
3148 paranoid_free(current_drive);
3149 return ('L');
3150 } else if (count_grubs == 1 && count_lilos == 1) {
3151 log_it("I'll bet you used to use LILO but switched to GRUB...");
3152 paranoid_free(current_drive);
3153 return ('G');
3154 } else {
3155 // We need to look on each partition then
3156 mr_asprintf(&list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep -E \"^/dev/\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/");
3157 log_it("list_drives_cmd = %s", list_drives_cmd);
3158
3159 if (!(pdrives = popen(list_drives_cmd, "r"))) {
3160 log_OS_error("Unable to open list of drives");
3161 mr_free(list_drives_cmd);
3162 paranoid_free(current_drive);
3163 return ('\0');
3164 }
3165 mr_free(list_drives_cmd);
3166
3167 for ((void)fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
3168 (void)fgets(current_drive, MAX_STR_LEN, pdrives)) {
3169 strip_spaces(current_drive);
3170 log_it("looking at partition %s's BR", current_drive);
3171 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
3172 count_grubs++;
3173 strcpy(which_device, current_drive);
3174 break;
3175 }
3176 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
3177 count_lilos++;
3178 strcpy(which_device, current_drive);
3179 break;
3180 }
3181 }
3182 if (pclose(pdrives)) {
3183 log_OS_error("Cannot pclose pdrives");
3184 }
3185 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
3186 paranoid_free(current_drive);
3187 if (count_grubs && !count_lilos) {
3188 return ('G');
3189 } else if (count_lilos && !count_grubs) {
3190 return ('L');
3191 } else if (count_grubs == 1 && count_lilos == 1) {
3192 log_it("I'll bet you used to use LILO but switched to GRUB...");
3193 return ('G');
3194 } else {
3195 log_it("Unknown boot loader");
3196 return ('U');
3197 }
3198 }
3199}
3200#endif
3201
3202
3203
3204
3205/**
3206 * Write zeroes over the first 16K of @p device.
3207 * @param device The device to zero.
3208 * @return 0 for success, 1 for failure.
3209 */
3210int zero_out_a_device(char *device)
3211{
3212 FILE *fout;
3213 int i;
3214
3215 assert_string_is_neither_NULL_nor_zerolength(device);
3216
3217 log_it("Zeroing drive %s", device);
3218 if (!(fout = fopen(device, "w"))) {
3219 log_OS_error("Unable to open/write to device");
3220 return (1);
3221 }
3222 for (i = 0; i < 16384; i++) {
3223 fputc('\0', fout);
3224 }
3225 paranoid_fclose(fout);
3226 log_it("Device successfully zeroed.");
3227 return (0);
3228}
3229
3230/**
3231 * Return the device pointed to by @p incoming.
3232 * @param incoming The device to resolve symlinks for.
3233 * @return The path to the real device file.
3234 * @note The returned string points to static storage that will be overwritten with each call.
3235 * @bug Won't work with file v4.0; needs to be written in C.
3236 */
3237char *resolve_softlinks_to_get_to_actual_device_file(char *incoming)
3238{
3239 static char output[MAX_STR_LEN];
3240 char *command;
3241 char *curr_fname;
3242 char *scratch = NULL;
3243 char *tmp = NULL;
3244 char *p;
3245
3246 struct stat statbuf;
3247 command = malloc(1000);
3248 malloc_string(curr_fname);
3249 if (!does_file_exist(incoming)) {
3250 log_it
3251 ("resolve_softlinks_to_get_to_actual_device_file --- device not found");
3252 strcpy(output, incoming);
3253 } else {
3254 strcpy(curr_fname, incoming);
3255 lstat(curr_fname, &statbuf);
3256 while (S_ISLNK(statbuf.st_mode)) {
3257 log_msg(1, "curr_fname = %s", curr_fname);
3258 sprintf(command, "file %s", curr_fname);
3259 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
3260 for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' ';
3261 p--);
3262 p++;
3263 mr_asprintf(&scratch, "%s", p);
3264 for (p = scratch; *p != '\0' && *p != '\''; p++);
3265 *p = '\0';
3266 log_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp, scratch);
3267 mr_free(tmp);
3268
3269 if (scratch[0] == '/') {
3270 strcpy(curr_fname, scratch); // copy whole thing because it's an absolute softlink
3271 } else { // copy over the basename cos it's a relative softlink
3272 p = curr_fname + strlen(curr_fname);
3273 while (p != curr_fname && *p != '/') {
3274 p--;
3275 }
3276 if (*p == '/') {
3277 p++;
3278 }
3279 strcpy(p, scratch);
3280 }
3281 mr_free(scratch);
3282 lstat(curr_fname, &statbuf);
3283 }
3284 strcpy(output, curr_fname);
3285 log_it("resolved %s to %s", incoming, output);
3286 }
3287 paranoid_free(command);
3288 paranoid_free(curr_fname);
3289 return (output);
3290}
3291
3292/* @} - end of deviceGroup */
3293
3294/**
3295 * Return the type of partition format (GPT or MBR)
3296 */
3297char *which_partition_format(const char *drive)
3298{
3299 static char output[4];
3300 char *tmp = NULL;
3301 char *command;
3302 char *fdisk;
3303#ifdef __IA64__
3304 struct stat buf;
3305#endif
3306 malloc_string(command);
3307 malloc_string(fdisk);
3308 sprintf(fdisk, "/sbin/parted2fdisk");
3309 sprintf(command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
3310 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
3311 if (strstr(tmp, "GPT") == NULL) {
3312 strcpy(output, "MBR");
3313 } else {
3314 strcpy(output, "GPT");
3315 }
3316 mr_free(tmp);
3317
3318 log_msg(0, "Found %s partition table format type", output);
3319 paranoid_free(command);
3320 paranoid_free(fdisk);
3321 return (output);
3322}
3323/* @} - end of deviceGroup */
Note: See TracBrowser for help on using the repository browser.