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

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

manual_cd_tray => manual_tray and usage of conf file for that field

  • Property svn:keywords set to Id
File size: 67.0 KB
Line 
1/* libmondo-devices.c Subroutines for handling devices
2 $Id: libmondo-devices.c 1609 2007-08-31 22:07:44Z 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 1609 2007-08-31 22:07:44Z 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 if (!popup_and_get_string
1797 ("Prefix.",
1798 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
1799 bkpinfo->prefix, MAX_STR_LEN / 4)) {
1800 log_to_screen("User has chosen not to backup the PC");
1801 finish(1);
1802 }
1803 mr_msg(3, "prefix set to %s", bkpinfo->prefix);
1804
1805 if (archiving_to_media) {
1806 if (!popup_and_get_string
1807 ("Size.",
1808 "Please enter how big you want each NFS image to be (in megabytes).",
1809 sz_size, 16)) {
1810 log_to_screen("User has chosen not to backup the PC");
1811 finish(1);
1812 }
1813 bkpinfo->media_size = atol(sz_size);
1814 if (bkpinfo->media_size <= 0L) {
1815 log_to_screen(_("User has chosen not to backup the PC"));
1816 finish(1);
1817 }
1818 }
1819 mr_msg(3, "Just set nfs_remote_dir to %s",
1820 bkpinfo->nfs_remote_dir);
1821 mr_msg(3, "isodir is still %s", bkpinfo->isodir);
1822 break;
1823
1824 case iso:
1825 if (!bkpinfo->disaster_recovery) {
1826 if (!popup_and_get_string
1827 ("Storage dir.",
1828 "Please enter the full path name to the directory for your ISO images. Example: /mnt/raid0_0",
1829 bkpinfo->isodir, MAX_STR_LEN / 4)) {
1830 log_to_screen("User has chosen not to backup the PC");
1831 finish(1);
1832 }
1833 if (archiving_to_media) {
1834 if ((bkpinfo->compression_level =
1835 which_compression_level()) == -1) {
1836 log_to_screen(_("User has chosen not to backup the PC"));
1837 finish(1);
1838 }
1839 if (!popup_and_get_string
1840 ("ISO size.",
1841 "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.",
1842 sz_size, 16)) {
1843 log_to_screen("User has chosen not to backup the PC");
1844 finish(1);
1845 }
1846 bkpinfo->media_size = atol(sz_size);
1847 /* BERLIOS: this should be useless
1848 */
1849 } else {
1850 bkpinfo->media_size = (long)650;
1851 }
1852 }
1853 if (!popup_and_get_string
1854 ("Prefix.",
1855 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
1856 bkpinfo->prefix, MAX_STR_LEN / 4)) {
1857 log_to_screen("User has chosen not to backup the PC");
1858 finish(1);
1859 }
1860 mr_msg(3, "prefix set to %s", bkpinfo->prefix);
1861 break;
1862 default:
1863 fatal_error
1864 ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
1865 }
1866 if (archiving_to_media) {
1867
1868#ifdef __FreeBSD__
1869 strcpy(bkpinfo->boot_device,
1870 call_program_and_get_last_line_of_output
1871 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
1872#else
1873 strcpy(bkpinfo->boot_device,
1874 call_program_and_get_last_line_of_output
1875 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
1876#endif
1877 i = which_boot_loader(bkpinfo->boot_device);
1878 if (i == 'U') // unknown
1879 {
1880
1881#ifdef __FreeBSD__
1882 if (!popup_and_get_string
1883 ("Boot device",
1884 "What is your boot device? (e.g. /dev/ad0)",
1885 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
1886 log_to_screen("User has chosen not to backup the PC");
1887 finish(1);
1888 }
1889 i = which_boot_loader(bkpinfo->boot_device);
1890#else
1891 if (!popup_and_get_string
1892 ("Boot device",
1893 "What is your boot device? (e.g. /dev/hda)",
1894 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
1895 log_to_screen("User has chosen not to backup the PC");
1896 finish(1);
1897 }
1898 if (does_string_exist_in_boot_block
1899 (bkpinfo->boot_device, "LILO")) {
1900 i = 'L';
1901 } else
1902 if (does_string_exist_in_boot_block
1903 (bkpinfo->boot_device, "ELILO")) {
1904 i = 'E';
1905 } else
1906 if (does_string_exist_in_boot_block
1907 (bkpinfo->boot_device, "GRUB")) {
1908 i = 'G';
1909 } else {
1910 i = 'U';
1911 }
1912#endif
1913 if (i == 'U') {
1914 if (ask_me_yes_or_no
1915 (_("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?")))
1916 {
1917 i = 'R'; // raw
1918 } else {
1919 log_to_screen
1920 (_("I cannot find your boot loader. Please run mondoarchive with parameters."));
1921 finish(1);
1922 }
1923 }
1924 }
1925 bkpinfo->boot_loader = i;
1926 strcpy(bkpinfo->include_paths, "/");
1927 if (!popup_and_get_string
1928 ("Backup paths",
1929 "Please enter paths which you want me to backup. The default is '/' (i.e. everything).",
1930 bkpinfo->include_paths, MAX_STR_LEN)) {
1931 log_to_screen("User has chosen not to backup the PC");
1932 finish(1);
1933 }
1934 mr_asprintf(&tmp, list_of_NFS_mounts_only());
1935 if (strlen(tmp) > 2) {
1936 if (bkpinfo->exclude_paths[0]) {
1937 strcat(bkpinfo->exclude_paths, " ");
1938 }
1939 strncpy(bkpinfo->exclude_paths, tmp, MAX_STR_LEN);
1940 }
1941 mr_free(tmp);
1942// NTFS
1943 mr_asprintf(&tmp,
1944 call_program_and_get_last_line_of_output
1945 ("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'"));
1946 if (strlen(tmp) > 2) {
1947 if (!popup_and_get_string
1948 ("NTFS partitions",
1949 "Please enter/confirm the NTFS partitions you wish to backup as well.",
1950 tmp, MAX_STR_LEN / 4)) {
1951 log_to_screen("User has chosen not to backup the PC");
1952 finish(1);
1953 }
1954 strncpy(bkpinfo->image_devs, tmp, MAX_STR_LEN / 4);
1955 }
1956 mr_free(tmp);
1957
1958 if (!popup_and_get_string
1959 ("Exclude paths",
1960 "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.",
1961 bkpinfo->exclude_paths, (4*MAX_STR_LEN)-1)) {
1962 log_to_screen("User has chosen not to backup the PC");
1963 finish(1);
1964 }
1965// Interactive mode:
1966#ifdef __IA64__
1967 bkpinfo->make_cd_use_lilo = TRUE;
1968#else
1969 bkpinfo->make_cd_use_lilo = FALSE;
1970#endif
1971 bkpinfo->backup_data = TRUE;
1972 bkpinfo->verify_data =
1973 ask_me_yes_or_no
1974 (_("Will you want to verify your backups after Mondo has created them?"));
1975
1976#ifndef __FreeBSD__
1977 if (!ask_me_yes_or_no
1978 ("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."))
1979#endif
1980 {
1981 strcpy(bkpinfo->kernel_path, "FAILSAFE");
1982 }
1983
1984 if (!ask_me_yes_or_no
1985 (_("Are you sure you want to proceed? Hit 'no' to abort."))) {
1986 log_to_screen(_("User has chosen not to backup the PC"));
1987 finish(1);
1988 }
1989 } else {
1990 bkpinfo->restore_data = TRUE; // probably...
1991 }
1992
1993 if (bkpinfo->backup_media_type == iso
1994 || bkpinfo->backup_media_type == nfs) {
1995 g_ISO_restore_mode = TRUE;
1996 }
1997#ifdef __FreeBSD__
1998// skip
1999#else
2000 if (bkpinfo->backup_media_type == nfs) {
2001 mr_msg(3, "I think the NFS mount is mounted at %s",
2002 bkpinfo->isodir);
2003 }
2004 log_it("isodir = %s", bkpinfo->isodir);
2005 log_it("nfs_mount = '%s'", bkpinfo->nfs_mount);
2006#endif
2007
2008 log_it("media device = %s", bkpinfo->media_device);
2009 log_it("media size = %ld", bkpinfo->media_size);
2010 log_it("media type = %s", bkpinfo->backup_media_string);
2011 log_it("prefix = %s", bkpinfo->prefix);
2012 log_it("compression = %ld", bkpinfo->compression_level);
2013 log_it("include_paths = '%s'", bkpinfo->include_paths);
2014 log_it("exclude_paths = '%s'", bkpinfo->exclude_paths);
2015 log_it("scratchdir = '%s'", bkpinfo->scratchdir);
2016 log_it("tmpdir = '%s'", bkpinfo->tmpdir);
2017 log_it("image_devs = '%s'", bkpinfo->image_devs);
2018 log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device,
2019 bkpinfo->boot_loader);
2020 if (bkpinfo->media_size < 0L) {
2021 if (archiving_to_media) {
2022 fatal_error("Media size is less than zero.");
2023 } else {
2024 mr_msg(2, "Warning - media size is less than zero.");
2025 bkpinfo->media_size = 0L;
2026 }
2027 }
2028 return (0);
2029}
2030
2031
2032/**
2033 * Get a space-separated list of NFS mounts.
2034 * @return The list created.
2035 * @note The return value points to static data that will be overwritten with each call.
2036 * @bug Even though we only want the mounts, the devices are still checked.
2037 */
2038char *list_of_NFS_mounts_only(void)
2039{
2040 char *exclude_these_devices;
2041 char *exclude_these_directories;
2042 static char result_sz[512];
2043
2044 malloc_string(exclude_these_devices);
2045 malloc_string(exclude_these_directories);
2046 strcpy(exclude_these_directories,
2047 call_program_and_get_last_line_of_output
2048 ("mount -t coda,ncpfs,nfs,smbfs,cifs,afs,ocfs,ocfs2,mvfs | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' ' ' | awk '{print $0;}'"));
2049 strcpy(exclude_these_devices,
2050 call_program_and_get_last_line_of_output
2051 ("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;}'"));
2052 sprintf(result_sz, "%s", exclude_these_directories);
2053 mr_free(exclude_these_devices);
2054 mr_free(exclude_these_directories);
2055 return (result_sz);
2056}
2057/* @} - end of utilityGroup */
2058
2059
2060/**
2061 * Set the tmpdir and scratchdir to reside on the partition with the most free space.
2062 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
2063 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set.
2064 * @ingroup utilityGroup
2065 */
2066void sensibly_set_tmpdir_and_scratchdir(struct s_bkpinfo *bkpinfo)
2067{
2068 char *tmp = NULL;
2069 char *command = NULL;
2070 char *sz = NULL;
2071 int i = 0;
2072
2073 malloc_string(command);
2074 assert(bkpinfo != NULL);
2075
2076#ifdef __FreeBSD__
2077 mr_asprintf(&tmp,
2078 call_program_and_get_last_line_of_output
2079 ("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;}'"));
2080#else
2081 mr_asprintf(&tmp,
2082 call_program_and_get_last_line_of_output
2083 ("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;}'"));
2084#endif
2085
2086 if (tmp[0] != '/') {
2087 mr_asprintf(&sz, "/%s", tmp);
2088 mr_free(tmp);
2089 tmp = sz;
2090 }
2091 if (!tmp[0]) {
2092 fatal_error("I couldn't figure out the tempdir!");
2093 }
2094 i = (int) (random() % 32768);
2095 sprintf(bkpinfo->tmpdir, "%s/tmp.mondo.%d", tmp, i);
2096 log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir);
2097
2098 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%d", tmp, i);
2099 log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
2100
2101 sprintf(g_erase_tmpdir_and_scratchdir, "rm -Rf %s %s", bkpinfo->tmpdir,
2102 bkpinfo->scratchdir);
2103
2104 mr_asprintf(&command, "rm -Rf %s/tmp.mondo.* %s/mondo.scratch.*", tmp, tmp);
2105 mr_free(tmp);
2106
2107 paranoid_system(command);
2108 mr_free(command);
2109}
2110
2111
2112/**
2113 * @addtogroup deviceGroup
2114 * @{
2115 */
2116/**
2117 * If we can read @p dev, set @p output to it.
2118 * If @p dev cannot be read, set @p output to "".
2119 * @param dev The device to check for.
2120 * @param output Set to @p dev if @p dev exists, "" otherwise.
2121 * @return TRUE if @p dev exists, FALSE if it doesn't.
2122 */
2123bool set_dev_to_this_if_rx_OK(char *output, char *dev)
2124{
2125 char *command = NULL;
2126
2127 if (!dev || dev[0] == '\0') {
2128 output[0] = '\0';
2129 return (FALSE);
2130 }
2131 mr_msg(10, "Injecting %s", dev);
2132 inject_device(dev);
2133 if (!does_file_exist(dev)) {
2134 mr_msg(10, "%s doesn't exist. Returning FALSE.", dev);
2135 return (FALSE);
2136 }
2137 mr_asprintf(&command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null",
2138 512L, dev);
2139 if (!run_program_and_log_output(command, FALSE)
2140 && !run_program_and_log_output(command, FALSE)) {
2141 strcpy(output, dev);
2142 mr_msg(4, "Found it - %s", dev);
2143 mr_free(command);
2144 return (TRUE);
2145 } else {
2146 output[0] = '\0';
2147 mr_msg(4, "It's not %s", dev);
2148 mr_free(command);
2149 return (FALSE);
2150 }
2151}
2152
2153
2154/**
2155 * Find out what number CD is in the drive.
2156 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
2157 * @return The current CD number, or -1 if it could not be found.
2158 * @note If the CD is not mounted, it will be mounted
2159 * (and remain mounted after this function returns).
2160 */
2161int what_number_cd_is_this(struct s_bkpinfo *bkpinfo)
2162{
2163 int cd_number = -1;
2164 char *mountdev = NULL;
2165 char *tmp = NULL;
2166
2167 assert(bkpinfo != NULL);
2168 if (g_ISO_restore_mode) {
2169 mr_asprintf(&tmp, "mount | grep iso9660 | awk '{print $3;}'");
2170
2171 mr_asprintf(&mountdev, "%s/archives/THIS-CD-NUMBER", call_program_and_get_last_line_of_output(tmp));
2172 cd_number = atoi(last_line_of_file(mountdev));
2173 mr_free(mountdev);
2174 mr_free(tmp);
2175 return (cd_number);
2176 }
2177
2178 mr_asprintf(&mountdev, bkpinfo->media_device);
2179 if (!is_this_device_mounted(MNT_CDROM)) {
2180 mount_CDROM_here(mountdev, MNT_CDROM);
2181 }
2182 cd_number =
2183 atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
2184 mr_free(mountdev);
2185 return (cd_number);
2186}
2187
2188
2189/**
2190 * Find out what device is mounted as root (/).
2191 * @return Root device.
2192 * @note The returned string points to static storage and will be overwritten with every call.
2193 * @bug A bit of a misnomer; it's actually finding out the root device.
2194 * The mountpoint (where it's mounted) will obviously be '/'.
2195 */
2196char *where_is_root_mounted()
2197{
2198 /*@ buffers **************** */
2199 static char tmp[MAX_STR_LEN];
2200
2201
2202#ifdef __FreeBSD__
2203 strcpy(tmp, call_program_and_get_last_line_of_output
2204 ("mount | grep \" on / \" | cut -d' ' -f1"));
2205#else
2206 strcpy(tmp, call_program_and_get_last_line_of_output
2207 ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"));
2208 if (strstr(tmp, "/dev/cciss/")) {
2209 strcpy(tmp, call_program_and_get_last_line_of_output
2210 ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"));
2211 }
2212 if (strstr(tmp, "/dev/md")) {
2213 strcpy(tmp,
2214 call_program_and_get_last_line_of_output
2215 ("mount | grep \" on / \" | cut -d' ' -f1"));
2216 }
2217#endif
2218
2219 return (tmp);
2220}
2221
2222
2223/**
2224 * Find out which boot loader is in use.
2225 * @param which_device Device to look for the boot loader on.
2226 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
2227 * @note Under Linux, all drives are examined, not just @p which_device.
2228 */
2229char which_boot_loader(char *which_device)
2230{
2231#ifdef __FreeBSD__
2232 int count_lilos = 0;
2233 int count_grubs = 0;
2234 int count_boot0s = 0;
2235 int count_dangerouslydedicated = 0;
2236
2237 log_it("looking at drive %s's MBR", which_device);
2238 if (does_string_exist_in_boot_block(which_device, "GRUB")) {
2239 count_grubs++;
2240 }
2241 if (does_string_exist_in_boot_block(which_device, "LILO")) {
2242 count_lilos++;
2243 }
2244 if (does_string_exist_in_boot_block(which_device, "Drive")) {
2245 count_boot0s++;
2246 }
2247 if (does_string_exist_in_first_N_blocks
2248 (which_device, "FreeBSD/i386", 17)) {
2249 count_dangerouslydedicated++;
2250 }
2251 log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
2252 count_grubs, count_lilos, count_elilos, count_boot0s,
2253 count_dangerouslydedicated);
2254
2255 if (count_grubs && !count_lilos) {
2256 return ('G');
2257 } else if (count_lilos && !count_grubs) {
2258 return ('L');
2259 } else if (count_grubs == 1 && count_lilos == 1) {
2260 log_it("I'll bet you used to use LILO but switched to GRUB...");
2261 return ('G');
2262 } else if (count_boot0s == 1) {
2263 return ('B');
2264 } else if (count_dangerouslydedicated) {
2265 return ('D');
2266 } else {
2267 log_it("Unknown boot loader");
2268 return ('U');
2269 }
2270#else
2271 /*@ buffer ***************************************************** */
2272 char *list_drives_cmd;
2273 char *current_drive = NULL;
2274
2275 /*@ pointers *************************************************** */
2276 FILE *pdrives;
2277
2278 /*@ int ******************************************************** */
2279 int count_lilos = 0;
2280 int count_grubs = 0;
2281 size_t n = 0;
2282
2283 /*@ end vars *************************************************** */
2284
2285#ifdef __IA64__
2286 /* No choice for it */
2287 return ('E');
2288#endif
2289 assert(which_device != NULL);
2290 mr_asprintf(&list_drives_cmd,
2291 "parted2fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s",
2292 where_is_root_mounted());
2293 log_it("list_drives_cmd = %s", list_drives_cmd);
2294
2295 if (!(pdrives = popen(list_drives_cmd, "r"))) {
2296 log_OS_error("Unable to open list of drives");
2297 mr_free(list_drives_cmd);
2298 return ('\0');
2299 }
2300 mr_free(list_drives_cmd);
2301
2302 for (mr_getline(&current_drive, &n, pdrives); !feof(pdrives);
2303 mr_getline(&current_drive, &n, pdrives)) {
2304 mr_strip_spaces(current_drive);
2305 log_it("looking at drive %s's MBR", current_drive);
2306 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
2307 count_grubs++;
2308 strcpy(which_device, current_drive);
2309 break;
2310 }
2311 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
2312 count_lilos++;
2313 strcpy(which_device, current_drive);
2314 break;
2315 }
2316 }
2317 mr_free(current_drive);
2318
2319 if (pclose(pdrives)) {
2320 log_OS_error("Cannot pclose pdrives");
2321 }
2322 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
2323 if (count_grubs && !count_lilos) {
2324 return ('G');
2325 } else if (count_lilos && !count_grubs) {
2326 return ('L');
2327 } else if (count_grubs == 1 && count_lilos == 1) {
2328 log_it("I'll bet you used to use LILO but switched to GRUB...");
2329 return ('G');
2330 } else {
2331 // We need to look on each partition then
2332 mr_asprintf(&list_drives_cmd,
2333 "parted2fdisk -l 2>/dev/null | grep -E \"^/dev/\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/");
2334 log_it("list_drives_cmd = %s", list_drives_cmd);
2335
2336 if (!(pdrives = popen(list_drives_cmd, "r"))) {
2337 log_OS_error("Unable to open list of drives");
2338 mr_free(list_drives_cmd);
2339 return ('\0');
2340 }
2341 mr_free(list_drives_cmd);
2342
2343 for (mr_getline(&current_drive, &n, pdrives); !feof(pdrives);
2344 mr_getline(&current_drive, &n, pdrives)) {
2345 mr_strip_spaces(current_drive);
2346 log_it("looking at partition %s's BR", current_drive);
2347 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
2348 count_grubs++;
2349 strcpy(which_device, current_drive);
2350 break;
2351 }
2352 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
2353 count_lilos++;
2354 strcpy(which_device, current_drive);
2355 break;
2356 }
2357 }
2358 mr_free(current_drive);
2359
2360 if (pclose(pdrives)) {
2361 log_OS_error("Cannot pclose pdrives");
2362 }
2363 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
2364 if (count_grubs && !count_lilos) {
2365 return ('G');
2366 } else if (count_lilos && !count_grubs) {
2367 return ('L');
2368 } else if (count_grubs == 1 && count_lilos == 1) {
2369 log_it("I'll bet you used to use LILO but switched to GRUB...");
2370 return ('G');
2371 } else {
2372 log_it("Unknown boot loader");
2373 return ('U');
2374 }
2375 }
2376#endif
2377}
2378
2379
2380/**
2381 * Write zeroes over the first 16K of @p device.
2382 * @param device The device to zero.
2383 * @return 0 for success, 1 for failure.
2384 */
2385int zero_out_a_device(char *device)
2386{
2387 FILE *fout;
2388 int i;
2389
2390 assert_string_is_neither_NULL_nor_zerolength(device);
2391
2392 log_it("Zeroing drive %s", device);
2393 if (!(fout = fopen(device, "w"))) {
2394 log_OS_error("Unable to open/write to device");
2395 return (1);
2396 }
2397 for (i = 0; i < 16384; i++) {
2398 fputc('\0', fout);
2399 }
2400 paranoid_fclose(fout);
2401 log_it("Device successfully zeroed.");
2402 return (0);
2403}
2404
2405
2406/**
2407 * Return the device pointed to by @p incoming.
2408 * @param incoming The device to resolve symlinks for.
2409 * @return The path to the real device file.
2410 * @note The returned string points to static storage that will be overwritten with each call.
2411 * @bug Won't work with file v4.0; needs to be written in C.
2412 */
2413char *resolve_softlinks_to_get_to_actual_device_file(char *incoming)
2414{
2415 static char output[MAX_STR_LEN];
2416 char *command = NULL;
2417 char *curr_fname = NULL;
2418 char *scratch = NULL;
2419 char *tmp = NULL;
2420 char *p = NULL;
2421
2422 struct stat statbuf;
2423 malloc_string(tmp);
2424 malloc_string(scratch);
2425 malloc_string(curr_fname);
2426 if (!does_file_exist(incoming)) {
2427 log_it
2428 ("resolve_softlinks_to_get_to_actual_device_file --- device not found");
2429 strcpy(output, incoming);
2430 } else {
2431 strcpy(curr_fname, incoming);
2432 lstat(curr_fname, &statbuf);
2433 while (S_ISLNK(statbuf.st_mode)) {
2434 mr_msg(1, "curr_fname = %s", curr_fname);
2435 mr_asprintf(&command, "file %s", curr_fname);
2436 strcpy(tmp, call_program_and_get_last_line_of_output(command));
2437 mr_free(command);
2438
2439 for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' ';
2440 p--);
2441 p++;
2442 strcpy(scratch, p);
2443 for (p = scratch; *p != '\0' && *p != '\''; p++);
2444 *p = '\0';
2445 mr_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp,
2446 scratch);
2447 if (scratch[0] == '/') {
2448 strcpy(curr_fname, scratch); // copy whole thing because it's an absolute softlink
2449 } else { // copy over the basename cos it's a relative softlink
2450 p = curr_fname + strlen(curr_fname);
2451 while (p != curr_fname && *p != '/') {
2452 p--;
2453 }
2454 if (*p == '/') {
2455 p++;
2456 }
2457 strcpy(p, scratch);
2458 }
2459 lstat(curr_fname, &statbuf);
2460 }
2461 strcpy(output, curr_fname);
2462 log_it("resolved %s to %s", incoming, output);
2463 }
2464 mr_free(curr_fname);
2465 mr_free(tmp);
2466 return (output);
2467}
2468
2469/* @} - end of deviceGroup */
2470
2471
2472/**
2473 * Return the type of partition format (GPT or MBR)
2474 */
2475char *which_partition_format(const char *drive)
2476{
2477 static char output[4];
2478 char *tmp = NULL;
2479 char *command = NULL;
2480 char *fdisk = NULL;
2481
2482 mr_msg(0, "Looking for partition table format type");
2483 mr_asprintf(&fdisk, "/sbin/parted2fdisk");
2484 mr_msg(1, "Using %s", fdisk);
2485 mr_asprintf(&command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
2486 mr_free(fdisk);
2487
2488 mr_asprintf(&tmp, call_program_and_get_last_line_of_output(command));
2489 mr_free(command);
2490
2491 if (strstr(tmp, "GPT") == NULL) {
2492 strcpy(output, "MBR");
2493 } else {
2494 strcpy(output, "GPT");
2495 }
2496 mr_free(tmp);
2497 mr_msg(0, "Found %s partition table format type", output);
2498 return(output);
2499}
2500/* @} - end of deviceGroup */
Note: See TracBrowser for help on using the repository browser.