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

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