source: MondoRescue/branches/2.2.9/mondo/src/common/libmondo-devices.c@ 2847

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