source: MondoRescue/branches/3.1/mondo/src/common/libmondo-devices.c@ 3190

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