source: MondoRescue/branches/3.0/mondo/src/common/libmondo-devices.c@ 3154

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