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

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

bkptype_to_string is now a public function (not static anymore)

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