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

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