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

Last change on this file since 3194 was 3194, checked in by Bruno Cornec, 11 years ago
  • Fix all compilation/link error due to the previous giant merge with 3.1. 3.2 is ready to test
  • Property svn:keywords set to Id
File size: 96.3 KB
Line 
1/* libmondo-devices.c Subroutines for handling devices
2 $Id: libmondo-devices.c 3194 2013-09-29 17:27:11Z 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 3194 2013-09-29 17:27:11Z 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 mr_asprintf(mount_cmd, "/mnt/isodir/%s/%s/%s-%d.iso", bkpinfo->isodir,
1343 bkpinfo->netfs_remote_dir, bkpinfo->prefix, g_current_media_number);
1344 mddev = make_vn(mount_cmd);
1345 mr_free(mount_cmd);
1346
1347 mr_asprintf(mount_cmd, "mount_cd9660 -r %s " MNT_CDROM, mddev);
1348#else
1349 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);
1350#endif
1351
1352 } else if (bkpinfo->backup_media_type == iso) {
1353 if (bkpinfo->subdir) {
1354 mr_asprintf(mountdir, "%s/%s", bkpinfo->isodir, bkpinfo->subdir);
1355 } else {
1356 mr_asprintf(mountdir, "%s", bkpinfo->isodir);
1357 }
1358#ifdef __FreeBSD__
1359 mr_asprintf(mount_cmd, "%s/%s-%d.iso", mountdir, bkpinfo->prefix, g_current_media_number);
1360 mddev = make_vn(mount_cmd);
1361 mr_free(mount_cmd);
1362
1363 mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s", mddev, MNT_CDROM);
1364#else
1365 mr_asprintf(mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s", mountdir, bkpinfo->prefix, g_current_media_number, MNT_CDROM);
1366#endif
1367 mr_free(mountdir);
1368 } else if (bkpinfo->backup_media_type == usb) {
1369 mr_asprintf(mount_cmd, "mount -t vfat %s %s", bkpinfo->media_device, MNT_CDROM);
1370 } else if (strstr(bkpinfo->media_device, "/dev/")) {
1371#ifdef __FreeBSD__
1372 mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s", bkpinfo->media_device, MNT_CDROM);
1373#else
1374 mr_asprintf(mount_cmd, "mount %s -t iso9660 -o ro %s", bkpinfo->media_device, MNT_CDROM);
1375#endif
1376 } else {
1377 if (bkpinfo->disaster_recovery
1378 && does_file_exist("/tmp/CDROM-LIVES-HERE")) {
1379 strcpy(bkpinfo->media_device,
1380 last_line_of_file("/tmp/CDROM-LIVES-HERE"));
1381 } else {
1382 find_cdrom_device(bkpinfo->media_device, TRUE);
1383 }
1384
1385#ifdef __FreeBSD__
1386 mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s", bkpinfo->media_device, MNT_CDROM);
1387#else
1388 mr_asprintf(mount_cmd, "mount %s -t iso9660 -o ro %s", bkpinfo->media_device, MNT_CDROM);
1389#endif
1390 }
1391
1392 log_msg(2, "(mount_media) --- command = %s", mount_cmd);
1393 for (i = 0; i < 2; i++) {
1394 res = run_program_and_log_output(mount_cmd, FALSE);
1395 if (!res) {
1396 break;
1397 } else {
1398 log_msg(2, "Failed to mount device.");
1399 sleep(5);
1400 sync();
1401 }
1402 }
1403 mr_free(mount_cmd);
1404
1405 if (res) {
1406 log_msg(2, "Failed, despite %d attempts", i);
1407 } else {
1408 log_msg(2, "Mounted media drive OK");
1409 }
1410 return (res);
1411}
1412/**************************************************************************
1413*END_MOUNT_CDROM *
1414**************************************************************************/
1415
1416
1417
1418
1419/**
1420 * Ask the user for CD number @p cd_number_i_want.
1421 * Sets g_current_media_number once the correct CD is inserted.
1422 * @param bkpinfo The backup information structure. Fields used:
1423 * - @c bkpinfo->backup_media_type
1424 * - @c bkpinfo->prefix
1425 * - @c bkpinfo->isodir
1426 * - @c bkpinfo->media_device
1427 * - @c bkpinfo->please_dont_eject_when_restoring
1428 * @param cd_number_i_want The CD number to ask for.
1429 */
1430void
1431insist_on_this_cd_number(int cd_number_i_want)
1432{
1433
1434 /*@ int ************************************************************* */
1435 int res = 0;
1436
1437
1438 /*@ buffers ********************************************************* */
1439 char *tmp = NULL;
1440 char *mds = NULL;
1441 char *request = NULL;
1442
1443 assert(bkpinfo != NULL);
1444 assert(cd_number_i_want > 0);
1445
1446// log_msg(3, "Insisting on CD number %d", cd_number_i_want);
1447
1448 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1449 log_msg(3,
1450 "No need to insist_on_this_cd_number when the backup type isn't CD-R(W) or NFS or ISO");
1451 return;
1452 }
1453 mr_asprintf(tmp, "mkdir -p " MNT_CDROM);
1454 run_program_and_log_output(tmp, 5);
1455 mr_free(tmp);
1456
1457 if (g_ISO_restore_mode || bkpinfo->backup_media_type == iso || bkpinfo->backup_media_type == netfs) {
1458 g_ISO_restore_mode = TRUE;
1459 }
1460 if ((res = what_number_cd_is_this()) != cd_number_i_want) {
1461 log_msg(3, "Currently, we hold %d but we want %d", res, cd_number_i_want);
1462
1463 /* Now we need to umount the current media to have the next mounted after */
1464 run_program_and_log_output("umount -d " MNT_CDROM, FALSE);
1465 log_msg(3, "Mounting next media %d",cd_number_i_want);
1466 g_current_media_number = cd_number_i_want;
1467 mount_media();
1468
1469 mds = media_descriptor_string(bkpinfo->backup_media_type);
1470 log_msg(3, "Insisting on %s #%d", mds, cd_number_i_want);
1471 mr_asprintf(request, "Please insert %s #%d and press Enter.", mds, cd_number_i_want);
1472 mr_free(mds);
1473
1474 while (what_number_cd_is_this() != cd_number_i_want) {
1475 sync();
1476 if (is_this_device_mounted(MNT_CDROM)) {
1477 res =
1478 run_program_and_log_output("umount -d " MNT_CDROM, FALSE);
1479 } else {
1480 res = 0;
1481 }
1482 if (res) {
1483 log_to_screen("WARNING - failed to unmount CD-ROM drive");
1484 }
1485 if (!bkpinfo->please_dont_eject) {
1486 res = eject_device(bkpinfo->media_device);
1487 } else {
1488 res = 0;
1489 }
1490 if (res) {
1491 log_to_screen("WARNING - failed to eject CD-ROM disk");
1492 }
1493 popup_and_OK(request);
1494 if (!bkpinfo->please_dont_eject) {
1495 inject_device(bkpinfo->media_device);
1496 }
1497 sync();
1498 }
1499 mr_free(request);
1500
1501 log_msg(1, "Thankyou. Proceeding...");
1502 g_current_media_number = cd_number_i_want;
1503 }
1504}
1505
1506/* @} - end of deviceGroup */
1507
1508
1509
1510/**
1511 * Creates a singly linked list of all of the non-NETFS mounted file systems.
1512 * @param DSFptr A pointer to the structure MOUNTED_FS_STRUCT used to hold
1513 * the list of mounted file systems.
1514 * @return None.
1515 */
1516static void add_mounted_fs_struct (MOUNTED_FS_STRUCT *DSFptr)
1517{
1518 assert (DSFptr);
1519 if (DSF_Head == NULL) {
1520 DSF_Head = DSFptr;
1521 } else {
1522 DSF_Tail->next = DSFptr;
1523 }
1524 DSFptr->next = NULL;
1525 DSF_Tail = DSFptr;
1526}
1527
1528/**
1529 * Find the structure, in the singly linked list of all of the non-NETFS
1530 * mounted file systems, that contains the specified device.
1531 * @param device The device to find
1532 * @return NULL if it didn't find the device, a pointer to the
1533 * structure if it did.
1534 */
1535static MOUNTED_FS_STRUCT *find_device_in_list (char *device)
1536{
1537 MOUNTED_FS_STRUCT *DSFptr = NULL;
1538
1539 DSFptr = DSF_Head;
1540 while (DSFptr != NULL) {
1541 if (!strcmp(DSFptr->device, device)) {
1542 break;
1543 }
1544 DSFptr = DSFptr->next;
1545 }
1546 return (DSFptr);
1547}
1548
1549/**
1550 * Find the structure, in the singly linked list of all of the non-NETFS
1551 * mounted file systems, that contains the specified mount point.
1552 * @param mount_point The mount point to find
1553 * @return NULL is it didn't find the mount point, a pointer to the
1554 * structure if it did.
1555 */
1556static MOUNTED_FS_STRUCT *find_mount_point_in_list (char *mount_point)
1557{
1558 MOUNTED_FS_STRUCT *DSFptr = NULL;
1559
1560 DSFptr = DSF_Head;
1561 while (DSFptr != NULL) {
1562 if (!strcmp(DSFptr->mount_point, mount_point)) {
1563 break;
1564 }
1565 DSFptr = DSFptr->next;
1566 }
1567 return (DSFptr);
1568}
1569
1570/**
1571 * Frees the memory for all of the structures on the linked list of
1572 * all of the non-NETFS mounted file systems.
1573 */
1574static void free_mounted_fs_list (void) {
1575 MOUNTED_FS_STRUCT *DSFptr = NULL;
1576 MOUNTED_FS_STRUCT *DSFnext = NULL;
1577
1578 DSFptr = DSF_Head;
1579 while (DSFptr != NULL) {
1580 DSFnext = DSFptr->next;
1581 paranoid_free(DSFptr);
1582 DSFptr = DSFnext;
1583 }
1584 DSF_Head = NULL;
1585 DSF_Tail = NULL;
1586}
1587
1588
1589/**
1590 * Creates a linked list of all of the non-NETFS mounted file systems.
1591 * We use a linked list because we don't know how many mounted file
1592 * there are (and there can be a lot).
1593 * @return 0 on success and greated than 0 on failure.
1594 */
1595static int create_list_of_non_NETFS_mounted_file_systems (void)
1596{
1597 int i = 0;
1598 int mount_cnt = 0;
1599 int lastpos = 0;
1600 char *mounted_file_system = NULL;
1601 char *command = NULL;
1602 char *token = NULL;
1603 char token_chars[] =" :\t\r\f\a\0";
1604 MOUNTED_FS_STRUCT *DSFptr = NULL;
1605
1606 free_mounted_fs_list();
1607 /********
1608 * Find the number of mounted file system entries and their respective mount points.
1609 * I can't return all of the entries as one string because it's length can be longer
1610 * than MAX_STR_LEN which is used in call_program_and_get_last_line_of_output().
1611 * So start looping and get the number of mounted file systems and query them one by one.
1612 ********/
1613 /* Get the number of mounted file systems ((those that start with "/dev/" */
1614 mr_asprintf(command, "mount 2>/dev/null | awk '{if($1 ~ \"^/dev/\"){print $0}}'|wc -l");
1615 log_msg(5, "Running: %s", command);
1616 mr_asprintf(mounted_file_system, "%s", call_program_and_get_last_line_of_output(command));
1617 mr_free(command);
1618
1619 mount_cnt = atoi(mounted_file_system);
1620 log_msg (5, "mount_cnt: %d", mount_cnt);
1621 mr_free(mounted_file_system);
1622
1623 for (i=mount_cnt; i > 0; i--) {
1624 mr_asprintf(command, "mount 2>/dev/null | awk '{if($1 ~ \"^/dev/\"){print $1,$3}}'|head -n %d", i);
1625 log_msg(5, "Running: %s", command);
1626 mr_asprintf(mounted_file_system, "%s", call_program_and_get_last_line_of_output(command));
1627 mr_free(command);
1628
1629 log_msg (5, "mounted_file_system: %s", mounted_file_system);
1630 if ((token = mr_strtok(mounted_file_system, token_chars, &lastpos)) == NULL) {
1631 log_msg (4, "Could not get the list of mounted file systems");
1632 mr_free(mounted_file_system);
1633 mr_free(token);
1634 return (1);
1635 }
1636 if (token) {
1637 log_msg (5, "token: %s", token);
1638 }
1639 while (token != NULL) {
1640 log_msg (5, "token: %s", token);
1641 if ((DSFptr = (MOUNTED_FS_STRUCT *) calloc(1, sizeof(MOUNTED_FS_STRUCT))) == NULL) {
1642 fatal_error ("Cannot allocate memory");
1643 }
1644 add_mounted_fs_struct(DSFptr);
1645 strcpy(DSFptr->device, token);
1646 mr_free(token);
1647 if ((token = mr_strtok(mounted_file_system, token_chars, &lastpos)) == NULL) {
1648 log_msg (5, "Ran out of entries on the mounted file systems list");
1649 mr_free(mounted_file_system);
1650 mr_free(token);
1651 return (1);
1652 }
1653 log_msg (5, "token: %s", token);
1654 strcpy(DSFptr->mount_point, token);
1655 mr_free(token);
1656 token = mr_strtok(mounted_file_system, token_chars, &lastpos);
1657 }
1658 mr_free(mounted_file_system);
1659 }
1660 return (0);
1661}
1662
1663
1664
1665/**
1666 * Given a whole disk device special file, determine which mounted file systems
1667 * are on the dsf's partitions and which mounted file systems are not.
1668 * @param dsf The whole disk device special file.
1669 * @param included_dsf_list A char pointer used to hold the list of mount points
1670 * that are on the dsf. Memory for the array will be allocated within the function.
1671 * @param excluded_dsf_list A char pointer used to hold the list of mount points
1672 * that are not on the dsf. Memory for the array will be allocated within the function.
1673 * @return 0 on success, -1 if no device special file was passed in, -2 if a device
1674 * special file was passed in but it has no partitions on it, or 1 on failure
1675 */
1676static int get_dsf_mount_list (const char *dsf, char **included_dsf_list, char **excluded_dsf_list) {
1677 int i = 0;
1678 int c = 0;
1679 int lastpos = 0;
1680 char VG[MAX_STR_LEN];
1681 char *tmp = NULL;
1682 char *command = NULL;
1683 char *partition_list = NULL;
1684 char partitions[64][MAX_STR_LEN];
1685 char *mount_list = NULL;
1686 char *token = NULL;
1687 char *ndsf = NULL;
1688 char token_chars[] =" \t\r\f\a\0";
1689 MOUNTED_FS_STRUCT *DSFptr = NULL;
1690
1691 memset((char *)partitions, 0, sizeof(partitions));
1692
1693 log_msg(5, "dsf: %s", dsf);
1694
1695 /********
1696 * See if a device special file was passed in (i.e. it must start with /dev/
1697 ********/
1698 if (strncmp(dsf, "/dev/", 5)) {
1699 log_msg (4, "%s does not start with /dev/ and (probably) is not a device special file", dsf);
1700 return (-1);
1701 }
1702 log_msg(4, " %s looks like a device special file", dsf);
1703 /* Verify that the dsf exists */
1704 mr_asprintf(command, "ls -al %s 2>/dev/null | wc -l", dsf);
1705 log_msg(5, " Executing: %s", command);
1706 mr_asprintf(tmp, "%s", call_program_and_get_last_line_of_output(command));
1707 mr_free(command);
1708
1709 log_msg(5, " Return value: %s", tmp);
1710 c = atoi(tmp);
1711 mr_free(tmp);
1712
1713 if (!c) {
1714 log_to_screen("Cannot find device special file %s", dsf);
1715 return (1);
1716 }
1717 log_msg(4, " %s device special file exists", dsf);
1718
1719 /* Get a list of the mounted file systems */
1720 if (create_list_of_non_NETFS_mounted_file_systems()) {
1721 log_to_screen ("Could not get the list of mounted file systems");
1722 return (1);
1723 }
1724 log_msg (5, "Processing dsf: %s", dsf);
1725 /********
1726 * Get a list of the dsf's partitions. There could be no partitions on the disk
1727 * or a dsf of a partition was passed in (e.g. /dev/sda1 instead of /dev/sda).
1728 * Either way, it's an error.
1729 ********/
1730 mr_asprintf(command, "parted2fdisk -l %s 2>/dev/null|grep -E \"^/dev/\"|awk '{printf(\"%%s \", $1)}END{print \"\"}'", dsf);
1731 log_msg(5, "Executing: %s", command);
1732 mr_asprintf(partition_list, "%s", call_program_and_get_last_line_of_output(command));
1733 mr_free(command);
1734 log_msg(4, "Partition list for %s: %s", dsf, partition_list);
1735 if (!strlen(partition_list)) {
1736 /* There were no partitions on the disk */
1737 log_msg(4, "No partitions on device special file %s", dsf);
1738 log_msg(4, "I guess it's a partition itself");
1739 strcpy(partitions[0], dsf);
1740 ndsf = truncate_to_drive_name(dsf);
1741 } else {
1742 /* Fill the partition list */
1743 i = 0;
1744 lastpos = 0;
1745 while ((token = mr_strtok(partition_list, token_chars, &lastpos)) != NULL) {
1746 log_msg (4, "Found partition: %s", token);
1747 strcpy(partitions[i++], token);
1748 mr_free(token);
1749 }
1750 mr_asprintf(ndsf, "%s", dsf);
1751 }
1752 mr_free(partition_list);
1753
1754 /* In any case we want to exclude the dsf itself from all MondRescue activities
1755 * at restore time (LVM, fdisk, ...) so we want it in our exclude_dev list */
1756 if ((DSFptr = (MOUNTED_FS_STRUCT *) calloc(1, sizeof(MOUNTED_FS_STRUCT))) == NULL) {
1757 fatal_error ("Cannot allocate memory");
1758 }
1759 add_mounted_fs_struct(DSFptr);
1760 strcpy(DSFptr->device, dsf);
1761 DSFptr->check = 1;
1762
1763 /* For the rest ndsf is the new dsf to deal with */
1764 /********
1765 * At this point, we have a list of all of the partitions on the dsf. Now try to
1766 * see which partitions have a file system on them.
1767 *
1768 * Loop through each partition on the disk and:
1769 *
1770 * - If the partition is swap, it ignores it.
1771 *
1772 * - If the partition is mounted (e.g. /dev/sda1 is mounted on /boot), it adds an entry
1773 * to the linked list, copies to it the device name and mount point, and sets check == 1.
1774 *
1775 * - If the partition is part of a Volume Group that has Logical Volumes mounted, it adds
1776 * an entry to the linked list for each mounted Logical Volume in that Volume Group, copying
1777 * to it the device name and mount point, and sets check == 1. Note that if the Volume Group
1778 * contains more than one disk, it will still add the entry even if the Logical Volume's
1779 * extents are not on the dsf that was passed in to the function. For example, Volume Group
1780 * VolGroup00 contains the disks /dev/sda1 and /dev/sdb1, and the Logical Volumes LogVol01,
1781 * which is mounted on /var and has all of its extents on /dev/sda1, and LogVol02, which is
1782 * mounted as /usr and has all of its extents on /dev/sdb1. If you pass /dev/sda into the
1783 * function, both /var and /usr will be archived even though /usr is actually on/dev/sdb.
1784 *
1785 * - If the partition is part of a Volume Group that has Logical Volumes used in a mounted
1786 * software raid device, it adds an entry to the linked list, copies to it the software raid
1787 * device name and mount point, and sets check == 1.
1788 *
1789 * - If the partition is part of a mounted software raid device, it adds an entry to the linked
1790 * list, copies to it the software raid device name and mount point, and sets check == 1.
1791 *
1792 ********/
1793 for (i=0; strlen(partitions[i]); i++) {
1794 log_msg(4, "Processing partition: %s", partitions[i]);
1795 /* See if it's swap. If it is, ignore it. */
1796 mr_asprintf(command, "parted2fdisk -l %s 2>/dev/null | awk '{if(($1==\"%s\")&&(toupper($0) ~ \"SWAP\")){print $1;exit}}'", ndsf, partitions[i]);
1797 log_msg(5, " Running: %s", command);
1798 mr_asprintf(tmp, "%s", call_program_and_get_last_line_of_output(command));
1799 mr_free(command);
1800
1801 log_msg(5, " Return value: %s", tmp);
1802 c = strlen(tmp);
1803 mr_free(tmp);
1804
1805 if (c) {
1806 log_msg(4, "It's swap. Ignoring partition %s", partitions[i]);
1807 continue;
1808 }
1809
1810 /* It's not swap. See if we can find the mount point from the mount command. */
1811 mr_asprintf(command, "mount 2>/dev/null | awk '{if((NF>0)&&($1==\"%s\")){print $3}}'", partitions[i]);
1812 mr_asprintf(tmp, "%s", call_program_and_get_last_line_of_output(command));
1813 mr_free(command);
1814
1815 if (strlen(tmp)) {
1816 log_msg(4, " %s is mounted: %s", partitions[i], tmp);
1817 if ((DSFptr = find_mount_point_in_list(tmp)) == NULL) {
1818 log_msg (4, "Can't find mount point %s in mounted file systems list", tmp);
1819 mr_free(tmp);
1820 return (1);
1821 }
1822 DSFptr->check = 1;
1823 mr_free(tmp);
1824 continue;
1825 }
1826 mr_free(tmp);
1827
1828 /* It's not swap and it's not mounted. See if it's LVM */
1829 log_msg(4, " It's not mounted. Checking to see if it's LVM...");
1830
1831 /* Check for LVM */
1832 mr_asprintf(command, "pvdisplay -c %s 2> /dev/null", partitions[i]);
1833 log_msg(5, " Running: %s", command);
1834 mr_asprintf(tmp, "%s", call_program_and_get_last_line_of_output(command));
1835 mr_free(command);
1836
1837 if (strlen(tmp)) {
1838 log_msg(4, "Found an LVM partition at %s. Find the VG it's in...", partitions[i]);
1839 /* It's LVM: Find the VG it's in */
1840 mr_asprintf(command, "pvdisplay -v %s 2>/dev/null|grep \"VG Name\"|awk '{print $NF}'", partitions[i]);
1841 log_msg(5, " Running: %s", command);
1842 strcpy(VG, call_program_and_get_last_line_of_output(command));
1843 mr_free(command);
1844
1845 log_msg(4, " Volume Group: %s", VG);
1846 if (strlen(VG)) {
1847 /* Found the Volume Group. Now find all of the VG's mount points */
1848 log_msg(4, " Found the Volume Group. Now find all of the VG's mount points");
1849 mr_asprintf(command, "mount 2>/dev/null|grep -E \"/dev/mapper/%s|/dev/%s/\"|awk '{printf(\"%%s \",$3)}END{print \"\"}'", VG, VG);
1850 log_msg(5, " Running: %s", command);
1851 mr_asprintf(mount_list, "%s", call_program_and_get_last_line_of_output(command));
1852 mr_free(command);
1853
1854 log_msg(4, " VG %s mount_list: %s", VG, mount_list);
1855 lastpos = 0;
1856 while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
1857 log_msg (5, "mount point token: %s", token);
1858 if ((DSFptr = find_mount_point_in_list(token)) == NULL) {
1859 log_msg (4, "Can't find mount point %s in mounted file systems list", token);
1860 mr_free(tmp);
1861 mr_free(token);
1862 return (1);
1863 }
1864 DSFptr->check = 1;
1865 mr_free(token);
1866 }
1867 /********
1868 * Now we want to see if there are any software raid devices using
1869 * any of the Logical Volumes on the Volume Group.
1870 *******/
1871 mr_free(mount_list);
1872
1873 mr_asprintf(command, "%s", "cat /proc/mdstat|grep -iv Personal|awk '{if($0~\"^.*[ ]+:\"){printf(\"/dev/%s \", $1)}}END{print \"\"}'");
1874 log_msg (5, "Running: %s", command);
1875 mr_asprintf(mount_list, "%s", call_program_and_get_last_line_of_output(command));
1876 mr_free(command);
1877 log_msg(4, " Software raid device list: %s", mount_list);
1878 lastpos = 0;
1879 while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
1880 mr_asprintf(command, "mdadm --detail %s 2>/dev/null | grep -c %s", token, VG);
1881 log_msg (5, "Running: %s", command);
1882 mr_free(tmp);
1883 mr_asprintf(tmp, "%s", call_program_and_get_last_line_of_output(command));
1884 mr_free(command);
1885 log_msg(4, "Number of Software raid device: %s", tmp);
1886 if (atoi(tmp)) {
1887 /* This device is on our disk */
1888 if ((DSFptr = find_device_in_list(token)) == NULL) {
1889 log_msg (4, "Can't find device %s in mounted file systems list", token);
1890 mr_free(tmp);
1891 mr_free(token);
1892 return (1);
1893 }
1894 DSFptr->check = 1;
1895 }
1896 }
1897 mr_free(token);
1898 paranoid_free(mount_list);
1899 } else {
1900 log_msg (4, "Error finding Volume Group for partition %s", partitions[i]);
1901 mr_free(tmp);
1902 return (1);
1903 }
1904 mr_free(tmp);
1905 continue;
1906 } else {
1907 log_msg (4, "Error finding partition type for the partition %s", partitions[i]);
1908 }
1909 mr_free(tmp);
1910
1911 /********
1912 * It's not swap, mounted, or LVM. See if it's used in a software raid device.
1913 ********/
1914 log_msg (5, "It's not swap, mounted, or LVM. See if it's used in a software raid device.");
1915 mr_asprintf(command, "mdadm --examine %s 2>/dev/null | awk '{if($1 == \"UUID\"){print $3}}'", partitions[i]);
1916 log_msg(4, " Running: %s", command);
1917 mr_asprintf(tmp, "%s", call_program_and_get_last_line_of_output(command));
1918 mr_free(command);
1919
1920 if (!strlen(tmp)) {
1921 log_msg(4, " Partition %s is not used in a non-LVM software raid device", partitions[i]);
1922 mr_free(tmp);
1923 continue;
1924 }
1925 log_msg (5, " UUID: %s", tmp);
1926
1927 /* Get the Software raid device list */
1928 mr_asprintf(command, "%s", "cat /proc/mdstat|grep -iv Personal|awk '{if($0~\"^.*[ ]+:\"){printf(\"/dev/%s \", $1)}}END{print \"\"}'");
1929 log_msg (5, " Running: %s", command);
1930 mr_asprintf(mount_list, "%s", call_program_and_get_last_line_of_output(command));
1931 mr_free(command);
1932
1933 log_msg(4, " Software raid device list: %s", mount_list);
1934 /* Loop through the software raid device list to see if we can find the partition */
1935 lastpos = 0;
1936 while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
1937 mr_asprintf(command, "mdadm --detail %s 2>/dev/null | grep -c %s", token, tmp);
1938 log_msg(4, " Running: %s", command);
1939 mr_free(tmp);
1940 mr_asprintf(tmp, "%s", call_program_and_get_last_line_of_output(command));
1941 mr_free(command);
1942
1943 if (!atoi(tmp)) {
1944 log_msg (4," Didn't find partition %s in software raid device %s", partitions[i], token);
1945 } else {
1946 if ((DSFptr = find_device_in_list(token)) == NULL) {
1947 log_msg (4, "Can't find device %s in mounted file systems list", token);
1948 mr_free(tmp);
1949 mr_free(token);
1950 return (1);
1951 }
1952 DSFptr->check = 1;
1953 break;
1954 }
1955 mr_free(token);
1956 }
1957 mr_free(tmp);
1958 mr_free(mount_list);
1959 }
1960
1961 /* Determine how much memory to allocate for included_dsf_list and excluded_dsf_list */
1962 i = 0;
1963 DSFptr= DSF_Head;
1964 while (DSFptr != NULL) {
1965 i += strlen(DSFptr->mount_point) + 1;
1966 DSFptr = DSFptr->next;
1967 }
1968 log_msg (5, "i: %d", i);
1969 if ((*included_dsf_list = (char *) calloc(i+100, sizeof(char))) == NULL) {
1970 fatal_error ("Cannot allocate memory");
1971 }
1972 if ((*excluded_dsf_list = (char *) calloc(i+100, sizeof(char))) == NULL) {
1973 fatal_error ("Cannot allocate memory");
1974 }
1975 DSFptr= DSF_Head;
1976 while (DSFptr != NULL) {
1977 if (DSFptr->check) {
1978 log_msg (4, "%s is mounted on %s and is on disk %s", DSFptr->device, DSFptr->mount_point, ndsf);
1979 strcat(*included_dsf_list, DSFptr->mount_point);
1980 strcat(*included_dsf_list, "|");
1981 } else {
1982 log_msg (4, "%s is mounted on %s and is NOT on disk %s", DSFptr->device, DSFptr->mount_point, ndsf);
1983 strcat(*excluded_dsf_list, DSFptr->mount_point);
1984 strcat(*excluded_dsf_list, "|");
1985 }
1986 DSFptr = DSFptr->next;
1987 }
1988 mr_free(ndsf);
1989
1990 log_msg (5, "included_dsf_list: %s", *included_dsf_list);
1991 log_msg (5, "excluded_dsf_list: %s", *excluded_dsf_list);
1992 return (0);
1993}
1994
1995
1996/* Update the bkpinfo structure for exclude & include paths
1997 * in order to handle correctly paths corresponding to devices */
1998void mr_make_devlist_from_pathlist(char *pathlist, char mode) {
1999
2000char *token = NULL;
2001int lastpos = 0;
2002char *mounted_on_dsf = NULL;
2003char *not_mounted_on_dsf = NULL;
2004char token_chars[] ="|\t\r\f\a\0\n";
2005char *tmp = NULL;
2006char *tmp1 = NULL;
2007char *tmp2 = NULL;
2008
2009if (pathlist == NULL) {
2010 return;
2011}
2012while ((token = mr_strtok(pathlist, token_chars, &lastpos)) != NULL) {
2013 switch (get_dsf_mount_list(token, &mounted_on_dsf, &not_mounted_on_dsf)) {
2014 case 1:
2015 if (mode == 'E') {
2016 log_msg(1, "WARNING ! %s doesn't exist in -E option", token);
2017 } else {
2018 log_msg(1, "ERROR ! %s doesn't exist in -I option", token);
2019 fatal_error("Error processing -I option");
2020 }
2021 break;
2022 /* Everything is OK; proceed to archive data */
2023 case 0:
2024 if (mode == 'E') {
2025 if (strlen(mounted_on_dsf)) {
2026 log_to_screen("Excluding the following file systems on %s:", token);
2027 log_to_screen("==> %s", mounted_on_dsf);
2028 log_msg (5, "Adding to bkpinfo->exclude_paths due to -E option: %s", mounted_on_dsf);
2029 if (bkpinfo->exclude_paths) {
2030 mr_strcat(bkpinfo->exclude_paths,"|%s",mounted_on_dsf);
2031 } else {
2032 mr_asprintf(bkpinfo->exclude_paths,"%s",mounted_on_dsf);
2033 }
2034 if (bkpinfo->exclude_devs) {
2035 mr_strcat(bkpinfo->exclude_devs,"|%s",token);
2036 } else {
2037 mr_asprintf(bkpinfo->exclude_devs,"%s",token);
2038 }
2039 }
2040 } else {
2041 log_to_screen("Archiving only the following file systems on %s:", token);
2042 log_to_screen("==> %s", mounted_on_dsf);
2043 mr_free(bkpinfo->include_paths);
2044 mr_asprintf(bkpinfo->include_paths, "%s", "/");
2045 if (strlen(not_mounted_on_dsf)) {
2046 log_msg (5, "Adding to bkpinfo->exclude_paths due to -I option: %s", not_mounted_on_dsf);
2047 log_to_screen("Not archiving the following file systems:");
2048 log_to_screen("==> %s", not_mounted_on_dsf);
2049 if (bkpinfo->exclude_paths) {
2050 mr_strcat(bkpinfo->exclude_paths, "|%s",not_mounted_on_dsf);
2051 } else {
2052 mr_asprintf(bkpinfo->exclude_paths,"%s",not_mounted_on_dsf);
2053 }
2054 }
2055 }
2056 break;
2057 /* It's a dsf but not a whole disk dsf */
2058 case -2:
2059 log_to_screen("Could %s be a partition instead of a whole disk device special file?\nIgnored.", token);
2060 break;
2061 /* A device special file was not passed in. Process it as a path. */
2062 case -1:
2063 /* Adds a | to ensure correct detection even at both ends */
2064 mr_asprintf(tmp1,"|%s",token);
2065 mr_asprintf(tmp2,"|%s|",token);
2066 if (mode == 'E') {
2067 /* Add the token if not already in the list */
2068 mr_asprintf(tmp,"|%s|",bkpinfo->exclude_paths);
2069 if (strstr(tmp,tmp2) == NULL) {
2070 if (bkpinfo->exclude_paths) {
2071 mr_strcat(bkpinfo->exclude_paths,tmp1);
2072 mr_free(tmp1);
2073 } else {
2074 bkpinfo->exclude_paths = tmp1;
2075 }
2076 }
2077 } else {
2078 /* Add the token if not already in the list */
2079 mr_asprintf(tmp,"|%s|",bkpinfo->include_paths);
2080 if (strstr(tmp,tmp2) == NULL) {
2081 mr_strcat(bkpinfo->include_paths, "%s", tmp1);
2082 }
2083 mr_free(tmp1);
2084 }
2085 mr_free(tmp);
2086 mr_free(tmp2);
2087 break;
2088 }
2089 mr_free(token);
2090
2091 if (bkpinfo->include_paths != NULL) {
2092 log_msg(1, "include_paths is now '%s'", bkpinfo->include_paths);
2093 }
2094 if (bkpinfo->exclude_paths != NULL) {
2095 log_msg(1, "exclude_paths is now '%s'", bkpinfo->exclude_paths);
2096 }
2097 if (bkpinfo->exclude_devs != NULL) {
2098 log_msg(1, "exclude_devs is now '%s'", bkpinfo->exclude_devs);
2099 }
2100}
2101}
2102
2103
2104
2105
2106/**
2107 * Ask user for details of backup/restore information.
2108 * Called when @c mondoarchive doesn't get any parameters.
2109 * @param bkpinfo The backup information structure to fill out with the user's data.
2110 * @param archiving_to_media TRUE if archiving, FALSE if restoring.
2111 * @return 0, always.
2112 * @bug No point of `int' return value.
2113 * @ingroup archiveGroup
2114 */
2115int interactively_obtain_media_parameters_from_user(bool archiving_to_media)
2116// archiving_to_media is TRUE if I'm being called by mondoarchive
2117// archiving_to_media is FALSE if I'm being called by mondorestore
2118{
2119 char *tmp = NULL;
2120 char *sz = NULL;
2121 char *tmpro = NULL;
2122 char *tmp1 = NULL;
2123 char *mds = NULL;
2124 char *q = NULL;
2125 char p[16*MAX_STR_LEN];
2126 char *sz_size = NULL;
2127 char *command = NULL;
2128 char *compression_type = NULL;
2129 char *comment = NULL;
2130 int i;
2131 FILE *fin;
2132
2133 malloc_string(tmp1);
2134 assert(bkpinfo != NULL);
2135 bkpinfo->nonbootable_backup = FALSE;
2136
2137 // Tape, CD, NETFS, ...?
2138 srandom(getpid());
2139 bkpinfo->backup_media_type =
2140 (g_restoring_live_from_cd) ? cdr :
2141 which_backup_media_type(bkpinfo->restore_data);
2142 if (bkpinfo->backup_media_type == none) {
2143 log_to_screen("User has chosen not to backup the PC");
2144 finish(1);
2145 }
2146 /* Why asking to remove the media with tape ?
2147 if (bkpinfo->backup_media_type == tape && bkpinfo->restore_data) {
2148 popup_and_OK("Please remove media from drive(s)");
2149 }
2150 */
2151 if (archiving_to_media) {
2152 setup_tmpdir(NULL);
2153 /*
2154 * Set the scratchdir to reside on the partition with the most free space.
2155 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
2156 */
2157#ifdef __FreeBSD__
2158 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"));
2159#else
2160 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"));
2161#endif
2162
2163 if (tmp[0] != '/') {
2164 mr_asprintf(sz, "%s", tmp);
2165 mr_free(tmp);
2166 mr_asprintf(tmp, "/%s", sz);
2167 mr_free(sz);
2168 }
2169 setup_scratchdir(tmp);
2170 }
2171 log_msg(3, "media type = %s", bkptype_to_string(bkpinfo->backup_media_type));
2172 bkpinfo->cdrw_speed = (bkpinfo->backup_media_type == cdstream) ? 2 : 4;
2173 bkpinfo->compression_level = (bkpinfo->backup_media_type == cdstream) ? 1 : 5;
2174 bkpinfo->use_lzo = (bkpinfo->backup_media_type == cdstream) ? TRUE : FALSE;
2175 mvaddstr_and_log_it(2, 0, " ");
2176
2177 // Find device's /dev (or SCSI) entry
2178 switch (bkpinfo->backup_media_type) {
2179 case cdr:
2180 case cdrw:
2181 case dvd:
2182 case usb:
2183 /* Never try to eject a USB device */
2184 if (bkpinfo->backup_media_type == usb) {
2185 bkpinfo->please_dont_eject = TRUE;
2186 }
2187 if (archiving_to_media) {
2188 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
2189 if (ask_me_yes_or_no("Is your computer a laptop, or does the CD writer incorporate BurnProof technology?")) {
2190 bkpinfo->manual_cd_tray = TRUE;
2191 }
2192 }
2193 if ((compression_type = which_compression_type()) == NULL) {
2194 log_to_screen("User has chosen not to backup the PC");
2195 finish(1);
2196 }
2197
2198 if ((bkpinfo->compression_level = which_compression_level()) == -1) {
2199 log_to_screen("User has chosen not to backup the PC");
2200 finish(1);
2201 }
2202 mds = media_descriptor_string(bkpinfo->backup_media_type);
2203 mr_asprintf(comment, "What speed is your %s (re)writer?", mds);
2204 if (bkpinfo->backup_media_type == dvd) {
2205 find_dvd_device(bkpinfo->media_device, FALSE);
2206 strcpy(tmp1, "1");
2207 mr_asprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB
2208 log_msg(1, "Setting to DVD defaults");
2209 } else {
2210 strcpy(bkpinfo->media_device, VANILLA_SCSI_CDROM);
2211 strcpy(tmp1, "4");
2212 mr_asprintf(sz_size, "%d", 650);
2213 log_msg(1, "Setting to CD defaults");
2214 }
2215 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
2216 if (!popup_and_get_string("Speed", comment, tmp1, 4)) {
2217 log_to_screen("User has chosen not to backup the PC");
2218 mr_free(comment);
2219 finish(1);
2220 }
2221 }
2222 mr_free(comment);
2223 bkpinfo->cdrw_speed = atoi(tmp1); // if DVD then this shouldn't ever be used anyway :)
2224
2225 strcpy(tmp1, sz_size);
2226 mr_asprintf(comment, "How much data (in Megabytes) will each %s store?", mds);
2227 mr_free(mds);
2228 if (!popup_and_get_string("Size", comment, tmp1, 5)) {
2229 log_to_screen("User has chosen not to backup the PC");
2230 finish(1);
2231 }
2232 mr_asprintf(sz_size, "%s", tmp1);
2233 bkpinfo->media_size = atoi(sz_size);
2234
2235 if (bkpinfo->media_size <= 0) {
2236 log_to_screen("User has chosen not to backup the PC");
2237 finish(1);
2238 }
2239 }
2240 /* No break because we continue even for usb */
2241 case cdstream:
2242 mds = media_descriptor_string(bkpinfo->backup_media_type);
2243
2244 if ((bkpinfo->disaster_recovery) && (bkpinfo->backup_media_type != usb)) {
2245 strcpy(bkpinfo->media_device, "/dev/cdrom");
2246 log_msg(2, "CD-ROM device assumed to be at %s", bkpinfo->media_device);
2247 } else if ((bkpinfo->restore_data && (bkpinfo->backup_media_type != usb)) || bkpinfo->backup_media_type == dvd) {
2248 if (!bkpinfo->media_device[0]) {
2249 strcpy(bkpinfo->media_device, "/dev/cdrom");
2250 } // just for the heck of it :)
2251 log_msg(1, "bkpinfo->media_device = %s", bkpinfo->media_device);
2252 if (bkpinfo->backup_media_type == dvd || find_cdrom_device(bkpinfo->media_device, FALSE)) {
2253 log_msg(1, "bkpinfo->media_device = %s", bkpinfo->media_device);
2254 mr_asprintf(comment, "Please specify your %s drive's /dev entry", mds);
2255 if (!popup_and_get_string("Device?", comment, bkpinfo->media_device, MAX_STR_LEN / 4)) {
2256 log_to_screen("User has chosen not to backup the PC");
2257 finish(1);
2258 }
2259 }
2260 log_msg(2, "%s device found at %s", mds, bkpinfo->media_device);
2261 } else {
2262 if ((find_cdrw_device(bkpinfo->media_device)) && (bkpinfo->backup_media_type != usb)) {
2263 bkpinfo->media_device[0] = '\0';
2264 }
2265 if (bkpinfo->media_device[0]) {
2266 if (bkpinfo->backup_media_type == usb) {
2267 mr_asprintf(tmp, "I think your %s media corresponds to %s. Is this correct?", mds, bkpinfo->media_device);
2268 } else {
2269 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);
2270 }
2271 if (!ask_me_yes_or_no(tmp)) {
2272 bkpinfo->media_device[0] = '\0';
2273 }
2274 mr_free(tmp);
2275 }
2276 if (!bkpinfo->media_device[0]) {
2277 if (bkpinfo->backup_media_type == usb) {
2278 i = popup_and_get_string("/dev entry?",
2279 "What is the /dev entry of your USB Disk/Key, please?",
2280 bkpinfo->media_device,
2281 MAX_STR_LEN / 4);
2282 } else {
2283 if (g_kernel_version < 2.6) {
2284 i = popup_and_get_string("Device node?",
2285 "What is the SCSI node of your CD (re)writer, please?",
2286 bkpinfo->media_device,
2287 MAX_STR_LEN / 4);
2288 } else {
2289 i = popup_and_get_string("/dev entry?",
2290 "What is the /dev entry of your CD (re)writer, please?",
2291 bkpinfo->media_device,
2292 MAX_STR_LEN / 4);
2293 }
2294 }
2295 if (!i) {
2296 log_to_screen("User has chosen not to backup the PC");
2297 finish(1);
2298 }
2299 }
2300 }
2301 mr_free(mds);
2302
2303 if (bkpinfo->backup_media_type == cdstream) {
2304 bkpinfo->media_size = 650;
2305 }
2306 break;
2307 case udev:
2308 if (!ask_me_yes_or_no
2309 ("This option is for advanced users only. Are you sure?")) {
2310 log_to_screen("User has chosen not to backup the PC");
2311 finish(1);
2312 }
2313 case tape:
2314
2315 if ((!bkpinfo->restore_mode) && (find_tape_device_and_size(bkpinfo->media_device, sz_size))) {
2316 log_msg(3, "Ok, using vanilla scsi tape.");
2317 strcpy(bkpinfo->media_device, VANILLA_SCSI_TAPE);
2318 if ((fin = fopen(bkpinfo->media_device, "r"))) {
2319 paranoid_fclose(fin);
2320 } else {
2321 strcpy(bkpinfo->media_device, "/dev/osst0");
2322 }
2323 }
2324 if (bkpinfo->media_device[0]) {
2325 if ((fin = fopen(bkpinfo->media_device, "r"))) {
2326 paranoid_fclose(fin);
2327 } else {
2328 if (does_file_exist("/tmp/mondo-restore.cfg")) {
2329 read_cfg_var("/tmp/mondo-restore.cfg", "media-dev", bkpinfo->media_device);
2330 }
2331 }
2332 }
2333 if (bkpinfo->media_device[0]) {
2334 mr_asprintf(tmp, "I think I've found your tape streamer at %s; am I right on the money?", bkpinfo->media_device);
2335 if (!ask_me_yes_or_no(tmp)) {
2336 bkpinfo->media_device[0] = '\0';
2337 }
2338 mr_free(tmp);
2339 }
2340 if (!bkpinfo->media_device[0]) {
2341 if (!popup_and_get_string
2342 ("Device name?",
2343 "What is the /dev entry of your tape streamer?",
2344 bkpinfo->media_device, MAX_STR_LEN / 4)) {
2345 log_to_screen("User has chosen not to backup the PC");
2346 finish(1);
2347 }
2348 }
2349 mr_asprintf(tmp, "ls -l %s", bkpinfo->media_device);
2350 if (run_program_and_log_output(tmp, FALSE)) {
2351 log_to_screen("User has not specified a valid /dev entry");
2352 finish(1);
2353 }
2354 mr_free(tmp);
2355
2356 if (!popup_and_get_string
2357 ("Tape block size?",
2358 "What is the block size of your tape streamer?",
2359 sz_size, 15)) {
2360 log_to_screen("User has chosen not to backup the PC");
2361 finish(1);
2362 }
2363 bkpinfo->internal_tape_block_size = atol(sz_size);
2364 if (bkpinfo->internal_tape_block_size <= 0) {
2365 log_to_screen("User has chosen not to backup the PC");
2366 finish(1);
2367 }
2368
2369 bkpinfo->media_size = 0;
2370 log_msg(4, "media_size = %ld", bkpinfo->media_size);
2371
2372 bkpinfo->use_obdr = ask_me_yes_or_no
2373 ("Do you want to activate OBDR support for your tapes ?");
2374 if (bkpinfo->use_obdr) {
2375 log_msg(4, "obdr mode = TRUE");
2376 } else {
2377 log_msg(4, "obdr mode = FALSE");
2378 }
2379 if (archiving_to_media) {
2380 if ((compression_type = which_compression_type()) == NULL) {
2381 log_to_screen("User has chosen not to backup the PC");
2382 finish(1);
2383 }
2384 if ((bkpinfo->compression_level = which_compression_level()) == -1) {
2385 log_to_screen("User has chosen not to backup the PC");
2386 finish(1);
2387 }
2388 }
2389 break;
2390
2391
2392
2393 case netfs:
2394 /* Never try to eject a NETFS device */
2395 bkpinfo->please_dont_eject = TRUE;
2396 /* Force NFS to be the protocol by default */
2397 if (bkpinfo->netfs_proto == NULL) {
2398 mr_asprintf(bkpinfo->netfs_proto, "nfs");
2399 }
2400
2401 /* Initiate bkpinfo netfs_mount path from running environment if not already done */
2402 if (bkpinfo->netfs_mount == NULL) {
2403 mr_asprintf(bkpinfo->netfs_mount, "%s", call_program_and_get_last_line_of_output("mount | grep \":\" | cut -d' ' -f1 | head -n1"));
2404 }
2405#ifdef __FreeBSD__
2406 if (TRUE)
2407#else
2408 if (!bkpinfo->disaster_recovery)
2409#endif
2410 {
2411 if (!popup_and_get_string
2412 ("Network shared dir.",
2413 "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.)",
2414 p, MAX_STR_LEN / 4)) {
2415 log_to_screen("User has chosen not to backup the PC");
2416 finish(1);
2417 }
2418 mr_free(bkpinfo->netfs_mount);
2419 mr_asprintf(bkpinfo->netfs_mount, "%s", p);
2420 if (!bkpinfo->restore_data) {
2421 if ((compression_type = which_compression_type()) == NULL) {
2422 log_to_screen("User has chosen not to backup the PC");
2423 finish(1);
2424 }
2425
2426 if ((bkpinfo->compression_level = which_compression_level()) == -1) {
2427 log_to_screen("User has chosen not to backup the PC");
2428 finish(1);
2429 }
2430 }
2431 // check whether already mounted - we better remove
2432 // surrounding spaces and trailing '/' for this
2433 mr_strip_spaces(bkpinfo->netfs_mount);
2434 if (bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] == '/')
2435 bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] = '\0';
2436 q = strchr(bkpinfo->netfs_mount, '@');
2437 if (q != NULL) {
2438 /* User found. Store the 2 values */
2439 q++;
2440 /* new netfs mount */
2441 strcpy(tmp1,q);
2442 } else {
2443 strcpy(tmp1,bkpinfo->netfs_mount);
2444 }
2445 mr_asprintf(command, "mount | grep \"%s \" | cut -d' ' -f3", tmp1);
2446 strcpy(bkpinfo->isodir, call_program_and_get_last_line_of_output(command));
2447 mr_free(command);
2448
2449 if (!bkpinfo->restore_data) {
2450 mr_asprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB
2451 mr_asprintf(comment, "How much data (in Megabytes) will each media store?");
2452 strcpy(tmp1, sz_size);
2453 mr_free(sz_size);
2454 if (!popup_and_get_string("Size", comment, tmp1, 5)) {
2455 log_to_screen("User has chosen not to backup the PC");
2456 finish(1);
2457 }
2458 mr_free(comment);
2459 mr_asprintf(sz_size, "%s", tmp1);
2460 } else {
2461 mr_asprintf(sz_size, "0");
2462 }
2463 bkpinfo->media_size = atoi(sz_size);
2464 mr_free(sz_size);
2465
2466 if (bkpinfo->media_size < 0) {
2467 log_to_screen("User has chosen not to backup the PC");
2468 finish(1);
2469 }
2470 }
2471 if (bkpinfo->disaster_recovery) {
2472 mr_asprintf(command ,"umount %s/isodir 2> /dev/null", bkpinfo->tmpdir);
2473 paranoid_system(command);
2474 mr_free(command);
2475
2476 }
2477 strcpy(tmp1, bkpinfo->netfs_proto);
2478 if (!popup_and_get_string("Network protocol", "Which protocol should I use (nfs/sshfs/smbfs) ?",tmp1, MAX_STR_LEN)) {
2479 log_to_screen("User has chosen not to backup the PC");
2480 finish(1);
2481 }
2482 mr_free(bkpinfo->netfs_proto);
2483 mr_asprintf(bkpinfo->netfs_proto, "%s", tmp1);
2484
2485 strcpy(tmp1, bkpinfo->netfs_mount);
2486 if (!popup_and_get_string("Network share", "Which remote share should I mount?", tmp1, MAX_STR_LEN)) {
2487 log_to_screen("User has chosen not to backup the PC");
2488 finish(1);
2489 }
2490 mr_free(bkpinfo->netfs_mount);
2491 mr_asprintf(bkpinfo->netfs_mount, "%s", tmp1);
2492
2493 if (bkpinfo->netfs_user) {
2494 strcpy(tmp1, bkpinfo->netfs_user);
2495 } else {
2496 strcpy(tmp1, "");
2497 }
2498 if (!popup_and_get_string("Network user", "Which user should I use if any ?",tmp1, MAX_STR_LEN)) {
2499 log_to_screen("User has chosen not to backup the PC");
2500 finish(1);
2501 }
2502 mr_free(bkpinfo->netfs_user);
2503 if (strcmp(tmp1, "") != 0) {
2504 mr_asprintf(bkpinfo->netfs_user, "%s", tmp1);
2505 }
2506
2507 /* Initiate bkpinfo isodir path from running environment if mount already done */
2508 if (is_this_device_mounted(bkpinfo->netfs_mount)) {
2509 strcpy(bkpinfo->isodir, call_program_and_get_last_line_of_output("mount | grep \":\" | cut -d' ' -f3 | head -n1"));
2510 } else {
2511 sprintf(bkpinfo->isodir, "%s/netfsdir", bkpinfo->tmpdir);
2512 mr_asprintf(command, "mkdir -p %s", bkpinfo->isodir);
2513 run_program_and_log_output(command, 5);
2514 mr_free(command);
2515
2516 if (bkpinfo->restore_data) {
2517 /* mount th FS read-only in restore mode to avoid any erase of whatever */
2518 mr_asprintf(tmpro, "-o ro");
2519 } else {
2520 mr_asprintf(tmpro, "");
2521 }
2522
2523 /* Build the mount string */
2524 if (strstr(bkpinfo->netfs_proto, "smbfs")) {
2525 mr_asprintf(tmp, "mount -t cifs %s %s %s",bkpinfo->netfs_mount, bkpinfo->isodir,tmpro);
2526 if (bkpinfo->netfs_user) {
2527 mr_strcat(tmp, " -o user=%s", bkpinfo->netfs_user);
2528 }
2529 else {
2530 if (strstr(bkpinfo->netfs_proto, "sshfs")) {
2531 mr_asprintf(tmp, "sshfs %s ",tmpro);
2532 } else {
2533 mr_asprintf(tmp, "mount -t %s -o nolock %s ", bkpinfo->netfs_proto,tmpro);
2534 }
2535 if (bkpinfo->netfs_user) {
2536 mr_strcat(tmp, "%s@", bkpinfo->netfs_user);
2537 }
2538 mr_strcat(tmp, "%s %s", bkpinfo->netfs_mount, bkpinfo->isodir);
2539 }
2540 run_program_and_log_output(tmp, 3);
2541 mr_free(tmp);
2542
2543 malloc_string(g_selfmounted_isodir);
2544 strcpy(g_selfmounted_isodir, bkpinfo->isodir);
2545 }
2546 }
2547 if (!is_this_device_mounted(bkpinfo->netfs_mount)) {
2548 popup_and_OK("Please mount that partition before you try to backup to or restore from it.");
2549 finish(1);
2550 }
2551 strcpy(tmp1, bkpinfo->netfs_remote_dir);
2552 if (!popup_and_get_string
2553 ("Directory", "Which directory within that mountpoint?", tmp1,
2554 MAX_STR_LEN)) {
2555 log_to_screen("User has chosen not to backup the PC");
2556 finish(1);
2557 }
2558 mr_asprintf(bkpinfo->netfs_remote_dir, "%s", tmp1);
2559
2560 // check whether writable - we better remove surrounding spaces for this
2561 mr_strip_spaces(bkpinfo->netfs_remote_dir);
2562
2563 if (!popup_and_get_string
2564 ("Prefix.",
2565 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
2566 bkpinfo->prefix, MAX_STR_LEN / 4)) {
2567 log_to_screen("User has chosen not to backup the PC");
2568 finish(1);
2569 }
2570 log_msg(3, "prefix set to %s", bkpinfo->prefix);
2571
2572 log_msg(3, "Just set netfs_remote_dir to %s", bkpinfo->netfs_remote_dir);
2573 log_msg(3, "isodir is still %s", bkpinfo->isodir);
2574 break;
2575
2576 case iso:
2577 if (!bkpinfo->disaster_recovery) {
2578 if (!popup_and_get_string
2579 ("Storage dir.",
2580 "Please enter the full path name to the directory for your ISO images. Example: /mnt/raid0_0",
2581 bkpinfo->isodir, MAX_STR_LEN / 4)) {
2582 log_to_screen("User has chosen not to backup the PC");
2583 finish(1);
2584 }
2585 if (archiving_to_media) {
2586 if ((compression_type = which_compression_type()) == NULL) {
2587 log_to_screen("User has chosen not to backup the PC");
2588 finish(1);
2589 }
2590 if ((bkpinfo->compression_level = which_compression_level()) == -1) {
2591 log_to_screen("User has chosen not to backup the PC");
2592 finish(1);
2593 }
2594 sprintf(tmp1, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB
2595 if (!popup_and_get_string
2596 ("ISO size.",
2597 "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.",
2598 tmp1, 16)) {
2599 log_to_screen("User has chosen not to backup the PC");
2600 finish(1);
2601 }
2602 bkpinfo->media_size = atoi(tmp1);
2603 } else {
2604 bkpinfo->media_size = 650;
2605 }
2606 }
2607 if (!popup_and_get_string
2608 ("Prefix.",
2609 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
2610 bkpinfo->prefix, MAX_STR_LEN / 4)) {
2611 log_to_screen("User has chosen not to backup the PC");
2612 finish(1);
2613 }
2614 log_msg(3, "prefix set to %s", bkpinfo->prefix);
2615 break;
2616 default:
2617 fatal_error
2618 ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
2619 }
2620
2621 if (archiving_to_media) {
2622
2623#ifdef __FreeBSD__
2624 strcpy(bkpinfo->boot_device,
2625 call_program_and_get_last_line_of_output
2626 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
2627#else
2628 strcpy(bkpinfo->boot_device,
2629 call_program_and_get_last_line_of_output
2630 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
2631#endif
2632 i = which_boot_loader(bkpinfo->boot_device);
2633 if (i == 'U') // unknown
2634 {
2635
2636#ifdef __FreeBSD__
2637 if (!popup_and_get_string
2638 ("Boot device",
2639 "What is your boot device? (e.g. /dev/ad0)",
2640 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2641 log_to_screen("User has chosen not to backup the PC");
2642 finish(1);
2643 }
2644 i = which_boot_loader(bkpinfo->boot_device);
2645#else
2646 if (!popup_and_get_string
2647 ("Boot device",
2648 "What is your boot device? (e.g. /dev/hda)",
2649 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2650 log_to_screen("User has chosen not to backup the PC");
2651 finish(1);
2652 }
2653 if (does_string_exist_in_boot_block(bkpinfo->boot_device, "LILO")) {
2654 i = 'L';
2655 } else
2656 if (does_string_exist_in_boot_block(bkpinfo->boot_device, "ELILO")) {
2657 i = 'E';
2658 } else
2659 if (does_string_exist_in_boot_block(bkpinfo->boot_device, "GRUB")) {
2660 i = 'G';
2661 } else {
2662 i = 'U';
2663 }
2664#endif
2665 if (i == 'U') {
2666 if (ask_me_yes_or_no("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?")) {
2667 i = 'R'; // raw
2668 } else {
2669 log_to_screen("I cannot find your boot loader. Please run mondoarchive with parameters.");
2670 finish(1);
2671 }
2672 }
2673 }
2674 bkpinfo->boot_loader = i;
2675
2676 mr_free(bkpinfo->include_paths);
2677 strcpy(tmp1, "/");
2678 if (!popup_and_get_string
2679 ("Backup paths",
2680 "Please enter paths (separated by '|') which you want me to backup. The default is '/' (i.e. everything).",
2681 tmp1, MAX_STR_LEN)) {
2682 log_to_screen("User has chosen not to backup the PC");
2683 finish(1);
2684 }
2685 mr_asprintf(bkpinfo->include_paths, "%s", tmp1);
2686
2687 tmp = list_of_NETFS_mounts_only();
2688 if (strlen(tmp) > 2) {
2689 mr_strcat(bkpinfo->exclude_paths, "|%s",tmp);
2690 }
2691 mr_free(tmp);
2692// NTFS
2693 strcpy(tmp1, call_program_and_get_last_line_of_output("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'"));
2694 if (strlen(tmp1) > 2) {
2695 if (!popup_and_get_string
2696 ("NTFS partitions",
2697 "Please enter/confirm the NTFS partitions you wish to backup as well.",
2698 tmp1, MAX_STR_LEN / 4)) {
2699 log_to_screen("User has chosen not to backup the PC");
2700 finish(1);
2701 }
2702 strncpy(bkpinfo->image_devs, tmp1, MAX_STR_LEN / 4);
2703 }
2704
2705 if (bkpinfo->exclude_paths != NULL ) {
2706 strncpy(p,bkpinfo->exclude_paths,(16*MAX_STR_LEN)-1);
2707 } else {
2708 p[0] = '\0';
2709 }
2710 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);
2711 if (p == NULL) {
2712 log_to_screen("User has chosen not to backup the PC");
2713 finish(1);
2714 }
2715 mr_free(bkpinfo->exclude_paths);
2716 mr_asprintf(tmp, "%s", p);
2717 bkpinfo->exclude_paths = tmp;
2718
2719 if (!popup_and_get_string
2720 ("Temporary directory",
2721 "Please enter your temporary directory.",
2722 bkpinfo->tmpdir, (4*MAX_STR_LEN)-1)) {
2723 log_to_screen("User has chosen not to backup the PC");
2724 finish(1);
2725 }
2726 /* if modified to another path */
2727 if (strstr(bkpinfo->tmpdir,"mondo.tmp.") == NULL) {
2728 setup_tmpdir(bkpinfo->tmpdir);
2729 }
2730 if (!popup_and_get_string
2731 ("Scratch directory",
2732 "Please enter your scratch directory.",
2733 bkpinfo->scratchdir, (4*MAX_STR_LEN)-1)) {
2734 log_to_screen("User has chosen not to backup the PC");
2735 finish(1);
2736 }
2737 /* if modified to another path */
2738 if (strstr(bkpinfo->scratchdir,"mondo.scratch.") == NULL) {
2739 setup_scratchdir(bkpinfo->scratchdir);
2740 }
2741 if (ask_me_yes_or_no("Do you want to backup extended attributes?")) {
2742 if (find_home_of_exe("getfattr")) {
2743 mr_free(g_getfattr);
2744 mr_asprintf(g_getfattr,"getfattr");
2745 }
2746 if (find_home_of_exe("getfacl")) {
2747 mr_free(g_getfacl);
2748 mr_asprintf(g_getfacl,"getfacl");
2749 }
2750 log_it("Backup of extended attributes");
2751 }
2752// Interactive mode:
2753#ifdef __IA64__
2754 bkpinfo->make_cd_use_lilo = TRUE;
2755#else
2756 bkpinfo->make_cd_use_lilo = FALSE;
2757#endif
2758 bkpinfo->backup_data = TRUE;
2759 if (strcmp(compression_type,"lzo") == 0) {
2760 strcpy(bkpinfo->zip_exe, "lzop");
2761 strcpy(bkpinfo->zip_suffix, "lzo");
2762 } else if (strcmp(compression_type,"gzip") == 0) {
2763 strcpy(bkpinfo->zip_exe, "gzip");
2764 strcpy(bkpinfo->zip_suffix, "gz");
2765 } else if (strcmp(compression_type,"lzma") == 0) {
2766 //strcpy(bkpinfo->zip_exe, "xy");
2767 //strcpy(bkpinfo->zip_suffix, "xy");
2768 } else if (strcmp(compression_type,"bzip2") == 0) {
2769 strcpy(bkpinfo->zip_exe, "bzip2");
2770 strcpy(bkpinfo->zip_suffix, "bz2");
2771 } else {
2772 bkpinfo->zip_exe[0] = bkpinfo->zip_suffix[0] = '\0';
2773 }
2774
2775 bkpinfo->verify_data =
2776 ask_me_yes_or_no
2777 ("Will you want to verify your backups after Mondo has created them?");
2778
2779 if (!ask_me_yes_or_no
2780 ("Are you sure you want to proceed? Hit 'no' to abort.")) {
2781 log_to_screen("User has chosen not to backup the PC");
2782 finish(1);
2783 }
2784 } else {
2785 bkpinfo->restore_data = TRUE; // probably...
2786 }
2787 mr_free(compression_type);
2788
2789 if (bkpinfo->backup_media_type == iso
2790 || bkpinfo->backup_media_type == netfs) {
2791 g_ISO_restore_mode = TRUE;
2792 }
2793#ifdef __FreeSD__
2794// skip
2795#else
2796 if (bkpinfo->backup_media_type == netfs) {
2797 log_msg(3, "I think the Remote mount is mounted at %s", bkpinfo->isodir);
2798 }
2799 log_it("isodir = %s", bkpinfo->isodir);
2800 if (bkpinfo->netfs_mount) {
2801 log_it("netfs_mount = '%s'", bkpinfo->netfs_mount);
2802 }
2803 if (bkpinfo->netfs_user) {
2804 log_it("netfs_user = '%s'", bkpinfo->netfs_user);
2805 }
2806 if (bkpinfo->netfs_proto) {
2807 log_it("netfs_proto = '%s'", bkpinfo->netfs_proto);
2808 }
2809#endif
2810
2811 log_it("media device = %s", bkpinfo->media_device);
2812 log_it("media size = %ld", bkpinfo->media_size);
2813 log_it("media type = %s", bkptype_to_string(bkpinfo->backup_media_type));
2814 if (bkpinfo->prefix) {
2815 log_it("prefix = %s", bkpinfo->prefix);
2816 }
2817 log_it("compression = %ld", bkpinfo->compression_level);
2818 log_it("exclude_path = %s", bkpinfo->exclude_paths);
2819 log_it("include_path = %s", bkpinfo->include_paths);
2820
2821 /* Handle devices passed in bkpinfo and print result */
2822 /* the mr_make_devlist_from_pathlist function appends */
2823 /* to the *_paths variables so copy before */
2824 mr_make_devlist_from_pathlist(bkpinfo->exclude_paths, 'E');
2825 mr_make_devlist_from_pathlist(bkpinfo->include_paths, 'I');
2826
2827 log_it("scratchdir = '%s'", bkpinfo->scratchdir);
2828 log_it("tmpdir = '%s'", bkpinfo->tmpdir);
2829 if (bkpinfo->image_devs) {
2830 log_it("image_devs = '%s'", bkpinfo->image_devs);
2831 }
2832 log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device, bkpinfo->boot_loader);
2833 if (bkpinfo->media_size < 0) {
2834 if (archiving_to_media) {
2835 fatal_error("Media size is less than zero.");
2836 } else {
2837 log_msg(2, "Warning - media size is less than zero.");
2838 bkpinfo->media_size = 0;
2839 }
2840 }
2841 paranoid_free(sz_size);
2842 paranoid_free(tmp1);
2843 return (0);
2844}
2845
2846
2847/**
2848 * Get a |-separated list of NETFS mounts.
2849 * @return The list created.
2850 * @note The return value points to allocated string that needs to be freed
2851 * @bug Even though we only want the mounts, the devices are still checked.
2852 */
2853char *list_of_NETFS_mounts_only(void)
2854{
2855 char *exclude_these_directories = NULL;
2856
2857 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;}'"));
2858 log_msg(9,"list_of_NETFS_mounts_only returns %s\n",exclude_these_directories);
2859 return(exclude_these_directories);
2860}
2861
2862/* @} - end of utilityGroup */
2863
2864
2865
2866
2867
2868/**
2869 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
2870 * [random] is a random number between 1 and 32767.
2871 * @param store_name_here Where to store the new filename.
2872 * @param stub A random number will be appended to this to make the FIFO's name.
2873 * @ingroup deviceGroup
2874 */
2875void make_fifo(char *store_name_here, char *stub)
2876{
2877 char *tmp;
2878
2879 malloc_string(tmp);
2880 assert_string_is_neither_NULL_nor_zerolength(stub);
2881
2882 sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
2883 (int) (random() % 32768));
2884 make_hole_for_file(store_name_here);
2885 mkfifo(store_name_here, S_IRWXU | S_IRWXG);
2886 sprintf(tmp, "chmod 770 %s", store_name_here);
2887 paranoid_system(tmp);
2888 paranoid_free(tmp);
2889}
2890
2891
2892
2893/**
2894 * @addtogroup deviceGroup
2895 * @{
2896 */
2897/**
2898 * If we can read @p dev, set @p output to it.
2899 * If @p dev cannot be read, set @p output to "".
2900 * @param dev The device to check for.
2901 * @param output Set to @p dev if @p dev exists, "" otherwise.
2902 * @return TRUE if @p dev exists, FALSE if it doesn't.
2903 */
2904bool set_dev_to_this_if_rx_OK(char *output, char *dev)
2905{
2906 char *command;
2907
2908 malloc_string(command);
2909 if (!dev || dev[0] == '\0') {
2910 output[0] = '\0';
2911 return (FALSE);
2912 }
2913// assert_string_is_neither_NULL_nor_zerolength(dev);
2914 if (!bkpinfo->please_dont_eject) {
2915 log_msg(10, "Injecting %s", dev);
2916 inject_device(dev);
2917 }
2918 if (!does_file_exist(dev)) {
2919 log_msg(10, "%s doesn't exist. Returning FALSE.", dev);
2920 return (FALSE);
2921 }
2922 sprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null",
2923 512L, dev);
2924 if (!run_program_and_log_output(command, FALSE)
2925 && !run_program_and_log_output(command, FALSE)) {
2926 strcpy(output, dev);
2927 log_msg(4, "Found it - %s", dev);
2928 return (TRUE);
2929 } else {
2930 output[0] = '\0';
2931 log_msg(4, "It's not %s", dev);
2932 return (FALSE);
2933 }
2934}
2935
2936
2937
2938
2939
2940/**
2941 * Find out what number CD is in the drive.
2942 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
2943 * @return The current CD number, or -1 if it could not be found.
2944 * @note If the CD is not mounted, it will be mounted
2945 * (and remain mounted after this function returns).
2946 */
2947int what_number_cd_is_this()
2948{
2949 int cd_number = -1;
2950 char *mountdev = NULL;
2951 char *tmp = NULL;
2952
2953 assert(bkpinfo != NULL);
2954// log_it("Asking what_number_cd_is_this");
2955 if (g_ISO_restore_mode) {
2956 mr_asprintf(tmp, "mount | grep iso9660 | awk '{print $3;}'");
2957
2958 mr_asprintf(mountdev, "%s%s", call_program_and_get_last_line_of_output(tmp), "/archives/THIS-CD-NUMBER");
2959 cd_number = atoi(last_line_of_file(mountdev));
2960 paranoid_free(mountdev);
2961 paranoid_free(tmp);
2962
2963 return (cd_number);
2964 }
2965
2966 mr_asprintf(mountdev, "%s", bkpinfo->media_device);
2967 if (!mountdev[0]) {
2968 log_it
2969 ("(what_number_cd_is_this) Warning - media_device unknown. Finding out...");
2970 find_cdrom_device(bkpinfo->media_device, FALSE);
2971 }
2972 if (!is_this_device_mounted(MNT_CDROM)) {
2973 if (bkpinfo->backup_media_type == usb) {
2974 mount_USB_here(mountdev, MNT_CDROM);
2975 } else {
2976 mount_CDROM_here(mountdev, MNT_CDROM);
2977 }
2978 }
2979 paranoid_free(mountdev);
2980
2981 cd_number = atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
2982 return (cd_number);
2983}
2984
2985
2986
2987
2988
2989
2990
2991/**
2992 * Find out what device is mounted as root (/).
2993 * @return Root device.
2994 * @note The returned string points to static storage and will be overwritten with every call.
2995 * @bug A bit of a misnomer; it's actually finding out the root device.
2996 * The mountpoint (where it's mounted) will obviously be '/'.
2997 */
2998char *where_is_root_mounted()
2999{
3000 /*@ buffers **************** */
3001 static char tmp[MAX_STR_LEN];
3002
3003
3004#ifdef __FreeBSD__
3005 strcpy(tmp, call_program_and_get_last_line_of_output
3006 ("mount | grep \" on / \" | cut -d' ' -f1"));
3007#else
3008 strcpy(tmp, call_program_and_get_last_line_of_output
3009 ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"));
3010 if (strstr(tmp, "/dev/cciss/")) {
3011 strcpy(tmp, call_program_and_get_last_line_of_output
3012 ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"));
3013 }
3014 if (strstr(tmp, "/dev/md")) {
3015 strcpy(tmp,
3016 call_program_and_get_last_line_of_output
3017 ("mount | grep \" on / \" | cut -d' ' -f1"));
3018 }
3019#endif
3020
3021 return (tmp);
3022}
3023
3024
3025/**
3026 * Find out which boot loader is in use.
3027 * @param which_device Device to look for the boot loader on.
3028 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
3029 * @note Under Linux, all drives are examined, not just @p which_device.
3030 */
3031#ifdef __FreeBSD__
3032char which_boot_loader(char *which_device)
3033{
3034 int count_lilos = 0;
3035 int count_grubs = 0;
3036 int count_boot0s = 0;
3037 int count_dangerouslydedicated = 0;
3038
3039 log_it("looking at drive %s's MBR", which_device);
3040 if (does_string_exist_in_boot_block(which_device, "GRUB")) {
3041 count_grubs++;
3042 }
3043 if (does_string_exist_in_boot_block(which_device, "LILO")) {
3044 count_lilos++;
3045 }
3046 if (does_string_exist_in_boot_block(which_device, "Drive")) {
3047 count_boot0s++;
3048 }
3049 if (does_string_exist_in_first_N_blocks
3050 (which_device, "FreeBSD/i386", 17)) {
3051 count_dangerouslydedicated++;
3052 }
3053 log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
3054 count_grubs, count_lilos, count_elilos, count_boot0s,
3055 count_dangerouslydedicated);
3056
3057 if (count_grubs && !count_lilos) {
3058 return ('G');
3059 } else if (count_lilos && !count_grubs) {
3060 return ('L');
3061 } else if (count_grubs == 1 && count_lilos == 1) {
3062 log_it("I'll bet you used to use LILO but switched to GRUB...");
3063 return ('G');
3064 } else if (count_boot0s == 1) {
3065 return ('B');
3066 } else if (count_dangerouslydedicated) {
3067 return ('D');
3068 } else {
3069 log_it("Unknown boot loader");
3070 return ('U');
3071 }
3072}
3073
3074#else
3075
3076char which_boot_loader(char *which_device)
3077{
3078 /*@ buffer ***************************************************** */
3079 char *list_drives_cmd = NULL;
3080 char *current_drive;
3081 char *tmp;
3082
3083 /*@ pointers *************************************************** */
3084 FILE *pdrives;
3085
3086 /*@ int ******************************************************** */
3087 int count_lilos = 0;
3088 int count_grubs = 0;
3089
3090 /*@ end vars *************************************************** */
3091
3092 malloc_string(current_drive);
3093
3094 /* UEFI is not supported here - but should be managed as a BIOS/UEFI option not a Boot Loader one per se */
3095
3096#ifdef __IA64__
3097 /* No choice for it */
3098 return ('E');
3099#endif
3100 assert(which_device != NULL);
3101
3102 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());
3103 log_it("list_drives_cmd = %s", list_drives_cmd);
3104
3105 if (!(pdrives = popen(list_drives_cmd, "r"))) {
3106 log_OS_error("Unable to open list of drives");
3107 mr_free(list_drives_cmd);
3108 paranoid_free(current_drive);
3109 return ('\0');
3110 }
3111 mr_free(list_drives_cmd);
3112
3113 for (tmp = fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives) && (tmp != NULL);
3114 tmp = fgets(current_drive, MAX_STR_LEN, pdrives)) {
3115 strip_spaces(current_drive);
3116 log_it("looking at drive %s's MBR", current_drive);
3117 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
3118 count_grubs++;
3119 strcpy(which_device, current_drive);
3120 break;
3121 }
3122 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
3123 count_lilos++;
3124 strcpy(which_device, current_drive);
3125 break;
3126 }
3127 }
3128 if (pclose(pdrives)) {
3129 log_OS_error("Cannot pclose pdrives");
3130 }
3131 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
3132 if (count_grubs && !count_lilos) {
3133 paranoid_free(current_drive);
3134 return ('G');
3135 } else if (count_lilos && !count_grubs) {
3136 paranoid_free(current_drive);
3137 return ('L');
3138 } else if (count_grubs == 1 && count_lilos == 1) {
3139 log_it("I'll bet you used to use LILO but switched to GRUB...");
3140 paranoid_free(current_drive);
3141 return ('G');
3142 } else {
3143 // We need to look on each partition then
3144 mr_asprintf(list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep -E \"^/dev/\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/");
3145 log_it("list_drives_cmd = %s", list_drives_cmd);
3146
3147 if (!(pdrives = popen(list_drives_cmd, "r"))) {
3148 log_OS_error("Unable to open list of drives");
3149 mr_free(list_drives_cmd);
3150 paranoid_free(current_drive);
3151 return ('\0');
3152 }
3153 mr_free(list_drives_cmd);
3154
3155 for (tmp = fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives) && (tmp != NULL);
3156 tmp = fgets(current_drive, MAX_STR_LEN, pdrives)) {
3157 strip_spaces(current_drive);
3158 log_it("looking at partition %s's BR", current_drive);
3159 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
3160 count_grubs++;
3161 strcpy(which_device, current_drive);
3162 break;
3163 }
3164 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
3165 count_lilos++;
3166 strcpy(which_device, current_drive);
3167 break;
3168 }
3169 }
3170 if (pclose(pdrives)) {
3171 log_OS_error("Cannot pclose pdrives");
3172 }
3173 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
3174 paranoid_free(current_drive);
3175 if (count_grubs && !count_lilos) {
3176 return ('G');
3177 } else if (count_lilos && !count_grubs) {
3178 return ('L');
3179 } else if (count_grubs == 1 && count_lilos == 1) {
3180 log_it("I'll bet you used to use LILO but switched to GRUB...");
3181 return ('G');
3182 } else {
3183 log_it("Unknown boot loader");
3184 return ('U');
3185 }
3186 }
3187}
3188#endif
3189
3190
3191
3192
3193/**
3194 * Write zeroes over the first 16K of @p device.
3195 * @param device The device to zero.
3196 * @return 0 for success, 1 for failure.
3197 */
3198int zero_out_a_device(char *device)
3199{
3200 FILE *fout;
3201 int i;
3202
3203 assert_string_is_neither_NULL_nor_zerolength(device);
3204
3205 log_it("Zeroing drive %s", device);
3206 if (!(fout = fopen(device, "w"))) {
3207 log_OS_error("Unable to open/write to device");
3208 return (1);
3209 }
3210 for (i = 0; i < 16384; i++) {
3211 fputc('\0', fout);
3212 }
3213 paranoid_fclose(fout);
3214 log_it("Device successfully zeroed.");
3215 return (0);
3216}
3217
3218/**
3219 * Return the device pointed to by @p incoming.
3220 * @param incoming The device to resolve symlinks for.
3221 * @return The path to the real device file.
3222 * @note The returned string points to static storage that will be overwritten with each call.
3223 * @bug Won't work with file v4.0; needs to be written in C.
3224 */
3225char *resolve_softlinks_to_get_to_actual_device_file(char *incoming)
3226{
3227 static char output[MAX_STR_LEN];
3228 char *command;
3229 char *curr_fname;
3230 char *scratch = NULL;
3231 char *tmp = NULL;
3232 char *p;
3233
3234 struct stat statbuf;
3235 command = malloc(1000);
3236 malloc_string(curr_fname);
3237 if (!does_file_exist(incoming)) {
3238 log_it
3239 ("resolve_softlinks_to_get_to_actual_device_file --- device not found");
3240 strcpy(output, incoming);
3241 } else {
3242 strcpy(curr_fname, incoming);
3243 lstat(curr_fname, &statbuf);
3244 while (S_ISLNK(statbuf.st_mode)) {
3245 log_msg(1, "curr_fname = %s", curr_fname);
3246 sprintf(command, "file %s", curr_fname);
3247 mr_asprintf(tmp, "%s", call_program_and_get_last_line_of_output(command));
3248 for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' ';
3249 p--);
3250 p++;
3251 mr_asprintf(scratch, "%s", p);
3252 for (p = scratch; *p != '\0' && *p != '\''; p++);
3253 *p = '\0';
3254 log_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp, scratch);
3255 mr_free(tmp);
3256
3257 if (scratch[0] == '/') {
3258 strcpy(curr_fname, scratch); // copy whole thing because it's an absolute softlink
3259 } else { // copy over the basename cos it's a relative softlink
3260 p = curr_fname + strlen(curr_fname);
3261 while (p != curr_fname && *p != '/') {
3262 p--;
3263 }
3264 if (*p == '/') {
3265 p++;
3266 }
3267 strcpy(p, scratch);
3268 }
3269 mr_free(scratch);
3270 lstat(curr_fname, &statbuf);
3271 }
3272 strcpy(output, curr_fname);
3273 log_it("resolved %s to %s", incoming, output);
3274 }
3275 paranoid_free(command);
3276 paranoid_free(curr_fname);
3277 return (output);
3278}
3279
3280/* @} - end of deviceGroup */
3281
3282/**
3283 * Return the type of partition format (GPT or MBR)
3284 */
3285char *which_partition_format(const char *drive)
3286{
3287 static char output[4];
3288 char *tmp = NULL;
3289 char *command;
3290 char *fdisk;
3291#ifdef __IA64__
3292 struct stat buf;
3293#endif
3294 malloc_string(command);
3295 malloc_string(fdisk);
3296 sprintf(fdisk, "/sbin/parted2fdisk");
3297 sprintf(command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
3298 mr_asprintf(tmp, "%s", call_program_and_get_last_line_of_output(command));
3299 if (strstr(tmp, "GPT") == NULL) {
3300 strcpy(output, "MBR");
3301 } else {
3302 strcpy(output, "GPT");
3303 }
3304 mr_free(tmp);
3305
3306 log_msg(0, "Found %s partition table format type", output);
3307 paranoid_free(command);
3308 paranoid_free(fdisk);
3309 return (output);
3310}
3311/* @} - end of deviceGroup */
Note: See TracBrowser for help on using the repository browser.