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

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