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

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

Huge patch to introduce low level functions that will bw used everywhere (mr_free, mr_asprintf, ...)
Nearly linking now due to that.

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