source: MondoRescue/branches/stable/mondo/src/common/libmondo-devices.c@ 1817

Last change on this file since 1817 was 1817, checked in by Bruno Cornec, 16 years ago

exclude_paths now a configuration item

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