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

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