source: MondoRescue/trunk/mondo/src/common/libmondo-devices.c@ 817

Last change on this file since 817 was 808, checked in by Bruno Cornec, 18 years ago

merge -r793:807 $SVN_M/branches/stable
src => common for the moment it's easier to manage merges

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