source: MondoRescue/branches/2.2.10/mondo/src/common/libmondo-devices.c@ 2258

Last change on this file since 2258 was 2257, checked in by Bruno Cornec, 15 years ago
  • Reorder code to allow compilation by older gcc versions
  • 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 2257 2009-07-05 16:56:03Z 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 2257 2009-07-05 16:56:03Z 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",
1151 SWAPLIST_COMMAND, device_with_space);
1152 log_msg(4, "tmp (command) = '%s'", tmp);
1153 if (!system(tmp)) {
1154 retval = TRUE;
1155 }
1156 mr_free(tmp);
1157 paranoid_free(incoming);
1158 return(retval);
1159}
1160
1161#ifdef __FreeBSD__
1162// CODE IS FREEBSD-SPECIFIC
1163/**
1164 * Create a loopback device for specified @p fname.
1165 * @param fname The file to associate with a device.
1166 * @return /dev entry for the device, or NULL if it couldn't be allocated.
1167 */
1168char *make_vn(char *fname)
1169{
1170 char *device = (char *) malloc(MAX_STR_LEN);
1171 char *mddevice = (char *) malloc(32);
1172 char command[MAX_STR_LEN];
1173 int vndev = 2;
1174 if (atoi
1175 (call_program_and_get_last_line_of_output
1176 ("/sbin/sysctl -n kern.osreldate")) < 500000) {
1177 do {
1178 sprintf(mddevice, "vn%ic", vndev++);
1179 sprintf(command, "vnconfig %s %s", mddevice, fname);
1180 if (vndev > 10) {
1181 return NULL;
1182 }
1183 }
1184 while (system(command));
1185 } else {
1186 sprintf(command, "mdconfig -a -t vnode -f %s", fname);
1187 mddevice = call_program_and_get_last_line_of_output(command);
1188 if (!strstr(mddevice, "md")) {
1189 return NULL;
1190 }
1191 }
1192 sprintf(device, "/dev/%s", mddevice);
1193 return device;
1194}
1195
1196
1197
1198// CODE IS FREEBSD-SPECIFIC
1199/**
1200 * Deallocate specified @p dname.
1201 * This should be called when you are done with the device created by make_vn(),
1202 * so the system does not run out of @c vn devices.
1203 * @param dname The device to deallocate.
1204 * @return 0 for success, nonzero for failure.
1205 */
1206int kick_vn(char *dname)
1207{
1208 char command[MAX_STR_LEN];
1209
1210 if (strncmp(dname, "/dev/", 5) == 0) {
1211 dname += 5;
1212 }
1213
1214 if (atoi
1215 (call_program_and_get_last_line_of_output
1216 ("/sbin/sysctl -n kern.osreldate")) < 500000) {
1217 sprintf(command, "vnconfig -d %s", dname);
1218 return system(command);
1219 } else {
1220 sprintf(command, "mdconfig -d -u %s", dname);
1221 return system(command);
1222 }
1223 /*NOTREACHED*/ return 255;
1224}
1225#endif
1226
1227
1228/**
1229 * Mount the CD-ROM at @p mountpoint.
1230 * @param device The device (or file if g_ISO_restore_mode) to mount.
1231 * @param mountpoint The place to mount it.
1232 * @return 0 for success, nonzero for failure.
1233 */
1234int mount_USB_here(char *device, char *mountpoint)
1235{
1236 /*@ buffer ****************************************************** */
1237 char *command;
1238 int retval;
1239
1240 malloc_string(command);
1241 assert_string_is_neither_NULL_nor_zerolength(device);
1242 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
1243
1244 make_hole_for_dir(mountpoint);
1245 if (isdigit(device[0])) {
1246 return(1);
1247 }
1248 log_msg(4, "(mount_USB_here --- device=%s, mountpoint=%s", device,
1249 mountpoint);
1250
1251#ifdef __FreeBSD__
1252 sprintf(command, "mount_vfat %s %s 2>> %s",
1253 device, mountpoint, MONDO_LOGFILE);
1254
1255#else
1256 sprintf(command, "mount %s -t vfat %s 2>> %s",
1257 device, mountpoint, MONDO_LOGFILE);
1258#endif
1259
1260 log_msg(4, command);
1261 retval = system(command);
1262 log_msg(1, "system(%s) returned %d", command, retval);
1263
1264 paranoid_free(command);
1265 return (retval);
1266}
1267
1268/**
1269 * Mount the CD-ROM at @p mountpoint.
1270 * @param device The device (or file if g_ISO_restore_mode) to mount.
1271 * @param mountpoint The place to mount it.
1272 * @return 0 for success, nonzero for failure.
1273 */
1274int mount_CDROM_here(char *device, char *mountpoint)
1275{
1276 /*@ buffer ****************************************************** */
1277 char *command = NULL;
1278 int retval;
1279#ifdef __FreeBSD__
1280 char *dev = NULL;
1281#else
1282 char *options = NULL;
1283#endif
1284
1285 assert_string_is_neither_NULL_nor_zerolength(device);
1286 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
1287
1288 make_hole_for_dir(mountpoint);
1289
1290 if (isdigit(device[0])) {
1291 find_cdrom_device(device, FALSE);
1292 }
1293#ifndef __FreeBSD__
1294 mr_asprintf(&options, "ro");
1295#endif
1296
1297 if (g_ISO_restore_mode) {
1298
1299#ifdef __FreeBSD__
1300 mr_asprintf(&dev, make_vn(device));
1301 if (!dev) {
1302 mr_asprintf(&command, "Unable to mount ISO (make_vn(%s) failed)", device);
1303 fatal_error(command);
1304 }
1305 strcpy(device, dev);
1306 paranoid_free(dev);
1307#else
1308 mr_strcat(options, ",loop");
1309#endif
1310
1311 }
1312 log_msg(4, "(mount_CDROM_here --- device=%s, mountpoint=%s", device,
1313 mountpoint);
1314 /*@ end vars *************************************************** */
1315
1316#ifdef __FreeBSD__
1317 mr_asprintf(&command, "mount_cd9660 -r %s %s 2>> %s",
1318 device, mountpoint, MONDO_LOGFILE);
1319
1320#else
1321 mr_asprintf(&command, "mount %s -o %s -t iso9660 %s 2>> %s",
1322 device, options, mountpoint, MONDO_LOGFILE);
1323 paranoid_free(options);
1324#endif
1325
1326 log_msg(4, command);
1327 if (strncmp(device, "/dev/", 5) == 0) {
1328 retract_CD_tray_and_defeat_autorun();
1329 }
1330 retval = system(command);
1331 log_msg(1, "system(%s) returned %d", command, retval);
1332 paranoid_free(command);
1333
1334 return (retval);
1335}
1336
1337
1338
1339
1340
1341
1342/**
1343 * Ask the user for CD number @p cd_number_i_want.
1344 * Sets g_current_media_number once the correct CD is inserted.
1345 * @param bkpinfo The backup information structure. Fields used:
1346 * - @c bkpinfo->backup_media_type
1347 * - @c bkpinfo->prefix
1348 * - @c bkpinfo->isodir
1349 * - @c bkpinfo->media_device
1350 * - @c bkpinfo->please_dont_eject_when_restoring
1351 * @param cd_number_i_want The CD number to ask for.
1352 */
1353void
1354insist_on_this_cd_number(int cd_number_i_want)
1355{
1356
1357 /*@ int ************************************************************* */
1358 int res = 0;
1359
1360
1361 /*@ buffers ********************************************************* */
1362 char *tmp;
1363 char *mds = NULL;
1364 char *request;
1365
1366 assert(bkpinfo != NULL);
1367 assert(cd_number_i_want > 0);
1368
1369// log_msg(3, "Insisting on CD number %d", cd_number_i_want);
1370
1371 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1372 log_msg(3,
1373 "No need to insist_on_this_cd_number when the backup type isn't CD-R(W) or NFS or ISO");
1374 return;
1375 }
1376 malloc_string(tmp);
1377 malloc_string(request);
1378 sprintf(tmp, "mkdir -p " MNT_CDROM);
1379 run_program_and_log_output(tmp, 5);
1380 if (g_ISO_restore_mode || bkpinfo->backup_media_type == iso
1381 || bkpinfo->backup_media_type == nfs) {
1382 log_msg(3, "Remounting CD");
1383 g_ISO_restore_mode = TRUE;
1384// FIXME --- I'm tempted to do something about this...
1385// Why unmount and remount again and again?
1386 if (is_this_device_mounted(MNT_CDROM)) {
1387 run_program_and_log_output("umount " MNT_CDROM, 5);
1388 }
1389 sprintf(tmp, "mkdir -p %s/isodir &> /dev/null", bkpinfo->tmpdir);
1390 (void)system(tmp);
1391 sprintf(tmp, "%s/%s/%s-%d.iso", bkpinfo->isodir,
1392 bkpinfo->nfs_remote_dir, bkpinfo->prefix,
1393 cd_number_i_want);
1394 if (!does_file_exist(tmp)) {
1395 sprintf(tmp, "%s/isodir/%s/%s-%d.iso", bkpinfo->tmpdir,
1396 bkpinfo->nfs_remote_dir, bkpinfo->prefix,
1397 cd_number_i_want);
1398 if (does_file_exist(tmp)) {
1399 log_msg(1,
1400 "FIXME - hacking bkpinfo->isodir from '%s' to %s/isodir",
1401 bkpinfo->isodir, bkpinfo->tmpdir);
1402 sprintf(bkpinfo->isodir, "%s/isodir", bkpinfo->tmpdir);
1403 }
1404 }
1405 log_msg(3, "Mounting %s at %s", tmp, MNT_CDROM);
1406 if (mount_CDROM_here(tmp, MNT_CDROM)) {
1407 fatal_error("Mommy!");
1408 }
1409// g_current_media_number = cd_number_i_want;
1410// return;
1411 }
1412 if ((res = what_number_cd_is_this()) != cd_number_i_want) {
1413 log_msg(3, "Currently, we hold %d but we want %d", res,
1414 cd_number_i_want);
1415 mds = media_descriptor_string(bkpinfo->backup_media_type);
1416 sprintf(tmp, "Insisting on %s #%d", mds, cd_number_i_want);
1417 sprintf(request, "Please insert %s #%d and press Enter.", mds, cd_number_i_want);
1418 mr_free(mds);
1419 log_msg(3, tmp);
1420 while (what_number_cd_is_this() != cd_number_i_want) {
1421 paranoid_system("sync");
1422 if (is_this_device_mounted(MNT_CDROM)) {
1423 res =
1424 run_program_and_log_output("umount " MNT_CDROM, FALSE);
1425 } else {
1426 res = 0;
1427 }
1428 if (res) {
1429 log_to_screen("WARNING - failed to unmount CD-ROM drive");
1430 }
1431 if (!bkpinfo->please_dont_eject) {
1432 res = eject_device(bkpinfo->media_device);
1433 } else {
1434 res = 0;
1435 }
1436 if (res) {
1437 log_to_screen("WARNING - failed to eject CD-ROM disk");
1438 }
1439 popup_and_OK(request);
1440 if (!bkpinfo->please_dont_eject) {
1441 inject_device(bkpinfo->media_device);
1442 }
1443 paranoid_system("sync");
1444 }
1445 log_msg(1, "Thankyou. Proceeding...");
1446 g_current_media_number = cd_number_i_want;
1447 }
1448 paranoid_free(tmp);
1449 paranoid_free(request);
1450}
1451
1452/* @} - end of deviceGroup */
1453
1454
1455
1456
1457
1458
1459/**
1460 * Ask user for details of backup/restore information.
1461 * Called when @c mondoarchive doesn't get any parameters.
1462 * @param bkpinfo The backup information structure to fill out with the user's data.
1463 * @param archiving_to_media TRUE if archiving, FALSE if restoring.
1464 * @return 0, always.
1465 * @bug No point of `int' return value.
1466 * @ingroup archiveGroup
1467 */
1468int interactively_obtain_media_parameters_from_user(bool archiving_to_media)
1469// archiving_to_media is TRUE if I'm being called by mondoarchive
1470// archiving_to_media is FALSE if I'm being called by mondorestore
1471{
1472 char *tmp = NULL;
1473 char *mds = NULL;
1474 char *sz_size;
1475 char *command;
1476 char *comment;
1477 char *prompt;
1478 int i;
1479 FILE *fin;
1480
1481 malloc_string(sz_size);
1482 malloc_string(command);
1483 malloc_string(comment);
1484 malloc_string(prompt);
1485 assert(bkpinfo != NULL);
1486 sz_size[0] = '\0';
1487 bkpinfo->nonbootable_backup = FALSE;
1488
1489 // Tape, CD, NFS, ...?
1490 srandom(getpid());
1491 bkpinfo->backup_media_type =
1492 (g_restoring_live_from_cd) ? cdr :
1493 which_backup_media_type(bkpinfo->restore_data);
1494 if (bkpinfo->backup_media_type == none) {
1495 log_to_screen("User has chosen not to backup the PC");
1496 finish(1);
1497 }
1498 /* Why asking to remove the media with tape ?
1499 if (bkpinfo->backup_media_type == tape && bkpinfo->restore_data) {
1500 popup_and_OK("Please remove media from drive(s)");
1501 }
1502 */
1503 log_msg(3, "media type = %s",
1504 bkptype_to_string(bkpinfo->backup_media_type));
1505 if (archiving_to_media) {
1506 sensibly_set_tmpdir_and_scratchdir();
1507 }
1508 bkpinfo->cdrw_speed = (bkpinfo->backup_media_type == cdstream) ? 2 : 4;
1509 bkpinfo->compression_level =
1510 (bkpinfo->backup_media_type == cdstream) ? 1 : 5;
1511 bkpinfo->use_lzo =
1512 (bkpinfo->backup_media_type == cdstream) ? TRUE : FALSE;
1513 mvaddstr_and_log_it(2, 0, " ");
1514
1515 // Find device's /dev (or SCSI) entry
1516 switch (bkpinfo->backup_media_type) {
1517 case cdr:
1518 case cdrw:
1519 case dvd:
1520 case usb:
1521 /* Never try to eject a USB device */
1522 if (bkpinfo->backup_media_type == usb) {
1523 bkpinfo->please_dont_eject = TRUE;
1524 }
1525 if (archiving_to_media) {
1526 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
1527 if (ask_me_yes_or_no
1528 ("Is your computer a laptop, or does the CD writer incorporate BurnProof technology?"))
1529 {
1530 bkpinfo->manual_cd_tray = TRUE;
1531 }
1532 }
1533 if ((bkpinfo->compression_level =
1534 which_compression_level()) == -1) {
1535 log_to_screen("User has chosen not to backup the PC");
1536 finish(1);
1537 }
1538 mds = media_descriptor_string(bkpinfo->backup_media_type);
1539 sprintf(comment, "What speed is your %s (re)writer?", mds);
1540 if (bkpinfo->backup_media_type == dvd) {
1541 find_dvd_device(bkpinfo->media_device, FALSE);
1542 mr_asprintf(&tmp, "1");
1543 sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB
1544 log_msg(1, "Setting to DVD defaults");
1545 } else {
1546 strcpy(bkpinfo->media_device, VANILLA_SCSI_CDROM);
1547 mr_asprintf(&tmp, "4");
1548 strcpy(sz_size, "650");
1549 log_msg(1, "Setting to CD defaults");
1550 }
1551 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
1552 if (!popup_and_get_string("Speed", comment, tmp, 4)) {
1553 log_to_screen("User has chosen not to backup the PC");
1554 finish(1);
1555 }
1556 }
1557 bkpinfo->cdrw_speed = atoi(tmp); // if DVD then this shouldn't ever be used anyway :)
1558 mr_free(tmp);
1559
1560 sprintf(comment,
1561 "How much data (in Megabytes) will each %s store?", mds);
1562 mr_free(mds);
1563 if (!popup_and_get_string("Size", comment, sz_size, 5)) {
1564 log_to_screen("User has chosen not to backup the PC");
1565 finish(1);
1566 }
1567 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1568 bkpinfo->media_size[i] = atoi(sz_size);
1569 }
1570 if (bkpinfo->media_size[0] <= 0) {
1571 log_to_screen("User has chosen not to backup the PC");
1572 finish(1);
1573 }
1574 }
1575 /* No break because we continue even for usb */
1576 case cdstream:
1577 mds = media_descriptor_string(bkpinfo->backup_media_type);
1578
1579 if ((bkpinfo->disaster_recovery) && (bkpinfo->backup_media_type != usb)) {
1580 strcpy(bkpinfo->media_device, "/dev/cdrom");
1581 log_msg(2, "CD-ROM device assumed to be at %s",
1582 bkpinfo->media_device);
1583 } else if ((bkpinfo->restore_data && (bkpinfo->backup_media_type != usb))
1584 || bkpinfo->backup_media_type == dvd) {
1585 if (!bkpinfo->media_device[0]) {
1586 strcpy(bkpinfo->media_device, "/dev/cdrom");
1587 } // just for the heck of it :)
1588 log_msg(1, "bkpinfo->media_device = %s",
1589 bkpinfo->media_device);
1590 if (bkpinfo->backup_media_type == dvd
1591 || find_cdrom_device(bkpinfo->media_device, FALSE)) {
1592 log_msg(1, "bkpinfo->media_device = %s",
1593 bkpinfo->media_device);
1594 sprintf(comment,
1595 "Please specify your %s drive's /dev entry", mds);
1596 if (!popup_and_get_string
1597 ("Device?", comment, bkpinfo->media_device,
1598 MAX_STR_LEN / 4)) {
1599 log_to_screen("User has chosen not to backup the PC");
1600 finish(1);
1601 }
1602 }
1603 log_msg(2, "%s device found at %s", mds, bkpinfo->media_device);
1604 } else {
1605 if ((find_cdrw_device(bkpinfo->media_device)) && (bkpinfo->backup_media_type != usb)) {
1606 bkpinfo->media_device[0] = '\0';
1607 }
1608 if (bkpinfo->media_device[0]) {
1609 if (bkpinfo->backup_media_type == usb) {
1610 mr_asprintf(&tmp,
1611 "I think your %s media corresponds to %s. Is this correct?", mds,
1612 bkpinfo->media_device);
1613 } else {
1614 mr_asprintf(&tmp,
1615 "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,
1616 bkpinfo->media_device);
1617 }
1618 if (!ask_me_yes_or_no(tmp)) {
1619 bkpinfo->media_device[0] = '\0';
1620 }
1621 mr_free(tmp);
1622 }
1623 if (!bkpinfo->media_device[0]) {
1624 if (bkpinfo->backup_media_type == usb) {
1625 i = popup_and_get_string("/dev entry?",
1626 "What is the /dev entry of your USB Disk/Key, please?",
1627 bkpinfo->media_device,
1628 MAX_STR_LEN / 4);
1629 } else {
1630 if (g_kernel_version < 2.6) {
1631 i = popup_and_get_string("Device node?",
1632 "What is the SCSI node of your CD (re)writer, please?",
1633 bkpinfo->media_device,
1634 MAX_STR_LEN / 4);
1635 } else {
1636 i = popup_and_get_string("/dev entry?",
1637 "What is the /dev entry of your CD (re)writer, please?",
1638 bkpinfo->media_device,
1639 MAX_STR_LEN / 4);
1640 }
1641 }
1642 if (!i) {
1643 log_to_screen("User has chosen not to backup the PC");
1644 finish(1);
1645 }
1646 }
1647 }
1648 mr_free(mds);
1649
1650 if (bkpinfo->backup_media_type == cdstream) {
1651 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1652 bkpinfo->media_size[i] = 650;
1653 }
1654 }
1655 break;
1656 case udev:
1657 if (!ask_me_yes_or_no
1658 ("This option is for advanced users only. Are you sure?")) {
1659 log_to_screen("User has chosen not to backup the PC");
1660 finish(1);
1661 }
1662 case tape:
1663
1664 if ((!bkpinfo->restore_mode) && (find_tape_device_and_size(bkpinfo->media_device, sz_size))) {
1665 log_msg(3, "Ok, using vanilla scsi tape.");
1666 strcpy(bkpinfo->media_device, VANILLA_SCSI_TAPE);
1667 if ((fin = fopen(bkpinfo->media_device, "r"))) {
1668 paranoid_fclose(fin);
1669 } else {
1670 strcpy(bkpinfo->media_device, "/dev/osst0");
1671 }
1672 }
1673 if (bkpinfo->media_device[0]) {
1674 if ((fin = fopen(bkpinfo->media_device, "r"))) {
1675 paranoid_fclose(fin);
1676 } else {
1677 if (does_file_exist("/tmp/mondo-restore.cfg")) {
1678 read_cfg_var("/tmp/mondo-restore.cfg", "media-dev",
1679 bkpinfo->media_device);
1680 }
1681 }
1682 }
1683 if (bkpinfo->media_device[0]) {
1684 mr_asprintf(&tmp,
1685 "I think I've found your tape streamer at %s; am I right on the money?",
1686 bkpinfo->media_device);
1687 if (!ask_me_yes_or_no(tmp)) {
1688 bkpinfo->media_device[0] = '\0';
1689 }
1690 mr_free(tmp);
1691 }
1692 if (!bkpinfo->media_device[0]) {
1693 if (!popup_and_get_string
1694 ("Device name?",
1695 "What is the /dev entry of your tape streamer?",
1696 bkpinfo->media_device, MAX_STR_LEN / 4)) {
1697 log_to_screen("User has chosen not to backup the PC");
1698 finish(1);
1699 }
1700 }
1701 mr_asprintf(&tmp, "ls -l %s", bkpinfo->media_device);
1702 if (run_program_and_log_output(tmp, FALSE)) {
1703 log_to_screen("User has not specified a valid /dev entry");
1704 finish(1);
1705 }
1706 mr_free(tmp);
1707 log_msg(4, "sz_size = %s", sz_size);
1708 sz_size[0] = '\0';
1709
1710 bkpinfo->use_obdr = ask_me_yes_or_no
1711 ("Do you want to activate OBDR support for your tapes ?");
1712 if (sz_size[0] == '\0') {
1713 bkpinfo->media_size[0] = 0;
1714 } else {
1715 bkpinfo->media_size[0] =
1716 friendly_sizestr_to_sizelong(sz_size) / 2 - 50;
1717 }
1718 log_msg(4, "media_size[0] = %ld", bkpinfo->media_size[0]);
1719 if (bkpinfo->media_size[0] <= 0) {
1720 bkpinfo->media_size[0] = 0;
1721 }
1722 for (i = 1; i <= MAX_NOOF_MEDIA; i++) {
1723 bkpinfo->media_size[i] = bkpinfo->media_size[0];
1724 }
1725 if (archiving_to_media) {
1726 if ((bkpinfo->compression_level =
1727 which_compression_level()) == -1) {
1728 log_to_screen("User has chosen not to backup the PC");
1729 finish(1);
1730 }
1731 }
1732 break;
1733
1734
1735
1736 case nfs:
1737 /* Never try to eject a NFS device */
1738 bkpinfo->please_dont_eject = TRUE;
1739
1740 /* Initiate bkpinfo nfs_mount path from running environment if not already done */
1741 if (!bkpinfo->nfs_mount[0]) {
1742 strcpy(bkpinfo->nfs_mount,
1743 call_program_and_get_last_line_of_output
1744 ("mount | grep \":\" | cut -d' ' -f1 | head -n1"));
1745 }
1746#ifdef __FreeBSD__
1747 if (TRUE)
1748#else
1749 if (!bkpinfo->disaster_recovery)
1750#endif
1751 {
1752 if (!popup_and_get_string
1753 ("NFS dir.",
1754 "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.)",
1755 bkpinfo->nfs_mount, MAX_STR_LEN / 4)) {
1756 log_to_screen("User has chosen not to backup the PC");
1757 finish(1);
1758 }
1759 if (!bkpinfo->restore_data) {
1760 if ((bkpinfo->compression_level =
1761 which_compression_level()) == -1) {
1762 log_to_screen("User has chosen not to backup the PC");
1763 finish(1);
1764 }
1765 }
1766 // check whether already mounted - we better remove
1767 // surrounding spaces and trailing '/' for this
1768 strip_spaces(bkpinfo->nfs_mount);
1769 if (bkpinfo->nfs_mount[strlen(bkpinfo->nfs_mount) - 1] == '/')
1770 bkpinfo->nfs_mount[strlen(bkpinfo->nfs_mount) - 1] = '\0';
1771 sprintf(command, "mount | grep \"%s \" | cut -d' ' -f3",
1772 bkpinfo->nfs_mount);
1773 strcpy(bkpinfo->isodir,
1774 call_program_and_get_last_line_of_output(command));
1775
1776 if (!bkpinfo->restore_data) {
1777 sprintf(comment,
1778 "How much data (in Megabytes) will each media store?");
1779 if (!popup_and_get_string("Size", comment, sz_size, 5)) {
1780 log_to_screen("User has chosen not to backup the PC");
1781 finish(1);
1782 }
1783 } else {
1784 strcpy(sz_size, "0");
1785 }
1786 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1787 bkpinfo->media_size[i] = atoi(sz_size);
1788 }
1789 if (bkpinfo->media_size[0] < 0) {
1790 log_to_screen("User has chosen not to backup the PC");
1791 finish(1);
1792 }
1793 }
1794 if (bkpinfo->disaster_recovery) {
1795 sprintf(command ,"umount %s/isodir 2> /dev/null", bkpinfo->tmpdir);
1796 (void)system(command);
1797 if (!popup_and_get_string
1798 ("NFS share", "Which remote NFS share should I mount?",
1799 bkpinfo->nfs_mount, MAX_STR_LEN)) {
1800 log_to_screen("User has chosen not to backup the PC");
1801 finish(1);
1802 }
1803 }
1804 /* Initiate bkpinfo isodir path from running environment if mount already done */
1805 if (is_this_device_mounted(bkpinfo->nfs_mount)) {
1806 strcpy(bkpinfo->isodir,
1807 call_program_and_get_last_line_of_output
1808 ("mount | grep \":\" | cut -d' ' -f3 | head -n1"));
1809 } else {
1810 sprintf(bkpinfo->isodir, "%s/nfsdir", bkpinfo->tmpdir);
1811 sprintf(command, "mkdir -p %s", bkpinfo->isodir);
1812 run_program_and_log_output(command, 5);
1813 mr_asprintf(&tmp, "mount -t nfs -o nolock %s %s", bkpinfo->nfs_mount,
1814 bkpinfo->isodir);
1815 run_program_and_log_output(tmp, 3);
1816 mr_free(tmp);
1817
1818 malloc_string(g_selfmounted_isodir);
1819 strcpy(g_selfmounted_isodir, bkpinfo->isodir);
1820 }
1821 if (!is_this_device_mounted(bkpinfo->nfs_mount)) {
1822 popup_and_OK
1823 ("Please mount that partition before you try to backup to or restore from it.");
1824 finish(1);
1825 }
1826 mr_asprintf(&tmp, bkpinfo->nfs_remote_dir);
1827 if (!popup_and_get_string
1828 ("Directory", "Which directory within that mountpoint?", tmp,
1829 MAX_STR_LEN)) {
1830 log_to_screen("User has chosen not to backup the PC");
1831 finish(1);
1832 }
1833 strcpy(bkpinfo->nfs_remote_dir, tmp);
1834 mr_free(tmp);
1835
1836 // check whether writable - we better remove surrounding spaces for this
1837 strip_spaces(bkpinfo->nfs_remote_dir);
1838
1839 if (!popup_and_get_string
1840 ("Prefix.",
1841 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
1842 bkpinfo->prefix, MAX_STR_LEN / 4)) {
1843 log_to_screen("User has chosen not to backup the PC");
1844 finish(1);
1845 }
1846 log_msg(3, "prefix set to %s", bkpinfo->prefix);
1847
1848 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1849 bkpinfo->media_size[i] = 650;
1850 }
1851 log_msg(3, "Just set nfs_remote_dir to %s",
1852 bkpinfo->nfs_remote_dir);
1853 log_msg(3, "isodir is still %s", bkpinfo->isodir);
1854 break;
1855
1856 case iso:
1857 if (!bkpinfo->disaster_recovery) {
1858 if (!popup_and_get_string
1859 ("Storage dir.",
1860 "Please enter the full path name to the directory for your ISO images. Example: /mnt/raid0_0",
1861 bkpinfo->isodir, MAX_STR_LEN / 4)) {
1862 log_to_screen("User has chosen not to backup the PC");
1863 finish(1);
1864 }
1865 if (archiving_to_media) {
1866 if ((bkpinfo->compression_level =
1867 which_compression_level()) == -1) {
1868 log_to_screen("User has chosen not to backup the PC");
1869 finish(1);
1870 }
1871 if (!popup_and_get_string
1872 ("ISO size.",
1873 "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.",
1874 sz_size, 16)) {
1875 log_to_screen("User has chosen not to backup the PC");
1876 finish(1);
1877 }
1878 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1879 bkpinfo->media_size[i] = atoi(sz_size);
1880 }
1881 } else {
1882 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1883 bkpinfo->media_size[i] = 650;
1884 }
1885 }
1886 }
1887 if (!popup_and_get_string
1888 ("Prefix.",
1889 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
1890 bkpinfo->prefix, MAX_STR_LEN / 4)) {
1891 log_to_screen("User has chosen not to backup the PC");
1892 finish(1);
1893 }
1894 log_msg(3, "prefix set to %s", bkpinfo->prefix);
1895 break;
1896 default:
1897 fatal_error
1898 ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
1899 }
1900
1901 if (archiving_to_media) {
1902
1903#ifdef __FreeBSD__
1904 strcpy(bkpinfo->boot_device,
1905 call_program_and_get_last_line_of_output
1906 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
1907#else
1908 strcpy(bkpinfo->boot_device,
1909 call_program_and_get_last_line_of_output
1910 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
1911#endif
1912 i = which_boot_loader(bkpinfo->boot_device);
1913 if (i == 'U') // unknown
1914 {
1915
1916#ifdef __FreeBSD__
1917 if (!popup_and_get_string
1918 ("Boot device",
1919 "What is your boot device? (e.g. /dev/ad0)",
1920 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
1921 log_to_screen("User has chosen not to backup the PC");
1922 finish(1);
1923 }
1924 i = which_boot_loader(bkpinfo->boot_device);
1925#else
1926 if (!popup_and_get_string
1927 ("Boot device",
1928 "What is your boot device? (e.g. /dev/hda)",
1929 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
1930 log_to_screen("User has chosen not to backup the PC");
1931 finish(1);
1932 }
1933 if (does_string_exist_in_boot_block
1934 (bkpinfo->boot_device, "LILO")) {
1935 i = 'L';
1936 } else
1937 if (does_string_exist_in_boot_block
1938 (bkpinfo->boot_device, "ELILO")) {
1939 i = 'E';
1940 } else
1941 if (does_string_exist_in_boot_block
1942 (bkpinfo->boot_device, "GRUB")) {
1943 i = 'G';
1944 } else {
1945 i = 'U';
1946 }
1947#endif
1948 if (i == 'U') {
1949 if (ask_me_yes_or_no
1950 ("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?"))
1951 {
1952 i = 'R'; // raw
1953 } else {
1954 log_to_screen
1955 ("I cannot find your boot loader. Please run mondoarchive with parameters.");
1956 finish(1);
1957 }
1958 }
1959 }
1960 bkpinfo->boot_loader = i;
1961 strcpy(bkpinfo->include_paths, "/");
1962 if (!popup_and_get_string
1963 ("Backup paths",
1964 "Please enter paths which you want me to backup. The default is '/' (i.e. everything).",
1965 bkpinfo->include_paths, MAX_STR_LEN)) {
1966 log_to_screen("User has chosen not to backup the PC");
1967 finish(1);
1968 }
1969 mr_asprintf(&tmp, "%s", list_of_NFS_mounts_only());
1970 if (strlen(tmp) > 2) {
1971 if (bkpinfo->exclude_paths[0]) {
1972 strcat(bkpinfo->exclude_paths, " ");
1973 }
1974 strncpy(bkpinfo->exclude_paths, tmp, MAX_STR_LEN);
1975 }
1976 mr_free(tmp);
1977// NTFS
1978 mr_asprintf(&tmp, "%s",
1979 call_program_and_get_last_line_of_output
1980 ("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'"));
1981 if (strlen(tmp) > 2) {
1982 if (!popup_and_get_string
1983 ("NTFS partitions",
1984 "Please enter/confirm the NTFS partitions you wish to backup as well.",
1985 tmp, MAX_STR_LEN / 4)) {
1986 log_to_screen("User has chosen not to backup the PC");
1987 finish(1);
1988 }
1989 strncpy(bkpinfo->image_devs, tmp, MAX_STR_LEN / 4);
1990 }
1991 mr_free(tmp);
1992
1993
1994 if (!popup_and_get_string
1995 ("Exclude paths",
1996 "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.",
1997 bkpinfo->exclude_paths, (4*MAX_STR_LEN)-1)) {
1998 log_to_screen("User has chosen not to backup the PC");
1999 finish(1);
2000 }
2001 if (!popup_and_get_string
2002 ("Temporary directory",
2003 "Please enter your temporary directory.",
2004 bkpinfo->tmpdir, (4*MAX_STR_LEN)-1)) {
2005 log_to_screen("User has chosen not to backup the PC");
2006 finish(1);
2007 }
2008 if (!popup_and_get_string
2009 ("Scratch directory",
2010 "Please enter your scratch directory.",
2011 bkpinfo->scratchdir, (4*MAX_STR_LEN)-1)) {
2012 log_to_screen("User has chosen not to backup the PC");
2013 finish(1);
2014 }
2015// Interactive mode:
2016#ifdef __IA64__
2017 bkpinfo->make_cd_use_lilo = TRUE;
2018#else
2019 bkpinfo->make_cd_use_lilo = FALSE;
2020#endif
2021 bkpinfo->backup_data = TRUE;
2022 bkpinfo->verify_data =
2023 ask_me_yes_or_no
2024 ("Will you want to verify your backups after Mondo has created them?");
2025
2026#ifndef __FreeBSD__
2027 if (!ask_me_yes_or_no
2028 ("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."))
2029#endif
2030 {
2031 strcpy(bkpinfo->kernel_path, "FAILSAFE");
2032 }
2033
2034 if (!ask_me_yes_or_no
2035 ("Are you sure you want to proceed? Hit 'no' to abort.")) {
2036 log_to_screen("User has chosen not to backup the PC");
2037 finish(1);
2038 }
2039 } else {
2040 bkpinfo->restore_data = TRUE; // probably...
2041 }
2042
2043 if (bkpinfo->backup_media_type == iso
2044 || bkpinfo->backup_media_type == nfs) {
2045 g_ISO_restore_mode = TRUE;
2046 }
2047#ifdef __FreeSD__
2048// skip
2049#else
2050 if (bkpinfo->backup_media_type == nfs) {
2051 log_msg(3, "I think the NFS mount is mounted at %s",
2052 bkpinfo->isodir);
2053 }
2054 log_it("isodir = %s", bkpinfo->isodir);
2055 log_it("nfs_mount = '%s'", bkpinfo->nfs_mount);
2056 if (bkpinfo->nfs_user) {
2057 log_it("nfs_user = '%s'", bkpinfo->nfs_user);
2058 }
2059#endif
2060
2061 log_it("media device = %s", bkpinfo->media_device);
2062 log_it("media size = %ld", bkpinfo->media_size[1]);
2063 log_it("media type = %s",
2064 bkptype_to_string(bkpinfo->backup_media_type));
2065 log_it("prefix = %s", bkpinfo->prefix);
2066 log_it("compression = %ld", bkpinfo->compression_level);
2067 log_it("include_paths = '%s'", bkpinfo->include_paths);
2068 log_it("exclude_paths = '%s'", bkpinfo->exclude_paths);
2069 log_it("scratchdir = '%s'", bkpinfo->scratchdir);
2070 log_it("tmpdir = '%s'", bkpinfo->tmpdir);
2071 log_it("image_devs = '%s'", bkpinfo->image_devs);
2072 log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device,
2073 bkpinfo->boot_loader);
2074 if (bkpinfo->media_size[0] < 0) {
2075 if (archiving_to_media) {
2076 fatal_error("Media size is less than zero.");
2077 } else {
2078 log_msg(2, "Warning - media size is less than zero.");
2079 bkpinfo->media_size[0] = 0;
2080 }
2081 }
2082 paranoid_free(sz_size);
2083 paranoid_free(command);
2084 paranoid_free(comment);
2085 paranoid_free(prompt);
2086 return (0);
2087}
2088
2089
2090
2091
2092/**
2093 * @addtogroup utilityGroup
2094 * @{
2095 */
2096/**
2097 * Get a space-separated list of NFS devices and mounts.
2098 * @return The list created.
2099 * @note The return value points to static data that will be overwritten with each call.
2100 */
2101char *list_of_NFS_devices_and_mounts(void)
2102{
2103 char *exclude_these_devices = NULL;
2104 char *exclude_these_directories = NULL;
2105 static char result_sz[1024];
2106
2107 mr_asprintf(&exclude_these_directories,"%s",list_of_NFS_mounts_only());
2108 mr_asprintf(&exclude_these_devices,"%s",
2109 call_program_and_get_last_line_of_output
2110 ("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;}'"));
2111 snprintf(result_sz, 1023, "%s %s", exclude_these_directories, exclude_these_devices);
2112 mr_free(exclude_these_devices);
2113 mr_free(exclude_these_directories);
2114 return (result_sz);
2115}
2116
2117
2118
2119
2120/**
2121 * Get a space-separated list of NFS mounts.
2122 * @return The list created.
2123 * @note The return value points to static data that will be overwritten with each call.
2124 * @bug Even though we only want the mounts, the devices are still checked.
2125 */
2126char *list_of_NFS_mounts_only(void)
2127{
2128 char *exclude_these_directories = NULL;
2129 static char result_sz[512];
2130
2131 mr_asprintf(&exclude_these_directories,"%s",
2132 call_program_and_get_last_line_of_output
2133 ("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;}'"));
2134 snprintf(result_sz, 511, "%s", exclude_these_directories);
2135 mr_free(exclude_these_directories);
2136 return (result_sz);
2137}
2138
2139/* @} - end of utilityGroup */
2140
2141
2142
2143
2144
2145/**
2146 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
2147 * [random] is a random number between 1 and 32767.
2148 * @param store_name_here Where to store the new filename.
2149 * @param stub A random number will be appended to this to make the FIFO's name.
2150 * @ingroup deviceGroup
2151 */
2152void make_fifo(char *store_name_here, char *stub)
2153{
2154 char *tmp;
2155
2156 malloc_string(tmp);
2157 assert_string_is_neither_NULL_nor_zerolength(stub);
2158
2159 sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
2160 (int) (random() % 32768));
2161 make_hole_for_file(store_name_here);
2162 mkfifo(store_name_here, S_IRWXU | S_IRWXG);
2163 sprintf(tmp, "chmod 770 %s", store_name_here);
2164 paranoid_system(tmp);
2165 paranoid_free(tmp);
2166}
2167
2168
2169
2170
2171
2172
2173/**
2174 * Set the tmpdir and scratchdir to reside on the partition with the most free space.
2175 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
2176 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set.
2177 * @ingroup utilityGroup
2178 */
2179void sensibly_set_tmpdir_and_scratchdir()
2180{
2181 char *tmp = NULL;
2182 char *command = NULL;
2183 char *sz = NULL;
2184
2185 assert(bkpinfo != NULL);
2186
2187#ifdef __FreeBSD__
2188 mr_asprintf(&tmp,
2189 call_program_and_get_last_line_of_output
2190 ("LANGUAGE=C df -m -P -t nonfs,msdosfs,ntfs,ntfs-3g,smbfs,smb,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol | tr -s '\t' ' ' | grep -vE \"none|Filesystem\" | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -n | tail -n1 | awk '{print $NF;}'"));
2191#else
2192 mr_asprintf(&tmp,
2193 call_program_and_get_last_line_of_output
2194 ("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| sed 's/ /devdev/' | tr -s '\t' ' ' | grep -vE \"none|Filesystem|/dev/shm\" | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -n | tail -n1 | awk '{print $NF;}'"));
2195#endif
2196
2197 if (tmp[0] != '/') {
2198 mr_asprintf(&sz, tmp);
2199 paranoid_free(tmp);
2200 mr_asprintf(&tmp, "/%s", sz);
2201 mr_free(sz);
2202 }
2203 if (!tmp[0]) {
2204 fatal_error("I couldn't figure out the tempdir!");
2205 }
2206 setup_tmpdir(tmp);
2207 log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir);
2208
2209 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%d", tmp,
2210 (int) (random() % 32768));
2211 log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
2212
2213 mr_asprintf(&command, "rm -Rf %s/tmp.mondo.* %s/mondo.scratch.*", tmp, tmp);
2214 paranoid_free(tmp);
2215
2216 paranoid_system(command);
2217 mr_free(command);
2218}
2219
2220
2221
2222
2223
2224
2225/**
2226 * @addtogroup deviceGroup
2227 * @{
2228 */
2229/**
2230 * If we can read @p dev, set @p output to it.
2231 * If @p dev cannot be read, set @p output to "".
2232 * @param dev The device to check for.
2233 * @param output Set to @p dev if @p dev exists, "" otherwise.
2234 * @return TRUE if @p dev exists, FALSE if it doesn't.
2235 */
2236bool set_dev_to_this_if_rx_OK(char *output, char *dev)
2237{
2238 char *command;
2239
2240 malloc_string(command);
2241 if (!dev || dev[0] == '\0') {
2242 output[0] = '\0';
2243 return (FALSE);
2244 }
2245// assert_string_is_neither_NULL_nor_zerolength(dev);
2246 log_msg(10, "Injecting %s", dev);
2247 inject_device(dev);
2248 if (!does_file_exist(dev)) {
2249 log_msg(10, "%s doesn't exist. Returning FALSE.", dev);
2250 return (FALSE);
2251 }
2252 sprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null",
2253 512L, dev);
2254 if (!run_program_and_log_output(command, FALSE)
2255 && !run_program_and_log_output(command, FALSE)) {
2256 strcpy(output, dev);
2257 log_msg(4, "Found it - %s", dev);
2258 return (TRUE);
2259 } else {
2260 output[0] = '\0';
2261 log_msg(4, "It's not %s", dev);
2262 return (FALSE);
2263 }
2264}
2265
2266
2267
2268
2269
2270/**
2271 * Find out what number CD is in the drive.
2272 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
2273 * @return The current CD number, or -1 if it could not be found.
2274 * @note If the CD is not mounted, it will be mounted
2275 * (and remain mounted after this function returns).
2276 */
2277int what_number_cd_is_this()
2278{
2279 int cd_number = -1;
2280 char *mountdev = NULL;
2281 char *tmp = NULL;
2282
2283 assert(bkpinfo != NULL);
2284// log_it("Asking what_number_cd_is_this");
2285 if (g_ISO_restore_mode) {
2286 mr_asprintf(&tmp, "mount | grep iso9660 | awk '{print $3;}'");
2287
2288 mr_asprintf(&mountdev, "%s%s", call_program_and_get_last_line_of_output(tmp), "/archives/THIS-CD-NUMBER");
2289 cd_number = atoi(last_line_of_file(mountdev));
2290 paranoid_free(mountdev);
2291 paranoid_free(tmp);
2292
2293 return (cd_number);
2294 }
2295
2296 mr_asprintf(&mountdev, bkpinfo->media_device);
2297 if (!mountdev[0]) {
2298 log_it
2299 ("(what_number_cd_is_this) Warning - media_device unknown. Finding out...");
2300 find_cdrom_device(bkpinfo->media_device, FALSE);
2301 }
2302 if (!is_this_device_mounted(MNT_CDROM)) {
2303 if (bkpinfo->backup_media_type == usb) {
2304 mount_USB_here(mountdev, MNT_CDROM);
2305 } else {
2306 mount_CDROM_here(mountdev, MNT_CDROM);
2307 }
2308 }
2309 paranoid_free(mountdev);
2310
2311 cd_number = atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
2312 return (cd_number);
2313}
2314
2315
2316
2317
2318
2319
2320
2321/**
2322 * Find out what device is mounted as root (/).
2323 * @return Root device.
2324 * @note The returned string points to static storage and will be overwritten with every call.
2325 * @bug A bit of a misnomer; it's actually finding out the root device.
2326 * The mountpoint (where it's mounted) will obviously be '/'.
2327 */
2328char *where_is_root_mounted()
2329{
2330 /*@ buffers **************** */
2331 static char tmp[MAX_STR_LEN];
2332
2333
2334#ifdef __FreeBSD__
2335 strcpy(tmp, call_program_and_get_last_line_of_output
2336 ("mount | grep \" on / \" | cut -d' ' -f1"));
2337#else
2338 strcpy(tmp, call_program_and_get_last_line_of_output
2339 ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"));
2340 if (strstr(tmp, "/dev/cciss/")) {
2341 strcpy(tmp, call_program_and_get_last_line_of_output
2342 ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"));
2343 }
2344 if (strstr(tmp, "/dev/md")) {
2345 strcpy(tmp,
2346 call_program_and_get_last_line_of_output
2347 ("mount | grep \" on / \" | cut -d' ' -f1"));
2348 }
2349#endif
2350
2351 return (tmp);
2352}
2353
2354
2355/**
2356 * Find out which boot loader is in use.
2357 * @param which_device Device to look for the boot loader on.
2358 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
2359 * @note Under Linux, all drives are examined, not just @p which_device.
2360 */
2361#ifdef __FreeBSD__
2362char which_boot_loader(char *which_device)
2363{
2364 int count_lilos = 0;
2365 int count_grubs = 0;
2366 int count_boot0s = 0;
2367 int count_dangerouslydedicated = 0;
2368
2369 log_it("looking at drive %s's MBR", which_device);
2370 if (does_string_exist_in_boot_block(which_device, "GRUB")) {
2371 count_grubs++;
2372 }
2373 if (does_string_exist_in_boot_block(which_device, "LILO")) {
2374 count_lilos++;
2375 }
2376 if (does_string_exist_in_boot_block(which_device, "Drive")) {
2377 count_boot0s++;
2378 }
2379 if (does_string_exist_in_first_N_blocks
2380 (which_device, "FreeBSD/i386", 17)) {
2381 count_dangerouslydedicated++;
2382 }
2383 log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
2384 count_grubs, count_lilos, count_elilos, count_boot0s,
2385 count_dangerouslydedicated);
2386
2387 if (count_grubs && !count_lilos) {
2388 return ('G');
2389 } else if (count_lilos && !count_grubs) {
2390 return ('L');
2391 } else if (count_grubs == 1 && count_lilos == 1) {
2392 log_it("I'll bet you used to use LILO but switched to GRUB...");
2393 return ('G');
2394 } else if (count_boot0s == 1) {
2395 return ('B');
2396 } else if (count_dangerouslydedicated) {
2397 return ('D');
2398 } else {
2399 log_it("Unknown boot loader");
2400 return ('U');
2401 }
2402}
2403
2404#else
2405
2406char which_boot_loader(char *which_device)
2407{
2408 /*@ buffer ***************************************************** */
2409 char *list_drives_cmd = NULL;
2410 char *current_drive;
2411
2412 /*@ pointers *************************************************** */
2413 FILE *pdrives;
2414
2415 /*@ int ******************************************************** */
2416 int count_lilos = 0;
2417 int count_grubs = 0;
2418
2419 /*@ end vars *************************************************** */
2420
2421 malloc_string(current_drive);
2422
2423#ifdef __IA64__
2424 /* No choice for it */
2425 return ('E');
2426#endif
2427 assert(which_device != NULL);
2428
2429 mr_asprintf(&list_drives_cmd,
2430 "parted2fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s",
2431 where_is_root_mounted());
2432 log_it("list_drives_cmd = %s", list_drives_cmd);
2433
2434 if (!(pdrives = popen(list_drives_cmd, "r"))) {
2435 log_OS_error("Unable to open list of drives");
2436 mr_free(list_drives_cmd);
2437 paranoid_free(current_drive);
2438 return ('\0');
2439 }
2440 mr_free(list_drives_cmd);
2441
2442 for ((void)fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
2443 (void)fgets(current_drive, MAX_STR_LEN, pdrives)) {
2444 strip_spaces(current_drive);
2445 log_it("looking at drive %s's MBR", current_drive);
2446 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
2447 count_grubs++;
2448 strcpy(which_device, current_drive);
2449 break;
2450 }
2451 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
2452 count_lilos++;
2453 strcpy(which_device, current_drive);
2454 break;
2455 }
2456 }
2457 if (pclose(pdrives)) {
2458 log_OS_error("Cannot pclose pdrives");
2459 }
2460 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
2461 if (count_grubs && !count_lilos) {
2462 paranoid_free(current_drive);
2463 return ('G');
2464 } else if (count_lilos && !count_grubs) {
2465 paranoid_free(current_drive);
2466 return ('L');
2467 } else if (count_grubs == 1 && count_lilos == 1) {
2468 log_it("I'll bet you used to use LILO but switched to GRUB...");
2469 paranoid_free(current_drive);
2470 return ('G');
2471 } else {
2472 // We need to look on each partition then
2473 mr_asprintf(&list_drives_cmd,
2474 "parted2fdisk -l 2>/dev/null | grep -E \"^/dev/\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/");
2475 log_it("list_drives_cmd = %s", list_drives_cmd);
2476
2477 if (!(pdrives = popen(list_drives_cmd, "r"))) {
2478 log_OS_error("Unable to open list of drives");
2479 mr_free(list_drives_cmd);
2480 paranoid_free(current_drive);
2481 return ('\0');
2482 }
2483 mr_free(list_drives_cmd);
2484
2485 for ((void)fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
2486 (void)fgets(current_drive, MAX_STR_LEN, pdrives)) {
2487 strip_spaces(current_drive);
2488 log_it("looking at partition %s's BR", current_drive);
2489 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
2490 count_grubs++;
2491 strcpy(which_device, current_drive);
2492 break;
2493 }
2494 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
2495 count_lilos++;
2496 strcpy(which_device, current_drive);
2497 break;
2498 }
2499 }
2500 if (pclose(pdrives)) {
2501 log_OS_error("Cannot pclose pdrives");
2502 }
2503 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
2504 paranoid_free(current_drive);
2505 if (count_grubs && !count_lilos) {
2506 return ('G');
2507 } else if (count_lilos && !count_grubs) {
2508 return ('L');
2509 } else if (count_grubs == 1 && count_lilos == 1) {
2510 log_it("I'll bet you used to use LILO but switched to GRUB...");
2511 return ('G');
2512 } else {
2513 log_it("Unknown boot loader");
2514 return ('U');
2515 }
2516 }
2517}
2518#endif
2519
2520
2521
2522
2523/**
2524 * Write zeroes over the first 16K of @p device.
2525 * @param device The device to zero.
2526 * @return 0 for success, 1 for failure.
2527 */
2528int zero_out_a_device(char *device)
2529{
2530 FILE *fout;
2531 int i;
2532
2533 assert_string_is_neither_NULL_nor_zerolength(device);
2534
2535 log_it("Zeroing drive %s", device);
2536 if (!(fout = fopen(device, "w"))) {
2537 log_OS_error("Unable to open/write to device");
2538 return (1);
2539 }
2540 for (i = 0; i < 16384; i++) {
2541 fputc('\0', fout);
2542 }
2543 paranoid_fclose(fout);
2544 log_it("Device successfully zeroed.");
2545 return (0);
2546}
2547
2548/**
2549 * Return the device pointed to by @p incoming.
2550 * @param incoming The device to resolve symlinks for.
2551 * @return The path to the real device file.
2552 * @note The returned string points to static storage that will be overwritten with each call.
2553 * @bug Won't work with file v4.0; needs to be written in C.
2554 */
2555char *resolve_softlinks_to_get_to_actual_device_file(char *incoming)
2556{
2557 static char output[MAX_STR_LEN];
2558 char *command;
2559 char *curr_fname;
2560 char *scratch = NULL;
2561 char *tmp = NULL;
2562 char *p;
2563
2564 struct stat statbuf;
2565 command = malloc(1000);
2566 malloc_string(curr_fname);
2567 if (!does_file_exist(incoming)) {
2568 log_it
2569 ("resolve_softlinks_to_get_to_actual_device_file --- device not found");
2570 strcpy(output, incoming);
2571 } else {
2572 strcpy(curr_fname, incoming);
2573 lstat(curr_fname, &statbuf);
2574 while (S_ISLNK(statbuf.st_mode)) {
2575 log_msg(1, "curr_fname = %s", curr_fname);
2576 sprintf(command, "file %s", curr_fname);
2577 mr_asprintf(&tmp, call_program_and_get_last_line_of_output(command));
2578 for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' ';
2579 p--);
2580 p++;
2581 mr_asprintf(&scratch, p);
2582 for (p = scratch; *p != '\0' && *p != '\''; p++);
2583 *p = '\0';
2584 log_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp, scratch);
2585 mr_free(tmp);
2586
2587 if (scratch[0] == '/') {
2588 strcpy(curr_fname, scratch); // copy whole thing because it's an absolute softlink
2589 } else { // copy over the basename cos it's a relative softlink
2590 p = curr_fname + strlen(curr_fname);
2591 while (p != curr_fname && *p != '/') {
2592 p--;
2593 }
2594 if (*p == '/') {
2595 p++;
2596 }
2597 strcpy(p, scratch);
2598 }
2599 mr_free(scratch);
2600 lstat(curr_fname, &statbuf);
2601 }
2602 strcpy(output, curr_fname);
2603 log_it("resolved %s to %s", incoming, output);
2604 }
2605 paranoid_free(command);
2606 paranoid_free(curr_fname);
2607 return (output);
2608}
2609
2610/* @} - end of deviceGroup */
2611
2612
2613/**
2614 * Return the type of partition format (GPT or MBR)
2615 */
2616char *which_partition_format(const char *drive)
2617{
2618 static char output[4];
2619 char *tmp = NULL;
2620 char *command;
2621 char *fdisk;
2622#ifdef __IA64__
2623 struct stat buf;
2624#endif
2625 malloc_string(command);
2626 malloc_string(fdisk);
2627 log_msg(0, "Looking for partition table format type");
2628 sprintf(fdisk, "/sbin/parted2fdisk");
2629 log_msg(1, "Using %s", fdisk);
2630 sprintf(command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
2631 mr_asprintf(&tmp, call_program_and_get_last_line_of_output(command));
2632 if (strstr(tmp, "GPT") == NULL) {
2633 strcpy(output, "MBR");
2634 } else {
2635 strcpy(output, "GPT");
2636 }
2637 mr_free(tmp);
2638
2639 log_msg(0, "Found %s partition table format type", output);
2640 paranoid_free(command);
2641 paranoid_free(fdisk);
2642 return (output);
2643}
2644
2645/* @} - end of deviceGroup */
Note: See TracBrowser for help on using the repository browser.