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

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

Fix trunk transfer errors to libmondo-devices.c

  • Property svn:keywords set to Id
File size: 67.7 KB
Line 
1/* libmondo-devices.c Subroutines for handling devices
2 $Id: libmondo-devices.c 1130 2007-02-10 14:28:05Z 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 1130 2007-02-10 14:28:05Z 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, "Harddisk geometry wrong");
996 }
997 } else {
998 mr_msg(1,
999 "Error in ioctl() getting new hard disk geometry (%s), resizing in unsafe mode", strerror(errno));
1000 }
1001 close(fileid);
1002 } else {
1003 mr_msg(1, "Failed to open %s for reading: %s", drive,
1004 strerror(errno));
1005 }
1006 if (!gotgeo) {
1007 mr_msg(1, "Failed to get harddisk geometry, using old mode");
1008 }
1009/*
1010 if ((fd = open (drive, O_RDONLY)) != -1) {
1011 if (ioctl (fd, HDIO_GETGEO, &hdgeo) != -1) {
1012 close (fd);
1013 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));
1014 if ( hdgeo.cylinders && hdgeo.heads && hdgeo.sectors ) {
1015 outvalB = ((long) (hdgeo.cylinders * hdgeo.heads * hdgeo.sectors / 2 / 1024));
1016 }
1017 }
1018 close (fd);
1019 */
1020#endif
1021 }
1022// OLDER DISKS will give ridiculously low value for outvalB (so outvalA is returned) :)
1023// NEWER DISKS will give sane value for outvalB (close to outvalA, in other words) :)
1024
1025 outvalC = (outvalA > outvalB) ? outvalA : outvalB;
1026
1027// mr_msg (5, "drive = %s, error = %s", drive, strerror (errno));
1028// fatal_error ("GPSOD: Unable to get size of drive");
1029 mr_msg(1, "%s --> %ld or %ld --> %ld", drive, outvalA, outvalB,
1030 outvalC);
1031
1032 return (outvalC);
1033}
1034
1035
1036/**
1037 * Determine whether @p format is supported by the kernel. Uses /proc/filesystems
1038 * under Linux and @c lsvfs under FreeBSD.
1039 * @param format The format to test.
1040 * @return TRUE if the format is supported, FALSE if not.
1041 */
1042bool is_this_a_valid_disk_format(char *format)
1043{
1044 char *good_formats = NULL;
1045 char *command = NULL;
1046 char *tmp = NULL;
1047 char *format_sz = NULL;
1048
1049 FILE *pin = NULL;
1050 bool retval;
1051 size_t n = 0;
1052 assert_string_is_neither_NULL_nor_zerolength(format);
1053
1054 mr_asprintf(&format_sz, "%s ", format);
1055
1056#ifdef __FreeBSD__
1057 mr_asprintf(&command,
1058 "lsvfs | tr -s '\t' ' ' | grep -v Filesys | grep -v -- -- | cut -d' ' -f1 | tr -s '\n' ' '");
1059#else
1060 mr_asprintf(&command,
1061 "grep -v nodev /proc/filesystems | tr -s '\t' ' ' | cut -d' ' -f2 | tr -s '\n' ' '");
1062#endif
1063
1064 pin = popen(command, "r");
1065 mr_free(command);
1066
1067 if (!pin) {
1068 log_OS_error("Unable to read good formats");
1069 retval = FALSE;
1070 } else {
1071 mr_getline(&good_formats, &n , pin);
1072 if (pclose(pin)) {
1073 log_OS_error("Cannot pclose good formats");
1074 }
1075 strip_spaces(good_formats);
1076 // " ntfs 7 " -- um, cheating much? :)
1077 mr_asprintf(&tmp, " %s swap lvm raid ntfs 7 ",good_formats);
1078 mr_free(good_formats);
1079 good_formats = tmp;
1080
1081 if (strstr(good_formats, format_sz)) {
1082 retval = TRUE;
1083 } else {
1084 retval = FALSE;
1085 }
1086 mr_free(good_formats);
1087 }
1088 mr_free(format_sz);
1089 return (retval);
1090}
1091
1092
1093/** @def SWAPLIST_COMMAND The command to list the swap files/partitions in use. */
1094
1095/**
1096 * Determine whether @p device_raw is currently mounted.
1097 * @param device_raw The device to check.
1098 * @return TRUE if it's mounted, FALSE if not.
1099 */
1100bool is_this_device_mounted(char *device_raw)
1101{
1102
1103 /*@ pointers **************************************************** */
1104 FILE *fin;
1105
1106 /*@ buffers ***************************************************** */
1107 char *incoming = NULL;
1108 char *device_with_tab = NULL;
1109 char *device_with_space = NULL;
1110 char *tmp = NULL;
1111 size_t n = 0;
1112
1113#ifdef __FreeBSD__
1114#define SWAPLIST_COMMAND "swapinfo"
1115#else
1116#define SWAPLIST_COMMAND "cat /proc/swaps"
1117#endif
1118
1119 /*@ end vars **************************************************** */
1120
1121 assert(device_raw != NULL);
1122// assert_string_is_neither_NULL_nor_zerolength(device_raw);
1123 if (device_raw[0] != '/' && !strstr(device_raw, ":/")) {
1124 mr_msg(1, "%s needs to have a '/' prefixed - I'll do it",
1125 device_raw);
1126 mr_asprintf(&tmp, "/%s", device_raw);
1127 } else {
1128 mr_asprintf(&tmp, device_raw);
1129 }
1130 mr_msg(1, "Is %s mounted?", tmp);
1131 if (!strcmp(tmp, "/proc") || !strcmp(tmp, "proc")) {
1132 mr_msg(1,
1133 "I don't know how the heck /proc made it into the mountlist. I'll ignore it.");
1134 return (FALSE);
1135 }
1136 mr_asprintf(&device_with_tab, "%s\t", tmp);
1137 mr_asprintf(&device_with_space, "%s ", tmp);
1138 mr_free(tmp);
1139
1140 if (!(fin = popen("mount", "r"))) {
1141 log_OS_error("Cannot popen 'mount'");
1142 return (FALSE);
1143 }
1144 for (mr_getline(&incoming, &n, fin); !feof(fin);
1145 mr_getline(&incoming, &n, fin)) {
1146 if (strstr(incoming, device_with_space) //> incoming
1147 || strstr(incoming, device_with_tab)) // > incoming)
1148 {
1149 paranoid_pclose(fin);
1150 mr_free(incoming);
1151 return(TRUE);
1152 }
1153 }
1154 mr_free(incoming);
1155 mr_free(device_with_tab);
1156 paranoid_pclose(fin);
1157
1158 mr_asprintf(&tmp, "%s | grep -E \"^%s\" > /dev/null 2> /dev/null",
1159 SWAPLIST_COMMAND, device_with_space);
1160 mr_free(device_with_space);
1161
1162 mr_msg(4, "tmp (command) = '%s'", tmp);
1163 if (!system(tmp)) {
1164 mr_free(tmp);
1165 return(TRUE);
1166 }
1167 mr_free(tmp);
1168 return (FALSE);
1169}
1170
1171
1172#ifdef __FreeBSD__
1173// CODE IS FREEBSD-SPECIFIC
1174/**
1175 * Create a loopback device for specified @p fname.
1176 * @param fname The file to associate with a device.
1177 * @return /dev entry for the device, or NULL if it couldn't be allocated.
1178 */
1179char *make_vn(char *fname)
1180{
1181 char *device = NULL;
1182 char *mddevice = NULL;
1183 char *command = NULL;
1184 int vndev = 2;
1185
1186 if (atoi
1187 (call_program_and_get_last_line_of_output
1188 ("/sbin/sysctl -n kern.osreldate")) < 500000) {
1189 do {
1190 mr_free(mddevice);
1191 mr_asprintf(&mddevice, "vn%ic", vndev++);
1192 mr_free(command);
1193 mr_asprintf(&command, "vnconfig %s %s", mddevice, fname);
1194
1195 if (vndev > 10) {
1196 mr_free(command);
1197 mr_free(mddevice);
1198 return NULL;
1199 }
1200 }
1201 while (system(command));
1202 mr_free(command);
1203 } else {
1204 mr_asprintf(&command, "mdconfig -a -t vnode -f %s", fname);
1205 mr_asprintf(&mddevice, call_program_and_get_last_line_of_output(command));
1206 mr_free(command);
1207
1208 if (!strstr(mddevice, "md")) {
1209 mr_free(mddevice);
1210 return NULL;
1211 }
1212 }
1213 mr_asprintf(&device, "/dev/%s", mddevice);
1214 mr_free(mddevice);
1215 return(device);
1216}
1217
1218
1219// CODE IS FREEBSD-SPECIFIC
1220/**
1221 * Deallocate specified @p dname.
1222 * This should be called when you are done with the device created by make_vn(),
1223 * so the system does not run out of @c vn devices.
1224 * @param dname The device to deallocate.
1225 * @return 0 for success, nonzero for failure.
1226 */
1227int kick_vn(char *dname)
1228{
1229 char *command;
1230 int ret = 0;
1231
1232 if (strncmp(dname, "/dev/", 5) == 0) {
1233 dname += 5;
1234 }
1235
1236 if (atoi
1237 (call_program_and_get_last_line_of_output
1238 ("/sbin/sysctl -n kern.osreldate")) < 500000) {
1239 mr_asprintf(&command, "vnconfig -d %s", dname);
1240 } else {
1241 mr_asprintf(&command, "mdconfig -d -u %s", dname);
1242 }
1243 ret = system(command);
1244 mr_free(command);
1245 return(ret);
1246}
1247#endif
1248
1249
1250/**
1251 * Mount the CD-ROM at @p mountpoint.
1252 * @param device The device (or file if g_ISO_restore_mode) to mount.
1253 * @param mountpoint The place to mount it.
1254 * @return 0 for success, nonzero for failure.
1255 */
1256int mount_CDROM_here(char *device, char *mountpoint)
1257{
1258 /*@ buffer ****************************************************** */
1259 char *command;
1260 char *dev;
1261 char *options;
1262 int retval;
1263
1264 malloc_string(command);
1265 malloc_string(dev);
1266 malloc_string(options);
1267 assert_string_is_neither_NULL_nor_zerolength(device);
1268 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
1269
1270 make_hole_for_dir(mountpoint);
1271 strcpy(options, "ro");
1272 if (isdigit(device[0])) {
1273 find_cdrom_device(device, FALSE);
1274 } else {
1275 strcpy(dev, device);
1276 }
1277 if (g_ISO_restore_mode) {
1278
1279#ifdef __FreeBSD__
1280 strcpy(dev, make_vn(device));
1281 if (!dev) {
1282 sprintf(command, "Unable to mount ISO (make_vn(%s) failed)",
1283 device);
1284 fatal_error(command);
1285 }
1286 strcpy(device, dev);
1287#else
1288 strcat(options, ",loop");
1289#endif
1290
1291 }
1292 mr_msg(4, "(mount_CDROM_here --- device=%s, mountpoint=%s", device,
1293 mountpoint);
1294 /*@ end vars *************************************************** */
1295
1296#ifdef __FreeBSD__
1297 sprintf(command, "mount_cd9660 -r %s %s 2>> %s",
1298 device, mountpoint, MONDO_LOGFILE);
1299
1300#else
1301 sprintf(command, "mount %s -o %s -t iso9660 %s 2>> %s",
1302 device, options, mountpoint, MONDO_LOGFILE);
1303#endif
1304
1305 mr_msg(4, command);
1306 if (strncmp(device, "/dev/", 5) == 0) {
1307 retract_CD_tray_and_defeat_autorun();
1308 }
1309 retval = system(command);
1310 mr_msg(1, "system(%s) returned %d", command, retval);
1311
1312 mr_free(command);
1313 mr_free(dev);
1314 mr_free(options);
1315 return (retval);
1316}
1317
1318
1319/**
1320 * Ask the user for CD number @p cd_number_i_want.
1321 * Sets g_current_media_number once the correct CD is inserted.
1322 * @param bkpinfo The backup information structure. Fields used:
1323 * - @c bkpinfo->backup_media_type
1324 * - @c bkpinfo->prefix
1325 * - @c bkpinfo->isodir
1326 * - @c bkpinfo->media_device
1327 * - @c bkpinfo->please_dont_eject_when_restoring
1328 * @param cd_number_i_want The CD number to ask for.
1329 */
1330void
1331insist_on_this_cd_number(struct s_bkpinfo *bkpinfo, int cd_number_i_want)
1332{
1333
1334 /*@ int ************************************************************* */
1335 int res = 0;
1336
1337
1338 /*@ buffers ********************************************************* */
1339 char *tmp = NULL;
1340 char *request = NULL;
1341
1342 assert(bkpinfo != NULL);
1343 assert(cd_number_i_want > 0);
1344
1345// mr_msg(3, "Insisting on CD number %d", cd_number_i_want);
1346
1347 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1348 mr_msg(3,
1349 "No need to insist_on_this_cd_number when the backup type isn't CD-R(W) or NFS or ISO");
1350 return;
1351 }
1352 mr_asprintf(&tmp, "mkdir -p " MNT_CDROM);
1353 run_program_and_log_output(tmp, 5);
1354 mr_free(tmp);
1355
1356 if (g_ISO_restore_mode || bkpinfo->backup_media_type == iso
1357 || bkpinfo->backup_media_type == nfs) {
1358 mr_msg(3, "Remounting CD");
1359 g_ISO_restore_mode = TRUE;
1360// FIXME --- I'm tempted to do something about this...
1361// Why unmount and remount again and again?
1362 if (is_this_device_mounted(MNT_CDROM)) {
1363 run_program_and_log_output("umount " MNT_CDROM, 5);
1364 }
1365 system("mkdir -p /tmp/isodir &> /dev/null");
1366 mr_asprintf(&tmp, "%s/%s/%s-%d.iso", bkpinfo->isodir,
1367 bkpinfo->nfs_remote_dir, bkpinfo->prefix,
1368 cd_number_i_want);
1369 if (!does_file_exist(tmp)) {
1370 mr_free(tmp);
1371 mr_asprintf(&tmp, "/tmp/isodir/%s/%s-%d.iso",
1372 bkpinfo->nfs_remote_dir, bkpinfo->prefix,
1373 cd_number_i_want);
1374 if (does_file_exist(tmp)) {
1375 mr_msg(1,
1376 "FIXME - hacking bkpinfo->isodir from '%s' to /tmp/isodir",
1377 bkpinfo->isodir);
1378 strcpy(bkpinfo->isodir, "/tmp/isodir");
1379 }
1380 }
1381 mr_msg(3, "Mounting %s at %s", tmp, MNT_CDROM);
1382 if (mount_CDROM_here(tmp, MNT_CDROM)) {
1383 fatal_error("Mommy!");
1384 }
1385 mr_free(tmp);
1386 }
1387 if ((res = what_number_cd_is_this(bkpinfo)) != cd_number_i_want) {
1388 mr_msg(3, "Currently, we hold %d but we want %d", res,
1389 cd_number_i_want);
1390 mr_asprintf(&tmp, "Insisting on %s #%d",
1391 bkpinfo->backup_media_string,
1392 cd_number_i_want);
1393 mr_asprintf(&request, "Please insert %s #%d and press Enter.",
1394 bkpinfo->backup_media_string,
1395 cd_number_i_want);
1396 mr_msg(3, tmp);
1397 mr_free(tmp);
1398
1399 while (what_number_cd_is_this(bkpinfo) != cd_number_i_want) {
1400 sync();
1401 if (is_this_device_mounted(MNT_CDROM)) {
1402 res =
1403 run_program_and_log_output("umount " MNT_CDROM, FALSE);
1404 } else {
1405 res = 0;
1406 }
1407 if (res) {
1408 log_to_screen(_("WARNING - failed to unmount CD-ROM drive"));
1409 }
1410 if (!bkpinfo->please_dont_eject) {
1411 res = eject_device(bkpinfo->media_device);
1412 } else {
1413 res = 0;
1414 }
1415 if (res) {
1416 log_to_screen(_("WARNING - failed to eject CD-ROM disk"));
1417 }
1418 popup_and_OK(request);
1419 if (!bkpinfo->please_dont_eject) {
1420 inject_device(bkpinfo->media_device);
1421 }
1422 sync();
1423 }
1424 mr_free(request);
1425
1426 mr_msg(1, "Thankyou. Proceeding...");
1427 g_current_media_number = cd_number_i_want;
1428 }
1429}
1430/* @} - end of deviceGroup */
1431
1432
1433/**
1434 * Ask user for details of backup/restore information.
1435 * Called when @c mondoarchive doesn't get any parameters.
1436 * @param bkpinfo The backup information structure to fill out with the user's data.
1437 * @param archiving_to_media TRUE if archiving, FALSE if restoring.
1438 * @return 0, always.
1439 * @bug No point of `int' return value.
1440 * @ingroup archiveGroup
1441 */
1442int interactively_obtain_media_parameters_from_user(struct s_bkpinfo
1443 *bkpinfo,
1444 bool
1445 archiving_to_media)
1446// archiving_to_media is TRUE if I'm being called by mondoarchive
1447// archiving_to_media is FALSE if I'm being called by mondorestore
1448{
1449 char *tmp = NULL;
1450 char *tmp1 = NULL;
1451 char *tmp2 = NULL;
1452 char *sz_size = NULL;
1453 char *command = NULL;
1454 char *comment = NULL;
1455 char *prompt = NULL;
1456 int i = 0;
1457 FILE *fin = NULL;
1458
1459 assert(bkpinfo != NULL);
1460 bkpinfo->nonbootable_backup = FALSE;
1461
1462// Tape, CD, NFS, ...?
1463 srandom(getpid());
1464 bkpinfo->backup_media_type =
1465 (g_restoring_live_from_cd) ? cdr :
1466 which_backup_media_type(bkpinfo->restore_data);
1467 if (bkpinfo->backup_media_type == none) {
1468 log_to_screen(_("User has chosen not to backup the PC"));
1469 finish(1);
1470 }
1471 if (bkpinfo->backup_media_type == tape && bkpinfo->restore_data) {
1472 popup_and_OK(_("Please remove CD/floppy from drive(s)"));
1473 }
1474 mr_msg(3, "media type = %s",
1475 bkptype_to_string(bkpinfo->backup_media_type));
1476 if (archiving_to_media) {
1477 sensibly_set_tmpdir_and_scratchdir(bkpinfo);
1478 }
1479 bkpinfo->cdrw_speed = (bkpinfo->backup_media_type == cdstream) ? 2 : 4;
1480 bkpinfo->compression_level =
1481 (bkpinfo->backup_media_type == cdstream) ? 1 : 5;
1482 bkpinfo->use_lzo =
1483 (bkpinfo->backup_media_type == cdstream) ? TRUE : FALSE;
1484 mvaddstr_and_log_it(2, 0, " ");
1485
1486// Find device's /dev (or SCSI) entry
1487 switch (bkpinfo->backup_media_type) {
1488 case cdr:
1489 case cdrw:
1490 case dvd:
1491 case usb:
1492 if (archiving_to_media) {
1493 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
1494 if (ask_me_yes_or_no
1495 (_("Is your computer a laptop, or does the CD writer incorporate BurnProof technology?")))
1496 {
1497 bkpinfo->manual_cd_tray = TRUE;
1498 }
1499 }
1500 if ((bkpinfo->compression_level =
1501 which_compression_level()) == -1) {
1502 log_to_screen(_("User has chosen not to backup the PC"));
1503 finish(1);
1504 }
1505 mr_asprintf(&comment, _("What speed is your %s (re)writer?"),
1506 bkpinfo->backup_media_string);
1507 if (bkpinfo->backup_media_type == dvd) {
1508 find_dvd_device(bkpinfo->media_device, FALSE);
1509 mr_asprintf(&tmp, "1");
1510 mr_asprintf(&sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4582 MB
1511 mr_msg(1, "Setting to DVD defaults");
1512 } else if (bkpinfo->backup_media_type == usb) {
1513 strcpy(bkpinfo->media_device, VANILLA_USB_DEVICE);
1514 strcpy(sz_size, "512");
1515 } else {
1516 strcpy(bkpinfo->media_device, VANILLA_SCSI_CDROM);
1517 mr_asprintf(&tmp, "4");
1518 mr_asprintf(&sz_size, "650");
1519 mr_msg(1, "Setting to CD defaults");
1520 }
1521 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
1522 if (!popup_and_get_string(_("Speed"), comment, tmp, 4)) {
1523 log_to_screen(_("User has chosen not to backup the PC"));
1524 finish(1);
1525 }
1526 }
1527 mr_free(comment);
1528
1529 bkpinfo->cdrw_speed = atoi(tmp); // if DVD then this shouldn't ever be used anyway :)
1530 mr_free(tmp);
1531
1532 mr_asprintf(&comment,
1533 _("How much data (in Megabytes) will each %s store?"),
1534 bkpinfo->backup_media_string);
1535
1536 if (!popup_and_get_string("Size", comment, sz_size, 5)) {
1537 log_to_screen(_("User has chosen not to backup the PC"));
1538 finish(1);
1539 }
1540 mr_free(comment);
1541
1542 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1543 bkpinfo->media_size[i] = atoi(sz_size);
1544 }
1545 mr_free(sz_size);
1546
1547 if (bkpinfo->media_size[0] <= 0) {
1548 log_to_screen(_("User has chosen not to backup the PC"));
1549 finish(1);
1550 }
1551 }
1552 case cdstream:
1553 if (bkpinfo->disaster_recovery) {
1554 strcpy(bkpinfo->media_device, "/dev/cdrom");
1555 mr_msg(2, "CD-ROM device assumed to be at %s",
1556 bkpinfo->media_device);
1557 } else if (bkpinfo->restore_data
1558 || bkpinfo->backup_media_type == dvd) {
1559 if (!bkpinfo->media_device[0]) {
1560 strcpy(bkpinfo->media_device, "/dev/cdrom");
1561 } // just for the heck of it :)
1562 mr_msg(1, "bkpinfo->media_device = %s",
1563 bkpinfo->media_device);
1564 if (bkpinfo->backup_media_type == dvd
1565 || find_cdrom_device(bkpinfo->media_device, FALSE)) {
1566 mr_msg(1, "bkpinfo->media_device = %s",
1567 bkpinfo->media_device);
1568 mr_asprintf(&comment,
1569 _("Please specify your %s drive's /dev entry"),
1570 bkpinfo->backup_media_string);
1571 if (!popup_and_get_string
1572 (_("Device?"), comment, bkpinfo->media_device, MAX_STR_LEN / 4)) {
1573 log_to_screen(_("User has chosen not to backup the PC"));
1574 finish(1);
1575 }
1576 mr_free(comment);
1577 }
1578 mr_msg(2, "%s device found at %s",
1579 bkpinfo->backup_media_string,
1580 bkpinfo->media_device);
1581 } else {
1582 if (find_cdrw_device(bkpinfo->media_device)) {
1583 bkpinfo->media_device[0] = '\0';
1584 }
1585 if (bkpinfo->media_device[0]) {
1586 mr_asprintf(&tmp,
1587 _("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."),
1588 bkpinfo->backup_media_string,
1589 bkpinfo->media_device);
1590 if (!ask_me_yes_or_no(tmp)) {
1591 bkpinfo->media_device[0] = '\0';
1592 }
1593 mr_free(tmp);
1594 } else {
1595 if (g_kernel_version < 2.6) {
1596 i = popup_and_get_string("Device node?",
1597 "What is the SCSI node of your CD (re)writer, please?",
1598 bkpinfo->media_device,
1599 MAX_STR_LEN / 4);
1600 } else {
1601 i = popup_and_get_string("/dev entry?",
1602 "What is the /dev entry of your CD (re)writer, please?",
1603 bkpinfo->media_device,
1604 MAX_STR_LEN / 4);
1605 }
1606 if (!i) {
1607 log_to_screen(_("User has chosen not to backup the PC"));
1608 finish(1);
1609 }
1610 }
1611 }
1612 if (bkpinfo->backup_media_type == cdstream) {
1613 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1614 bkpinfo->media_size[i] = 650;
1615 }
1616 }
1617 break;
1618 case udev:
1619 if (!ask_me_yes_or_no
1620 (_("This option is for advanced users only. Are you sure?"))) {
1621 log_to_screen(_("User has chosen not to backup the PC"));
1622 finish(1);
1623 }
1624 case tape:
1625
1626 if (find_tape_device_and_size(bkpinfo->media_device, sz_size)) {
1627 mr_msg(3, "Ok, using vanilla scsi tape.");
1628 strcpy(bkpinfo->media_device, VANILLA_SCSI_TAPE);
1629 if ((fin = fopen(bkpinfo->media_device, "r"))) {
1630 paranoid_fclose(fin);
1631 } else {
1632 strcpy(bkpinfo->media_device, "/dev/osst0");
1633 }
1634 }
1635 if (bkpinfo->media_device[0]) {
1636 if ((fin = fopen(bkpinfo->media_device, "r"))) {
1637 paranoid_fclose(fin);
1638 } else {
1639 if (does_file_exist("/tmp/mondo-restore.cfg")) {
1640 read_cfg_var("/tmp/mondo-restore.cfg", "media-dev",
1641 bkpinfo->media_device);
1642 }
1643 }
1644 mr_asprintf(&tmp,
1645 _("I think I've found your tape streamer at %s; am I right on the money?"),
1646 bkpinfo->media_device);
1647 if (!ask_me_yes_or_no(tmp)) {
1648 bkpinfo->media_device[0] = '\0';
1649 }
1650 mr_free(tmp);
1651 } else {
1652 if (!popup_and_get_string
1653 ("Device name?",
1654 "What is the /dev entry of your tape streamer?",
1655 bkpinfo->media_device, MAX_STR_LEN / 4)) {
1656 log_to_screen("User has chosen not to backup the PC");
1657 finish(1);
1658 }
1659 }
1660 mr_asprintf(&tmp, "ls -l %s", bkpinfo->media_device);
1661 if (run_program_and_log_output(tmp, FALSE)) {
1662 log_to_screen(_("User has not specified a valid /dev entry"));
1663 finish(1);
1664 }
1665 mr_free(tmp);
1666 mr_msg(4, "sz_size = %s", sz_size);
1667 mr_free(sz_size);
1668 bkpinfo->media_size[0] = 0;
1669 mr_msg(4, "media_size[0] = %ld", bkpinfo->media_size[0]);
1670 if (bkpinfo->media_size[0] <= 0) {
1671 bkpinfo->media_size[0] = 0;
1672 }
1673 for (i = 1; i <= MAX_NOOF_MEDIA; i++) {
1674 bkpinfo->media_size[i] = bkpinfo->media_size[0];
1675 }
1676 if (archiving_to_media) {
1677 if ((bkpinfo->compression_level =
1678 which_compression_level()) == -1) {
1679 log_to_screen(_("User has chosen not to backup the PC"));
1680 finish(1);
1681 }
1682 }
1683 break;
1684
1685
1686
1687 case nfs:
1688 if (!bkpinfo->nfs_mount[0]) {
1689 strcpy(bkpinfo->nfs_mount,
1690 call_program_and_get_last_line_of_output
1691 ("mount | grep \":\" | cut -d' ' -f1 | head -n1"));
1692 }
1693#ifdef __FreeBSD__
1694 if (TRUE)
1695#else
1696 if (!bkpinfo->disaster_recovery)
1697#endif
1698 {
1699 if (!popup_and_get_string
1700 ("NFS dir.",
1701 "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.)",
1702 bkpinfo->nfs_mount, MAX_STR_LEN / 4)) {
1703 log_to_screen("User has chosen not to backup the PC");
1704 finish(1);
1705 }
1706 if (!bkpinfo->restore_data) {
1707 if ((bkpinfo->compression_level =
1708 which_compression_level()) == -1) {
1709 log_to_screen(_("User has chosen not to backup the PC"));
1710 finish(1);
1711 }
1712 }
1713 // check whether already mounted - we better remove
1714 // surrounding spaces and trailing '/' for this
1715 /* BERLIOS: Useless
1716 strip_spaces(bkpinfo->nfs_mount);
1717 */
1718 if (bkpinfo->nfs_mount[strlen(bkpinfo->nfs_mount) - 1] == '/')
1719 bkpinfo->nfs_mount[strlen(bkpinfo->nfs_mount) - 1] = '\0';
1720 mr_asprintf(&command, "mount | grep \"%s \" | cut -d' ' -f3",
1721 bkpinfo->nfs_mount);
1722 strcpy(bkpinfo->isodir,
1723 call_program_and_get_last_line_of_output(command));
1724 mr_free(command);
1725
1726 mr_asprintf(&comment,
1727 _("How much data (in Megabytes) will each media store?"));
1728 if (!popup_and_get_string(_("Size"), comment, sz_size, 5)) {
1729 log_to_screen(_("User has chosen not to backup the PC"));
1730 finish(1);
1731 }
1732 mr_free(comment);
1733 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1734 bkpinfo->media_size[i] = atoi(sz_size);
1735 }
1736 if (bkpinfo->media_size[0] <= 0) {
1737 log_to_screen(_("User has chosen not to backup the PC"));
1738 finish(1);
1739 }
1740 }
1741 if (bkpinfo->disaster_recovery) {
1742 system("umount /tmp/isodir 2> /dev/null");
1743 if (!popup_and_get_string
1744 ("NFS share", "Which remote NFS share should I mount?",
1745 bkpinfo->nfs_mount, MAX_STR_LEN)) {
1746 log_to_screen("User has chosen not to backup the PC");
1747 finish(1);
1748 }
1749 }
1750 if (!is_this_device_mounted(bkpinfo->nfs_mount)) {
1751 sprintf(bkpinfo->isodir, "/tmp/isodir.mondo.%d",
1752 (int) (random() % 32768));
1753 mr_asprintf(&command, "mkdir -p %s", bkpinfo->isodir);
1754 run_program_and_log_output(command, 5);
1755 mr_free(command);
1756
1757 mr_asprintf(&tmp, "mount -t nfs -o nolock %s %s", bkpinfo->nfs_mount,
1758 bkpinfo->isodir);
1759 run_program_and_log_output(tmp, 5);
1760 mr_free(tmp);
1761 malloc_string(g_selfmounted_isodir);
1762 strcpy(g_selfmounted_isodir, bkpinfo->isodir);
1763 }
1764 if (!is_this_device_mounted(bkpinfo->nfs_mount)) {
1765 popup_and_OK
1766 (_("Please mount that partition before you try to backup to or restore from it."));
1767 finish(1);
1768 }
1769 mr_asprintf(&tmp, bkpinfo->nfs_remote_dir);
1770 if (!popup_and_get_string
1771 ("Directory", "Which directory within that mountpoint?", tmp,
1772 MAX_STR_LEN)) {
1773 log_to_screen("User has chosen not to backup the PC");
1774 finish(1);
1775 }
1776 strcpy(bkpinfo->nfs_remote_dir, tmp);
1777 mr_free(tmp);
1778 // check whether writable - we better remove surrounding spaces for this
1779 strip_spaces(bkpinfo->nfs_remote_dir);
1780 mr_asprintf(&command, "echo hi > '%s/%s/.dummy.txt'", bkpinfo->isodir,
1781 bkpinfo->nfs_remote_dir);
1782 while (run_program_and_log_output(command, FALSE)) {
1783 mr_asprintf(&tmp, bkpinfo->nfs_remote_dir);
1784 mr_asprintf(&prompt,
1785 _("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."),
1786 bkpinfo->nfs_remote_dir, bkpinfo->isodir);
1787 if (!popup_and_get_string
1788 ("Directory", prompt, tmp, MAX_STR_LEN)) {
1789 log_to_screen("User has chosen not to backup the PC");
1790 finish(1);
1791 }
1792 mr_free(prompt);
1793
1794 strcpy(bkpinfo->nfs_remote_dir, tmp);
1795 mr_free(tmp);
1796 // check whether writable - we better remove surrounding space s for this
1797 strip_spaces(bkpinfo->nfs_remote_dir);
1798
1799 mr_free(command);
1800 mr_asprintf(&command, "echo hi > '%s/%s/.dummy.txt'", bkpinfo->isodir,
1801 bkpinfo->nfs_remote_dir);
1802 }
1803 mr_free(command);
1804
1805 if (!popup_and_get_string
1806 ("Prefix.",
1807 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
1808 bkpinfo->prefix, MAX_STR_LEN / 4)) {
1809 log_to_screen("User has chosen not to backup the PC");
1810 finish(1);
1811 }
1812 mr_msg(3, "prefix set to %s", bkpinfo->prefix);
1813
1814 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1815 bkpinfo->media_size[i] = 650;
1816 }
1817 mr_msg(3, "Just set nfs_remote_dir to %s",
1818 bkpinfo->nfs_remote_dir);
1819 mr_msg(3, "isodir is still %s", bkpinfo->isodir);
1820 break;
1821
1822 case iso:
1823 if (!bkpinfo->disaster_recovery) {
1824 if (!popup_and_get_string
1825 ("Storage dir.",
1826 "Please enter the full path that contains your ISO images. Example: /mnt/raid0_0",
1827 bkpinfo->isodir, MAX_STR_LEN / 4)) {
1828 log_to_screen("User has chosen not to backup the PC");
1829 finish(1);
1830 }
1831 if (archiving_to_media) {
1832 if ((bkpinfo->compression_level =
1833 which_compression_level()) == -1) {
1834 log_to_screen(_("User has chosen not to backup the PC"));
1835 finish(1);
1836 }
1837 if (!popup_and_get_string
1838 ("ISO size.",
1839 "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.",
1840 sz_size, 16)) {
1841 log_to_screen("User has chosen not to backup the PC");
1842 finish(1);
1843 }
1844 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1845 bkpinfo->media_size[i] = atoi(sz_size);
1846 }
1847 } else {
1848 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1849 bkpinfo->media_size[i] = 650;
1850 }
1851 }
1852 }
1853 if (!popup_and_get_string
1854 ("Prefix.",
1855 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
1856 bkpinfo->prefix, MAX_STR_LEN / 4)) {
1857 log_to_screen("User has chosen not to backup the PC");
1858 finish(1);
1859 }
1860 mr_msg(3, "prefix set to %s", bkpinfo->prefix);
1861 break;
1862 default:
1863 fatal_error
1864 ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
1865 }
1866 if (archiving_to_media) {
1867
1868#ifdef __FreeBSD__
1869 strcpy(bkpinfo->boot_device,
1870 call_program_and_get_last_line_of_output
1871 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
1872#else
1873 strcpy(bkpinfo->boot_device,
1874 call_program_and_get_last_line_of_output
1875 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
1876#endif
1877 i = which_boot_loader(bkpinfo->boot_device);
1878 if (i == 'U') // unknown
1879 {
1880
1881#ifdef __FreeBSD__
1882 if (!popup_and_get_string
1883 ("Boot device",
1884 "What is your boot device? (e.g. /dev/ad0)",
1885 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
1886 log_to_screen("User has chosen not to backup the PC");
1887 finish(1);
1888 }
1889 i = which_boot_loader(bkpinfo->boot_device);
1890#else
1891 if (!popup_and_get_string
1892 ("Boot device",
1893 "What is your boot device? (e.g. /dev/hda)",
1894 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
1895 log_to_screen("User has chosen not to backup the PC");
1896 finish(1);
1897 }
1898 if (does_string_exist_in_boot_block
1899 (bkpinfo->boot_device, "LILO")) {
1900 i = 'L';
1901 } else
1902 if (does_string_exist_in_boot_block
1903 (bkpinfo->boot_device, "ELILO")) {
1904 i = 'E';
1905 } else
1906 if (does_string_exist_in_boot_block
1907 (bkpinfo->boot_device, "GRUB")) {
1908 i = 'G';
1909 } else {
1910 i = 'U';
1911 }
1912#endif
1913 if (i == 'U') {
1914 if (ask_me_yes_or_no
1915 (_("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?")))
1916 {
1917 i = 'R'; // raw
1918 } else {
1919 log_to_screen
1920 (_("I cannot find your boot loader. Please run mondoarchive with parameters."));
1921 finish(1);
1922 }
1923 }
1924 }
1925 bkpinfo->boot_loader = i;
1926 strcpy(bkpinfo->include_paths, "/");
1927 if (!popup_and_get_string
1928 ("Backup paths",
1929 "Please enter paths which you want me to backup. The default is '/' (i.e. everything).",
1930 bkpinfo->include_paths, MAX_STR_LEN)) {
1931 log_to_screen("User has chosen not to backup the PC");
1932 finish(1);
1933 }
1934 mr_asprintf(&tmp, list_of_NFS_mounts_only());
1935 if (strlen(tmp) > 2) {
1936 if (bkpinfo->exclude_paths[0]) {
1937 strcat(bkpinfo->exclude_paths, " ");
1938 }
1939 strncpy(bkpinfo->exclude_paths, tmp, MAX_STR_LEN);
1940 }
1941 mr_free(tmp);
1942// NTFS
1943 mr_asprintf(&tmp,
1944 call_program_and_get_last_line_of_output
1945 ("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'"));
1946 if (strlen(tmp) > 2) {
1947 if (!popup_and_get_string
1948 ("NTFS partitions",
1949 "Please enter/confirm the NTFS partitions you wish to backup as well.",
1950 tmp, MAX_STR_LEN / 4)) {
1951 log_to_screen("User has chosen not to backup the PC");
1952 finish(1);
1953 }
1954 strncpy(bkpinfo->image_devs, tmp, MAX_STR_LEN / 4);
1955 }
1956 mr_free(tmp);
1957
1958 if (!popup_and_get_string
1959 ("Exclude paths",
1960 "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.",
1961 bkpinfo->exclude_paths, MAX_STR_LEN)) {
1962 log_to_screen("User has chosen not to backup the PC");
1963 finish(1);
1964 }
1965 bkpinfo->make_cd_use_lilo = FALSE;
1966 bkpinfo->backup_data = TRUE;
1967 bkpinfo->verify_data =
1968 ask_me_yes_or_no
1969 (_("Will you want to verify your backups after Mondo has created them?"));
1970
1971#ifndef __FreeBSD__
1972 if (!ask_me_yes_or_no
1973 ("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."))
1974#endif
1975 {
1976 strcpy(bkpinfo->kernel_path, "FAILSAFE");
1977 }
1978
1979 if (!ask_me_yes_or_no
1980 (_("Are you sure you want to proceed? Hit 'no' to abort."))) {
1981 log_to_screen(_("User has chosen not to backup the PC"));
1982 finish(1);
1983 }
1984 } else {
1985 bkpinfo->restore_data = TRUE; // probably...
1986 }
1987
1988 if (bkpinfo->backup_media_type == iso
1989 || bkpinfo->backup_media_type == nfs) {
1990 g_ISO_restore_mode = TRUE;
1991 }
1992#ifdef __FreeSD__
1993// skip
1994#else
1995 if (bkpinfo->backup_media_type == nfs) {
1996 mr_msg(3, "I think the NFS mount is mounted at %s",
1997 bkpinfo->isodir);
1998 }
1999 log_it("isodir = %s", bkpinfo->isodir);
2000 log_it("nfs_mount = '%s'", bkpinfo->nfs_mount);
2001#endif
2002
2003 log_it("media device = %s", bkpinfo->media_device);
2004 log_it("media size = %ld", bkpinfo->media_size[1]);
2005 log_it("media type = %s", bkpinfo->backup_media_string);
2006 log_it("prefix = %s", bkpinfo->prefix);
2007 log_it("compression = %ld", bkpinfo->compression_level);
2008 log_it("include_paths = '%s'", bkpinfo->include_paths);
2009 log_it("exclude_paths = '%s'", bkpinfo->exclude_paths);
2010 log_it("scratchdir = '%s'", bkpinfo->scratchdir);
2011 log_it("tmpdir = '%s'", bkpinfo->tmpdir);
2012 log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device,
2013 bkpinfo->boot_loader);
2014 if (bkpinfo->media_size[0] < 0) {
2015 if (archiving_to_media) {
2016 fatal_error("Media size is less than zero.");
2017 } else {
2018 mr_msg(2, "Warning - media size is less than zero.");
2019 bkpinfo->media_size[0] = 0;
2020 }
2021 }
2022 return (0);
2023}
2024
2025
2026/**
2027 * @addtogroup utilityGroup
2028 * @{
2029 */
2030/**
2031 * Get a space-separated list of NFS devices and mounts.
2032 * @return The list created.
2033 * @note The return value points to static data that will be overwritten with each call.
2034 */
2035char *list_of_NFS_devices_and_mounts(void)
2036{
2037 char *exclude_these_devices;
2038 char *exclude_these_directories;
2039 static char result_sz[512];
2040
2041 malloc_string(exclude_these_devices);
2042 malloc_string(exclude_these_directories);
2043 strcpy(exclude_these_directories,
2044 call_program_and_get_last_line_of_output
2045 ("mount -t coda,ncpfs,nfs,smbfs,cifs,afs,mvfs | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' ' ' | awk '{print $0;}'"));
2046 strcpy(exclude_these_devices,
2047 call_program_and_get_last_line_of_output
2048 ("tr -s '\t' ' ' < /etc/fstab | grep -E '( (coda|ncpfs|nfs|smbfs|cifs|mvfs) )' | cut -d' ' -f1 | tr -s '\n' ' ' | awk '{print $0;}'"));
2049 sprintf(result_sz, "%s %s", exclude_these_directories,
2050 exclude_these_devices);
2051 mr_free(exclude_these_devices);
2052 mr_free(exclude_these_directories);
2053 return (result_sz);
2054}
2055
2056
2057/**
2058 * Get a space-separated list of NFS mounts.
2059 * @return The list created.
2060 * @note The return value points to static data that will be overwritten with each call.
2061 * @bug Even though we only want the mounts, the devices are still checked.
2062 */
2063char *list_of_NFS_mounts_only(void)
2064{
2065 char *exclude_these_devices;
2066 char *exclude_these_directories;
2067 static char result_sz[512];
2068
2069 malloc_string(exclude_these_devices);
2070 malloc_string(exclude_these_directories);
2071 strcpy(exclude_these_directories,
2072 call_program_and_get_last_line_of_output
2073 ("mount -t coda,ncpfs,nfs,smbfs,cifs,afs,mvfs | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' ' ' | awk '{print $0;}'"));
2074 strcpy(exclude_these_devices,
2075 call_program_and_get_last_line_of_output
2076 ("tr -s '\t' ' ' < /etc/fstab | grep -E '( (coda|ncpfs|nfs|smbfs|cifs|mvfs) )' | cut -d' ' -f1 | tr -s '\n' ' ' | awk '{print $0;}'"));
2077 sprintf(result_sz, "%s", exclude_these_directories);
2078 mr_free(exclude_these_devices);
2079 mr_free(exclude_these_directories);
2080 return (result_sz);
2081}
2082/* @} - end of utilityGroup */
2083
2084
2085/**
2086 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
2087 * [random] is a random number between 1 and 32767.
2088 * @param store_name_here Where to store the new filename.
2089 * @param stub A random number will be appended to this to make the FIFO's name.
2090 * @ingroup deviceGroup
2091 */
2092void make_fifo(char *store_name_here, char *stub)
2093{
2094 char *tmp;
2095
2096 malloc_string(tmp);
2097 assert_string_is_neither_NULL_nor_zerolength(stub);
2098
2099 sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
2100 (int) (random() % 32768));
2101 make_hole_for_file(store_name_here);
2102 mkfifo(store_name_here, S_IRWXU | S_IRWXG);
2103 sprintf(tmp, "chmod 770 %s", store_name_here);
2104 paranoid_system(tmp);
2105 mr_free(tmp);
2106}
2107
2108
2109/**
2110 * Set the tmpdir and scratchdir to reside on the partition with the most free space.
2111 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
2112 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set.
2113 * @ingroup utilityGroup
2114 */
2115void sensibly_set_tmpdir_and_scratchdir(struct s_bkpinfo *bkpinfo)
2116{
2117 char *tmp, *command, *sz;
2118
2119 malloc_string(tmp);
2120 malloc_string(command);
2121 malloc_string(sz);
2122 assert(bkpinfo != NULL);
2123
2124#ifdef __FreeBSD__
2125 strcpy(tmp,
2126 call_program_and_get_last_line_of_output
2127 ("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;}'"));
2128#else
2129 strcpy(tmp,
2130 call_program_and_get_last_line_of_output
2131 ("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;}'"));
2132#endif
2133
2134 if (tmp[0] != '/') {
2135 strcpy(sz, tmp);
2136 strcpy(tmp, "/");
2137 strcat(tmp, sz);
2138 }
2139 if (!tmp[0]) {
2140 fatal_error("I couldn't figure out the tempdir!");
2141 }
2142 sprintf(bkpinfo->tmpdir, "%s/tmp.mondo.%d", tmp,
2143 (int) (random() % 32768));
2144 log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir);
2145
2146 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%d", tmp,
2147 (int) (random() % 32768));
2148 log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
2149
2150 sprintf(g_erase_tmpdir_and_scratchdir, "rm -Rf %s %s", bkpinfo->tmpdir,
2151 bkpinfo->scratchdir);
2152
2153 sprintf(command, "rm -Rf %s/tmp.mondo.* %s/mondo.scratch.*", tmp, tmp);
2154 paranoid_system(command);
2155 mr_free(tmp);
2156 mr_free(command);
2157 mr_free(sz);
2158}
2159
2160
2161/**
2162 * @addtogroup deviceGroup
2163 * @{
2164 */
2165/**
2166 * If we can read @p dev, set @p output to it.
2167 * If @p dev cannot be read, set @p output to "".
2168 * @param dev The device to check for.
2169 * @param output Set to @p dev if @p dev exists, "" otherwise.
2170 * @return TRUE if @p dev exists, FALSE if it doesn't.
2171 */
2172bool set_dev_to_this_if_rx_OK(char *output, char *dev)
2173{
2174 char *command;
2175
2176 malloc_string(command);
2177 if (!dev || dev[0] == '\0') {
2178 output[0] = '\0';
2179 return (FALSE);
2180 }
2181// assert_string_is_neither_NULL_nor_zerolength(dev);
2182 mr_msg(10, "Injecting %s", dev);
2183 inject_device(dev);
2184 if (!does_file_exist(dev)) {
2185 mr_msg(10, "%s doesn't exist. Returning FALSE.", dev);
2186 return (FALSE);
2187 }
2188 sprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null",
2189 512L, dev);
2190 if (!run_program_and_log_output(command, FALSE)
2191 && !run_program_and_log_output(command, FALSE)) {
2192 strcpy(output, dev);
2193 mr_msg(4, "Found it - %s", dev);
2194 return (TRUE);
2195 } else {
2196 output[0] = '\0';
2197 mr_msg(4, "It's not %s", dev);
2198 return (FALSE);
2199 }
2200}
2201
2202
2203/**
2204 * Find out what number CD is in the drive.
2205 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
2206 * @return The current CD number, or -1 if it could not be found.
2207 * @note If the CD is not mounted, it will be mounted
2208 * (and remain mounted after this function returns).
2209 */
2210int what_number_cd_is_this(struct s_bkpinfo *bkpinfo)
2211{
2212 int cd_number = -1;
2213 char *mountdev;
2214 char *tmp;
2215
2216 malloc_string(mountdev);
2217 malloc_string(tmp);
2218 assert(bkpinfo != NULL);
2219// log_it("Asking what_number_cd_is_this");
2220 if (g_ISO_restore_mode) {
2221 sprintf(tmp, "mount | grep iso9660 | awk '{print $3;}'");
2222// log_it("tmp = %s", tmp);
2223
2224 strcpy(mountdev, call_program_and_get_last_line_of_output(tmp));
2225 strcat(mountdev, "/archives/THIS-CD-NUMBER");
2226// log_it("mountdev = %s", mountdev);
2227 cd_number = atoi(last_line_of_file(mountdev));
2228// log_it("cd_number = %d", cd_number);
2229 mr_free(mountdev);
2230 mr_free(tmp);
2231 return (cd_number);
2232 }
2233
2234 strcpy(mountdev, bkpinfo->media_device);
2235 if (!mountdev[0]) {
2236 log_it
2237 ("(what_number_cd_is_this) Warning - media_device unknown. Finding out...");
2238 find_cdrom_device(bkpinfo->media_device, FALSE);
2239 }
2240 if (!is_this_device_mounted(MNT_CDROM)) {
2241 mount_CDROM_here(mountdev, MNT_CDROM);
2242 }
2243 cd_number =
2244 atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
2245// log_it("cd_number..later.. = %d", cd_number);
2246 mr_free(mountdev);
2247 mr_free(tmp);
2248 return (cd_number);
2249}
2250
2251
2252/**
2253 * Find out what device is mounted as root (/).
2254 * @return Root device.
2255 * @note The returned string points to static storage and will be overwritten with every call.
2256 * @bug A bit of a misnomer; it's actually finding out the root device.
2257 * The mountpoint (where it's mounted) will obviously be '/'.
2258 */
2259char *where_is_root_mounted()
2260{
2261 /*@ buffers **************** */
2262 static char tmp[MAX_STR_LEN];
2263
2264
2265#ifdef __FreeBSD__
2266 strcpy(tmp, call_program_and_get_last_line_of_output
2267 ("mount | grep \" on / \" | cut -d' ' -f1"));
2268#else
2269 strcpy(tmp, call_program_and_get_last_line_of_output
2270 ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"));
2271 if (strstr(tmp, "/dev/cciss/")) {
2272 strcpy(tmp, call_program_and_get_last_line_of_output
2273 ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"));
2274 }
2275 if (strstr(tmp, "/dev/md")) {
2276 strcpy(tmp,
2277 call_program_and_get_last_line_of_output
2278 ("mount | grep \" on / \" | cut -d' ' -f1"));
2279 }
2280#endif
2281
2282 return (tmp);
2283}
2284
2285
2286/**
2287 * Find out which boot loader is in use.
2288 * @param which_device Device to look for the boot loader on.
2289 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
2290 * @note Under Linux, all drives are examined, not just @p which_device.
2291 */
2292char which_boot_loader(char *which_device)
2293{
2294#ifdef __FreeBSD__
2295 int count_lilos = 0;
2296 int count_grubs = 0;
2297 int count_boot0s = 0;
2298 int count_dangerouslydedicated = 0;
2299
2300 log_it("looking at drive %s's MBR", which_device);
2301 if (does_string_exist_in_boot_block(which_device, "GRUB")) {
2302 count_grubs++;
2303 }
2304 if (does_string_exist_in_boot_block(which_device, "LILO")) {
2305 count_lilos++;
2306 }
2307 if (does_string_exist_in_boot_block(which_device, "Drive")) {
2308 count_boot0s++;
2309 }
2310 if (does_string_exist_in_first_N_blocks
2311 (which_device, "FreeBSD/i386", 17)) {
2312 count_dangerouslydedicated++;
2313 }
2314 log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
2315 count_grubs, count_lilos, count_elilos, count_boot0s,
2316 count_dangerouslydedicated);
2317
2318 if (count_grubs && !count_lilos) {
2319 return ('G');
2320 } else if (count_lilos && !count_grubs) {
2321 return ('L');
2322 } else if (count_grubs == 1 && count_lilos == 1) {
2323 log_it("I'll bet you used to use LILO but switched to GRUB...");
2324 return ('G');
2325 } else if (count_boot0s == 1) {
2326 return ('B');
2327 } else if (count_dangerouslydedicated) {
2328 return ('D');
2329 } else {
2330 log_it("Unknown boot loader");
2331 return ('U');
2332 }
2333#else
2334 /*@ buffer ***************************************************** */
2335 char *list_drives_cmd;
2336 char *current_drive = NULL;
2337
2338 /*@ pointers *************************************************** */
2339 FILE *pdrives;
2340
2341 /*@ int ******************************************************** */
2342 int count_lilos = 0;
2343 int count_grubs = 0;
2344 size_t n = 0;
2345
2346 /*@ end vars *************************************************** */
2347
2348#ifdef __IA64__
2349 /* No choice for it */
2350 return ('E');
2351#endif
2352 assert(which_device != NULL);
2353 mr_asprintf(&list_drives_cmd,
2354 "parted2fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s",
2355 where_is_root_mounted());
2356 log_it("list_drives_cmd = %s", list_drives_cmd);
2357
2358 if (!(pdrives = popen(list_drives_cmd, "r"))) {
2359 log_OS_error("Unable to open list of drives");
2360 mr_free(list_drives_cmd);
2361 return ('\0');
2362 }
2363 mr_free(list_drives_cmd);
2364
2365 for (mr_getline(&current_drive, &n, pdrives); !feof(pdrives);
2366 mr_getline(&current_drive, &n, pdrives)) {
2367 strip_spaces(current_drive);
2368 log_it("looking at drive %s's MBR", current_drive);
2369 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
2370 count_grubs++;
2371 strcpy(which_device, current_drive);
2372 break;
2373 }
2374 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
2375 count_lilos++;
2376 strcpy(which_device, current_drive);
2377 break;
2378 }
2379 }
2380
2381 if (pclose(pdrives)) {
2382 log_OS_error("Cannot pclose pdrives");
2383 }
2384 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
2385 if (count_grubs && !count_lilos) {
2386 return ('G');
2387 } else if (count_lilos && !count_grubs) {
2388 return ('L');
2389 } else if (count_grubs == 1 && count_lilos == 1) {
2390 log_it("I'll bet you used to use LILO but switched to GRUB...");
2391 return ('G');
2392 } else {
2393 log_it("Unknown boot loader");
2394 return ('U');
2395 }
2396#endif
2397}
2398
2399
2400/**
2401 * Write zeroes over the first 16K of @p device.
2402 * @param device The device to zero.
2403 * @return 0 for success, 1 for failure.
2404 */
2405int zero_out_a_device(char *device)
2406{
2407 FILE *fout;
2408 int i;
2409
2410 assert_string_is_neither_NULL_nor_zerolength(device);
2411
2412 log_it("Zeroing drive %s", device);
2413 if (!(fout = fopen(device, "w"))) {
2414 log_OS_error("Unable to open/write to device");
2415 return (1);
2416 }
2417 for (i = 0; i < 16384; i++) {
2418 fputc('\0', fout);
2419 }
2420 paranoid_fclose(fout);
2421 log_it("Device successfully zeroed.");
2422 return (0);
2423}
2424
2425
2426/**
2427 * Return the device pointed to by @p incoming.
2428 * @param incoming The device to resolve symlinks for.
2429 * @return The path to the real device file.
2430 * @note The returned string points to static storage that will be overwritten with each call.
2431 * @bug Won't work with file v4.0; needs to be written in C.
2432 */
2433char *resolve_softlinks_to_get_to_actual_device_file(char *incoming)
2434{
2435 static char output[MAX_STR_LEN];
2436 char *command = NULL;
2437 char *curr_fname = NULL;
2438 char *scratch = NULL;
2439 char *tmp = NULL;
2440 char *p = NULL;
2441
2442 struct stat statbuf;
2443 malloc_string(tmp);
2444 malloc_string(scratch);
2445 malloc_string(curr_fname);
2446 if (!does_file_exist(incoming)) {
2447 log_it
2448 ("resolve_softlinks_to_get_to_actual_device_file --- device not found");
2449 strcpy(output, incoming);
2450 } else {
2451 strcpy(curr_fname, incoming);
2452 lstat(curr_fname, &statbuf);
2453 while (S_ISLNK(statbuf.st_mode)) {
2454 mr_msg(1, "curr_fname = %s", curr_fname);
2455 mr_asprintf(&command, "file %s", curr_fname);
2456 strcpy(tmp, call_program_and_get_last_line_of_output(command));
2457 mr_free(command);
2458
2459 for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' ';
2460 p--);
2461 p++;
2462 strcpy(scratch, p);
2463 for (p = scratch; *p != '\0' && *p != '\''; p++);
2464 *p = '\0';
2465 mr_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp,
2466 scratch);
2467 if (scratch[0] == '/') {
2468 strcpy(curr_fname, scratch); // copy whole thing because it's an absolute softlink
2469 } else { // copy over the basename cos it's a relative softlink
2470 p = curr_fname + strlen(curr_fname);
2471 while (p != curr_fname && *p != '/') {
2472 p--;
2473 }
2474 if (*p == '/') {
2475 p++;
2476 }
2477 strcpy(p, scratch);
2478 }
2479 lstat(curr_fname, &statbuf);
2480 }
2481 strcpy(output, curr_fname);
2482 log_it("resolved %s to %s", incoming, output);
2483 }
2484 mr_free(curr_fname);
2485 mr_free(tmp);
2486 return (output);
2487}
2488
2489/* @} - end of deviceGroup */
2490
2491
2492/**
2493 * Return the type of partition format (GPT or MBR)
2494 */
2495char *which_partition_format(const char *drive)
2496{
2497 static char output[4];
2498 char *tmp = NULL;
2499 char *command = NULL;
2500 char *fdisk = NULL;
2501#ifdef __IA64__
2502 struct stat buf;
2503#endif
2504 malloc_string(tmp);
2505 mr_msg(0, "Looking for partition table format type");
2506 mr_asprintf(&fdisk, "/sbin/parted2fdisk");
2507 mr_msg(1, "Using %s", fdisk);
2508 mr_asprintf(&command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
2509 mr_free(fdisk);
2510
2511 strcpy(tmp, call_program_and_get_last_line_of_output(command));
2512 mr_free(command);
2513
2514 if (strstr(tmp, "GPT") == NULL) {
2515 strcpy(output, "MBR");
2516 } else {
2517 strcpy(output, "GPT");
2518 }
2519 mr_msg(0, "Found %s partition table format type", output);
2520 mr_free(tmp);
2521 return(output);
2522}
2523/* @} - end of deviceGroup */
Note: See TracBrowser for help on using the repository browser.