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

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