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

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

End on memory mngt for libmondo-devices.c for the moment

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