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

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