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

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

Still linker fixes (grrr)

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