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

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