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

Last change on this file since 3060 was 3060, checked in by Bruno Cornec, 11 years ago

r5035@localhost: bruno | 2012-11-09 03:17:01 +0100

  • Fix a compilation error and most compilation warnings
  • Property svn:keywords set to Id
File size: 97.9 KB
Line 
1/* libmondo-devices.c Subroutines for handling devices
2 $Id: libmondo-devices.c 3060 2012-11-10 04:05:37Z 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 3060 2012-11-10 04:05:37Z 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 *tmp1 = NULL;
2177 char *mds = NULL;
2178 char *q = NULL;
2179 char p[8*MAX_STR_LEN];
2180 char *sz_size;
2181 char *command;
2182 char *compression_type = NULL;
2183 char *comment;
2184 char *prompt;
2185 int i;
2186 FILE *fin;
2187
2188 malloc_string(sz_size);
2189 malloc_string(command);
2190 malloc_string(comment);
2191 malloc_string(prompt);
2192 malloc_string(tmp1);
2193 assert(bkpinfo != NULL);
2194 sz_size[0] = '\0';
2195 bkpinfo->nonbootable_backup = FALSE;
2196
2197 // Tape, CD, NETFS, ...?
2198 srandom(getpid());
2199 bkpinfo->backup_media_type =
2200 (g_restoring_live_from_cd) ? cdr :
2201 which_backup_media_type(bkpinfo->restore_data);
2202 if (bkpinfo->backup_media_type == none) {
2203 log_to_screen("User has chosen not to backup the PC");
2204 finish(1);
2205 }
2206 /* Why asking to remove the media with tape ?
2207 if (bkpinfo->backup_media_type == tape && bkpinfo->restore_data) {
2208 popup_and_OK("Please remove media from drive(s)");
2209 }
2210 */
2211 log_msg(3, "media type = %s",
2212 bkptype_to_string(bkpinfo->backup_media_type));
2213 if (archiving_to_media) {
2214 sensibly_set_tmpdir_and_scratchdir();
2215 }
2216 bkpinfo->cdrw_speed = (bkpinfo->backup_media_type == cdstream) ? 2 : 4;
2217 bkpinfo->compression_level =
2218 (bkpinfo->backup_media_type == cdstream) ? 1 : 5;
2219 bkpinfo->use_lzo =
2220 (bkpinfo->backup_media_type == cdstream) ? TRUE : FALSE;
2221 mvaddstr_and_log_it(2, 0, " ");
2222
2223 // Find device's /dev (or SCSI) entry
2224 switch (bkpinfo->backup_media_type) {
2225 case cdr:
2226 case cdrw:
2227 case dvd:
2228 case usb:
2229 /* Never try to eject a USB device */
2230 if (bkpinfo->backup_media_type == usb) {
2231 bkpinfo->please_dont_eject = TRUE;
2232 }
2233 if (archiving_to_media) {
2234 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
2235 if (ask_me_yes_or_no
2236 ("Is your computer a laptop, or does the CD writer incorporate BurnProof technology?"))
2237 {
2238 bkpinfo->manual_cd_tray = TRUE;
2239 }
2240 }
2241 if ((compression_type = which_compression_type()) == NULL) {
2242 log_to_screen("User has chosen not to backup the PC");
2243 finish(1);
2244 }
2245 if ((bkpinfo->compression_level =
2246 which_compression_level()) == -1) {
2247 log_to_screen("User has chosen not to backup the PC");
2248 finish(1);
2249 }
2250 mds = media_descriptor_string(bkpinfo->backup_media_type);
2251 sprintf(comment, "What speed is your %s (re)writer?", mds);
2252 if (bkpinfo->backup_media_type == dvd) {
2253 find_dvd_device(bkpinfo->media_device, FALSE);
2254 strcpy(tmp1, "1");
2255 sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB
2256 log_msg(1, "Setting to DVD defaults");
2257 } else {
2258 strcpy(bkpinfo->media_device, VANILLA_SCSI_CDROM);
2259 strcpy(tmp1, "4");
2260 strcpy(sz_size, "650");
2261 log_msg(1, "Setting to CD defaults");
2262 }
2263 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
2264 if (!popup_and_get_string("Speed", comment, tmp1, 4)) {
2265 log_to_screen("User has chosen not to backup the PC");
2266 finish(1);
2267 }
2268 }
2269 bkpinfo->cdrw_speed = atoi(tmp1); // if DVD then this shouldn't ever be used anyway :)
2270
2271 sprintf(comment,
2272 "How much data (in Megabytes) will each %s store?", mds);
2273 mr_free(mds);
2274 if (!popup_and_get_string("Size", comment, sz_size, 5)) {
2275 log_to_screen("User has chosen not to backup the PC");
2276 finish(1);
2277 }
2278 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2279 bkpinfo->media_size[i] = atoi(sz_size);
2280 }
2281 if (bkpinfo->media_size[0] <= 0) {
2282 log_to_screen("User has chosen not to backup the PC");
2283 finish(1);
2284 }
2285 }
2286 /* No break because we continue even for usb */
2287 case cdstream:
2288 mds = media_descriptor_string(bkpinfo->backup_media_type);
2289
2290 if ((bkpinfo->disaster_recovery) && (bkpinfo->backup_media_type != usb)) {
2291 strcpy(bkpinfo->media_device, "/dev/cdrom");
2292 log_msg(2, "CD-ROM device assumed to be at %s",
2293 bkpinfo->media_device);
2294 } else if ((bkpinfo->restore_data && (bkpinfo->backup_media_type != usb))
2295 || bkpinfo->backup_media_type == dvd) {
2296 if (!bkpinfo->media_device[0]) {
2297 strcpy(bkpinfo->media_device, "/dev/cdrom");
2298 } // just for the heck of it :)
2299 log_msg(1, "bkpinfo->media_device = %s",
2300 bkpinfo->media_device);
2301 if (bkpinfo->backup_media_type == dvd
2302 || find_cdrom_device(bkpinfo->media_device, FALSE)) {
2303 log_msg(1, "bkpinfo->media_device = %s",
2304 bkpinfo->media_device);
2305 sprintf(comment,
2306 "Please specify your %s drive's /dev entry", mds);
2307 if (!popup_and_get_string
2308 ("Device?", comment, bkpinfo->media_device,
2309 MAX_STR_LEN / 4)) {
2310 log_to_screen("User has chosen not to backup the PC");
2311 finish(1);
2312 }
2313 }
2314 log_msg(2, "%s device found at %s", mds, bkpinfo->media_device);
2315 } else {
2316 if ((find_cdrw_device(bkpinfo->media_device)) && (bkpinfo->backup_media_type != usb)) {
2317 bkpinfo->media_device[0] = '\0';
2318 }
2319 if (bkpinfo->media_device[0]) {
2320 if (bkpinfo->backup_media_type == usb) {
2321 mr_asprintf(&tmp, "I think your %s media corresponds to %s. Is this correct?", mds, bkpinfo->media_device);
2322 } else {
2323 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);
2324 }
2325 if (!ask_me_yes_or_no(tmp)) {
2326 bkpinfo->media_device[0] = '\0';
2327 }
2328 mr_free(tmp);
2329 }
2330 if (!bkpinfo->media_device[0]) {
2331 if (bkpinfo->backup_media_type == usb) {
2332 i = popup_and_get_string("/dev entry?",
2333 "What is the /dev entry of your USB Disk/Key, please?",
2334 bkpinfo->media_device,
2335 MAX_STR_LEN / 4);
2336 } else {
2337 if (g_kernel_version < 2.6) {
2338 i = popup_and_get_string("Device node?",
2339 "What is the SCSI node of your CD (re)writer, please?",
2340 bkpinfo->media_device,
2341 MAX_STR_LEN / 4);
2342 } else {
2343 i = popup_and_get_string("/dev entry?",
2344 "What is the /dev entry of your CD (re)writer, please?",
2345 bkpinfo->media_device,
2346 MAX_STR_LEN / 4);
2347 }
2348 }
2349 if (!i) {
2350 log_to_screen("User has chosen not to backup the PC");
2351 finish(1);
2352 }
2353 }
2354 }
2355 mr_free(mds);
2356
2357 if (bkpinfo->backup_media_type == cdstream) {
2358 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2359 bkpinfo->media_size[i] = 650;
2360 }
2361 }
2362 break;
2363 case udev:
2364 if (!ask_me_yes_or_no
2365 ("This option is for advanced users only. Are you sure?")) {
2366 log_to_screen("User has chosen not to backup the PC");
2367 finish(1);
2368 }
2369 case tape:
2370
2371 if ((!bkpinfo->restore_mode) && (find_tape_device_and_size(bkpinfo->media_device, sz_size))) {
2372 log_msg(3, "Ok, using vanilla scsi tape.");
2373 strcpy(bkpinfo->media_device, VANILLA_SCSI_TAPE);
2374 if ((fin = fopen(bkpinfo->media_device, "r"))) {
2375 paranoid_fclose(fin);
2376 } else {
2377 strcpy(bkpinfo->media_device, "/dev/osst0");
2378 }
2379 }
2380 if (bkpinfo->media_device[0]) {
2381 if ((fin = fopen(bkpinfo->media_device, "r"))) {
2382 paranoid_fclose(fin);
2383 } else {
2384 if (does_file_exist("/tmp/mondo-restore.cfg")) {
2385 read_cfg_var("/tmp/mondo-restore.cfg", "media-dev",
2386 bkpinfo->media_device);
2387 }
2388 }
2389 }
2390 if (bkpinfo->media_device[0]) {
2391 mr_asprintf(&tmp, "I think I've found your tape streamer at %s; am I right on the money?", bkpinfo->media_device);
2392 if (!ask_me_yes_or_no(tmp)) {
2393 bkpinfo->media_device[0] = '\0';
2394 }
2395 mr_free(tmp);
2396 }
2397 if (!bkpinfo->media_device[0]) {
2398 if (!popup_and_get_string
2399 ("Device name?",
2400 "What is the /dev entry of your tape streamer?",
2401 bkpinfo->media_device, MAX_STR_LEN / 4)) {
2402 log_to_screen("User has chosen not to backup the PC");
2403 finish(1);
2404 }
2405 }
2406 mr_asprintf(&tmp, "ls -l %s", bkpinfo->media_device);
2407 if (run_program_and_log_output(tmp, FALSE)) {
2408 log_to_screen("User has not specified a valid /dev entry");
2409 finish(1);
2410 }
2411 mr_free(tmp);
2412 log_msg(4, "sz_size = %s", sz_size);
2413 sz_size[0] = '\0';
2414
2415 if (sz_size[0] == '\0') {
2416 bkpinfo->media_size[0] = 0;
2417 } else {
2418 bkpinfo->media_size[0] =
2419 friendly_sizestr_to_sizelong(sz_size) / 2 - 50;
2420 }
2421 log_msg(4, "media_size[0] = %ld", bkpinfo->media_size[0]);
2422 if (bkpinfo->media_size[0] <= 0) {
2423 bkpinfo->media_size[0] = 0;
2424 }
2425 for (i = 1; i <= MAX_NOOF_MEDIA; i++) {
2426 bkpinfo->media_size[i] = bkpinfo->media_size[0];
2427 }
2428 bkpinfo->use_obdr = ask_me_yes_or_no
2429 ("Do you want to activate OBDR support for your tapes ?");
2430 if (bkpinfo->use_obdr) {
2431 log_msg(4, "obdr mode = TRUE");
2432 } else {
2433 log_msg(4, "obdr mode = FALSE");
2434 }
2435 if (archiving_to_media) {
2436 if ((compression_type = which_compression_type()) == NULL) {
2437 log_to_screen("User has chosen not to backup the PC");
2438 finish(1);
2439 }
2440 if ((bkpinfo->compression_level =
2441 which_compression_level()) == -1) {
2442 log_to_screen("User has chosen not to backup the PC");
2443 finish(1);
2444 }
2445 }
2446 break;
2447
2448
2449
2450 case netfs:
2451 /* Never try to eject a NETFS device */
2452 bkpinfo->please_dont_eject = TRUE;
2453
2454 /* Initiate bkpinfo netfs_mount path from running environment if not already done */
2455 if (!bkpinfo->netfs_mount[0]) {
2456 strcpy(bkpinfo->netfs_mount,
2457 call_program_and_get_last_line_of_output
2458 ("mount | grep \":\" | cut -d' ' -f1 | head -n1"));
2459 }
2460#ifdef __FreeBSD__
2461 if (TRUE)
2462#else
2463 if (!bkpinfo->disaster_recovery)
2464#endif
2465 {
2466 if (!popup_and_get_string
2467 ("Network shared dir.",
2468 "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.)",
2469 bkpinfo->netfs_mount, MAX_STR_LEN / 4)) {
2470 log_to_screen("User has chosen not to backup the PC");
2471 finish(1);
2472 }
2473 if (!bkpinfo->restore_data) {
2474 if ((compression_type = which_compression_type()) == NULL) {
2475 log_to_screen("User has chosen not to backup the PC");
2476 finish(1);
2477 }
2478 if ((bkpinfo->compression_level =
2479 which_compression_level()) == -1) {
2480 log_to_screen("User has chosen not to backup the PC");
2481 finish(1);
2482 }
2483 }
2484 // check whether already mounted - we better remove
2485 // surrounding spaces and trailing '/' for this
2486 strip_spaces(bkpinfo->netfs_mount);
2487 if (bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] == '/')
2488 bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] = '\0';
2489 q = strchr(bkpinfo->netfs_mount, '@');
2490 if (q != NULL) {
2491 /* User found. Store the 2 values */
2492 q++;
2493 /* new netfs mount */
2494 strcpy(tmp1,q);
2495 } else {
2496 strcpy(tmp1,bkpinfo->netfs_mount);
2497 }
2498 sprintf(command, "mount | grep \"%s \" | cut -d' ' -f3", tmp1);
2499 strcpy(bkpinfo->isodir, call_program_and_get_last_line_of_output(command));
2500
2501 if (!bkpinfo->restore_data) {
2502 sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB
2503 sprintf(comment,
2504 "How much data (in Megabytes) will each media store?");
2505 if (!popup_and_get_string("Size", comment, sz_size, 5)) {
2506 log_to_screen("User has chosen not to backup the PC");
2507 finish(1);
2508 }
2509 } else {
2510 strcpy(sz_size, "0");
2511 }
2512 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2513 bkpinfo->media_size[i] = atoi(sz_size);
2514 }
2515 if (bkpinfo->media_size[0] < 0) {
2516 log_to_screen("User has chosen not to backup the PC");
2517 finish(1);
2518 }
2519 }
2520 /* Force NFS to be the protocol by default */
2521 if (bkpinfo->netfs_proto == NULL) {
2522 mr_asprintf(&(bkpinfo->netfs_proto), "nfs");
2523 }
2524 if (bkpinfo->disaster_recovery) {
2525 sprintf(command ,"umount %s/isodir 2> /dev/null", bkpinfo->tmpdir);
2526 paranoid_system(command);
2527 }
2528 strcpy(tmp1, bkpinfo->netfs_proto);
2529 if (!popup_and_get_string
2530 ("Network protocol", "Which protocol should I use (nfs/sshfs) ?",
2531 tmp1, MAX_STR_LEN)) {
2532 log_to_screen("User has chosen not to backup the PC");
2533 finish(1);
2534 }
2535 mr_free(bkpinfo->netfs_proto);
2536 mr_asprintf(&(bkpinfo->netfs_proto), "%s", tmp1);
2537 if (!popup_and_get_string
2538 ("Network share", "Which remote share should I mount?",
2539 bkpinfo->netfs_mount, MAX_STR_LEN)) {
2540 log_to_screen("User has chosen not to backup the PC");
2541 finish(1);
2542 }
2543
2544 if (bkpinfo->netfs_user) {
2545 strcpy(tmp1, bkpinfo->netfs_user);
2546 } else {
2547 strcpy(tmp1, "");
2548 }
2549 if (!popup_and_get_string
2550 ("Network user", "Which user should I use if any ?",
2551 tmp1, MAX_STR_LEN)) {
2552 log_to_screen("User has chosen not to backup the PC");
2553 finish(1);
2554 }
2555 mr_free(bkpinfo->netfs_user);
2556 if (strcmp(tmp1, "") != 0) {
2557 mr_asprintf(&(bkpinfo->netfs_user), "%s", tmp1);
2558 }
2559
2560 /* Initiate bkpinfo isodir path from running environment if mount already done */
2561 if (is_this_device_mounted(bkpinfo->netfs_mount)) {
2562 strcpy(bkpinfo->isodir,
2563 call_program_and_get_last_line_of_output
2564 ("mount | grep \":\" | cut -d' ' -f3 | head -n1"));
2565 } else {
2566 sprintf(bkpinfo->isodir, "%s/netfsdir", bkpinfo->tmpdir);
2567 sprintf(command, "mkdir -p %s", bkpinfo->isodir);
2568 run_program_and_log_output(command, 5);
2569 if (bkpinfo->restore_data) {
2570 if (strstr(bkpinfo->netfs_proto, "sshfs")) {
2571 mr_asprintf(&tmp, "sshfs -o ro");
2572 } else {
2573 mr_asprintf(&tmp, "mount -t %s -o nolock,ro", bkpinfo->netfs_proto);
2574 }
2575 } else {
2576 if (strstr(bkpinfo->netfs_proto, "sshfs")) {
2577 mr_asprintf(&tmp, "sshfs");
2578 } else {
2579 mr_asprintf(&tmp, "mount -t %s -o nolock", bkpinfo->netfs_proto);
2580 }
2581 }
2582 mr_strcat(tmp, " ");
2583 if (bkpinfo->netfs_user) {
2584 mr_strcat(tmp, "%s@", bkpinfo->netfs_user);
2585 }
2586 mr_strcat(tmp, "%s %s", bkpinfo->netfs_mount, bkpinfo->isodir);
2587 run_program_and_log_output(tmp, 3);
2588 mr_free(tmp);
2589
2590 malloc_string(g_selfmounted_isodir);
2591 strcpy(g_selfmounted_isodir, bkpinfo->isodir);
2592 }
2593 if (!is_this_device_mounted(bkpinfo->netfs_mount)) {
2594 popup_and_OK
2595 ("Please mount that partition before you try to backup to or restore from it.");
2596 finish(1);
2597 }
2598 strcpy(tmp1, bkpinfo->netfs_remote_dir);
2599 if (!popup_and_get_string
2600 ("Directory", "Which directory within that mountpoint?", tmp1,
2601 MAX_STR_LEN)) {
2602 log_to_screen("User has chosen not to backup the PC");
2603 finish(1);
2604 }
2605 strcpy(bkpinfo->netfs_remote_dir, tmp1);
2606
2607 // check whether writable - we better remove surrounding spaces for this
2608 strip_spaces(bkpinfo->netfs_remote_dir);
2609
2610 if (!popup_and_get_string
2611 ("Prefix.",
2612 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
2613 bkpinfo->prefix, MAX_STR_LEN / 4)) {
2614 log_to_screen("User has chosen not to backup the PC");
2615 finish(1);
2616 }
2617 log_msg(3, "prefix set to %s", bkpinfo->prefix);
2618
2619 log_msg(3, "Just set netfs_remote_dir to %s",
2620 bkpinfo->netfs_remote_dir);
2621 log_msg(3, "isodir is still %s", bkpinfo->isodir);
2622 break;
2623
2624 case iso:
2625 if (!bkpinfo->disaster_recovery) {
2626 if (!popup_and_get_string
2627 ("Storage dir.",
2628 "Please enter the full path name to the directory for your ISO images. Example: /mnt/raid0_0",
2629 bkpinfo->isodir, MAX_STR_LEN / 4)) {
2630 log_to_screen("User has chosen not to backup the PC");
2631 finish(1);
2632 }
2633 if (archiving_to_media) {
2634 if ((compression_type = which_compression_type()) == NULL) {
2635 log_to_screen("User has chosen not to backup the PC");
2636 finish(1);
2637 }
2638 if ((bkpinfo->compression_level =
2639 which_compression_level()) == -1) {
2640 log_to_screen("User has chosen not to backup the PC");
2641 finish(1);
2642 }
2643 sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB
2644 if (!popup_and_get_string
2645 ("ISO size.",
2646 "Please enter how big you want each ISO image to be (in megabytes). This should be less than or equal to the size of the CD-R[W]'s (700) or DVD's (4480) you plan to backup to.",
2647 sz_size, 16)) {
2648 log_to_screen("User has chosen not to backup the PC");
2649 finish(1);
2650 }
2651 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2652 bkpinfo->media_size[i] = atoi(sz_size);
2653 }
2654 } else {
2655 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2656 bkpinfo->media_size[i] = 650;
2657 }
2658 }
2659 }
2660 if (!popup_and_get_string
2661 ("Prefix.",
2662 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
2663 bkpinfo->prefix, MAX_STR_LEN / 4)) {
2664 log_to_screen("User has chosen not to backup the PC");
2665 finish(1);
2666 }
2667 log_msg(3, "prefix set to %s", bkpinfo->prefix);
2668 break;
2669 default:
2670 fatal_error
2671 ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
2672 }
2673
2674 if (archiving_to_media) {
2675
2676#ifdef __FreeBSD__
2677 strcpy(bkpinfo->boot_device,
2678 call_program_and_get_last_line_of_output
2679 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
2680#else
2681 strcpy(bkpinfo->boot_device,
2682 call_program_and_get_last_line_of_output
2683 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
2684#endif
2685 i = which_boot_loader(bkpinfo->boot_device);
2686 if (i == 'U') // unknown
2687 {
2688
2689#ifdef __FreeBSD__
2690 if (!popup_and_get_string
2691 ("Boot device",
2692 "What is your boot device? (e.g. /dev/ad0)",
2693 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2694 log_to_screen("User has chosen not to backup the PC");
2695 finish(1);
2696 }
2697 i = which_boot_loader(bkpinfo->boot_device);
2698#else
2699 if (!popup_and_get_string
2700 ("Boot device",
2701 "What is your boot device? (e.g. /dev/hda)",
2702 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2703 log_to_screen("User has chosen not to backup the PC");
2704 finish(1);
2705 }
2706 if (does_string_exist_in_boot_block
2707 (bkpinfo->boot_device, "LILO")) {
2708 i = 'L';
2709 } else
2710 if (does_string_exist_in_boot_block
2711 (bkpinfo->boot_device, "ELILO")) {
2712 i = 'E';
2713 } else
2714 if (does_string_exist_in_boot_block
2715 (bkpinfo->boot_device, "GRUB")) {
2716 i = 'G';
2717 } else {
2718 i = 'U';
2719 }
2720#endif
2721 if (i == 'U') {
2722 if (ask_me_yes_or_no
2723 ("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?"))
2724 {
2725 i = 'R'; // raw
2726 } else {
2727 log_to_screen
2728 ("I cannot find your boot loader. Please run mondoarchive with parameters.");
2729 finish(1);
2730 }
2731 }
2732 }
2733 bkpinfo->boot_loader = i;
2734 strcpy(bkpinfo->include_paths, "/");
2735 if (!popup_and_get_string
2736 ("Backup paths",
2737 "Please enter paths (separated by '|') which you want me to backup. The default is '/' (i.e. everything).",
2738 bkpinfo->include_paths, MAX_STR_LEN)) {
2739 log_to_screen("User has chosen not to backup the PC");
2740 finish(1);
2741 }
2742 tmp = list_of_NETFS_mounts_only();
2743 if (strlen(tmp) > 2) {
2744 mr_strcat(bkpinfo->exclude_paths, "|%s",tmp);
2745 }
2746 mr_free(tmp);
2747// NTFS
2748 strcpy(tmp1, call_program_and_get_last_line_of_output("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'"));
2749 if (strlen(tmp1) > 2) {
2750 if (!popup_and_get_string
2751 ("NTFS partitions",
2752 "Please enter/confirm the NTFS partitions you wish to backup as well.",
2753 tmp1, MAX_STR_LEN / 4)) {
2754 log_to_screen("User has chosen not to backup the PC");
2755 finish(1);
2756 }
2757 strncpy(bkpinfo->image_devs, tmp1, MAX_STR_LEN / 4);
2758 }
2759
2760 if (bkpinfo->exclude_paths != NULL ) {
2761 strncpy(p,bkpinfo->exclude_paths,(8*MAX_STR_LEN)-1);
2762 } else {
2763 p[0] = '\0';
2764 }
2765 popup_and_get_string("Exclude paths", "Please enter paths which you do NOT want to backup. Separate them with '|'. NB: /tmp and /proc are always excluded. :-) Just hit 'Enter' if you want to do a full system backup.", p, (8*MAX_STR_LEN)-1);
2766 if (p == NULL) {
2767 log_to_screen("User has chosen not to backup the PC");
2768 finish(1);
2769 }
2770 mr_free(bkpinfo->exclude_paths);
2771 mr_asprintf(&tmp, "%s", p);
2772 bkpinfo->exclude_paths = tmp;
2773
2774 if (!popup_and_get_string
2775 ("Temporary directory",
2776 "Please enter your temporary directory.",
2777 bkpinfo->tmpdir, (4*MAX_STR_LEN)-1)) {
2778 log_to_screen("User has chosen not to backup the PC");
2779 finish(1);
2780 }
2781 if (!popup_and_get_string
2782 ("Scratch directory",
2783 "Please enter your scratch directory.",
2784 bkpinfo->scratchdir, (4*MAX_STR_LEN)-1)) {
2785 log_to_screen("User has chosen not to backup the PC");
2786 finish(1);
2787 }
2788 if (ask_me_yes_or_no("Do you want to backup extended attributes?")) {
2789 if (find_home_of_exe("getfattr")) {
2790 mr_asprintf(&g_getfattr,"getfattr");
2791 }
2792 if (find_home_of_exe("getfacl")) {
2793 mr_asprintf(&g_getfacl,"getfacl");
2794 }
2795 }
2796// Interactive mode:
2797#ifdef __IA64__
2798 bkpinfo->make_cd_use_lilo = TRUE;
2799#else
2800 bkpinfo->make_cd_use_lilo = FALSE;
2801#endif
2802 bkpinfo->backup_data = TRUE;
2803 if (strcmp(compression_type,"lzo") == 0) {
2804 strcpy(bkpinfo->zip_exe, "lzop");
2805 strcpy(bkpinfo->zip_suffix, "lzo");
2806 } else if (strcmp(compression_type,"gzip") == 0) {
2807 strcpy(bkpinfo->zip_exe, "gzip");
2808 strcpy(bkpinfo->zip_suffix, "gz");
2809 //} else if (strcmp(compression_type,"lzma") == 0) {
2810 //strcpy(bkpinfo->zip_exe, "xy");
2811 //strcpy(bkpinfo->zip_suffix, "xy");
2812 } else if (strcmp(compression_type,"bzip2") == 0) {
2813 strcpy(bkpinfo->zip_exe, "bzip2");
2814 strcpy(bkpinfo->zip_suffix, "bz2");
2815 } else {
2816 bkpinfo->zip_exe[0] = bkpinfo->zip_suffix[0] = '\0';
2817 }
2818
2819 bkpinfo->verify_data =
2820 ask_me_yes_or_no
2821 ("Will you want to verify your backups after Mondo has created them?");
2822
2823#ifndef __FreeBSD__
2824 if (!ask_me_yes_or_no
2825 ("Are you confident that your kernel is a sane, sensible, standard Linux kernel? Say 'no' if you are using a Gentoo <1.4 or Debian <3.0, please."))
2826#endif
2827 {
2828 strcpy(bkpinfo->kernel_path, "FAILSAFE");
2829 }
2830
2831 if (!ask_me_yes_or_no
2832 ("Are you sure you want to proceed? Hit 'no' to abort.")) {
2833 log_to_screen("User has chosen not to backup the PC");
2834 finish(1);
2835 }
2836 } else {
2837 bkpinfo->restore_data = TRUE; // probably...
2838 }
2839 mr_free(compression_type);
2840
2841 if (bkpinfo->backup_media_type == iso
2842 || bkpinfo->backup_media_type == netfs) {
2843 g_ISO_restore_mode = TRUE;
2844 }
2845#ifdef __FreeSD__
2846// skip
2847#else
2848 if (bkpinfo->backup_media_type == netfs) {
2849 log_msg(3, "I think the Remote mount is mounted at %s",
2850 bkpinfo->isodir);
2851 }
2852 log_it("isodir = %s", bkpinfo->isodir);
2853 log_it("netfs_mount = '%s'", bkpinfo->netfs_mount);
2854 if (bkpinfo->netfs_proto) {
2855 log_it("netfs_proto = '%s'", bkpinfo->netfs_proto);
2856 }
2857 if (bkpinfo->netfs_user) {
2858 log_it("netfs_user = '%s'", bkpinfo->netfs_user);
2859 }
2860#endif
2861
2862 log_it("media device = %s", bkpinfo->media_device);
2863 log_it("media size = %ld", bkpinfo->media_size[1]);
2864 log_it("media type = %s", bkptype_to_string(bkpinfo->backup_media_type));
2865 log_it("prefix = %s", bkpinfo->prefix);
2866 log_it("compression = %ld", bkpinfo->compression_level);
2867 log_it("exclude_path = %s", bkpinfo->exclude_paths);
2868 log_it("include_path = %s", bkpinfo->include_paths);
2869
2870 /* Handle devices passed in bkpinfo and print result */
2871 /* the mr_make_devlist_from_pathlist function appends
2872 * to the *_paths variables so copy before */
2873 mr_make_devlist_from_pathlist(bkpinfo->exclude_paths, 'E');
2874 mr_make_devlist_from_pathlist(bkpinfo->include_paths, 'I');
2875
2876 log_it("scratchdir = '%s'", bkpinfo->scratchdir);
2877 log_it("tmpdir = '%s'", bkpinfo->tmpdir);
2878 log_it("image_devs = '%s'", bkpinfo->image_devs);
2879 log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device,
2880 bkpinfo->boot_loader);
2881 if (bkpinfo->media_size[0] < 0) {
2882 if (archiving_to_media) {
2883 fatal_error("Media size is less than zero.");
2884 } else {
2885 log_msg(2, "Warning - media size is less than zero.");
2886 bkpinfo->media_size[0] = 0;
2887 }
2888 }
2889 paranoid_free(sz_size);
2890 paranoid_free(tmp1);
2891 paranoid_free(command);
2892 paranoid_free(comment);
2893 paranoid_free(prompt);
2894 return (0);
2895}
2896
2897
2898/**
2899 * Get a |-separated list of NETFS mounts.
2900 * @return The list created.
2901 * @note The return value points to allocated string that needs to be freed
2902 * @bug Even though we only want the mounts, the devices are still checked.
2903 */
2904char *list_of_NETFS_mounts_only(void)
2905{
2906 char *exclude_these_directories = NULL;
2907
2908 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;}'"));
2909 log_msg(9,"list_of_NETFS_mounts_only returns %s\n",exclude_these_directories);
2910 return(exclude_these_directories);
2911}
2912
2913/* @} - end of utilityGroup */
2914
2915
2916
2917
2918
2919/**
2920 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
2921 * [random] is a random number between 1 and 32767.
2922 * @param store_name_here Where to store the new filename.
2923 * @param stub A random number will be appended to this to make the FIFO's name.
2924 * @ingroup deviceGroup
2925 */
2926void make_fifo(char *store_name_here, char *stub)
2927{
2928 char *tmp;
2929
2930 malloc_string(tmp);
2931 assert_string_is_neither_NULL_nor_zerolength(stub);
2932
2933 sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
2934 (int) (random() % 32768));
2935 make_hole_for_file(store_name_here);
2936 mkfifo(store_name_here, S_IRWXU | S_IRWXG);
2937 sprintf(tmp, "chmod 770 %s", store_name_here);
2938 paranoid_system(tmp);
2939 paranoid_free(tmp);
2940}
2941
2942
2943
2944
2945
2946
2947/**
2948 * Set the tmpdir and scratchdir to reside on the partition with the most free space.
2949 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
2950 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set.
2951 * @ingroup utilityGroup
2952 */
2953void sensibly_set_tmpdir_and_scratchdir()
2954{
2955 char *tmp = NULL;
2956 char *tmp1 = NULL;
2957 char *command = NULL;
2958 char *sz = NULL;
2959
2960 assert(bkpinfo != NULL);
2961
2962#ifdef __FreeBSD__
2963 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"));
2964#else
2965 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"));
2966#endif
2967
2968 if (tmp[0] != '/') {
2969 mr_asprintf(&sz, "%s", tmp);
2970 paranoid_free(tmp);
2971 mr_asprintf(&tmp, "/%s", sz);
2972 mr_free(sz);
2973 }
2974 if (!tmp[0]) {
2975 fatal_error("I couldn't figure out the tempdir!");
2976 }
2977 setup_tmpdir(tmp);
2978 log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir);
2979
2980 /* Before changing remove old ones if any */
2981 if (bkpinfo->scratchdir) {
2982 if (chdir("/tmp")) {
2983 // FIXME
2984 }
2985 mr_asprintf(&tmp1, "rm -Rf %s", bkpinfo->scratchdir);
2986 paranoid_system(tmp1);
2987 mr_free(tmp1);
2988 }
2989 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%d", tmp,
2990 (int) (random() % 32768));
2991 log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
2992
2993 mr_asprintf(&command, "rm -Rf %s/tmp.mondo.* %s/mondo.scratch.*", tmp, tmp);
2994 paranoid_free(tmp);
2995
2996 paranoid_system(command);
2997 mr_free(command);
2998}
2999
3000
3001
3002
3003
3004
3005/**
3006 * @addtogroup deviceGroup
3007 * @{
3008 */
3009/**
3010 * If we can read @p dev, set @p output to it.
3011 * If @p dev cannot be read, set @p output to "".
3012 * @param dev The device to check for.
3013 * @param output Set to @p dev if @p dev exists, "" otherwise.
3014 * @return TRUE if @p dev exists, FALSE if it doesn't.
3015 */
3016bool set_dev_to_this_if_rx_OK(char *output, char *dev)
3017{
3018 char *command;
3019
3020 malloc_string(command);
3021 if (!dev || dev[0] == '\0') {
3022 output[0] = '\0';
3023 return (FALSE);
3024 }
3025// assert_string_is_neither_NULL_nor_zerolength(dev);
3026 if (!bkpinfo->please_dont_eject) {
3027 log_msg(10, "Injecting %s", dev);
3028 inject_device(dev);
3029 }
3030 if (!does_file_exist(dev)) {
3031 log_msg(10, "%s doesn't exist. Returning FALSE.", dev);
3032 return (FALSE);
3033 }
3034 sprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null",
3035 512L, dev);
3036 if (!run_program_and_log_output(command, FALSE)
3037 && !run_program_and_log_output(command, FALSE)) {
3038 strcpy(output, dev);
3039 log_msg(4, "Found it - %s", dev);
3040 return (TRUE);
3041 } else {
3042 output[0] = '\0';
3043 log_msg(4, "It's not %s", dev);
3044 return (FALSE);
3045 }
3046}
3047
3048
3049
3050
3051
3052/**
3053 * Find out what number CD is in the drive.
3054 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
3055 * @return The current CD number, or -1 if it could not be found.
3056 * @note If the CD is not mounted, it will be mounted
3057 * (and remain mounted after this function returns).
3058 */
3059int what_number_cd_is_this()
3060{
3061 int cd_number = -1;
3062 char *mountdev = NULL;
3063 char *tmp = NULL;
3064
3065 assert(bkpinfo != NULL);
3066// log_it("Asking what_number_cd_is_this");
3067 if (g_ISO_restore_mode) {
3068 mr_asprintf(&tmp, "mount | grep iso9660 | awk '{print $3;}'");
3069
3070 mr_asprintf(&mountdev, "%s%s", call_program_and_get_last_line_of_output(tmp), "/archives/THIS-CD-NUMBER");
3071 cd_number = atoi(last_line_of_file(mountdev));
3072 paranoid_free(mountdev);
3073 paranoid_free(tmp);
3074
3075 return (cd_number);
3076 }
3077
3078 mr_asprintf(&mountdev, "%s", bkpinfo->media_device);
3079 if (!mountdev[0]) {
3080 log_it
3081 ("(what_number_cd_is_this) Warning - media_device unknown. Finding out...");
3082 find_cdrom_device(bkpinfo->media_device, FALSE);
3083 }
3084 if (!is_this_device_mounted(MNT_CDROM)) {
3085 if (bkpinfo->backup_media_type == usb) {
3086 mount_USB_here(mountdev, MNT_CDROM);
3087 } else {
3088 mount_CDROM_here(mountdev, MNT_CDROM);
3089 }
3090 }
3091 paranoid_free(mountdev);
3092
3093 cd_number = atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
3094 return (cd_number);
3095}
3096
3097
3098
3099
3100
3101
3102
3103/**
3104 * Find out what device is mounted as root (/).
3105 * @return Root device.
3106 * @note The returned string points to static storage and will be overwritten with every call.
3107 * @bug A bit of a misnomer; it's actually finding out the root device.
3108 * The mountpoint (where it's mounted) will obviously be '/'.
3109 */
3110char *where_is_root_mounted()
3111{
3112 /*@ buffers **************** */
3113 static char tmp[MAX_STR_LEN];
3114
3115
3116#ifdef __FreeBSD__
3117 strcpy(tmp, call_program_and_get_last_line_of_output
3118 ("mount | grep \" on / \" | cut -d' ' -f1"));
3119#else
3120 strcpy(tmp, call_program_and_get_last_line_of_output
3121 ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"));
3122 if (strstr(tmp, "/dev/cciss/")) {
3123 strcpy(tmp, call_program_and_get_last_line_of_output
3124 ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"));
3125 }
3126 if (strstr(tmp, "/dev/md")) {
3127 strcpy(tmp,
3128 call_program_and_get_last_line_of_output
3129 ("mount | grep \" on / \" | cut -d' ' -f1"));
3130 }
3131#endif
3132
3133 return (tmp);
3134}
3135
3136
3137/**
3138 * Find out which boot loader is in use.
3139 * @param which_device Device to look for the boot loader on.
3140 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
3141 * @note Under Linux, all drives are examined, not just @p which_device.
3142 */
3143#ifdef __FreeBSD__
3144char which_boot_loader(char *which_device)
3145{
3146 int count_lilos = 0;
3147 int count_grubs = 0;
3148 int count_boot0s = 0;
3149 int count_dangerouslydedicated = 0;
3150
3151 log_it("looking at drive %s's MBR", which_device);
3152 if (does_string_exist_in_boot_block(which_device, "GRUB")) {
3153 count_grubs++;
3154 }
3155 if (does_string_exist_in_boot_block(which_device, "LILO")) {
3156 count_lilos++;
3157 }
3158 if (does_string_exist_in_boot_block(which_device, "Drive")) {
3159 count_boot0s++;
3160 }
3161 if (does_string_exist_in_first_N_blocks
3162 (which_device, "FreeBSD/i386", 17)) {
3163 count_dangerouslydedicated++;
3164 }
3165 log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
3166 count_grubs, count_lilos, count_elilos, count_boot0s,
3167 count_dangerouslydedicated);
3168
3169 if (count_grubs && !count_lilos) {
3170 return ('G');
3171 } else if (count_lilos && !count_grubs) {
3172 return ('L');
3173 } else if (count_grubs == 1 && count_lilos == 1) {
3174 log_it("I'll bet you used to use LILO but switched to GRUB...");
3175 return ('G');
3176 } else if (count_boot0s == 1) {
3177 return ('B');
3178 } else if (count_dangerouslydedicated) {
3179 return ('D');
3180 } else {
3181 log_it("Unknown boot loader");
3182 return ('U');
3183 }
3184}
3185
3186#else
3187
3188char which_boot_loader(char *which_device)
3189{
3190 /*@ buffer ***************************************************** */
3191 char *list_drives_cmd = NULL;
3192 char *current_drive;
3193 char *tmp;
3194
3195 /*@ pointers *************************************************** */
3196 FILE *pdrives;
3197
3198 /*@ int ******************************************************** */
3199 int count_lilos = 0;
3200 int count_grubs = 0;
3201
3202 /*@ end vars *************************************************** */
3203
3204 malloc_string(current_drive);
3205
3206#ifdef __IA64__
3207 /* No choice for it */
3208 return ('E');
3209#endif
3210 assert(which_device != NULL);
3211
3212 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());
3213 log_it("list_drives_cmd = %s", list_drives_cmd);
3214
3215 if (!(pdrives = popen(list_drives_cmd, "r"))) {
3216 log_OS_error("Unable to open list of drives");
3217 mr_free(list_drives_cmd);
3218 paranoid_free(current_drive);
3219 return ('\0');
3220 }
3221 mr_free(list_drives_cmd);
3222
3223 for (tmp = fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives) && (tmp != NULL);
3224 tmp = fgets(current_drive, MAX_STR_LEN, pdrives)) {
3225 strip_spaces(current_drive);
3226 log_it("looking at drive %s's MBR", current_drive);
3227 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
3228 count_grubs++;
3229 strcpy(which_device, current_drive);
3230 break;
3231 }
3232 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
3233 count_lilos++;
3234 strcpy(which_device, current_drive);
3235 break;
3236 }
3237 }
3238 if (pclose(pdrives)) {
3239 log_OS_error("Cannot pclose pdrives");
3240 }
3241 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
3242 if (count_grubs && !count_lilos) {
3243 paranoid_free(current_drive);
3244 return ('G');
3245 } else if (count_lilos && !count_grubs) {
3246 paranoid_free(current_drive);
3247 return ('L');
3248 } else if (count_grubs == 1 && count_lilos == 1) {
3249 log_it("I'll bet you used to use LILO but switched to GRUB...");
3250 paranoid_free(current_drive);
3251 return ('G');
3252 } else {
3253 // We need to look on each partition then
3254 mr_asprintf(&list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep -E \"^/dev/\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/");
3255 log_it("list_drives_cmd = %s", list_drives_cmd);
3256
3257 if (!(pdrives = popen(list_drives_cmd, "r"))) {
3258 log_OS_error("Unable to open list of drives");
3259 mr_free(list_drives_cmd);
3260 paranoid_free(current_drive);
3261 return ('\0');
3262 }
3263 mr_free(list_drives_cmd);
3264
3265 for (tmp = fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives) && (tmp != NULL);
3266 tmp = fgets(current_drive, MAX_STR_LEN, pdrives)) {
3267 strip_spaces(current_drive);
3268 log_it("looking at partition %s's BR", current_drive);
3269 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
3270 count_grubs++;
3271 strcpy(which_device, current_drive);
3272 break;
3273 }
3274 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
3275 count_lilos++;
3276 strcpy(which_device, current_drive);
3277 break;
3278 }
3279 }
3280 if (pclose(pdrives)) {
3281 log_OS_error("Cannot pclose pdrives");
3282 }
3283 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
3284 paranoid_free(current_drive);
3285 if (count_grubs && !count_lilos) {
3286 return ('G');
3287 } else if (count_lilos && !count_grubs) {
3288 return ('L');
3289 } else if (count_grubs == 1 && count_lilos == 1) {
3290 log_it("I'll bet you used to use LILO but switched to GRUB...");
3291 return ('G');
3292 } else {
3293 log_it("Unknown boot loader");
3294 return ('U');
3295 }
3296 }
3297}
3298#endif
3299
3300
3301
3302
3303/**
3304 * Write zeroes over the first 16K of @p device.
3305 * @param device The device to zero.
3306 * @return 0 for success, 1 for failure.
3307 */
3308int zero_out_a_device(char *device)
3309{
3310 FILE *fout;
3311 int i;
3312
3313 assert_string_is_neither_NULL_nor_zerolength(device);
3314
3315 log_it("Zeroing drive %s", device);
3316 if (!(fout = fopen(device, "w"))) {
3317 log_OS_error("Unable to open/write to device");
3318 return (1);
3319 }
3320 for (i = 0; i < 16384; i++) {
3321 fputc('\0', fout);
3322 }
3323 paranoid_fclose(fout);
3324 log_it("Device successfully zeroed.");
3325 return (0);
3326}
3327
3328/**
3329 * Return the device pointed to by @p incoming.
3330 * @param incoming The device to resolve symlinks for.
3331 * @return The path to the real device file.
3332 * @note The returned string points to static storage that will be overwritten with each call.
3333 * @bug Won't work with file v4.0; needs to be written in C.
3334 */
3335char *resolve_softlinks_to_get_to_actual_device_file(char *incoming)
3336{
3337 static char output[MAX_STR_LEN];
3338 char *command;
3339 char *curr_fname;
3340 char *scratch = NULL;
3341 char *tmp = NULL;
3342 char *p;
3343
3344 struct stat statbuf;
3345 command = malloc(1000);
3346 malloc_string(curr_fname);
3347 if (!does_file_exist(incoming)) {
3348 log_it
3349 ("resolve_softlinks_to_get_to_actual_device_file --- device not found");
3350 strcpy(output, incoming);
3351 } else {
3352 strcpy(curr_fname, incoming);
3353 lstat(curr_fname, &statbuf);
3354 while (S_ISLNK(statbuf.st_mode)) {
3355 log_msg(1, "curr_fname = %s", curr_fname);
3356 sprintf(command, "file %s", curr_fname);
3357 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
3358 for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' ';
3359 p--);
3360 p++;
3361 mr_asprintf(&scratch, "%s", p);
3362 for (p = scratch; *p != '\0' && *p != '\''; p++);
3363 *p = '\0';
3364 log_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp, scratch);
3365 mr_free(tmp);
3366
3367 if (scratch[0] == '/') {
3368 strcpy(curr_fname, scratch); // copy whole thing because it's an absolute softlink
3369 } else { // copy over the basename cos it's a relative softlink
3370 p = curr_fname + strlen(curr_fname);
3371 while (p != curr_fname && *p != '/') {
3372 p--;
3373 }
3374 if (*p == '/') {
3375 p++;
3376 }
3377 strcpy(p, scratch);
3378 }
3379 mr_free(scratch);
3380 lstat(curr_fname, &statbuf);
3381 }
3382 strcpy(output, curr_fname);
3383 log_it("resolved %s to %s", incoming, output);
3384 }
3385 paranoid_free(command);
3386 paranoid_free(curr_fname);
3387 return (output);
3388}
3389
3390/* @} - end of deviceGroup */
3391
3392/**
3393 * Return the type of partition format (GPT or MBR)
3394 */
3395char *which_partition_format(const char *drive)
3396{
3397 static char output[4];
3398 char *tmp = NULL;
3399 char *command;
3400 char *fdisk;
3401#ifdef __IA64__
3402 struct stat buf;
3403#endif
3404 malloc_string(command);
3405 malloc_string(fdisk);
3406 sprintf(fdisk, "/sbin/parted2fdisk");
3407 sprintf(command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
3408 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
3409 if (strstr(tmp, "GPT") == NULL) {
3410 strcpy(output, "MBR");
3411 } else {
3412 strcpy(output, "GPT");
3413 }
3414 mr_free(tmp);
3415
3416 log_msg(0, "Found %s partition table format type", output);
3417 paranoid_free(command);
3418 paranoid_free(fdisk);
3419 return (output);
3420}
3421/* @} - end of deviceGroup */
Note: See TracBrowser for help on using the repository browser.