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

Last change on this file since 147 was 147, checked in by bcornec, 18 years ago

Quality errors handled

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