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

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