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

Last change on this file since 2368 was 2368, checked in by Bruno Cornec, 15 years ago

Fix compilation issue

  • Property svn:keywords set to Id
File size: 70.3 KB
Line 
1/* libmondo-devices.c Subroutines for handling devices
2 $Id: libmondo-devices.c 2368 2009-09-07 13:36:23Z 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 "mondostructures.h"
13#include "libmondo-files-EXT.h"
14#include "libmondo-devices.h"
15#include "lib-common-externs.h"
16#include "libmondo-string-EXT.h"
17#include "libmondo-tools-EXT.h"
18#include "libmondo-gui-EXT.h"
19#include "libmondo-fork-EXT.h"
20#include "libmondo-stream-EXT.h"
21
22#include <sys/types.h>
23#ifdef __FreeBSD__
24#define DKTYPENAMES
25#define FSTYPENAMES
26#include <sys/disklabel.h>
27#include <sys/disk.h>
28#elif linux
29#define u64 unsigned long long
30#include <linux/fs.h> /* for BLKGETSIZE64 */
31#include <linux/hdreg.h>
32#endif
33
34/*@unused@*/
35//static char cvsid[] = "$Id: libmondo-devices.c 2368 2009-09-07 13:36:23Z bruno $";
36
37extern int g_current_media_number;
38extern double g_kernel_version;
39
40extern bool g_ISO_restore_mode;
41extern char *g_selfmounted_isodir;
42extern char *MONDO_LOGFILE;
43
44extern void setup_tmpdir(char *path);
45
46static char g_cdrw_drive_is_here[MAX_STR_LEN / 4] = "";
47static char g_cdrom_drive_is_here[MAX_STR_LEN / 4] = "";
48static char g_dvd_drive_is_here[MAX_STR_LEN / 4] = "";
49
50
51/**
52 * ????? @bug ?????
53 * @ingroup globalGroup
54 */
55bool g_restoring_live_from_cd = FALSE;
56bool g_restoring_live_from_nfs = FALSE;
57
58extern t_bkptype g_backup_media_type; // set by main()
59
60/* Reference to global bkpinfo */
61extern struct s_bkpinfo *bkpinfo;
62
63
64
65
66void set_g_cdrom_and_g_dvd_to_bkpinfo_value()
67{
68 strcpy(g_cdrom_drive_is_here, bkpinfo->media_device); // just in case
69 strcpy(g_dvd_drive_is_here, bkpinfo->media_device); // just in case
70}
71
72
73
74/**
75 * Retract all CD trays and wait for autorun to complete.
76 * @ingroup deviceGroup
77 */
78void retract_CD_tray_and_defeat_autorun(void)
79{
80// log_it("rctada: Retracting all CD trays", __LINE__);
81 if (strlen(g_cdrom_drive_is_here) > 0) {
82 inject_device(g_cdrom_drive_is_here);
83 }
84 if (strlen(g_dvd_drive_is_here) > 0) {
85 inject_device(g_dvd_drive_is_here);
86 }
87 if (strlen(g_cdrw_drive_is_here) > 0) {
88 inject_device(g_cdrw_drive_is_here);
89 }
90// log_it("rctada: killing autorun");
91// run_program_and_log_output("killall autorun", TRUE);
92 if (!run_program_and_log_output("ps | grep autorun | grep -v grep", 5)) {
93 log_it("autorun detected; sleeping for 2 seconds");
94 sleep(2);
95 }
96 log_it("rctada: Unmounting all CD drives", __LINE__);
97 run_program_and_log_output("umount /dev/cdr* /dev/dvd*", 5);
98}
99
100
101
102/**
103 * Determine whether we're booted off a ramdisk.
104 * @return @c TRUE (we are) or @c FALSE (we aren't).
105 * @ingroup utilityGroup
106 */
107bool am_I_in_disaster_recovery_mode(void)
108{
109 char *tmp = NULL;
110 char *comment;
111 bool is_this_a_ramdisk = FALSE;
112
113 malloc_string(comment);
114 mr_asprintf(&tmp, "%s", where_is_root_mounted());
115 sprintf(comment, "root is mounted at %s\n", tmp);
116 log_msg(0, comment);
117 log_msg(0,
118 "No, Schlomo, that doesn't mean %s is the root partition. It's just a debugging message. Relax. It's part of am_I_in_disaster_recovery_mode().",
119 tmp);
120
121#ifdef __FreeBSD__
122 if (strstr(tmp, "/dev/md")) {
123 is_this_a_ramdisk = TRUE;
124 }
125#else
126 if (!strncmp(tmp, "/dev/ram", 8)
127 || (!strncmp(tmp, "/dev/rd", 7) && !strcmp(tmp, "/dev/rd/")
128 && strncmp(tmp, "/dev/rd/cd", 10)) || strstr(tmp, "rootfs")
129 || !strcmp(tmp, "/dev/root")) {
130 is_this_a_ramdisk = TRUE;
131 } else {
132 is_this_a_ramdisk = FALSE;
133 }
134#endif
135 mr_free(tmp);
136
137 if (is_this_a_ramdisk) {
138 if (!does_file_exist("/THIS-IS-A-RAMDISK")) {
139 log_to_screen
140 ("Using /dev/root is stupid of you but I'll forgive you.");
141 is_this_a_ramdisk = FALSE;
142 }
143 }
144 if (does_file_exist("/THIS-IS-A-RAMDISK")) {
145 is_this_a_ramdisk = TRUE;
146 }
147 paranoid_free(comment);
148 log_msg(1, "Is this a ramdisk? result = %d", is_this_a_ramdisk);
149 return (is_this_a_ramdisk);
150}
151
152
153
154
155
156/**
157 * Turn @c bkpinfo->backup_media_type into a human-readable string.
158 * @return The human readable string (e.g. @c cdr becomes <tt>"cdr"</tt>).
159 * @note The returned string points to static storage that will be overwritten with each call.
160 * @ingroup stringGroup
161 */
162static char *bkptype_to_string(t_bkptype bt)
163{
164 static char output[MAX_STR_LEN / 4];
165 switch (bt) {
166 case none:
167 strcpy(output, "none");
168 break;
169 case iso:
170 strcpy(output, "iso");
171 break;
172 case cdr:
173 strcpy(output, "cdr");
174 break;
175 case cdrw:
176 strcpy(output, "cdrw");
177 break;
178 case cdstream:
179 strcpy(output, "cdstream");
180 break;
181 case nfs:
182 strcpy(output, "nfs");
183 break;
184 case tape:
185 strcpy(output, "tape");
186 break;
187 case udev:
188 strcpy(output, "udev");
189 break;
190 case usb:
191 strcpy(output, "usb");
192 break;
193 default:
194 strcpy(output, "default");
195 }
196 return (output);
197}
198
199
200
201/**
202 * @addtogroup deviceGroup
203 * @{
204 */
205/**
206 * Eject the tray of the specified CD device.
207 * @param dev The device to eject.
208 * @return the return value of the @c eject command. (0=success, nonzero=failure)
209 */
210int eject_device(char *dev)
211{
212 char *command;
213 int res1 = 0, res2 = 0;
214
215 malloc_string(command);
216
217 if (IS_THIS_A_STREAMING_BACKUP(g_backup_media_type)
218 && g_backup_media_type != udev) {
219 sprintf(command, "mt -f %s offline", dev);
220 res1 = run_program_and_log_output(command, 1);
221 } else {
222 res1 = 0;
223 }
224
225#ifdef __FreeBSD__
226 if (strstr(dev, "acd")) {
227 sprintf(command, "cdcontrol -f %s eject", dev);
228 } else {
229 sprintf(command, "camcontrol eject `echo %s | sed 's|/dev/||'`",
230 dev);
231 }
232#else
233 sprintf(command, "eject %s", dev);
234#endif
235
236 log_msg(3, "Ejecting %s", dev);
237 res2 = run_program_and_log_output(command, 1);
238 paranoid_free(command);
239 if (res1 && res2) {
240 return (1);
241 } else {
242 return (0);
243 }
244}
245
246/**
247 * Load (inject) the tray of the specified CD device.
248 * @param dev The device to load/inject.
249 * @return 0 for success, nonzero for failure.
250 */
251int inject_device(char *dev)
252{
253 char *command;
254 int i;
255
256 malloc_string(command);
257
258
259#ifdef __FreeBSD__
260 if (strstr(dev, "acd")) {
261 sprintf(command, "cdcontrol -f %s close", dev);
262 } else {
263 sprintf(command, "camcontrol load `echo %s | sed 's|/dev/||'`",
264 dev);
265 }
266#else
267 sprintf(command, "eject -t %s", dev);
268#endif
269 i = run_program_and_log_output(command, FALSE);
270 paranoid_free(command);
271 return (i);
272}
273
274
275/**
276 * Determine whether the specified @p device (really, you can use any file)
277 * exists.
278 * @return TRUE if it exists, FALSE if it doesn't.
279 */
280bool does_device_exist(char *device)
281{
282
283 /*@ buffers *********************************************************** */
284 char *tmp;
285 bool ret;
286
287 malloc_string(tmp);
288 assert_string_is_neither_NULL_nor_zerolength(device);
289
290 sprintf(tmp, "ls %s > /dev/null 2> /dev/null", device);
291
292 if (system(tmp)) {
293 ret = FALSE;
294 } else {
295 ret = TRUE;
296 }
297 paranoid_free(tmp);
298 return (ret);
299}
300
301
302/**
303 * Determine whether a non-Microsoft partition exists on any connected hard drive.
304 * @return TRUE (there's a Linux/FreeBSD partition) or FALSE (Microsoft has taken over yet another innocent PC).
305 */
306bool does_nonMS_partition_exist(void)
307{
308#if __FreeBSD__
309 return
310 !system
311 ("for drive in /dev/ad? /dev/da?; do fdisk $drive | grep -q FreeBSD && exit 0; done; false");
312#else
313 return
314 !system
315 ("parted2fdisk -l 2>/dev/null | grep '^/dev/' | grep -Eqv '(MS|DOS|FAT|NTFS)'");
316#endif
317}
318
319/**
320 * Determine whether the specified @p partno exists on the specified @p drive.
321 * @param drive The drive to search for the partition in.
322 * @param partno The partition number to look for.
323 * @return 0 if it exists, nonzero otherwise.
324 */
325int does_partition_exist(const char *drive, int partno)
326{
327 /*@ buffers **************************************************** */
328 char *program;
329 char *incoming;
330 char *searchstr = NULL;
331 char *tmp;
332
333 /*@ ints ******************************************************* */
334 int res = 0;
335
336 /*@ pointers *************************************************** */
337 FILE *fin;
338
339
340 /*@ end vars *************************************************** */
341 assert_string_is_neither_NULL_nor_zerolength(drive);
342 assert(partno >= 0 && partno < 999);
343
344 malloc_string(program);
345 malloc_string(incoming);
346 malloc_string(searchstr);
347 malloc_string(tmp);
348
349#ifdef __FreeBSD__
350 // We assume here that this is running from mondorestore. (It is.)
351 sprintf(program, "ls %s %s >/dev/null 2>&1", drive,
352 build_partition_name(tmp, drive, partno));
353 return system(program);
354#else
355 tmp[0] = '\0';
356#endif
357
358 sprintf(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 return (0);
364 }
365 (void) build_partition_name(searchstr, drive, partno);
366 strcat(searchstr, " ");
367 for (res = 0; !res && fgets(incoming, MAX_STR_LEN - 1, fin);) {
368 if (strstr(incoming, searchstr)) {
369 res = 1;
370 }
371 }
372 if (pclose(fin)) {
373 log_OS_error("Cannot pclose fin");
374 }
375 paranoid_free(program);
376 paranoid_free(incoming);
377 paranoid_free(searchstr);
378 paranoid_free(tmp);
379 return (res);
380}
381
382
383
384
385
386/**
387 * Determine whether given NULL-terminated @p str exists in the MBR of @p dev.
388 * @param dev The device to look in.
389 * @param str The string to look for.
390 * @return TRUE if it exists, FALSE if it doesn't.
391 */
392bool does_string_exist_in_boot_block(char *dev, char *str)
393{
394 /*@ buffers **************************************************** */
395 char *command;
396
397 /*@ end vars *************************************************** */
398 int i;
399
400 assert_string_is_neither_NULL_nor_zerolength(dev);
401 assert_string_is_neither_NULL_nor_zerolength(str);
402
403 malloc_string(command);
404 sprintf(command,
405 "dd if=%s bs=446 count=1 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null",
406 dev, str);
407 i = system(command);
408 paranoid_free(command);
409 if (i) {
410 return (FALSE);
411 } else {
412 return (TRUE);
413 }
414}
415
416/**
417 * Determine whether specified @p str exists in the first @p n sectors of
418 * @p dev.
419 * @param dev The device to look in.
420 * @param str The string to look for.
421 * @param n The number of 512-byte sectors to search.
422 */
423bool does_string_exist_in_first_N_blocks(char *dev, char *str, int n)
424{
425 /*@ buffers **************************************************** */
426 char *command;
427 /*@ end vars *************************************************** */
428 int i;
429
430 malloc_string(command);
431 sprintf(command,
432 "dd if=%s bs=512 count=%i 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null",
433 dev, n, str);
434 i = system(command);
435 paranoid_free(command);
436 if (i) {
437 return (FALSE);
438 } else {
439 return (TRUE);
440 }
441}
442
443
444
445/**
446 * Try to mount CD-ROM at @p mountpoint. If the CD-ROM is not found or has
447 * not been specified, call find_cdrom_device() to find it.
448 * @param bkpinfo The backup information structure. The only field used is @c bkpinfo->media_device.
449 * @param mountpoint Where to mount the CD-ROM.
450 * @return 0 for success, nonzero for failure.
451 * @see mount_CDROM_here
452 */
453int find_and_mount_actual_cd(char *mountpoint)
454{
455 /*@ buffers ***************************************************** */
456
457 /*@ int's ****************************************************** */
458 int res;
459 char *dev;
460
461 /*@ end vars **************************************************** */
462
463 malloc_string(dev);
464 assert(bkpinfo != NULL);
465 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
466
467 if (g_backup_media_type == dvd) {
468 strcpy(dev, g_dvd_drive_is_here);
469 if (!dev[0]) {
470 find_dvd_device(dev, FALSE);
471 }
472 } else {
473 strcpy(dev, g_cdrom_drive_is_here);
474 if (!dev[0]) {
475 find_cdrom_device(dev, FALSE);
476 }
477 }
478
479 if (bkpinfo->backup_media_type != iso) {
480 retract_CD_tray_and_defeat_autorun();
481 }
482
483 if (!dev[0] || (res = mount_CDROM_here(dev, mountpoint))) {
484 if (!popup_and_get_string
485 ("CD-ROM device", "Please enter your CD-ROM's /dev device",
486 dev, MAX_STR_LEN / 4)) {
487 res = 1;
488 } else {
489 res = mount_CDROM_here(dev, mountpoint);
490 }
491 }
492 if (res) {
493 log_msg(1, "mount failed");
494 } else {
495 log_msg(1, "mount succeeded with %s", dev);
496 }
497 paranoid_free(dev);
498 return (res);
499}
500
501
502
503
504
505
506/**
507 * Locate a CD-R/W writer's SCSI node.
508 * @param cdrw_device SCSI node will be placed here.
509 * @return 0 for success, nonzero for failure.
510 */
511int find_cdrw_device(char *cdrw_device)
512{
513 /*@ buffers ************************ */
514 char *comment;
515 char *tmp = NULL;
516 char *cdr_exe = NULL;
517 char *command;
518
519 malloc_string(comment);
520 malloc_string(command);
521 if (g_cdrw_drive_is_here[0]) {
522 strcpy(cdrw_device, g_cdrw_drive_is_here);
523 log_msg(3, "Been there, done that. Returning %s", cdrw_device);
524 paranoid_free(comment);
525 paranoid_free(command);
526 return (0);
527 }
528 if (g_backup_media_type == dvd) {
529 log_msg(1,
530 "This is dumb. You're calling find_cdrw_device() but you're backing up to DVD. WTF?");
531 paranoid_free(comment);
532 paranoid_free(command);
533 return (1);
534 }
535 run_program_and_log_output("insmod ide-scsi", -1);
536 if (find_home_of_exe("cdrecord")) {
537 mr_asprintf(&cdr_exe, "cdrecord");
538 } else {
539 mr_asprintf(&cdr_exe, "dvdrecord");
540 }
541 if (find_home_of_exe(cdr_exe)) {
542 sprintf(command,
543 "%s -scanbus 2> /dev/null | tr -s '\t' ' ' | grep \"[0-9]*,[0-9]*,[0-9]*\" | grep -v \"[0-9]*) \\*\" | grep CD | cut -d' ' -f2 | head -n1",
544 cdr_exe);
545 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
546 }
547 if ((tmp == NULL) || (strlen(tmp) < 2)) {
548 paranoid_free(comment);
549 mr_free(tmp);
550 mr_free(cdr_exe);
551 paranoid_free(command);
552 return 1;
553 } else {
554 strcpy(cdrw_device, tmp);
555 sprintf(comment, "Found CDRW device - %s", cdrw_device);
556 log_it(comment);
557 strcpy(g_cdrw_drive_is_here, cdrw_device);
558 paranoid_free(comment);
559 mr_free(tmp);
560 mr_free(cdr_exe);
561 paranoid_free(command);
562 return (0);
563 }
564}
565
566
567
568
569/**
570 * Attempt to locate a CD-ROM device's /dev entry.
571 * Several different methods may be used to find the device, including
572 * calling @c cdrecord, searching @c dmesg, and trial-and-error.
573 * @param output Where to put the located /dev entry.
574 * @param try_to_mount Whether to mount the CD as part of the test; if mount
575 * fails then return failure.
576 * @return 0 for success, nonzero for failure.
577 */
578int find_cdrom_device(char *output, bool try_to_mount)
579{
580 /*@ pointers **************************************************** */
581 FILE *fin;
582 char *p;
583 char *q;
584 char *r;
585 int retval = 0;
586
587 /*@ bool's ****************************************************** */
588 bool found_it = FALSE;
589
590 /*@ buffers ***************************************************** */
591 char *tmp;
592 char *tmp1 = NULL;
593 char *cdr_exe = NULL;
594 char *phrase_one;
595 char *phrase_two;
596 char *command;
597 char *dvd_last_resort;
598 char *mountpoint;
599 static char the_last_place_i_found_it[MAX_STR_LEN] = "";
600
601 /*@ intialize *************************************************** */
602 malloc_string(tmp);
603 malloc_string(phrase_one);
604 malloc_string(phrase_two);
605 malloc_string(command);
606 malloc_string(dvd_last_resort);
607 malloc_string(mountpoint);
608
609 output[0] = '\0';
610 phrase_one[0] = '\0';
611 phrase_two[0] = '\0';
612 dvd_last_resort[0] = '\0';
613
614 /*@ end vars **************************************************** */
615
616 if (g_cdrom_drive_is_here[0] && !isdigit(g_cdrom_drive_is_here[0])) {
617 strcpy(output, g_cdrom_drive_is_here);
618 log_msg(3, "Been there, done that. Returning %s", output);
619 retval = 0;
620 goto end_of_find_cdrom_device;
621 }
622 if (the_last_place_i_found_it[0] != '\0' && !try_to_mount) {
623 strcpy(output, the_last_place_i_found_it);
624 log_msg(3,
625 "find_cdrom_device() --- returning last found location - '%s'",
626 output);
627 retval = 0;
628 goto end_of_find_cdrom_device;
629 }
630
631 sprintf(mountpoint, "%s/cd.mnt", bkpinfo->tmpdir);
632 make_hole_for_dir(mountpoint);
633
634 if (find_home_of_exe("cdrecord")) {
635 mr_asprintf(&cdr_exe, "cdrecord");
636 } else {
637 mr_asprintf(&cdr_exe, "dvdrecord");
638 }
639 tmp[0] = '\0';
640 if (!find_home_of_exe(cdr_exe)) {
641 strcpy(output, "/dev/cdrom");
642 log_msg(4, "Can't find cdrecord; assuming %s", output);
643 if (!does_device_exist(output)) {
644 log_msg(4, "That didn't work. Sorry.");
645 retval = 1;
646 goto end_of_find_cdrom_device;
647 } else {
648 retval = 0;
649 goto end_of_find_cdrom_device;
650 }
651 }
652
653 sprintf(command, "%s -scanbus 2> /dev/null", cdr_exe);
654 fin = popen(command, "r");
655 if (!fin) {
656 log_msg(4, "command=%s", command);
657 log_OS_error("Cannot popen command");
658 mr_free(cdr_exe);
659 return (1);
660 }
661 for ((void)fgets(tmp, MAX_STR_LEN, fin); !feof(fin);
662 (void)fgets(tmp, MAX_STR_LEN, fin)) {
663 p = strchr(tmp, '\'');
664 if (p) {
665 q = strchr(++p, '\'');
666 if (q) {
667 for (r = q; *(r - 1) == ' '; r--);
668 *r = '\0';
669 strcpy(phrase_one, p);
670 p = strchr(++q, '\'');
671 if (p) {
672 q = strchr(++p, '\'');
673 if (q) {
674 while (*(q - 1) == ' ') {
675 q--;
676 }
677 *q = '\0';
678 strcpy(phrase_two, p);
679 }
680 }
681 }
682 }
683 }
684 paranoid_pclose(fin);
685
686#ifndef __FreeBSD__
687 if (strlen(phrase_two) == 0) {
688 log_msg(4, "Not running phase two. String is empty.");
689 } else {
690 sprintf(command, "dmesg | grep \"%s\" 2> /dev/null", phrase_two);
691 fin = popen(command, "r");
692 if (!fin) {
693 log_msg(4, "Cannot run 2nd command - non-fatal, fortunately");
694 } else {
695 for ((void)fgets(tmp, MAX_STR_LEN, fin); !feof(fin);
696 (void)fgets(tmp, MAX_STR_LEN, fin)) {
697 log_msg(5, "--> '%s'", tmp);
698 if (tmp[0] != ' ' && tmp[1] != ' ') {
699 p = strchr(tmp, ':');
700 if (p) {
701 *p = '\0';
702 if (strstr(tmp, "DVD")) {
703 sprintf(dvd_last_resort, "/dev/%s", tmp);
704 log_msg(4,
705 "Ignoring '%s' because it's a DVD drive",
706 tmp);
707 } else {
708 sprintf(output, "/dev/%s", tmp);
709 found_it = TRUE;
710 }
711 }
712 }
713 }
714 paranoid_pclose(fin);
715 }
716 }
717
718#endif
719#ifdef __FreeBSD__
720 if (!found_it) {
721 log_msg(4, "OK, approach 2");
722 if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/cdrom"))) {
723 if (!
724 (found_it =
725 set_dev_to_this_if_rx_OK(output, "/dev/cdrom1"))) {
726 if (!
727 (found_it =
728 set_dev_to_this_if_rx_OK(output, "/dev/dvd"))) {
729 if (!
730 (found_it =
731 set_dev_to_this_if_rx_OK(output, "/dev/acd0"))) {
732 if (!
733 (found_it =
734 set_dev_to_this_if_rx_OK(output,
735 "/dev/cd01"))) {
736 if (!
737 (found_it =
738 set_dev_to_this_if_rx_OK(output,
739 "/dev/acd1"))) {
740 if (!
741 (found_it =
742 set_dev_to_this_if_rx_OK(output,
743 "/dev/cd1")))
744 {
745 retval = 1;
746 goto end_of_find_cdrom_device;
747 }
748 }
749 }
750 }
751 }
752 }
753 }
754 }
755#else
756 if (!found_it && strlen(dvd_last_resort) > 0) {
757 log_msg(4, "Well, I'll use the DVD - %s - as a last resort",
758 dvd_last_resort);
759 strcpy(output, dvd_last_resort);
760 found_it = TRUE;
761 }
762 if (found_it) {
763 sprintf(tmp, "grep \"%s=ide-scsi\" /proc/cmdline &> /dev/null",
764 strrchr(output, '/') + 1);
765 if (system(tmp) == 0) {
766 log_msg(4,
767 "%s is not right. It's being SCSI-emulated. Continuing.",
768 output);
769 found_it = FALSE;
770 output[0] = '\0';
771 }
772 }
773
774 if (found_it) {
775 log_msg(4, "(find_cdrom_device) --> '%s'", output);
776 if (!does_device_exist(output)) {
777 found_it = FALSE;
778 log_msg(4, "OK, I was wrong, I haven't found it... yet.");
779 }
780 }
781
782 if (!found_it) {
783 log_msg(4, "OK, approach 2");
784 if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/scd0"))) {
785 if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/sr0"))) {
786 if (!
787 (found_it =
788 set_dev_to_this_if_rx_OK(output, "/dev/cdrom"))) {
789 if (!
790 (found_it =
791 set_dev_to_this_if_rx_OK(output,
792 "/dev/cdrom0"))) {
793 if (!
794 (found_it =
795 set_dev_to_this_if_rx_OK(output,
796 "/dev/cdrom1"))) {
797 if (!
798 (found_it =
799 set_dev_to_this_if_rx_OK(output,
800 "/dev/sr1"))) {
801 if (!
802 (found_it =
803 set_dev_to_this_if_rx_OK(output,
804 "/dev/dvd")))
805 {
806 if (!
807 (found_it =
808 set_dev_to_this_if_rx_OK(output,
809 g_cdrw_drive_is_here)))
810 {
811 retval = 1;
812 goto end_of_find_cdrom_device;
813 }
814 }
815 }
816 }
817 }
818 }
819 }
820 }
821 }
822#endif
823
824 if (found_it && try_to_mount) {
825 if (mount_CDROM_here(output, mountpoint)) {
826 log_msg(4, "[Cardigans] I've changed my mind");
827 found_it = FALSE;
828 } else {
829 sprintf(tmp, "%s/archives", mountpoint);
830 if (!does_file_exist(tmp)) {
831 log_msg(4, "[Cardigans] I'll take it back");
832 found_it = FALSE;
833 } else {
834 sprintf(command, "umount %s", output);
835 paranoid_system(command);
836 log_msg(4, "I'm confident the Mondo CD is in %s", output);
837 }
838 }
839 }
840 unlink(mountpoint);
841
842 if (found_it) {
843 if (!does_file_exist(output)) {
844 log_msg(3, "I still haven't found it.");
845 return (1);
846 }
847 log_msg(3, "(find_cdrom_device) --> '%s'", output);
848 strcpy(the_last_place_i_found_it, output);
849 strcpy(g_cdrom_drive_is_here, output);
850 retval = 0;
851 goto end_of_find_cdrom_device;
852 }
853
854 sprintf(command,
855 "%s -scanbus | grep \"[0-9],[0-9],[0-9]\" | grep \"[D|C][V|D]\" | grep -n \"\" | grep \"%s\" | cut -d':' -f2",
856 cdr_exe, g_cdrw_drive_is_here);
857 log_msg(1, "command=%s", command);
858 mr_asprintf(&tmp1, "%s", call_program_and_get_last_line_of_output(command));
859 if (strlen(tmp1) > 0) {
860 strcpy(output, tmp1);
861 log_msg(4, "Finally found it at %s", output);
862 retval = 0;
863 } else {
864 log_msg(4, "Still couldn't find it.");
865 retval = 1;
866 }
867 mr_free(tmp1);
868
869 end_of_find_cdrom_device:
870 paranoid_free(tmp);
871 mr_free(cdr_exe);
872 paranoid_free(phrase_one);
873 paranoid_free(phrase_two);
874 paranoid_free(command);
875 paranoid_free(dvd_last_resort);
876 paranoid_free(mountpoint);
877 return (retval);
878}
879
880
881
882
883
884int find_dvd_device(char *output, bool try_to_mount)
885{
886 char *command;
887 char *tmp;
888 int retval = 0, devno = -1;
889
890 malloc_string(command);
891 malloc_string(tmp);
892
893 if (g_dvd_drive_is_here[0]) {
894 strcpy(output, g_dvd_drive_is_here);
895 log_msg(3, "Been there, done that. Returning %s", output);
896 return (0);
897 }
898
899 sprintf(tmp, "%s", call_program_and_get_last_line_of_output
900 ("dvdrecord -scanbus 2> /dev/null | grep \") '\" | grep -n \"\" | grep DVD | cut -d':' -f1")
901 );
902 log_msg(5, "tmp = '%s'", tmp);
903 if (!tmp[0])
904 sprintf(tmp, "%s", call_program_and_get_last_line_of_output
905 ("cdrecord -scanbus 2> /dev/null | grep \") '\" | grep -n \"\" | grep DVD | cut -d':' -f1")
906 );
907 if (tmp[0]) {
908 devno = atoi(tmp) - 1;
909 }
910 if (devno >= 0) {
911 retval = 0;
912 sprintf(output, "/dev/scd%d", devno);
913 strcpy(g_dvd_drive_is_here, output);
914 log_msg(2, "I think DVD is at %s", output);
915 } else {
916 log_msg(2, "I cannot find DVD");
917 retval = 1;
918 }
919
920 if (try_to_mount) {
921 log_msg(1, "Ignoring the fact that try_to_mount==TRUE");
922 }
923 return (retval);
924}
925
926
927
928
929
930#include <sys/ioctl.h>
931
932/**
933 * Find the size of the specified @p drive, in megabytes. Uses @c ioctl calls
934 * and @c dmesg.
935 * @param drive The device to find the size of.
936 * @return size in megabytes.
937 */
938long get_phys_size_of_drive(char *drive)
939{
940 int fd;
941#if linux
942 unsigned long long s = 0;
943 int fileid, cylinders = 0, cylindersleft = 0;
944 int cylindersize = 0;
945 int gotgeo = 0;
946
947
948 struct hd_geometry hdgeo;
949#elif __FreeBSD__
950 off_t s;
951#endif
952
953 long outvalA = -1;
954 long outvalB = -1;
955 long outvalC = -1;
956
957 if ((fd = open(drive, O_RDONLY)) != -1) {
958 if (ioctl(fd,
959#if linux
960#ifdef BLKGETSIZE64
961 BLKGETSIZE64,
962#else
963 BLKGETSIZE,
964#endif
965#elif __FreeBSD__
966 DIOCGMEDIASIZE,
967#endif
968 &s) != -1) {
969 close(fd);
970 // s>>11 works for older disks but not for newer ones
971 outvalB =
972#if linux
973#ifdef BLKGETSIZE64
974 s >> 20
975#else
976 s >> 11
977#endif
978#else
979 s >> 20
980#endif
981 ;
982 }
983 }
984
985 if (outvalB <= 0) {
986 log_msg(1, "Error getting size of %s: %s", drive, strerror(errno));
987#if linux
988 fileid = open(drive, O_RDONLY);
989 if (fileid != -1) {
990 if (ioctl(fileid, HDIO_GETGEO, &hdgeo) != -1) {
991 if (hdgeo.cylinders && hdgeo.heads && hdgeo.sectors) {
992 cylindersleft = cylinders = hdgeo.cylinders;
993 cylindersize = hdgeo.heads * hdgeo.sectors / 2;
994 outvalA = cylindersize * cylinders / 1024;
995 log_msg(2, "Got Harddisk geometry, C:%d, H:%d, S:%d",
996 hdgeo.cylinders, hdgeo.heads, hdgeo.sectors);
997 gotgeo = 1;
998 } else {
999 log_msg(1, "Harddisk geometry wrong");
1000 }
1001 } else {
1002 log_msg(1,
1003 "Error in ioctl() getting new hard disk geometry (%s), resizing in unsafe mode",
1004 strerror(errno));
1005 }
1006 close(fileid);
1007 } else {
1008 log_msg(1, "Failed to open %s for reading: %s", drive,
1009 strerror(errno));
1010 }
1011 if (!gotgeo) {
1012 log_msg(1, "Failed to get harddisk geometry, using old mode");
1013 }
1014#endif
1015 }
1016// OLDER DISKS will give ridiculously low value for outvalB (so outvalA is returned) :)
1017// NEWER DISKS will give sane value for outvalB (close to outvalA, in other words) :)
1018
1019 outvalC = (outvalA > outvalB) ? outvalA : outvalB;
1020
1021// log_msg (5, "drive = %s, error = %s", drive, strerror (errno));
1022// fatal_error ("GPSOD: Unable to get size of drive");
1023 log_msg(1, "%s --> %ld or %ld --> %ld", drive, outvalA, outvalB,
1024 outvalC);
1025
1026 return (outvalC);
1027}
1028
1029/**
1030 * Determine whether @p format is supported by the kernel. Uses /proc/filesystems
1031 * under Linux and @c lsvfs under FreeBSD.
1032 * @param format The format to test.
1033 * @return TRUE if the format is supported, FALSE if not.
1034 */
1035bool is_this_a_valid_disk_format(char *format)
1036{
1037 char *good_formats = NULL;
1038 char *command;
1039 char *format_sz;
1040
1041 FILE *pin;
1042 int retval;
1043 malloc_string(good_formats);
1044 malloc_string(command);
1045 malloc_string(format_sz);
1046
1047 assert_string_is_neither_NULL_nor_zerolength(format);
1048
1049 sprintf(format_sz, "%s ", format);
1050
1051#ifdef __FreeBSD__
1052 sprintf(command,
1053 "lsvfs | tr -s '\t' ' ' | grep -v Filesys | grep -v -- -- | cut -d' ' -f1 | tr -s '\n' ' '");
1054#else
1055 sprintf(command,
1056 "grep -v nodev /proc/filesystems | tr -s '\t' ' ' | cut -d' ' -f2 | tr -s '\n' ' '");
1057#endif
1058
1059 pin = popen(command, "r");
1060 if (!pin) {
1061 log_OS_error("Unable to read good formats");
1062 retval = 0;
1063 } else {
1064 strcpy(good_formats, " ");
1065 (void) fgets(good_formats + 1, MAX_STR_LEN - 1, pin);
1066 if (pclose(pin)) {
1067 log_OS_error("Cannot pclose good formats");
1068 }
1069 strip_spaces(good_formats);
1070 strcat(good_formats, " swap lvm raid ntfs-3g ntfs 7 "); // " ntfs 7 " -- um, cheating much? :)
1071 if (strstr(good_formats, format_sz)) {
1072 retval = 1;
1073 } else {
1074 retval = 0;
1075 }
1076 }
1077 paranoid_free(good_formats);
1078 paranoid_free(command);
1079 paranoid_free(format_sz);
1080 return (retval);
1081}
1082
1083
1084/** @def SWAPLIST_COMMAND The command to list the swap files/partitions in use. */
1085
1086/**
1087 * Determine whether @p device_raw is currently mounted.
1088 * @param device_raw The device to check.
1089 * @return TRUE if it's mounted, FALSE if not.
1090 */
1091bool is_this_device_mounted(char *device_raw)
1092{
1093
1094 /*@ pointers **************************************************** */
1095 FILE *fin;
1096
1097 /*@ buffers ***************************************************** */
1098 char *incoming;
1099 char *device_with_tab = NULL;
1100 char *device_with_space = NULL;
1101 char *tmp = NULL;
1102 bool retval = FALSE;
1103
1104#ifdef __FreeBSD__
1105#define SWAPLIST_COMMAND "swapinfo"
1106#else
1107#define SWAPLIST_COMMAND "cat /proc/swaps"
1108#endif
1109
1110 /*@ end vars **************************************************** */
1111
1112 malloc_string(incoming);
1113 assert(device_raw != NULL);
1114// assert_string_is_neither_NULL_nor_zerolength(device_raw);
1115 if (device_raw[0] != '/' && !strstr(device_raw, ":/")) {
1116 log_msg(1, "%s needs to have a '/' prefixed - I'll do it",
1117 device_raw);
1118 mr_asprintf(&tmp, "/%s", device_raw);
1119 } else {
1120 mr_asprintf(&tmp, "%s", device_raw);
1121 }
1122 log_msg(1, "Is %s mounted?", tmp);
1123 if (!strcmp(tmp, "/proc") || !strcmp(tmp, "proc")) {
1124 log_msg(1,
1125 "I don't know how the heck /proc made it into the mountlist. I'll ignore it.");
1126 mr_free(tmp);
1127 return(FALSE);
1128 }
1129 mr_asprintf(&device_with_tab, "%s\t", tmp);
1130 mr_asprintf(&device_with_space, "%s ", tmp);
1131 mr_free(tmp);
1132
1133 if (!(fin = popen("mount", "r"))) {
1134 log_OS_error("Cannot popen 'mount'");
1135 return(FALSE);
1136 }
1137 for ((void)fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin);
1138 (void)fgets(incoming, MAX_STR_LEN - 1, fin)) {
1139 if (strstr(incoming, device_with_space) //> incoming
1140 || strstr(incoming, device_with_tab)) // > incoming)
1141 {
1142 paranoid_pclose(fin);
1143 paranoid_free(incoming);
1144 return(TRUE);
1145 }
1146 }
1147 mr_free(device_with_tab);
1148 mr_free(device_with_space);
1149 paranoid_pclose(fin);
1150 mr_asprintf(&tmp, "%s | grep -E \"^%s\" > /dev/null 2> /dev/null", SWAPLIST_COMMAND, device_with_space);
1151 log_msg(4, "tmp (command) = '%s'", tmp);
1152 if (!system(tmp)) {
1153 retval = TRUE;
1154 }
1155 mr_free(tmp);
1156 paranoid_free(incoming);
1157 return(retval);
1158}
1159
1160#ifdef __FreeBSD__
1161// CODE IS FREEBSD-SPECIFIC
1162/**
1163 * Create a loopback device for specified @p fname.
1164 * @param fname The file to associate with a device.
1165 * @return /dev entry for the device, or NULL if it couldn't be allocated.
1166 */
1167char *make_vn(char *fname)
1168{
1169 char *device = (char *) malloc(MAX_STR_LEN);
1170 char *mddevice = (char *) malloc(32);
1171 char command[MAX_STR_LEN];
1172 int vndev = 2;
1173 if (atoi
1174 (call_program_and_get_last_line_of_output
1175 ("/sbin/sysctl -n kern.osreldate")) < 500000) {
1176 do {
1177 sprintf(mddevice, "vn%ic", vndev++);
1178 sprintf(command, "vnconfig %s %s", mddevice, fname);
1179 if (vndev > 10) {
1180 return NULL;
1181 }
1182 }
1183 while (system(command));
1184 } else {
1185 sprintf(command, "mdconfig -a -t vnode -f %s", fname);
1186 mddevice = call_program_and_get_last_line_of_output(command);
1187 if (!strstr(mddevice, "md")) {
1188 return NULL;
1189 }
1190 }
1191 sprintf(device, "/dev/%s", mddevice);
1192 return device;
1193}
1194
1195
1196
1197// CODE IS FREEBSD-SPECIFIC
1198/**
1199 * Deallocate specified @p dname.
1200 * This should be called when you are done with the device created by make_vn(),
1201 * so the system does not run out of @c vn devices.
1202 * @param dname The device to deallocate.
1203 * @return 0 for success, nonzero for failure.
1204 */
1205int kick_vn(char *dname)
1206{
1207 char command[MAX_STR_LEN];
1208
1209 if (strncmp(dname, "/dev/", 5) == 0) {
1210 dname += 5;
1211 }
1212
1213 if (atoi
1214 (call_program_and_get_last_line_of_output
1215 ("/sbin/sysctl -n kern.osreldate")) < 500000) {
1216 sprintf(command, "vnconfig -d %s", dname);
1217 return system(command);
1218 } else {
1219 sprintf(command, "mdconfig -d -u %s", dname);
1220 return system(command);
1221 }
1222 /*NOTREACHED*/ return 255;
1223}
1224#endif
1225
1226
1227/**
1228 * Mount the CD-ROM at @p mountpoint.
1229 * @param device The device (or file if g_ISO_restore_mode) to mount.
1230 * @param mountpoint The place to mount it.
1231 * @return 0 for success, nonzero for failure.
1232 */
1233int mount_USB_here(char *device, char *mountpoint)
1234{
1235 /*@ buffer ****************************************************** */
1236 char *command;
1237 int retval;
1238
1239 malloc_string(command);
1240 assert_string_is_neither_NULL_nor_zerolength(device);
1241 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
1242
1243 make_hole_for_dir(mountpoint);
1244 if (isdigit(device[0])) {
1245 return(1);
1246 }
1247 log_msg(4, "(mount_USB_here --- device=%s, mountpoint=%s", device,
1248 mountpoint);
1249
1250#ifdef __FreeBSD__
1251 sprintf(command, "mount_vfat %s %s 2>> %s",
1252 device, mountpoint, MONDO_LOGFILE);
1253
1254#else
1255 sprintf(command, "mount %s -t vfat %s 2>> %s",
1256 device, mountpoint, MONDO_LOGFILE);
1257#endif
1258
1259 log_msg(4, command);
1260 retval = system(command);
1261 log_msg(1, "system(%s) returned %d", command, retval);
1262
1263 paranoid_free(command);
1264 return (retval);
1265}
1266
1267/**
1268 * Mount the CD-ROM at @p mountpoint.
1269 * @param device The device (or file if g_ISO_restore_mode) to mount.
1270 * @param mountpoint The place to mount it.
1271 * @return 0 for success, nonzero for failure.
1272 */
1273int mount_CDROM_here(char *device, char *mountpoint)
1274{
1275 /*@ buffer ****************************************************** */
1276 char *command = NULL;
1277 int retval;
1278#ifdef __FreeBSD__
1279 char *dev = NULL;
1280#else
1281 char *options = NULL;
1282#endif
1283
1284 assert_string_is_neither_NULL_nor_zerolength(device);
1285 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
1286
1287 make_hole_for_dir(mountpoint);
1288
1289 if (isdigit(device[0])) {
1290 find_cdrom_device(device, FALSE);
1291 }
1292#ifndef __FreeBSD__
1293 mr_asprintf(&options, "ro");
1294#endif
1295
1296 if (g_ISO_restore_mode) {
1297
1298#ifdef __FreeBSD__
1299 mr_asprintf(&dev, "%s", make_vn(device));
1300 if (!dev) {
1301 mr_asprintf(&command, "Unable to mount ISO (make_vn(%s) failed)", device);
1302 fatal_error(command);
1303 }
1304 strcpy(device, dev);
1305 paranoid_free(dev);
1306#else
1307 mr_strcat(options, ",loop");
1308#endif
1309
1310 }
1311 log_msg(4, "(mount_CDROM_here --- device=%s, mountpoint=%s", device,
1312 mountpoint);
1313 /*@ end vars *************************************************** */
1314
1315#ifdef __FreeBSD__
1316 mr_asprintf(&command, "mount_cd9660 -r %s %s 2>> %s", device, mountpoint, MONDO_LOGFILE);
1317
1318#else
1319 mr_asprintf(&command, "mount %s -o %s -t iso9660 %s 2>> %s", device, options, mountpoint, MONDO_LOGFILE);
1320 paranoid_free(options);
1321#endif
1322
1323 log_msg(4, command);
1324 if (strncmp(device, "/dev/", 5) == 0) {
1325 retract_CD_tray_and_defeat_autorun();
1326 }
1327 retval = system(command);
1328 log_msg(1, "system(%s) returned %d", command, retval);
1329 paranoid_free(command);
1330
1331 return (retval);
1332}
1333
1334
1335
1336
1337
1338
1339/**
1340 * Ask the user for CD number @p cd_number_i_want.
1341 * Sets g_current_media_number once the correct CD is inserted.
1342 * @param bkpinfo The backup information structure. Fields used:
1343 * - @c bkpinfo->backup_media_type
1344 * - @c bkpinfo->prefix
1345 * - @c bkpinfo->isodir
1346 * - @c bkpinfo->media_device
1347 * - @c bkpinfo->please_dont_eject_when_restoring
1348 * @param cd_number_i_want The CD number to ask for.
1349 */
1350void
1351insist_on_this_cd_number(int cd_number_i_want)
1352{
1353
1354 /*@ int ************************************************************* */
1355 int res = 0;
1356
1357
1358 /*@ buffers ********************************************************* */
1359 char *tmp;
1360 char *mds = NULL;
1361 char *request;
1362
1363 assert(bkpinfo != NULL);
1364 assert(cd_number_i_want > 0);
1365
1366// log_msg(3, "Insisting on CD number %d", cd_number_i_want);
1367
1368 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1369 log_msg(3,
1370 "No need to insist_on_this_cd_number when the backup type isn't CD-R(W) or NFS or ISO");
1371 return;
1372 }
1373 malloc_string(tmp);
1374 malloc_string(request);
1375 sprintf(tmp, "mkdir -p " MNT_CDROM);
1376 run_program_and_log_output(tmp, 5);
1377 if (g_ISO_restore_mode || bkpinfo->backup_media_type == iso
1378 || bkpinfo->backup_media_type == nfs) {
1379 log_msg(3, "Remounting CD");
1380 g_ISO_restore_mode = TRUE;
1381// FIXME --- I'm tempted to do something about this...
1382// Why unmount and remount again and again?
1383 if (is_this_device_mounted(MNT_CDROM)) {
1384 run_program_and_log_output("umount " MNT_CDROM, 5);
1385 }
1386 sprintf(tmp, "mkdir -p %s/isodir &> /dev/null", bkpinfo->tmpdir);
1387 (void)system(tmp);
1388 sprintf(tmp, "%s/%s/%s-%d.iso", bkpinfo->isodir,
1389 bkpinfo->nfs_remote_dir, bkpinfo->prefix,
1390 cd_number_i_want);
1391 if (!does_file_exist(tmp)) {
1392 sprintf(tmp, "%s/isodir/%s/%s-%d.iso", bkpinfo->tmpdir,
1393 bkpinfo->nfs_remote_dir, bkpinfo->prefix,
1394 cd_number_i_want);
1395 if (does_file_exist(tmp)) {
1396 log_msg(1,
1397 "FIXME - hacking bkpinfo->isodir from '%s' to %s/isodir",
1398 bkpinfo->isodir, bkpinfo->tmpdir);
1399 sprintf(bkpinfo->isodir, "%s/isodir", bkpinfo->tmpdir);
1400 }
1401 }
1402 log_msg(3, "Mounting %s at %s", tmp, MNT_CDROM);
1403 if (mount_CDROM_here(tmp, MNT_CDROM)) {
1404 fatal_error("Mommy!");
1405 }
1406// g_current_media_number = cd_number_i_want;
1407// return;
1408 }
1409 if ((res = what_number_cd_is_this()) != cd_number_i_want) {
1410 log_msg(3, "Currently, we hold %d but we want %d", res,
1411 cd_number_i_want);
1412 mds = media_descriptor_string(bkpinfo->backup_media_type);
1413 sprintf(tmp, "Insisting on %s #%d", mds, cd_number_i_want);
1414 sprintf(request, "Please insert %s #%d and press Enter.", mds, cd_number_i_want);
1415 mr_free(mds);
1416 log_msg(3, tmp);
1417 while (what_number_cd_is_this() != cd_number_i_want) {
1418 paranoid_system("sync");
1419 if (is_this_device_mounted(MNT_CDROM)) {
1420 res =
1421 run_program_and_log_output("umount " MNT_CDROM, FALSE);
1422 } else {
1423 res = 0;
1424 }
1425 if (res) {
1426 log_to_screen("WARNING - failed to unmount CD-ROM drive");
1427 }
1428 if (!bkpinfo->please_dont_eject) {
1429 res = eject_device(bkpinfo->media_device);
1430 } else {
1431 res = 0;
1432 }
1433 if (res) {
1434 log_to_screen("WARNING - failed to eject CD-ROM disk");
1435 }
1436 popup_and_OK(request);
1437 if (!bkpinfo->please_dont_eject) {
1438 inject_device(bkpinfo->media_device);
1439 }
1440 paranoid_system("sync");
1441 }
1442 log_msg(1, "Thankyou. Proceeding...");
1443 g_current_media_number = cd_number_i_want;
1444 }
1445 paranoid_free(tmp);
1446 paranoid_free(request);
1447}
1448
1449/* @} - end of deviceGroup */
1450
1451
1452
1453
1454
1455
1456/**
1457 * Ask user for details of backup/restore information.
1458 * Called when @c mondoarchive doesn't get any parameters.
1459 * @param bkpinfo The backup information structure to fill out with the user's data.
1460 * @param archiving_to_media TRUE if archiving, FALSE if restoring.
1461 * @return 0, always.
1462 * @bug No point of `int' return value.
1463 * @ingroup archiveGroup
1464 */
1465int interactively_obtain_media_parameters_from_user(bool archiving_to_media)
1466// archiving_to_media is TRUE if I'm being called by mondoarchive
1467// archiving_to_media is FALSE if I'm being called by mondorestore
1468{
1469 char *tmp = NULL;
1470 char *tmp1 = NULL;
1471 char *mds = NULL;
1472 char *sz_size;
1473 char *command;
1474 char *comment;
1475 char *prompt;
1476 int i;
1477 FILE *fin;
1478
1479 malloc_string(sz_size);
1480 malloc_string(command);
1481 malloc_string(comment);
1482 malloc_string(prompt);
1483 malloc_string(tmp1);
1484 assert(bkpinfo != NULL);
1485 sz_size[0] = '\0';
1486 bkpinfo->nonbootable_backup = FALSE;
1487
1488 // Tape, CD, NFS, ...?
1489 srandom(getpid());
1490 bkpinfo->backup_media_type =
1491 (g_restoring_live_from_cd) ? cdr :
1492 which_backup_media_type(bkpinfo->restore_data);
1493 if (bkpinfo->backup_media_type == none) {
1494 log_to_screen("User has chosen not to backup the PC");
1495 finish(1);
1496 }
1497 /* Why asking to remove the media with tape ?
1498 if (bkpinfo->backup_media_type == tape && bkpinfo->restore_data) {
1499 popup_and_OK("Please remove media from drive(s)");
1500 }
1501 */
1502 log_msg(3, "media type = %s",
1503 bkptype_to_string(bkpinfo->backup_media_type));
1504 if (archiving_to_media) {
1505 sensibly_set_tmpdir_and_scratchdir();
1506 }
1507 bkpinfo->cdrw_speed = (bkpinfo->backup_media_type == cdstream) ? 2 : 4;
1508 bkpinfo->compression_level =
1509 (bkpinfo->backup_media_type == cdstream) ? 1 : 5;
1510 bkpinfo->use_lzo =
1511 (bkpinfo->backup_media_type == cdstream) ? TRUE : FALSE;
1512 mvaddstr_and_log_it(2, 0, " ");
1513
1514 // Find device's /dev (or SCSI) entry
1515 switch (bkpinfo->backup_media_type) {
1516 case cdr:
1517 case cdrw:
1518 case dvd:
1519 case usb:
1520 /* Never try to eject a USB device */
1521 if (bkpinfo->backup_media_type == usb) {
1522 bkpinfo->please_dont_eject = TRUE;
1523 }
1524 if (archiving_to_media) {
1525 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
1526 if (ask_me_yes_or_no
1527 ("Is your computer a laptop, or does the CD writer incorporate BurnProof technology?"))
1528 {
1529 bkpinfo->manual_cd_tray = TRUE;
1530 }
1531 }
1532 if ((bkpinfo->compression_level =
1533 which_compression_level()) == -1) {
1534 log_to_screen("User has chosen not to backup the PC");
1535 finish(1);
1536 }
1537 mds = media_descriptor_string(bkpinfo->backup_media_type);
1538 sprintf(comment, "What speed is your %s (re)writer?", mds);
1539 if (bkpinfo->backup_media_type == dvd) {
1540 find_dvd_device(bkpinfo->media_device, FALSE);
1541 strcpy(tmp1, "1");
1542 sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB
1543 log_msg(1, "Setting to DVD defaults");
1544 } else {
1545 strcpy(bkpinfo->media_device, VANILLA_SCSI_CDROM);
1546 strcpy(tmp1, "4");
1547 strcpy(sz_size, "650");
1548 log_msg(1, "Setting to CD defaults");
1549 }
1550 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
1551 if (!popup_and_get_string("Speed", comment, tmp1, 4)) {
1552 log_to_screen("User has chosen not to backup the PC");
1553 finish(1);
1554 }
1555 }
1556 bkpinfo->cdrw_speed = atoi(tmp1); // if DVD then this shouldn't ever be used anyway :)
1557
1558 sprintf(comment,
1559 "How much data (in Megabytes) will each %s store?", mds);
1560 mr_free(mds);
1561 if (!popup_and_get_string("Size", comment, sz_size, 5)) {
1562 log_to_screen("User has chosen not to backup the PC");
1563 finish(1);
1564 }
1565 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1566 bkpinfo->media_size[i] = atoi(sz_size);
1567 }
1568 if (bkpinfo->media_size[0] <= 0) {
1569 log_to_screen("User has chosen not to backup the PC");
1570 finish(1);
1571 }
1572 }
1573 /* No break because we continue even for usb */
1574 case cdstream:
1575 mds = media_descriptor_string(bkpinfo->backup_media_type);
1576
1577 if ((bkpinfo->disaster_recovery) && (bkpinfo->backup_media_type != usb)) {
1578 strcpy(bkpinfo->media_device, "/dev/cdrom");
1579 log_msg(2, "CD-ROM device assumed to be at %s",
1580 bkpinfo->media_device);
1581 } else if ((bkpinfo->restore_data && (bkpinfo->backup_media_type != usb))
1582 || bkpinfo->backup_media_type == dvd) {
1583 if (!bkpinfo->media_device[0]) {
1584 strcpy(bkpinfo->media_device, "/dev/cdrom");
1585 } // just for the heck of it :)
1586 log_msg(1, "bkpinfo->media_device = %s",
1587 bkpinfo->media_device);
1588 if (bkpinfo->backup_media_type == dvd
1589 || find_cdrom_device(bkpinfo->media_device, FALSE)) {
1590 log_msg(1, "bkpinfo->media_device = %s",
1591 bkpinfo->media_device);
1592 sprintf(comment,
1593 "Please specify your %s drive's /dev entry", mds);
1594 if (!popup_and_get_string
1595 ("Device?", comment, bkpinfo->media_device,
1596 MAX_STR_LEN / 4)) {
1597 log_to_screen("User has chosen not to backup the PC");
1598 finish(1);
1599 }
1600 }
1601 log_msg(2, "%s device found at %s", mds, bkpinfo->media_device);
1602 } else {
1603 if ((find_cdrw_device(bkpinfo->media_device)) && (bkpinfo->backup_media_type != usb)) {
1604 bkpinfo->media_device[0] = '\0';
1605 }
1606 if (bkpinfo->media_device[0]) {
1607 if (bkpinfo->backup_media_type == usb) {
1608 mr_asprintf(&tmp, "I think your %s media corresponds to %s. Is this correct?", mds, bkpinfo->media_device);
1609 } else {
1610 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);
1611 }
1612 if (!ask_me_yes_or_no(tmp)) {
1613 bkpinfo->media_device[0] = '\0';
1614 }
1615 mr_free(tmp);
1616 }
1617 if (!bkpinfo->media_device[0]) {
1618 if (bkpinfo->backup_media_type == usb) {
1619 i = popup_and_get_string("/dev entry?",
1620 "What is the /dev entry of your USB Disk/Key, please?",
1621 bkpinfo->media_device,
1622 MAX_STR_LEN / 4);
1623 } else {
1624 if (g_kernel_version < 2.6) {
1625 i = popup_and_get_string("Device node?",
1626 "What is the SCSI node of your CD (re)writer, please?",
1627 bkpinfo->media_device,
1628 MAX_STR_LEN / 4);
1629 } else {
1630 i = popup_and_get_string("/dev entry?",
1631 "What is the /dev entry of your CD (re)writer, please?",
1632 bkpinfo->media_device,
1633 MAX_STR_LEN / 4);
1634 }
1635 }
1636 if (!i) {
1637 log_to_screen("User has chosen not to backup the PC");
1638 finish(1);
1639 }
1640 }
1641 }
1642 mr_free(mds);
1643
1644 if (bkpinfo->backup_media_type == cdstream) {
1645 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1646 bkpinfo->media_size[i] = 650;
1647 }
1648 }
1649 break;
1650 case udev:
1651 if (!ask_me_yes_or_no
1652 ("This option is for advanced users only. Are you sure?")) {
1653 log_to_screen("User has chosen not to backup the PC");
1654 finish(1);
1655 }
1656 case tape:
1657
1658 if ((!bkpinfo->restore_mode) && (find_tape_device_and_size(bkpinfo->media_device, sz_size))) {
1659 log_msg(3, "Ok, using vanilla scsi tape.");
1660 strcpy(bkpinfo->media_device, VANILLA_SCSI_TAPE);
1661 if ((fin = fopen(bkpinfo->media_device, "r"))) {
1662 paranoid_fclose(fin);
1663 } else {
1664 strcpy(bkpinfo->media_device, "/dev/osst0");
1665 }
1666 }
1667 if (bkpinfo->media_device[0]) {
1668 if ((fin = fopen(bkpinfo->media_device, "r"))) {
1669 paranoid_fclose(fin);
1670 } else {
1671 if (does_file_exist("/tmp/mondo-restore.cfg")) {
1672 read_cfg_var("/tmp/mondo-restore.cfg", "media-dev",
1673 bkpinfo->media_device);
1674 }
1675 }
1676 }
1677 if (bkpinfo->media_device[0]) {
1678 mr_asprintf(&tmp, "I think I've found your tape streamer at %s; am I right on the money?", bkpinfo->media_device);
1679 if (!ask_me_yes_or_no(tmp)) {
1680 bkpinfo->media_device[0] = '\0';
1681 }
1682 mr_free(tmp);
1683 }
1684 if (!bkpinfo->media_device[0]) {
1685 if (!popup_and_get_string
1686 ("Device name?",
1687 "What is the /dev entry of your tape streamer?",
1688 bkpinfo->media_device, MAX_STR_LEN / 4)) {
1689 log_to_screen("User has chosen not to backup the PC");
1690 finish(1);
1691 }
1692 }
1693 mr_asprintf(&tmp, "ls -l %s", bkpinfo->media_device);
1694 if (run_program_and_log_output(tmp, FALSE)) {
1695 log_to_screen("User has not specified a valid /dev entry");
1696 finish(1);
1697 }
1698 mr_free(tmp);
1699 log_msg(4, "sz_size = %s", sz_size);
1700 sz_size[0] = '\0';
1701
1702 bkpinfo->use_obdr = ask_me_yes_or_no
1703 ("Do you want to activate OBDR support for your tapes ?");
1704 if (sz_size[0] == '\0') {
1705 bkpinfo->media_size[0] = 0;
1706 } else {
1707 bkpinfo->media_size[0] =
1708 friendly_sizestr_to_sizelong(sz_size) / 2 - 50;
1709 }
1710 log_msg(4, "media_size[0] = %ld", bkpinfo->media_size[0]);
1711 if (bkpinfo->media_size[0] <= 0) {
1712 bkpinfo->media_size[0] = 0;
1713 }
1714 for (i = 1; i <= MAX_NOOF_MEDIA; i++) {
1715 bkpinfo->media_size[i] = bkpinfo->media_size[0];
1716 }
1717 if (archiving_to_media) {
1718 if ((bkpinfo->compression_level =
1719 which_compression_level()) == -1) {
1720 log_to_screen("User has chosen not to backup the PC");
1721 finish(1);
1722 }
1723 }
1724 break;
1725
1726
1727
1728 case nfs:
1729 /* Never try to eject a NFS device */
1730 bkpinfo->please_dont_eject = TRUE;
1731
1732 /* Initiate bkpinfo nfs_mount path from running environment if not already done */
1733 if (!bkpinfo->nfs_mount[0]) {
1734 strcpy(bkpinfo->nfs_mount,
1735 call_program_and_get_last_line_of_output
1736 ("mount | grep \":\" | cut -d' ' -f1 | head -n1"));
1737 }
1738#ifdef __FreeBSD__
1739 if (TRUE)
1740#else
1741 if (!bkpinfo->disaster_recovery)
1742#endif
1743 {
1744 if (!popup_and_get_string
1745 ("NFS dir.",
1746 "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.)",
1747 bkpinfo->nfs_mount, MAX_STR_LEN / 4)) {
1748 log_to_screen("User has chosen not to backup the PC");
1749 finish(1);
1750 }
1751 if (!bkpinfo->restore_data) {
1752 if ((bkpinfo->compression_level =
1753 which_compression_level()) == -1) {
1754 log_to_screen("User has chosen not to backup the PC");
1755 finish(1);
1756 }
1757 }
1758 // check whether already mounted - we better remove
1759 // surrounding spaces and trailing '/' for this
1760 strip_spaces(bkpinfo->nfs_mount);
1761 if (bkpinfo->nfs_mount[strlen(bkpinfo->nfs_mount) - 1] == '/')
1762 bkpinfo->nfs_mount[strlen(bkpinfo->nfs_mount) - 1] = '\0';
1763 sprintf(command, "mount | grep \"%s \" | cut -d' ' -f3",
1764 bkpinfo->nfs_mount);
1765 strcpy(bkpinfo->isodir,
1766 call_program_and_get_last_line_of_output(command));
1767
1768 if (!bkpinfo->restore_data) {
1769 sprintf(comment,
1770 "How much data (in Megabytes) will each media store?");
1771 if (!popup_and_get_string("Size", comment, sz_size, 5)) {
1772 log_to_screen("User has chosen not to backup the PC");
1773 finish(1);
1774 }
1775 } else {
1776 strcpy(sz_size, "0");
1777 }
1778 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1779 bkpinfo->media_size[i] = atoi(sz_size);
1780 }
1781 if (bkpinfo->media_size[0] < 0) {
1782 log_to_screen("User has chosen not to backup the PC");
1783 finish(1);
1784 }
1785 }
1786 if (bkpinfo->disaster_recovery) {
1787 sprintf(command ,"umount %s/isodir 2> /dev/null", bkpinfo->tmpdir);
1788 (void)system(command);
1789 if (!popup_and_get_string
1790 ("NFS share", "Which remote NFS share should I mount?",
1791 bkpinfo->nfs_mount, MAX_STR_LEN)) {
1792 log_to_screen("User has chosen not to backup the PC");
1793 finish(1);
1794 }
1795 }
1796 /* Initiate bkpinfo isodir path from running environment if mount already done */
1797 if (is_this_device_mounted(bkpinfo->nfs_mount)) {
1798 strcpy(bkpinfo->isodir,
1799 call_program_and_get_last_line_of_output
1800 ("mount | grep \":\" | cut -d' ' -f3 | head -n1"));
1801 } else {
1802 sprintf(bkpinfo->isodir, "%s/nfsdir", bkpinfo->tmpdir);
1803 sprintf(command, "mkdir -p %s", bkpinfo->isodir);
1804 run_program_and_log_output(command, 5);
1805 if (bkpinfo->restore_data) {
1806 mr_asprintf(&tmp, "mount -t nfs -o nolock,ro %s %s", bkpinfo->nfs_mount, bkpinfo->isodir);
1807 } else {
1808 mr_asprintf(&tmp, "mount -t nfs -o nolock %s %s", bkpinfo->nfs_mount, bkpinfo->isodir);
1809 }
1810 run_program_and_log_output(tmp, 3);
1811 mr_free(tmp);
1812
1813 malloc_string(g_selfmounted_isodir);
1814 strcpy(g_selfmounted_isodir, bkpinfo->isodir);
1815 }
1816 if (!is_this_device_mounted(bkpinfo->nfs_mount)) {
1817 popup_and_OK
1818 ("Please mount that partition before you try to backup to or restore from it.");
1819 finish(1);
1820 }
1821 strcpy(tmp1, bkpinfo->nfs_remote_dir);
1822 if (!popup_and_get_string
1823 ("Directory", "Which directory within that mountpoint?", tmp1,
1824 MAX_STR_LEN)) {
1825 log_to_screen("User has chosen not to backup the PC");
1826 finish(1);
1827 }
1828 strcpy(bkpinfo->nfs_remote_dir, tmp1);
1829
1830 // check whether writable - we better remove surrounding spaces for this
1831 strip_spaces(bkpinfo->nfs_remote_dir);
1832
1833 if (!popup_and_get_string
1834 ("Prefix.",
1835 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
1836 bkpinfo->prefix, MAX_STR_LEN / 4)) {
1837 log_to_screen("User has chosen not to backup the PC");
1838 finish(1);
1839 }
1840 log_msg(3, "prefix set to %s", bkpinfo->prefix);
1841
1842 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1843 bkpinfo->media_size[i] = 650;
1844 }
1845 log_msg(3, "Just set nfs_remote_dir to %s",
1846 bkpinfo->nfs_remote_dir);
1847 log_msg(3, "isodir is still %s", bkpinfo->isodir);
1848 break;
1849
1850 case iso:
1851 if (!bkpinfo->disaster_recovery) {
1852 if (!popup_and_get_string
1853 ("Storage dir.",
1854 "Please enter the full path name to the directory for your ISO images. Example: /mnt/raid0_0",
1855 bkpinfo->isodir, MAX_STR_LEN / 4)) {
1856 log_to_screen("User has chosen not to backup the PC");
1857 finish(1);
1858 }
1859 if (archiving_to_media) {
1860 if ((bkpinfo->compression_level =
1861 which_compression_level()) == -1) {
1862 log_to_screen("User has chosen not to backup the PC");
1863 finish(1);
1864 }
1865 if (!popup_and_get_string
1866 ("ISO size.",
1867 "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 or DVD's you plan to backup to.",
1868 sz_size, 16)) {
1869 log_to_screen("User has chosen not to backup the PC");
1870 finish(1);
1871 }
1872 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1873 bkpinfo->media_size[i] = atoi(sz_size);
1874 }
1875 } else {
1876 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1877 bkpinfo->media_size[i] = 650;
1878 }
1879 }
1880 }
1881 if (!popup_and_get_string
1882 ("Prefix.",
1883 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
1884 bkpinfo->prefix, MAX_STR_LEN / 4)) {
1885 log_to_screen("User has chosen not to backup the PC");
1886 finish(1);
1887 }
1888 log_msg(3, "prefix set to %s", bkpinfo->prefix);
1889 break;
1890 default:
1891 fatal_error
1892 ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
1893 }
1894
1895 if (archiving_to_media) {
1896
1897#ifdef __FreeBSD__
1898 strcpy(bkpinfo->boot_device,
1899 call_program_and_get_last_line_of_output
1900 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
1901#else
1902 strcpy(bkpinfo->boot_device,
1903 call_program_and_get_last_line_of_output
1904 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
1905#endif
1906 i = which_boot_loader(bkpinfo->boot_device);
1907 if (i == 'U') // unknown
1908 {
1909
1910#ifdef __FreeBSD__
1911 if (!popup_and_get_string
1912 ("Boot device",
1913 "What is your boot device? (e.g. /dev/ad0)",
1914 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
1915 log_to_screen("User has chosen not to backup the PC");
1916 finish(1);
1917 }
1918 i = which_boot_loader(bkpinfo->boot_device);
1919#else
1920 if (!popup_and_get_string
1921 ("Boot device",
1922 "What is your boot device? (e.g. /dev/hda)",
1923 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
1924 log_to_screen("User has chosen not to backup the PC");
1925 finish(1);
1926 }
1927 if (does_string_exist_in_boot_block
1928 (bkpinfo->boot_device, "LILO")) {
1929 i = 'L';
1930 } else
1931 if (does_string_exist_in_boot_block
1932 (bkpinfo->boot_device, "ELILO")) {
1933 i = 'E';
1934 } else
1935 if (does_string_exist_in_boot_block
1936 (bkpinfo->boot_device, "GRUB")) {
1937 i = 'G';
1938 } else {
1939 i = 'U';
1940 }
1941#endif
1942 if (i == 'U') {
1943 if (ask_me_yes_or_no
1944 ("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?"))
1945 {
1946 i = 'R'; // raw
1947 } else {
1948 log_to_screen
1949 ("I cannot find your boot loader. Please run mondoarchive with parameters.");
1950 finish(1);
1951 }
1952 }
1953 }
1954 bkpinfo->boot_loader = i;
1955 strcpy(bkpinfo->include_paths, "/");
1956 if (!popup_and_get_string
1957 ("Backup paths",
1958 "Please enter paths which you want me to backup. The default is '/' (i.e. everything).",
1959 bkpinfo->include_paths, MAX_STR_LEN)) {
1960 log_to_screen("User has chosen not to backup the PC");
1961 finish(1);
1962 }
1963 mr_asprintf(&tmp, "%s", list_of_NFS_mounts_only());
1964 if (strlen(tmp) > 2) {
1965 if (bkpinfo->exclude_paths[0]) {
1966 strcat(bkpinfo->exclude_paths, " ");
1967 }
1968 strncpy(bkpinfo->exclude_paths, tmp, MAX_STR_LEN);
1969 }
1970 mr_free(tmp);
1971// NTFS
1972 strcpy(tmp1, call_program_and_get_last_line_of_output("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'"));
1973 if (strlen(tmp1) > 2) {
1974 if (!popup_and_get_string
1975 ("NTFS partitions",
1976 "Please enter/confirm the NTFS partitions you wish to backup as well.",
1977 tmp1, MAX_STR_LEN / 4)) {
1978 log_to_screen("User has chosen not to backup the PC");
1979 finish(1);
1980 }
1981 strncpy(bkpinfo->image_devs, tmp1, MAX_STR_LEN / 4);
1982 }
1983
1984
1985 if (!popup_and_get_string
1986 ("Exclude paths",
1987 "Please enter paths which you do NOT want to backup. Separate them with spaces. NB: /tmp and /proc are always excluded. :-) Just hit 'Enter' if you want to do a full system backup.",
1988 bkpinfo->exclude_paths, (4*MAX_STR_LEN)-1)) {
1989 log_to_screen("User has chosen not to backup the PC");
1990 finish(1);
1991 }
1992 if (!popup_and_get_string
1993 ("Temporary directory",
1994 "Please enter your temporary directory.",
1995 bkpinfo->tmpdir, (4*MAX_STR_LEN)-1)) {
1996 log_to_screen("User has chosen not to backup the PC");
1997 finish(1);
1998 }
1999 if (!popup_and_get_string
2000 ("Scratch directory",
2001 "Please enter your scratch directory.",
2002 bkpinfo->scratchdir, (4*MAX_STR_LEN)-1)) {
2003 log_to_screen("User has chosen not to backup the PC");
2004 finish(1);
2005 }
2006// Interactive mode:
2007#ifdef __IA64__
2008 bkpinfo->make_cd_use_lilo = TRUE;
2009#else
2010 bkpinfo->make_cd_use_lilo = FALSE;
2011#endif
2012 bkpinfo->backup_data = TRUE;
2013 bkpinfo->verify_data =
2014 ask_me_yes_or_no
2015 ("Will you want to verify your backups after Mondo has created them?");
2016
2017#ifndef __FreeBSD__
2018 if (!ask_me_yes_or_no
2019 ("Are you confident that your kernel is a sane, sensible, standard Linux kernel? Say 'no' if you are using a Gentoo <1.4 or Debian <3.0, please."))
2020#endif
2021 {
2022 strcpy(bkpinfo->kernel_path, "FAILSAFE");
2023 }
2024
2025 if (!ask_me_yes_or_no
2026 ("Are you sure you want to proceed? Hit 'no' to abort.")) {
2027 log_to_screen("User has chosen not to backup the PC");
2028 finish(1);
2029 }
2030 } else {
2031 bkpinfo->restore_data = TRUE; // probably...
2032 }
2033
2034 if (bkpinfo->backup_media_type == iso
2035 || bkpinfo->backup_media_type == nfs) {
2036 g_ISO_restore_mode = TRUE;
2037 }
2038#ifdef __FreeSD__
2039// skip
2040#else
2041 if (bkpinfo->backup_media_type == nfs) {
2042 log_msg(3, "I think the NFS mount is mounted at %s",
2043 bkpinfo->isodir);
2044 }
2045 log_it("isodir = %s", bkpinfo->isodir);
2046 log_it("nfs_mount = '%s'", bkpinfo->nfs_mount);
2047 if (bkpinfo->nfs_user) {
2048 log_it("nfs_user = '%s'", bkpinfo->nfs_user);
2049 }
2050#endif
2051
2052 log_it("media device = %s", bkpinfo->media_device);
2053 log_it("media size = %ld", bkpinfo->media_size[1]);
2054 log_it("media type = %s",
2055 bkptype_to_string(bkpinfo->backup_media_type));
2056 log_it("prefix = %s", bkpinfo->prefix);
2057 log_it("compression = %ld", bkpinfo->compression_level);
2058 log_it("include_paths = '%s'", bkpinfo->include_paths);
2059 log_it("exclude_paths = '%s'", bkpinfo->exclude_paths);
2060 log_it("scratchdir = '%s'", bkpinfo->scratchdir);
2061 log_it("tmpdir = '%s'", bkpinfo->tmpdir);
2062 log_it("image_devs = '%s'", bkpinfo->image_devs);
2063 log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device,
2064 bkpinfo->boot_loader);
2065 if (bkpinfo->media_size[0] < 0) {
2066 if (archiving_to_media) {
2067 fatal_error("Media size is less than zero.");
2068 } else {
2069 log_msg(2, "Warning - media size is less than zero.");
2070 bkpinfo->media_size[0] = 0;
2071 }
2072 }
2073 paranoid_free(sz_size);
2074 paranoid_free(tmp1);
2075 paranoid_free(command);
2076 paranoid_free(comment);
2077 paranoid_free(prompt);
2078 return (0);
2079}
2080
2081
2082
2083
2084/**
2085 * @addtogroup utilityGroup
2086 * @{
2087 */
2088/**
2089 * Get a space-separated list of NFS devices and mounts.
2090 * @return The list created.
2091 * @note The return value points to static data that will be overwritten with each call.
2092 */
2093char *list_of_NFS_devices_and_mounts(void)
2094{
2095 char *exclude_these_devices = NULL;
2096 char *exclude_these_directories = NULL;
2097 static char result_sz[1024];
2098
2099 mr_asprintf(&exclude_these_directories,"%s",list_of_NFS_mounts_only());
2100 mr_asprintf(&exclude_these_devices,"%s", call_program_and_get_last_line_of_output("tr -s '\t' ' ' < /etc/fstab | grep -E '( (coda|ncpfs|nfs|nfs4|smbfs|cifs|afs|gfs|ocfs|ocfs2|mvfs|nsspool|nsvol) )' | cut -d' ' -f1 | tr -s '\n' ' ' | awk '{print $0;}'"));
2101 snprintf(result_sz, 1023, "%s %s", exclude_these_directories, exclude_these_devices);
2102 mr_free(exclude_these_devices);
2103 mr_free(exclude_these_directories);
2104 return (result_sz);
2105}
2106
2107
2108
2109
2110/**
2111 * Get a space-separated list of NFS mounts.
2112 * @return The list created.
2113 * @note The return value points to static data that will be overwritten with each call.
2114 * @bug Even though we only want the mounts, the devices are still checked.
2115 */
2116char *list_of_NFS_mounts_only(void)
2117{
2118 char *exclude_these_directories = NULL;
2119 static char result_sz[512];
2120
2121 mr_asprintf(&exclude_these_directories,"%s", call_program_and_get_last_line_of_output("mount -t coda,ncpfs,nfs,nfs4,smbfs,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' ' ' | awk '{print $0;}'"));
2122 snprintf(result_sz, 511, "%s", exclude_these_directories);
2123 mr_free(exclude_these_directories);
2124 return (result_sz);
2125}
2126
2127/* @} - end of utilityGroup */
2128
2129
2130
2131
2132
2133/**
2134 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
2135 * [random] is a random number between 1 and 32767.
2136 * @param store_name_here Where to store the new filename.
2137 * @param stub A random number will be appended to this to make the FIFO's name.
2138 * @ingroup deviceGroup
2139 */
2140void make_fifo(char *store_name_here, char *stub)
2141{
2142 char *tmp;
2143
2144 malloc_string(tmp);
2145 assert_string_is_neither_NULL_nor_zerolength(stub);
2146
2147 sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
2148 (int) (random() % 32768));
2149 make_hole_for_file(store_name_here);
2150 mkfifo(store_name_here, S_IRWXU | S_IRWXG);
2151 sprintf(tmp, "chmod 770 %s", store_name_here);
2152 paranoid_system(tmp);
2153 paranoid_free(tmp);
2154}
2155
2156
2157
2158
2159
2160
2161/**
2162 * Set the tmpdir and scratchdir to reside on the partition with the most free space.
2163 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
2164 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set.
2165 * @ingroup utilityGroup
2166 */
2167void sensibly_set_tmpdir_and_scratchdir()
2168{
2169 char *tmp = NULL;
2170 char *command = NULL;
2171 char *sz = NULL;
2172
2173 assert(bkpinfo != NULL);
2174
2175#ifdef __FreeBSD__
2176 mr_asprintf(&tmp, "%s", 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;}'"));
2177#else
2178 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output("LANGUAGE=C df -m -P -x nfs -x nfs4 -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;}'"));
2179#endif
2180
2181 if (tmp[0] != '/') {
2182 mr_asprintf(&sz, "%s", tmp);
2183 paranoid_free(tmp);
2184 mr_asprintf(&tmp, "/%s", sz);
2185 mr_free(sz);
2186 }
2187 if (!tmp[0]) {
2188 fatal_error("I couldn't figure out the tempdir!");
2189 }
2190 setup_tmpdir(tmp);
2191 log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir);
2192
2193 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%d", tmp,
2194 (int) (random() % 32768));
2195 log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
2196
2197 mr_asprintf(&command, "rm -Rf %s/tmp.mondo.* %s/mondo.scratch.*", tmp, tmp);
2198 paranoid_free(tmp);
2199
2200 paranoid_system(command);
2201 mr_free(command);
2202}
2203
2204
2205
2206
2207
2208
2209/**
2210 * @addtogroup deviceGroup
2211 * @{
2212 */
2213/**
2214 * If we can read @p dev, set @p output to it.
2215 * If @p dev cannot be read, set @p output to "".
2216 * @param dev The device to check for.
2217 * @param output Set to @p dev if @p dev exists, "" otherwise.
2218 * @return TRUE if @p dev exists, FALSE if it doesn't.
2219 */
2220bool set_dev_to_this_if_rx_OK(char *output, char *dev)
2221{
2222 char *command;
2223
2224 malloc_string(command);
2225 if (!dev || dev[0] == '\0') {
2226 output[0] = '\0';
2227 return (FALSE);
2228 }
2229// assert_string_is_neither_NULL_nor_zerolength(dev);
2230 log_msg(10, "Injecting %s", dev);
2231 inject_device(dev);
2232 if (!does_file_exist(dev)) {
2233 log_msg(10, "%s doesn't exist. Returning FALSE.", dev);
2234 return (FALSE);
2235 }
2236 sprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null",
2237 512L, dev);
2238 if (!run_program_and_log_output(command, FALSE)
2239 && !run_program_and_log_output(command, FALSE)) {
2240 strcpy(output, dev);
2241 log_msg(4, "Found it - %s", dev);
2242 return (TRUE);
2243 } else {
2244 output[0] = '\0';
2245 log_msg(4, "It's not %s", dev);
2246 return (FALSE);
2247 }
2248}
2249
2250
2251
2252
2253
2254/**
2255 * Find out what number CD is in the drive.
2256 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
2257 * @return The current CD number, or -1 if it could not be found.
2258 * @note If the CD is not mounted, it will be mounted
2259 * (and remain mounted after this function returns).
2260 */
2261int what_number_cd_is_this()
2262{
2263 int cd_number = -1;
2264 char *mountdev = NULL;
2265 char *tmp = NULL;
2266
2267 assert(bkpinfo != NULL);
2268// log_it("Asking what_number_cd_is_this");
2269 if (g_ISO_restore_mode) {
2270 mr_asprintf(&tmp, "mount | grep iso9660 | awk '{print $3;}'");
2271
2272 mr_asprintf(&mountdev, "%s%s", call_program_and_get_last_line_of_output(tmp), "/archives/THIS-CD-NUMBER");
2273 cd_number = atoi(last_line_of_file(mountdev));
2274 paranoid_free(mountdev);
2275 paranoid_free(tmp);
2276
2277 return (cd_number);
2278 }
2279
2280 mr_asprintf(&mountdev, "%s", bkpinfo->media_device);
2281 if (!mountdev[0]) {
2282 log_it
2283 ("(what_number_cd_is_this) Warning - media_device unknown. Finding out...");
2284 find_cdrom_device(bkpinfo->media_device, FALSE);
2285 }
2286 if (!is_this_device_mounted(MNT_CDROM)) {
2287 if (bkpinfo->backup_media_type == usb) {
2288 mount_USB_here(mountdev, MNT_CDROM);
2289 } else {
2290 mount_CDROM_here(mountdev, MNT_CDROM);
2291 }
2292 }
2293 paranoid_free(mountdev);
2294
2295 cd_number = atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
2296 return (cd_number);
2297}
2298
2299
2300
2301
2302
2303
2304
2305/**
2306 * Find out what device is mounted as root (/).
2307 * @return Root device.
2308 * @note The returned string points to static storage and will be overwritten with every call.
2309 * @bug A bit of a misnomer; it's actually finding out the root device.
2310 * The mountpoint (where it's mounted) will obviously be '/'.
2311 */
2312char *where_is_root_mounted()
2313{
2314 /*@ buffers **************** */
2315 static char tmp[MAX_STR_LEN];
2316
2317
2318#ifdef __FreeBSD__
2319 strcpy(tmp, call_program_and_get_last_line_of_output
2320 ("mount | grep \" on / \" | cut -d' ' -f1"));
2321#else
2322 strcpy(tmp, call_program_and_get_last_line_of_output
2323 ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"));
2324 if (strstr(tmp, "/dev/cciss/")) {
2325 strcpy(tmp, call_program_and_get_last_line_of_output
2326 ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"));
2327 }
2328 if (strstr(tmp, "/dev/md")) {
2329 strcpy(tmp,
2330 call_program_and_get_last_line_of_output
2331 ("mount | grep \" on / \" | cut -d' ' -f1"));
2332 }
2333#endif
2334
2335 return (tmp);
2336}
2337
2338
2339/**
2340 * Find out which boot loader is in use.
2341 * @param which_device Device to look for the boot loader on.
2342 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
2343 * @note Under Linux, all drives are examined, not just @p which_device.
2344 */
2345#ifdef __FreeBSD__
2346char which_boot_loader(char *which_device)
2347{
2348 int count_lilos = 0;
2349 int count_grubs = 0;
2350 int count_boot0s = 0;
2351 int count_dangerouslydedicated = 0;
2352
2353 log_it("looking at drive %s's MBR", which_device);
2354 if (does_string_exist_in_boot_block(which_device, "GRUB")) {
2355 count_grubs++;
2356 }
2357 if (does_string_exist_in_boot_block(which_device, "LILO")) {
2358 count_lilos++;
2359 }
2360 if (does_string_exist_in_boot_block(which_device, "Drive")) {
2361 count_boot0s++;
2362 }
2363 if (does_string_exist_in_first_N_blocks
2364 (which_device, "FreeBSD/i386", 17)) {
2365 count_dangerouslydedicated++;
2366 }
2367 log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
2368 count_grubs, count_lilos, count_elilos, count_boot0s,
2369 count_dangerouslydedicated);
2370
2371 if (count_grubs && !count_lilos) {
2372 return ('G');
2373 } else if (count_lilos && !count_grubs) {
2374 return ('L');
2375 } else if (count_grubs == 1 && count_lilos == 1) {
2376 log_it("I'll bet you used to use LILO but switched to GRUB...");
2377 return ('G');
2378 } else if (count_boot0s == 1) {
2379 return ('B');
2380 } else if (count_dangerouslydedicated) {
2381 return ('D');
2382 } else {
2383 log_it("Unknown boot loader");
2384 return ('U');
2385 }
2386}
2387
2388#else
2389
2390char which_boot_loader(char *which_device)
2391{
2392 /*@ buffer ***************************************************** */
2393 char *list_drives_cmd = NULL;
2394 char *current_drive;
2395
2396 /*@ pointers *************************************************** */
2397 FILE *pdrives;
2398
2399 /*@ int ******************************************************** */
2400 int count_lilos = 0;
2401 int count_grubs = 0;
2402
2403 /*@ end vars *************************************************** */
2404
2405 malloc_string(current_drive);
2406
2407#ifdef __IA64__
2408 /* No choice for it */
2409 return ('E');
2410#endif
2411 assert(which_device != NULL);
2412
2413 mr_asprintf(&list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s", where_is_root_mounted());
2414 log_it("list_drives_cmd = %s", list_drives_cmd);
2415
2416 if (!(pdrives = popen(list_drives_cmd, "r"))) {
2417 log_OS_error("Unable to open list of drives");
2418 mr_free(list_drives_cmd);
2419 paranoid_free(current_drive);
2420 return ('\0');
2421 }
2422 mr_free(list_drives_cmd);
2423
2424 for ((void)fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
2425 (void)fgets(current_drive, MAX_STR_LEN, pdrives)) {
2426 strip_spaces(current_drive);
2427 log_it("looking at drive %s's MBR", current_drive);
2428 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
2429 count_grubs++;
2430 strcpy(which_device, current_drive);
2431 break;
2432 }
2433 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
2434 count_lilos++;
2435 strcpy(which_device, current_drive);
2436 break;
2437 }
2438 }
2439 if (pclose(pdrives)) {
2440 log_OS_error("Cannot pclose pdrives");
2441 }
2442 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
2443 if (count_grubs && !count_lilos) {
2444 paranoid_free(current_drive);
2445 return ('G');
2446 } else if (count_lilos && !count_grubs) {
2447 paranoid_free(current_drive);
2448 return ('L');
2449 } else if (count_grubs == 1 && count_lilos == 1) {
2450 log_it("I'll bet you used to use LILO but switched to GRUB...");
2451 paranoid_free(current_drive);
2452 return ('G');
2453 } else {
2454 // We need to look on each partition then
2455 mr_asprintf(&list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep -E \"^/dev/\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/");
2456 log_it("list_drives_cmd = %s", list_drives_cmd);
2457
2458 if (!(pdrives = popen(list_drives_cmd, "r"))) {
2459 log_OS_error("Unable to open list of drives");
2460 mr_free(list_drives_cmd);
2461 paranoid_free(current_drive);
2462 return ('\0');
2463 }
2464 mr_free(list_drives_cmd);
2465
2466 for ((void)fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
2467 (void)fgets(current_drive, MAX_STR_LEN, pdrives)) {
2468 strip_spaces(current_drive);
2469 log_it("looking at partition %s's BR", current_drive);
2470 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
2471 count_grubs++;
2472 strcpy(which_device, current_drive);
2473 break;
2474 }
2475 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
2476 count_lilos++;
2477 strcpy(which_device, current_drive);
2478 break;
2479 }
2480 }
2481 if (pclose(pdrives)) {
2482 log_OS_error("Cannot pclose pdrives");
2483 }
2484 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
2485 paranoid_free(current_drive);
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 static char output[MAX_STR_LEN];
2539 char *command;
2540 char *curr_fname;
2541 char *scratch = NULL;
2542 char *tmp = NULL;
2543 char *p;
2544
2545 struct stat statbuf;
2546 command = malloc(1000);
2547 malloc_string(curr_fname);
2548 if (!does_file_exist(incoming)) {
2549 log_it
2550 ("resolve_softlinks_to_get_to_actual_device_file --- device not found");
2551 strcpy(output, incoming);
2552 } else {
2553 strcpy(curr_fname, incoming);
2554 lstat(curr_fname, &statbuf);
2555 while (S_ISLNK(statbuf.st_mode)) {
2556 log_msg(1, "curr_fname = %s", curr_fname);
2557 sprintf(command, "file %s", curr_fname);
2558 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
2559 for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' ';
2560 p--);
2561 p++;
2562 mr_asprintf(&scratch, "%s", p);
2563 for (p = scratch; *p != '\0' && *p != '\''; p++);
2564 *p = '\0';
2565 log_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp, scratch);
2566 mr_free(tmp);
2567
2568 if (scratch[0] == '/') {
2569 strcpy(curr_fname, scratch); // copy whole thing because it's an absolute softlink
2570 } else { // copy over the basename cos it's a relative softlink
2571 p = curr_fname + strlen(curr_fname);
2572 while (p != curr_fname && *p != '/') {
2573 p--;
2574 }
2575 if (*p == '/') {
2576 p++;
2577 }
2578 strcpy(p, scratch);
2579 }
2580 mr_free(scratch);
2581 lstat(curr_fname, &statbuf);
2582 }
2583 strcpy(output, curr_fname);
2584 log_it("resolved %s to %s", incoming, output);
2585 }
2586 paranoid_free(command);
2587 paranoid_free(curr_fname);
2588 return (output);
2589}
2590
2591/* @} - end of deviceGroup */
2592
2593
2594/**
2595 * Return the type of partition format (GPT or MBR)
2596 */
2597char *which_partition_format(const char *drive)
2598{
2599 static char output[4];
2600 char *tmp = NULL;
2601 char *command;
2602 char *fdisk;
2603#ifdef __IA64__
2604 struct stat buf;
2605#endif
2606 malloc_string(command);
2607 malloc_string(fdisk);
2608 log_msg(0, "Looking for partition table format type");
2609 sprintf(fdisk, "/sbin/parted2fdisk");
2610 log_msg(1, "Using %s", fdisk);
2611 sprintf(command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
2612 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
2613 if (strstr(tmp, "GPT") == NULL) {
2614 strcpy(output, "MBR");
2615 } else {
2616 strcpy(output, "GPT");
2617 }
2618 mr_free(tmp);
2619
2620 log_msg(0, "Found %s partition table format type", output);
2621 paranoid_free(command);
2622 paranoid_free(fdisk);
2623 return (output);
2624}
2625
2626/* @} - end of deviceGroup */
Note: See TracBrowser for help on using the repository browser.