source: MondoRescue/branches/3.0/mondo/src/common/libmondo-devices.c@ 2941

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