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

Last change on this file since 1639 was 1638, checked in by Bruno Cornec, 17 years ago

Continue to use configuration file data (may not compile)

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