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

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

strip_spaces => mr_strip_spaces in mr_str.c and corrected at the same time :-)

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