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

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