source: MondoRescue/branches/3.2/mondo/src/common/libmondo-devices.c@ 3196

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