source: MondoRescue/branches/2.2.9/mondo/src/common/libmondo-devices.c@ 2613

Last change on this file since 2613 was 2613, checked in by Bruno Cornec, 14 years ago
  • Fix an initialization bug for network protocol in interactive mode (was NULL and not NFS by default)
  • Property svn:keywords set to Id
File size: 93.1 KB
Line 
1/* libmondo-devices.c Subroutines for handling devices
2 $Id: libmondo-devices.c 2613 2010-03-30 00:20:29Z bruno $
3*/
4
5/**
6 * @file
7 * Functions to handle interactions with backup devices.
8 */
9
10#include "my-stuff.h"
11#include "mr_mem.h"
12#include "mr_str.h"
13#include "mondostructures.h"
14#include "libmondo-files-EXT.h"
15#include "libmondo-devices.h"
16#include "lib-common-externs.h"
17#include "libmondo-string-EXT.h"
18#include "libmondo-tools-EXT.h"
19#include "libmondo-gui-EXT.h"
20#include "libmondo-fork-EXT.h"
21#include "libmondo-stream-EXT.h"
22
23#include <sys/types.h>
24#ifdef __FreeBSD__
25#define DKTYPENAMES
26#define FSTYPENAMES
27#include <sys/disklabel.h>
28#include <sys/disk.h>
29#elif linux
30#define u64 unsigned long long
31#include <linux/fs.h> /* for BLKGETSIZE64 */
32#include <linux/hdreg.h>
33#endif
34
35/*@unused@*/
36//static char cvsid[] = "$Id: libmondo-devices.c 2613 2010-03-30 00:20:29Z bruno $";
37
38extern int g_current_media_number;
39extern double g_kernel_version;
40
41extern bool g_ISO_restore_mode;
42extern char *g_selfmounted_isodir;
43extern char *MONDO_LOGFILE;
44
45extern void setup_tmpdir(char *path);
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;
57bool g_restoring_live_from_netfs = FALSE;
58
59extern t_bkptype g_backup_media_type; // set by main()
60
61/* Reference to global bkpinfo */
62extern struct s_bkpinfo *bkpinfo;
63
64/* Stuff that handles the -I and -E option when a whole disk DSF is used */
65typedef struct mounted_fs_struct {
66 char device[MAX_STR_LEN]; /* The name of the device */
67 char mount_point[MAX_STR_LEN]; /* The devices mount point */
68 unsigned char check; /* 1 == included on DSF */
69 struct mounted_fs_struct *next;
70} MOUNTED_FS_STRUCT;
71
72static MOUNTED_FS_STRUCT *DSF_Head = NULL; /* Points to the first entry of mounted_fs_struct list */
73static MOUNTED_FS_STRUCT *DSF_Tail = NULL; /* Points to the last entry of mounted_fs_struct list */
74
75
76void set_g_cdrom_and_g_dvd_to_bkpinfo_value()
77{
78 strcpy(g_cdrom_drive_is_here, bkpinfo->media_device); // just in case
79 strcpy(g_dvd_drive_is_here, bkpinfo->media_device); // just in case
80}
81
82
83
84/**
85 * Retract all CD trays and wait for autorun to complete.
86 * @ingroup deviceGroup
87 */
88void retract_CD_tray_and_defeat_autorun(void)
89{
90// log_it("rctada: Retracting all CD trays", __LINE__);
91 if (strlen(g_cdrom_drive_is_here) > 0) {
92 inject_device(g_cdrom_drive_is_here);
93 }
94 if (strlen(g_dvd_drive_is_here) > 0) {
95 inject_device(g_dvd_drive_is_here);
96 }
97 if (strlen(g_cdrw_drive_is_here) > 0) {
98 inject_device(g_cdrw_drive_is_here);
99 }
100// log_it("rctada: killing autorun");
101// run_program_and_log_output("killall autorun", TRUE);
102 if (!run_program_and_log_output("ps | grep autorun | grep -v grep", 5)) {
103 log_it("autorun detected; sleeping for 2 seconds");
104 sleep(2);
105 }
106 log_it("rctada: Unmounting all CD drives", __LINE__);
107 run_program_and_log_output("umount /dev/cdr* /dev/dvd*", 5);
108}
109
110
111
112/**
113 * Determine whether we're booted off a ramdisk.
114 * @return @c TRUE (we are) or @c FALSE (we aren't).
115 * @ingroup utilityGroup
116 */
117bool am_I_in_disaster_recovery_mode(void)
118{
119 char *tmp = NULL;
120 char *comment;
121 bool is_this_a_ramdisk = FALSE;
122
123 malloc_string(comment);
124 mr_asprintf(&tmp, "%s", where_is_root_mounted());
125 sprintf(comment, "root is mounted at %s\n", tmp);
126 log_msg(0, comment);
127 log_msg(0,
128 "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().",
129 tmp);
130
131#ifdef __FreeBSD__
132 if (strstr(tmp, "/dev/md")) {
133 is_this_a_ramdisk = TRUE;
134 }
135#else
136 if (!strncmp(tmp, "/dev/ram", 8)
137 || (!strncmp(tmp, "/dev/rd", 7) && !strcmp(tmp, "/dev/rd/")
138 && strncmp(tmp, "/dev/rd/cd", 10)) || strstr(tmp, "rootfs")
139 || !strcmp(tmp, "/dev/root")) {
140 is_this_a_ramdisk = TRUE;
141 } else {
142 is_this_a_ramdisk = FALSE;
143 }
144#endif
145 mr_free(tmp);
146
147 if (is_this_a_ramdisk) {
148 if (!does_file_exist("/THIS-IS-A-RAMDISK")) {
149 log_to_screen
150 ("Using /dev/root is stupid of you but I'll forgive you.");
151 is_this_a_ramdisk = FALSE;
152 }
153 }
154 if (does_file_exist("/THIS-IS-A-RAMDISK")) {
155 is_this_a_ramdisk = TRUE;
156 }
157 paranoid_free(comment);
158 log_msg(1, "Is this a ramdisk? result = %d", is_this_a_ramdisk);
159 return (is_this_a_ramdisk);
160}
161
162
163
164
165
166/**
167 * Turn @c bkpinfo->backup_media_type into a human-readable string.
168 * @return The human readable string (e.g. @c cdr becomes <tt>"cdr"</tt>).
169 * @note The returned string points to static storage that will be overwritten with each call.
170 * @ingroup stringGroup
171 */
172static char *bkptype_to_string(t_bkptype bt)
173{
174 static char output[MAX_STR_LEN / 4];
175 switch (bt) {
176 case none:
177 strcpy(output, "none");
178 break;
179 case iso:
180 strcpy(output, "iso");
181 break;
182 case cdr:
183 strcpy(output, "cdr");
184 break;
185 case cdrw:
186 strcpy(output, "cdrw");
187 break;
188 case cdstream:
189 strcpy(output, "cdstream");
190 break;
191 case netfs:
192 strcpy(output, "netfs");
193 break;
194 case tape:
195 strcpy(output, "tape");
196 break;
197 case udev:
198 strcpy(output, "udev");
199 break;
200 case usb:
201 strcpy(output, "usb");
202 break;
203 default:
204 strcpy(output, "default");
205 }
206 return (output);
207}
208
209
210
211/**
212 * @addtogroup deviceGroup
213 * @{
214 */
215/**
216 * Eject the tray of the specified CD device.
217 * @param dev The device to eject.
218 * @return the return value of the @c eject command. (0=success, nonzero=failure)
219 */
220int eject_device(char *dev)
221{
222 char *command;
223 int res1 = 0, res2 = 0;
224
225 malloc_string(command);
226
227 if (IS_THIS_A_STREAMING_BACKUP(g_backup_media_type)
228 && g_backup_media_type != udev) {
229 sprintf(command, "mt -f %s offline", dev);
230 res1 = run_program_and_log_output(command, 1);
231 } else {
232 res1 = 0;
233 }
234
235#ifdef __FreeBSD__
236 if (strstr(dev, "acd")) {
237 sprintf(command, "cdcontrol -f %s eject", dev);
238 } else {
239 sprintf(command, "camcontrol eject `echo %s | sed 's|/dev/||'`",
240 dev);
241 }
242#else
243 sprintf(command, "eject %s", dev);
244#endif
245
246 log_msg(3, "Ejecting %s", dev);
247 res2 = run_program_and_log_output(command, 1);
248 paranoid_free(command);
249 if (res1 && res2) {
250 return (1);
251 } else {
252 return (0);
253 }
254}
255
256/**
257 * Load (inject) the tray of the specified CD device.
258 * @param dev The device to load/inject.
259 * @return 0 for success, nonzero for failure.
260 */
261int inject_device(char *dev)
262{
263 char *command;
264 int i;
265
266 malloc_string(command);
267
268
269#ifdef __FreeBSD__
270 if (strstr(dev, "acd")) {
271 sprintf(command, "cdcontrol -f %s close", dev);
272 } else {
273 sprintf(command, "camcontrol load `echo %s | sed 's|/dev/||'`",
274 dev);
275 }
276#else
277 sprintf(command, "eject -t %s", dev);
278#endif
279 i = run_program_and_log_output(command, FALSE);
280 paranoid_free(command);
281 return (i);
282}
283
284
285/**
286 * Determine whether the specified @p device (really, you can use any file)
287 * exists.
288 * @return TRUE if it exists, FALSE if it doesn't.
289 */
290bool does_device_exist(char *device)
291{
292
293 /*@ buffers *********************************************************** */
294 char *tmp;
295 bool ret;
296
297 malloc_string(tmp);
298 assert_string_is_neither_NULL_nor_zerolength(device);
299
300 sprintf(tmp, "ls %s > /dev/null 2> /dev/null", device);
301
302 if (system(tmp)) {
303 ret = FALSE;
304 } else {
305 ret = TRUE;
306 }
307 paranoid_free(tmp);
308 return (ret);
309}
310
311
312/**
313 * Determine whether a non-Microsoft partition exists on any connected hard drive.
314 * @return TRUE (there's a Linux/FreeBSD partition) or FALSE (Microsoft has taken over yet another innocent PC).
315 */
316bool does_nonMS_partition_exist(void)
317{
318#if __FreeBSD__
319 return
320 !system
321 ("for drive in /dev/ad? /dev/da?; do fdisk $drive | grep -q FreeBSD && exit 0; done; false");
322#else
323 return
324 !system
325 ("parted2fdisk -l 2>/dev/null | grep '^/dev/' | grep -Eqv '(MS|DOS|FAT|NTFS)'");
326#endif
327}
328
329/**
330 * Determine whether the specified @p partno exists on the specified @p drive.
331 * @param drive The drive to search for the partition in.
332 * @param partno The partition number to look for.
333 * @return 0 if it exists, nonzero otherwise.
334 */
335int does_partition_exist(const char *drive, int partno)
336{
337 /*@ buffers **************************************************** */
338 char *program;
339 char *incoming;
340 char *searchstr = NULL;
341 char *tmp;
342
343 /*@ ints ******************************************************* */
344 int res = 0;
345
346 /*@ pointers *************************************************** */
347 FILE *fin;
348
349
350 /*@ end vars *************************************************** */
351 assert_string_is_neither_NULL_nor_zerolength(drive);
352 assert(partno >= 0 && partno < 999);
353
354 malloc_string(program);
355 malloc_string(incoming);
356 malloc_string(searchstr);
357 malloc_string(tmp);
358
359#ifdef __FreeBSD__
360 // We assume here that this is running from mondorestore. (It is.)
361 sprintf(program, "ls %s %s >/dev/null 2>&1", drive,
362 build_partition_name(tmp, drive, partno));
363 return system(program);
364#else
365 tmp[0] = '\0';
366#endif
367
368 sprintf(program, "parted2fdisk -l %s 2> /dev/null", drive);
369 fin = popen(program, "r");
370 if (!fin) {
371 log_it("program=%s", program);
372 log_OS_error("Cannot popen-in program");
373 return (0);
374 }
375 (void) build_partition_name(searchstr, drive, partno);
376 strcat(searchstr, " ");
377 for (res = 0; !res && fgets(incoming, MAX_STR_LEN - 1, fin);) {
378 if (strstr(incoming, searchstr)) {
379 res = 1;
380 }
381 }
382 if (pclose(fin)) {
383 log_OS_error("Cannot pclose fin");
384 }
385 paranoid_free(program);
386 paranoid_free(incoming);
387 paranoid_free(searchstr);
388 paranoid_free(tmp);
389 return (res);
390}
391
392
393
394
395
396/**
397 * Determine whether given NULL-terminated @p str exists in the MBR of @p dev.
398 * @param dev The device to look in.
399 * @param str The string to look for.
400 * @return TRUE if it exists, FALSE if it doesn't.
401 */
402bool does_string_exist_in_boot_block(char *dev, char *str)
403{
404 /*@ buffers **************************************************** */
405 char *command;
406
407 /*@ end vars *************************************************** */
408 int i;
409
410 assert_string_is_neither_NULL_nor_zerolength(dev);
411 assert_string_is_neither_NULL_nor_zerolength(str);
412
413 malloc_string(command);
414 sprintf(command,
415 "dd if=%s bs=446 count=1 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null",
416 dev, str);
417 i = system(command);
418 paranoid_free(command);
419 if (i) {
420 return (FALSE);
421 } else {
422 return (TRUE);
423 }
424}
425
426/**
427 * Determine whether specified @p str exists in the first @p n sectors of
428 * @p dev.
429 * @param dev The device to look in.
430 * @param str The string to look for.
431 * @param n The number of 512-byte sectors to search.
432 */
433bool does_string_exist_in_first_N_blocks(char *dev, char *str, int n)
434{
435 /*@ buffers **************************************************** */
436 char *command;
437 /*@ end vars *************************************************** */
438 int i;
439
440 malloc_string(command);
441 sprintf(command,
442 "dd if=%s bs=512 count=%i 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null",
443 dev, n, str);
444 i = system(command);
445 paranoid_free(command);
446 if (i) {
447 return (FALSE);
448 } else {
449 return (TRUE);
450 }
451}
452
453
454
455/**
456 * Try to mount CD-ROM at @p mountpoint. If the CD-ROM is not found or has
457 * not been specified, call find_cdrom_device() to find it.
458 * @param bkpinfo The backup information structure. The only field used is @c bkpinfo->media_device.
459 * @param mountpoint Where to mount the CD-ROM.
460 * @return 0 for success, nonzero for failure.
461 * @see mount_CDROM_here
462 */
463int find_and_mount_actual_cd(char *mountpoint)
464{
465 /*@ buffers ***************************************************** */
466
467 /*@ int's ****************************************************** */
468 int res;
469 char *dev;
470
471 /*@ end vars **************************************************** */
472
473 malloc_string(dev);
474 assert(bkpinfo != NULL);
475 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
476
477 if (g_backup_media_type == dvd) {
478 strcpy(dev, g_dvd_drive_is_here);
479 if (!dev[0]) {
480 find_dvd_device(dev, FALSE);
481 }
482 } else {
483 strcpy(dev, g_cdrom_drive_is_here);
484 if (!dev[0]) {
485 find_cdrom_device(dev, FALSE);
486 }
487 }
488
489 if (bkpinfo->backup_media_type != iso) {
490 retract_CD_tray_and_defeat_autorun();
491 }
492
493 if (!dev[0] || (res = mount_CDROM_here(dev, mountpoint))) {
494 if (!popup_and_get_string
495 ("CD-ROM device", "Please enter your CD-ROM's /dev device",
496 dev, MAX_STR_LEN / 4)) {
497 res = 1;
498 } else {
499 res = mount_CDROM_here(dev, mountpoint);
500 }
501 }
502 if (res) {
503 log_msg(1, "mount failed");
504 } else {
505 log_msg(1, "mount succeeded with %s", dev);
506 }
507 paranoid_free(dev);
508 return (res);
509}
510
511
512
513
514
515
516/**
517 * Locate a CD-R/W writer's SCSI node.
518 * @param cdrw_device SCSI node will be placed here.
519 * @return 0 for success, nonzero for failure.
520 */
521int find_cdrw_device(char *cdrw_device)
522{
523 /*@ buffers ************************ */
524 char *comment;
525 char *tmp = NULL;
526 char *cdr_exe = NULL;
527 char *command;
528
529 malloc_string(comment);
530 malloc_string(command);
531 if (g_cdrw_drive_is_here[0]) {
532 strcpy(cdrw_device, g_cdrw_drive_is_here);
533 log_msg(3, "Been there, done that. Returning %s", cdrw_device);
534 paranoid_free(comment);
535 paranoid_free(command);
536 return (0);
537 }
538 if (g_backup_media_type == dvd) {
539 log_msg(1,
540 "This is dumb. You're calling find_cdrw_device() but you're backing up to DVD. WTF?");
541 paranoid_free(comment);
542 paranoid_free(command);
543 return (1);
544 }
545 run_program_and_log_output("insmod ide-scsi", -1);
546 if (find_home_of_exe("cdrecord")) {
547 mr_asprintf(&cdr_exe, "cdrecord");
548 } else {
549 mr_asprintf(&cdr_exe, "dvdrecord");
550 }
551 if (find_home_of_exe(cdr_exe)) {
552 sprintf(command,
553 "%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",
554 cdr_exe);
555 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
556 }
557 if ((tmp == NULL) || (strlen(tmp) < 2)) {
558 paranoid_free(comment);
559 mr_free(tmp);
560 mr_free(cdr_exe);
561 paranoid_free(command);
562 return 1;
563 } else {
564 strcpy(cdrw_device, tmp);
565 sprintf(comment, "Found CDRW device - %s", cdrw_device);
566 log_it(comment);
567 strcpy(g_cdrw_drive_is_here, cdrw_device);
568 paranoid_free(comment);
569 mr_free(tmp);
570 mr_free(cdr_exe);
571 paranoid_free(command);
572 return (0);
573 }
574}
575
576
577
578
579/**
580 * Attempt to locate a CD-ROM device's /dev entry.
581 * Several different methods may be used to find the device, including
582 * calling @c cdrecord, searching @c dmesg, and trial-and-error.
583 * @param output Where to put the located /dev entry.
584 * @param try_to_mount Whether to mount the CD as part of the test; if mount
585 * fails then return failure.
586 * @return 0 for success, nonzero for failure.
587 */
588int find_cdrom_device(char *output, bool try_to_mount)
589{
590 /*@ pointers **************************************************** */
591 FILE *fin;
592 char *p;
593 char *q;
594 char *r;
595 int retval = 0;
596
597 /*@ bool's ****************************************************** */
598 bool found_it = FALSE;
599
600 /*@ buffers ***************************************************** */
601 char *tmp;
602 char *tmp1 = NULL;
603 char *cdr_exe = NULL;
604 char *phrase_one;
605 char *phrase_two;
606 char *command;
607 char *dvd_last_resort;
608 char *mountpoint;
609 static char the_last_place_i_found_it[MAX_STR_LEN] = "";
610
611 /*@ intialize *************************************************** */
612 malloc_string(tmp);
613 malloc_string(phrase_one);
614 malloc_string(phrase_two);
615 malloc_string(command);
616 malloc_string(dvd_last_resort);
617 malloc_string(mountpoint);
618
619 output[0] = '\0';
620 phrase_one[0] = '\0';
621 phrase_two[0] = '\0';
622 dvd_last_resort[0] = '\0';
623
624 /*@ end vars **************************************************** */
625
626 if (g_cdrom_drive_is_here[0] && !isdigit(g_cdrom_drive_is_here[0])) {
627 strcpy(output, g_cdrom_drive_is_here);
628 log_msg(3, "Been there, done that. Returning %s", output);
629 retval = 0;
630 goto end_of_find_cdrom_device;
631 }
632 if (the_last_place_i_found_it[0] != '\0' && !try_to_mount) {
633 strcpy(output, the_last_place_i_found_it);
634 log_msg(3,
635 "find_cdrom_device() --- returning last found location - '%s'",
636 output);
637 retval = 0;
638 goto end_of_find_cdrom_device;
639 }
640
641 sprintf(mountpoint, "%s/cd.mnt", bkpinfo->tmpdir);
642 make_hole_for_dir(mountpoint);
643
644 if (find_home_of_exe("cdrecord")) {
645 mr_asprintf(&cdr_exe, "cdrecord");
646 } else {
647 mr_asprintf(&cdr_exe, "dvdrecord");
648 }
649 tmp[0] = '\0';
650 if (!find_home_of_exe(cdr_exe)) {
651 strcpy(output, "/dev/cdrom");
652 log_msg(4, "Can't find cdrecord; assuming %s", output);
653 if (!does_device_exist(output)) {
654 log_msg(4, "That didn't work. Sorry.");
655 retval = 1;
656 goto end_of_find_cdrom_device;
657 } else {
658 retval = 0;
659 goto end_of_find_cdrom_device;
660 }
661 }
662
663 sprintf(command, "%s -scanbus 2> /dev/null", cdr_exe);
664 fin = popen(command, "r");
665 if (!fin) {
666 log_msg(4, "command=%s", command);
667 log_OS_error("Cannot popen command");
668 mr_free(cdr_exe);
669 return (1);
670 }
671 for ((void)fgets(tmp, MAX_STR_LEN, fin); !feof(fin);
672 (void)fgets(tmp, MAX_STR_LEN, fin)) {
673 p = strchr(tmp, '\'');
674 if (p) {
675 q = strchr(++p, '\'');
676 if (q) {
677 for (r = q; *(r - 1) == ' '; r--);
678 *r = '\0';
679 strcpy(phrase_one, p);
680 p = strchr(++q, '\'');
681 if (p) {
682 q = strchr(++p, '\'');
683 if (q) {
684 while (*(q - 1) == ' ') {
685 q--;
686 }
687 *q = '\0';
688 strcpy(phrase_two, p);
689 }
690 }
691 }
692 }
693 }
694 paranoid_pclose(fin);
695
696#ifndef __FreeBSD__
697 if (strlen(phrase_two) == 0) {
698 log_msg(4, "Not running phase two. String is empty.");
699 } else {
700 sprintf(command, "dmesg | grep \"%s\" 2> /dev/null", phrase_two);
701 fin = popen(command, "r");
702 if (!fin) {
703 log_msg(4, "Cannot run 2nd command - non-fatal, fortunately");
704 } else {
705 for ((void)fgets(tmp, MAX_STR_LEN, fin); !feof(fin);
706 (void)fgets(tmp, MAX_STR_LEN, fin)) {
707 log_msg(5, "--> '%s'", tmp);
708 if (tmp[0] != ' ' && tmp[1] != ' ') {
709 p = strchr(tmp, ':');
710 if (p) {
711 *p = '\0';
712 if (strstr(tmp, "DVD")) {
713 sprintf(dvd_last_resort, "/dev/%s", tmp);
714 log_msg(4,
715 "Ignoring '%s' because it's a DVD drive",
716 tmp);
717 } else {
718 sprintf(output, "/dev/%s", tmp);
719 found_it = TRUE;
720 }
721 }
722 }
723 }
724 paranoid_pclose(fin);
725 }
726 }
727
728#endif
729#ifdef __FreeBSD__
730 if (!found_it) {
731 log_msg(4, "OK, approach 2");
732 if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/cdrom"))) {
733 if (!
734 (found_it =
735 set_dev_to_this_if_rx_OK(output, "/dev/cdrom1"))) {
736 if (!
737 (found_it =
738 set_dev_to_this_if_rx_OK(output, "/dev/dvd"))) {
739 if (!
740 (found_it =
741 set_dev_to_this_if_rx_OK(output, "/dev/acd0"))) {
742 if (!
743 (found_it =
744 set_dev_to_this_if_rx_OK(output,
745 "/dev/cd01"))) {
746 if (!
747 (found_it =
748 set_dev_to_this_if_rx_OK(output,
749 "/dev/acd1"))) {
750 if (!
751 (found_it =
752 set_dev_to_this_if_rx_OK(output,
753 "/dev/cd1")))
754 {
755 retval = 1;
756 goto end_of_find_cdrom_device;
757 }
758 }
759 }
760 }
761 }
762 }
763 }
764 }
765#else
766 if (!found_it && strlen(dvd_last_resort) > 0) {
767 log_msg(4, "Well, I'll use the DVD - %s - as a last resort",
768 dvd_last_resort);
769 strcpy(output, dvd_last_resort);
770 found_it = TRUE;
771 }
772 if (found_it) {
773 sprintf(tmp, "grep \"%s=ide-scsi\" /proc/cmdline &> /dev/null",
774 strrchr(output, '/') + 1);
775 if (system(tmp) == 0) {
776 log_msg(4,
777 "%s is not right. It's being SCSI-emulated. Continuing.",
778 output);
779 found_it = FALSE;
780 output[0] = '\0';
781 }
782 }
783
784 if (found_it) {
785 log_msg(4, "(find_cdrom_device) --> '%s'", output);
786 if (!does_device_exist(output)) {
787 found_it = FALSE;
788 log_msg(4, "OK, I was wrong, I haven't found it... yet.");
789 }
790 }
791
792 if (!found_it) {
793 log_msg(4, "OK, approach 2");
794 if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/scd0"))) {
795 if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/sr0"))) {
796 if (!
797 (found_it =
798 set_dev_to_this_if_rx_OK(output, "/dev/cdrom"))) {
799 if (!
800 (found_it =
801 set_dev_to_this_if_rx_OK(output,
802 "/dev/cdrom0"))) {
803 if (!
804 (found_it =
805 set_dev_to_this_if_rx_OK(output,
806 "/dev/cdrom1"))) {
807 if (!
808 (found_it =
809 set_dev_to_this_if_rx_OK(output,
810 "/dev/sr1"))) {
811 if (!
812 (found_it =
813 set_dev_to_this_if_rx_OK(output,
814 "/dev/dvd")))
815 {
816 if (!
817 (found_it =
818 set_dev_to_this_if_rx_OK(output,
819 g_cdrw_drive_is_here)))
820 {
821 retval = 1;
822 goto end_of_find_cdrom_device;
823 }
824 }
825 }
826 }
827 }
828 }
829 }
830 }
831 }
832#endif
833
834 if (found_it && try_to_mount) {
835 if (mount_CDROM_here(output, mountpoint)) {
836 log_msg(4, "[Cardigans] I've changed my mind");
837 found_it = FALSE;
838 } else {
839 sprintf(tmp, "%s/archives", mountpoint);
840 if (!does_file_exist(tmp)) {
841 log_msg(4, "[Cardigans] I'll take it back");
842 found_it = FALSE;
843 } else {
844 sprintf(command, "umount %s", output);
845 paranoid_system(command);
846 log_msg(4, "I'm confident the Mondo CD is in %s", output);
847 }
848 }
849 }
850 unlink(mountpoint);
851
852 if (found_it) {
853 if (!does_file_exist(output)) {
854 log_msg(3, "I still haven't found it.");
855 return (1);
856 }
857 log_msg(3, "(find_cdrom_device) --> '%s'", output);
858 strcpy(the_last_place_i_found_it, output);
859 strcpy(g_cdrom_drive_is_here, output);
860 retval = 0;
861 goto end_of_find_cdrom_device;
862 }
863
864 sprintf(command,
865 "%s -scanbus | grep \"[0-9],[0-9],[0-9]\" | grep \"[D|C][V|D]\" | grep -n \"\" | grep \"%s\" | cut -d':' -f2",
866 cdr_exe, g_cdrw_drive_is_here);
867 log_msg(1, "command=%s", command);
868 mr_asprintf(&tmp1, "%s", call_program_and_get_last_line_of_output(command));
869 if (strlen(tmp1) > 0) {
870 strcpy(output, tmp1);
871 log_msg(4, "Finally found it at %s", output);
872 retval = 0;
873 } else {
874 log_msg(4, "Still couldn't find it.");
875 retval = 1;
876 }
877 mr_free(tmp1);
878
879 end_of_find_cdrom_device:
880 paranoid_free(tmp);
881 mr_free(cdr_exe);
882 paranoid_free(phrase_one);
883 paranoid_free(phrase_two);
884 paranoid_free(command);
885 paranoid_free(dvd_last_resort);
886 paranoid_free(mountpoint);
887 return (retval);
888}
889
890
891
892
893
894int find_dvd_device(char *output, bool try_to_mount)
895{
896 char *command;
897 char *tmp;
898 int retval = 0, devno = -1;
899
900 malloc_string(command);
901 malloc_string(tmp);
902
903 if (g_dvd_drive_is_here[0]) {
904 strcpy(output, g_dvd_drive_is_here);
905 log_msg(3, "Been there, done that. Returning %s", output);
906 return (0);
907 }
908
909 sprintf(tmp, "%s", call_program_and_get_last_line_of_output
910 ("dvdrecord -scanbus 2> /dev/null | grep \") '\" | grep -n \"\" | grep DVD | cut -d':' -f1")
911 );
912 log_msg(5, "tmp = '%s'", tmp);
913 if (!tmp[0])
914 sprintf(tmp, "%s", call_program_and_get_last_line_of_output
915 ("cdrecord -scanbus 2> /dev/null | grep \") '\" | grep -n \"\" | grep DVD | cut -d':' -f1")
916 );
917 if (tmp[0]) {
918 devno = atoi(tmp) - 1;
919 }
920 if (devno >= 0) {
921 retval = 0;
922 sprintf(output, "/dev/scd%d", devno);
923 strcpy(g_dvd_drive_is_here, output);
924 log_msg(2, "I think DVD is at %s", output);
925 } else {
926 log_msg(2, "I cannot find DVD");
927 retval = 1;
928 }
929
930 if (try_to_mount) {
931 log_msg(1, "Ignoring the fact that try_to_mount==TRUE");
932 }
933 return (retval);
934}
935
936
937
938
939
940#include <sys/ioctl.h>
941
942/**
943 * Find the size of the specified @p drive, in megabytes. Uses @c ioctl calls
944 * and @c dmesg.
945 * @param drive The device to find the size of.
946 * @return size in megabytes.
947 */
948long get_phys_size_of_drive(char *drive)
949{
950 int fd;
951#if linux
952 unsigned long long s = 0;
953 int fileid, cylinders = 0, cylindersleft = 0;
954 int cylindersize = 0;
955 int gotgeo = 0;
956
957
958 struct hd_geometry hdgeo;
959#elif __FreeBSD__
960 off_t s;
961#endif
962
963 long outvalA = -1;
964 long outvalB = -1;
965 long outvalC = -1;
966
967 if ((fd = open(drive, O_RDONLY)) != -1) {
968 if (ioctl(fd,
969#if linux
970#ifdef BLKGETSIZE64
971 BLKGETSIZE64,
972#else
973 BLKGETSIZE,
974#endif
975#elif __FreeBSD__
976 DIOCGMEDIASIZE,
977#endif
978 &s) != -1) {
979 close(fd);
980 // s>>11 works for older disks but not for newer ones
981 outvalB =
982#if linux
983#ifdef BLKGETSIZE64
984 s >> 20
985#else
986 s >> 11
987#endif
988#else
989 s >> 20
990#endif
991 ;
992 }
993 }
994
995 if (outvalB <= 0) {
996 log_msg(1, "Error getting size of %s: %s", drive, strerror(errno));
997#if linux
998 fileid = open(drive, O_RDONLY);
999 if (fileid != -1) {
1000 if (ioctl(fileid, HDIO_GETGEO, &hdgeo) != -1) {
1001 if (hdgeo.cylinders && hdgeo.heads && hdgeo.sectors) {
1002 cylindersleft = cylinders = hdgeo.cylinders;
1003 cylindersize = hdgeo.heads * hdgeo.sectors / 2;
1004 outvalA = cylindersize * cylinders / 1024;
1005 log_msg(2, "Got Harddisk geometry, C:%d, H:%d, S:%d",
1006 hdgeo.cylinders, hdgeo.heads, hdgeo.sectors);
1007 gotgeo = 1;
1008 } else {
1009 log_msg(1, "Harddisk geometry wrong");
1010 }
1011 } else {
1012 log_msg(1,
1013 "Error in ioctl() getting new hard disk geometry (%s), resizing in unsafe mode",
1014 strerror(errno));
1015 }
1016 close(fileid);
1017 } else {
1018 log_msg(1, "Failed to open %s for reading: %s", drive,
1019 strerror(errno));
1020 }
1021 if (!gotgeo) {
1022 log_msg(1, "Failed to get harddisk geometry, using old mode");
1023 }
1024#endif
1025 }
1026// OLDER DISKS will give ridiculously low value for outvalB (so outvalA is returned) :)
1027// NEWER DISKS will give sane value for outvalB (close to outvalA, in other words) :)
1028
1029 outvalC = (outvalA > outvalB) ? outvalA : outvalB;
1030
1031// log_msg (5, "drive = %s, error = %s", drive, strerror (errno));
1032// fatal_error ("GPSOD: Unable to get size of drive");
1033 log_msg(1, "%s --> %ld or %ld --> %ld", drive, outvalA, outvalB,
1034 outvalC);
1035
1036 return (outvalC);
1037}
1038
1039/**
1040 * Determine whether @p format is supported by the kernel. Uses /proc/filesystems
1041 * under Linux and @c lsvfs under FreeBSD.
1042 * @param format The format to test.
1043 * @return TRUE if the format is supported, FALSE if not.
1044 */
1045bool is_this_a_valid_disk_format(char *format)
1046{
1047 char *good_formats = NULL;
1048 char *command;
1049 char *format_sz;
1050
1051 FILE *pin;
1052 int retval;
1053 malloc_string(good_formats);
1054 malloc_string(command);
1055 malloc_string(format_sz);
1056
1057 assert_string_is_neither_NULL_nor_zerolength(format);
1058
1059 sprintf(format_sz, "%s ", format);
1060
1061#ifdef __FreeBSD__
1062 sprintf(command,
1063 "lsvfs | tr -s '\t' ' ' | grep -v Filesys | grep -v -- -- | cut -d' ' -f1 | tr -s '\n' ' '");
1064#else
1065 sprintf(command,
1066 "grep -v nodev /proc/filesystems | tr -s '\t' ' ' | cut -d' ' -f2 | tr -s '\n' ' '");
1067#endif
1068
1069 pin = popen(command, "r");
1070 if (!pin) {
1071 log_OS_error("Unable to read good formats");
1072 retval = 0;
1073 } else {
1074 strcpy(good_formats, " ");
1075 (void) fgets(good_formats + 1, MAX_STR_LEN - 1, pin);
1076 if (pclose(pin)) {
1077 log_OS_error("Cannot pclose good formats");
1078 }
1079 strip_spaces(good_formats);
1080 strcat(good_formats, " swap lvm raid ntfs-3g ntfs 7 "); // " ntfs 7 " -- um, cheating much? :)
1081 if (strstr(good_formats, format_sz)) {
1082 retval = 1;
1083 } else {
1084 retval = 0;
1085 }
1086 }
1087 paranoid_free(good_formats);
1088 paranoid_free(command);
1089 paranoid_free(format_sz);
1090 return (retval);
1091}
1092
1093
1094/** @def SWAPLIST_COMMAND The command to list the swap files/partitions in use. */
1095
1096/**
1097 * Determine whether @p device_raw is currently mounted.
1098 * @param device_raw The device to check.
1099 * @return TRUE if it's mounted, FALSE if not.
1100 */
1101bool is_this_device_mounted(char *device_raw)
1102{
1103
1104 /*@ pointers **************************************************** */
1105 FILE *fin;
1106
1107 /*@ buffers ***************************************************** */
1108 char *incoming;
1109 char *device_with_tab = NULL;
1110 char *device_with_space = NULL;
1111 char *tmp = NULL;
1112 bool retval = FALSE;
1113
1114#ifdef __FreeBSD__
1115#define SWAPLIST_COMMAND "swapinfo"
1116#else
1117#define SWAPLIST_COMMAND "cat /proc/swaps"
1118#endif
1119
1120 /*@ end vars **************************************************** */
1121
1122 malloc_string(incoming);
1123 assert(device_raw != NULL);
1124// assert_string_is_neither_NULL_nor_zerolength(device_raw);
1125 if (device_raw[0] != '/' && !strstr(device_raw, ":/")) {
1126 log_msg(1, "%s needs to have a '/' prefixed - I'll do it",
1127 device_raw);
1128 mr_asprintf(&tmp, "/%s", device_raw);
1129 } else {
1130 mr_asprintf(&tmp, "%s", device_raw);
1131 }
1132 log_msg(1, "Is %s mounted?", tmp);
1133 if (!strcmp(tmp, "/proc") || !strcmp(tmp, "proc")) {
1134 log_msg(1,
1135 "I don't know how the heck /proc made it into the mountlist. I'll ignore it.");
1136 mr_free(tmp);
1137 return(FALSE);
1138 }
1139 mr_asprintf(&device_with_tab, "%s\t", tmp);
1140 mr_asprintf(&device_with_space, "%s ", tmp);
1141 mr_free(tmp);
1142
1143 if (!(fin = popen("mount", "r"))) {
1144 log_OS_error("Cannot popen 'mount'");
1145 return(FALSE);
1146 }
1147 for ((void)fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin);
1148 (void)fgets(incoming, MAX_STR_LEN - 1, fin)) {
1149 if (strstr(incoming, device_with_space) //> incoming
1150 || strstr(incoming, device_with_tab)) // > incoming)
1151 {
1152 paranoid_pclose(fin);
1153 paranoid_free(incoming);
1154 return(TRUE);
1155 }
1156 }
1157 mr_free(device_with_tab);
1158 paranoid_pclose(fin);
1159 mr_asprintf(&tmp, "%s | grep -E \"^%s\" > /dev/null 2> /dev/null", SWAPLIST_COMMAND, device_with_space);
1160 mr_free(device_with_space);
1161 log_msg(4, "tmp (command) = '%s'", tmp);
1162 if (!system(tmp)) {
1163 retval = TRUE;
1164 }
1165 mr_free(tmp);
1166 paranoid_free(incoming);
1167 return(retval);
1168}
1169
1170#ifdef __FreeBSD__
1171// CODE IS FREEBSD-SPECIFIC
1172/**
1173 * Create a loopback device for specified @p fname.
1174 * @param fname The file to associate with a device.
1175 * @return /dev entry for the device, or NULL if it couldn't be allocated.
1176 */
1177char *make_vn(char *fname)
1178{
1179 char *device = (char *) malloc(MAX_STR_LEN);
1180 char *mddevice = (char *) malloc(32);
1181 char command[MAX_STR_LEN];
1182 int vndev = 2;
1183 if (atoi
1184 (call_program_and_get_last_line_of_output
1185 ("/sbin/sysctl -n kern.osreldate")) < 500000) {
1186 do {
1187 sprintf(mddevice, "vn%ic", vndev++);
1188 sprintf(command, "vnconfig %s %s", mddevice, fname);
1189 if (vndev > 10) {
1190 return NULL;
1191 }
1192 }
1193 while (system(command));
1194 } else {
1195 sprintf(command, "mdconfig -a -t vnode -f %s", fname);
1196 mddevice = call_program_and_get_last_line_of_output(command);
1197 if (!strstr(mddevice, "md")) {
1198 return NULL;
1199 }
1200 }
1201 sprintf(device, "/dev/%s", mddevice);
1202 return device;
1203}
1204
1205
1206
1207// CODE IS FREEBSD-SPECIFIC
1208/**
1209 * Deallocate specified @p dname.
1210 * This should be called when you are done with the device created by make_vn(),
1211 * so the system does not run out of @c vn devices.
1212 * @param dname The device to deallocate.
1213 * @return 0 for success, nonzero for failure.
1214 */
1215int kick_vn(char *dname)
1216{
1217 char command[MAX_STR_LEN];
1218
1219 if (strncmp(dname, "/dev/", 5) == 0) {
1220 dname += 5;
1221 }
1222
1223 if (atoi
1224 (call_program_and_get_last_line_of_output
1225 ("/sbin/sysctl -n kern.osreldate")) < 500000) {
1226 sprintf(command, "vnconfig -d %s", dname);
1227 return system(command);
1228 } else {
1229 sprintf(command, "mdconfig -d -u %s", dname);
1230 return system(command);
1231 }
1232 /*NOTREACHED*/ return 255;
1233}
1234#endif
1235
1236
1237/**
1238 * Mount the CD-ROM at @p mountpoint.
1239 * @param device The device (or file if g_ISO_restore_mode) to mount.
1240 * @param mountpoint The place to mount it.
1241 * @return 0 for success, nonzero for failure.
1242 */
1243int mount_USB_here(char *device, char *mountpoint)
1244{
1245 /*@ buffer ****************************************************** */
1246 char *command;
1247 int retval;
1248
1249 malloc_string(command);
1250 assert_string_is_neither_NULL_nor_zerolength(device);
1251 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
1252
1253 make_hole_for_dir(mountpoint);
1254 if (isdigit(device[0])) {
1255 return(1);
1256 }
1257 log_msg(4, "(mount_USB_here --- device=%s, mountpoint=%s", device,
1258 mountpoint);
1259
1260#ifdef __FreeBSD__
1261 sprintf(command, "mount_vfat %s %s 2>> %s",
1262 device, mountpoint, MONDO_LOGFILE);
1263
1264#else
1265 sprintf(command, "mount %s -t vfat %s 2>> %s",
1266 device, mountpoint, MONDO_LOGFILE);
1267#endif
1268
1269 log_msg(4, command);
1270 retval = system(command);
1271 log_msg(1, "system(%s) returned %d", command, retval);
1272
1273 paranoid_free(command);
1274 return (retval);
1275}
1276
1277/**
1278 * Mount the CD-ROM at @p mountpoint.
1279 * @param device The device (or file if g_ISO_restore_mode) to mount.
1280 * @param mountpoint The place to mount it.
1281 * @return 0 for success, nonzero for failure.
1282 */
1283int mount_CDROM_here(char *device, char *mountpoint)
1284{
1285 /*@ buffer ****************************************************** */
1286 char *command = NULL;
1287 int retval;
1288#ifdef __FreeBSD__
1289 char *dev = NULL;
1290#else
1291 char *options = NULL;
1292#endif
1293
1294 assert_string_is_neither_NULL_nor_zerolength(device);
1295 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
1296
1297 make_hole_for_dir(mountpoint);
1298
1299 if (isdigit(device[0])) {
1300 find_cdrom_device(device, FALSE);
1301 }
1302#ifndef __FreeBSD__
1303 mr_asprintf(&options, "ro");
1304#endif
1305
1306 if (g_ISO_restore_mode) {
1307
1308#ifdef __FreeBSD__
1309 mr_asprintf(&dev, "%s", make_vn(device));
1310 if (!dev) {
1311 mr_asprintf(&command, "Unable to mount ISO (make_vn(%s) failed)", device);
1312 fatal_error(command);
1313 }
1314 strcpy(device, dev);
1315 paranoid_free(dev);
1316#else
1317 mr_strcat(options, ",loop");
1318#endif
1319
1320 }
1321 log_msg(4, "(mount_CDROM_here --- device=%s, mountpoint=%s", device,
1322 mountpoint);
1323 /*@ end vars *************************************************** */
1324
1325#ifdef __FreeBSD__
1326 mr_asprintf(&command, "mount_cd9660 -r %s %s 2>> %s", device, mountpoint, MONDO_LOGFILE);
1327
1328#else
1329 mr_asprintf(&command, "mount %s -o %s -t iso9660 %s 2>> %s", device, options, mountpoint, MONDO_LOGFILE);
1330 paranoid_free(options);
1331#endif
1332
1333 log_msg(4, command);
1334 if (strncmp(device, "/dev/", 5) == 0) {
1335 retract_CD_tray_and_defeat_autorun();
1336 }
1337 retval = system(command);
1338 log_msg(1, "system(%s) returned %d", command, retval);
1339 paranoid_free(command);
1340
1341 return (retval);
1342}
1343
1344
1345
1346
1347
1348
1349/**
1350 * Ask the user for CD number @p cd_number_i_want.
1351 * Sets g_current_media_number once the correct CD is inserted.
1352 * @param bkpinfo The backup information structure. Fields used:
1353 * - @c bkpinfo->backup_media_type
1354 * - @c bkpinfo->prefix
1355 * - @c bkpinfo->isodir
1356 * - @c bkpinfo->media_device
1357 * - @c bkpinfo->please_dont_eject_when_restoring
1358 * @param cd_number_i_want The CD number to ask for.
1359 */
1360void
1361insist_on_this_cd_number(int cd_number_i_want)
1362{
1363
1364 /*@ int ************************************************************* */
1365 int res = 0;
1366
1367
1368 /*@ buffers ********************************************************* */
1369 char *tmp;
1370 char *mds = NULL;
1371 char *request;
1372
1373 assert(bkpinfo != NULL);
1374 assert(cd_number_i_want > 0);
1375
1376// log_msg(3, "Insisting on CD number %d", cd_number_i_want);
1377
1378 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1379 log_msg(3,
1380 "No need to insist_on_this_cd_number when the backup type isn't CD-R(W) or NFS or ISO");
1381 return;
1382 }
1383 malloc_string(tmp);
1384 malloc_string(request);
1385 sprintf(tmp, "mkdir -p " MNT_CDROM);
1386 run_program_and_log_output(tmp, 5);
1387 if (g_ISO_restore_mode || bkpinfo->backup_media_type == iso
1388 || bkpinfo->backup_media_type == netfs) {
1389 log_msg(3, "Remounting CD");
1390 g_ISO_restore_mode = TRUE;
1391// FIXME --- I'm tempted to do something about this...
1392// Why unmount and remount again and again?
1393 if (is_this_device_mounted(MNT_CDROM)) {
1394 run_program_and_log_output("umount " MNT_CDROM, 5);
1395 }
1396 sprintf(tmp, "mkdir -p %s/isodir &> /dev/null", bkpinfo->tmpdir);
1397 (void)system(tmp);
1398 sprintf(tmp, "%s/%s/%s-%d.iso", bkpinfo->isodir,
1399 bkpinfo->netfs_remote_dir, bkpinfo->prefix,
1400 cd_number_i_want);
1401 if (!does_file_exist(tmp)) {
1402 sprintf(tmp, "%s/isodir/%s/%s-%d.iso", bkpinfo->tmpdir,
1403 bkpinfo->netfs_remote_dir, bkpinfo->prefix,
1404 cd_number_i_want);
1405 if (does_file_exist(tmp)) {
1406 log_msg(1,
1407 "FIXME - hacking bkpinfo->isodir from '%s' to %s/isodir",
1408 bkpinfo->isodir, bkpinfo->tmpdir);
1409 sprintf(bkpinfo->isodir, "%s/isodir", bkpinfo->tmpdir);
1410 }
1411 }
1412 log_msg(3, "Mounting %s at %s", tmp, MNT_CDROM);
1413 if (mount_CDROM_here(tmp, MNT_CDROM)) {
1414 fatal_error("Mommy!");
1415 }
1416// g_current_media_number = cd_number_i_want;
1417// return;
1418 }
1419 if ((res = what_number_cd_is_this()) != cd_number_i_want) {
1420 log_msg(3, "Currently, we hold %d but we want %d", res,
1421 cd_number_i_want);
1422 mds = media_descriptor_string(bkpinfo->backup_media_type);
1423 sprintf(tmp, "Insisting on %s #%d", mds, cd_number_i_want);
1424 sprintf(request, "Please insert %s #%d and press Enter.", mds, cd_number_i_want);
1425 mr_free(mds);
1426 log_msg(3, tmp);
1427 while (what_number_cd_is_this() != cd_number_i_want) {
1428 paranoid_system("sync");
1429 if (is_this_device_mounted(MNT_CDROM)) {
1430 res =
1431 run_program_and_log_output("umount " MNT_CDROM, FALSE);
1432 } else {
1433 res = 0;
1434 }
1435 if (res) {
1436 log_to_screen("WARNING - failed to unmount CD-ROM drive");
1437 }
1438 if (!bkpinfo->please_dont_eject) {
1439 res = eject_device(bkpinfo->media_device);
1440 } else {
1441 res = 0;
1442 }
1443 if (res) {
1444 log_to_screen("WARNING - failed to eject CD-ROM disk");
1445 }
1446 popup_and_OK(request);
1447 if (!bkpinfo->please_dont_eject) {
1448 inject_device(bkpinfo->media_device);
1449 }
1450 paranoid_system("sync");
1451 }
1452 log_msg(1, "Thankyou. Proceeding...");
1453 g_current_media_number = cd_number_i_want;
1454 }
1455 paranoid_free(tmp);
1456 paranoid_free(request);
1457}
1458
1459/* @} - end of deviceGroup */
1460
1461
1462
1463/**
1464 * Creates a singly linked list of all of the non-NETFS mounted file systems.
1465 * @param DSFptr A pointer to the structure MOUNTED_FS_STRUCT used to hold
1466 * the list of mounted file systems.
1467 * @return None.
1468 */
1469static void add_mounted_fs_struct (MOUNTED_FS_STRUCT *DSFptr)
1470{
1471 assert (DSFptr);
1472 if (DSF_Head == NULL) {
1473 DSF_Head = DSFptr;
1474 } else {
1475 DSF_Tail->next = DSFptr;
1476 }
1477 DSFptr->next = NULL;
1478 DSF_Tail = DSFptr;
1479}
1480
1481/**
1482 * Find the structure, in the singly linked list of all of the non-NETFS
1483 * mounted file systems, that contains the specified device.
1484 * @param device The device to find
1485 * @return NULL if it didn't find the device, a pointer to the
1486 * structure if it did.
1487 */
1488static MOUNTED_FS_STRUCT *find_device_in_list (char *device)
1489{
1490 MOUNTED_FS_STRUCT *DSFptr = NULL;
1491
1492 DSFptr = DSF_Head;
1493 while (DSFptr != NULL) {
1494 if (!strcmp(DSFptr->device, device)) {
1495 break;
1496 }
1497 DSFptr = DSFptr->next;
1498 }
1499 return (DSFptr);
1500}
1501
1502/**
1503 * Find the structure, in the singly linked list of all of the non-NETFS
1504 * mounted file systems, that contains the specified mount point.
1505 * @param mount_point The mount point to find
1506 * @return NULL is it didn't find the mount point, a pointer to the
1507 * structure if it did.
1508 */
1509static MOUNTED_FS_STRUCT *find_mount_point_in_list (char *mount_point)
1510{
1511 MOUNTED_FS_STRUCT *DSFptr = NULL;
1512
1513 DSFptr = DSF_Head;
1514 while (DSFptr != NULL) {
1515 if (!strcmp(DSFptr->mount_point, mount_point)) {
1516 break;
1517 }
1518 DSFptr = DSFptr->next;
1519 }
1520 return (DSFptr);
1521}
1522
1523/**
1524 * Frees the memory for all of the structures on the linked list of
1525 * all of the non-NETFS mounted file systems.
1526 */
1527static void free_mounted_fs_list (void) {
1528 MOUNTED_FS_STRUCT *DSFptr = NULL;
1529 MOUNTED_FS_STRUCT *DSFnext = NULL;
1530
1531 DSFptr = DSF_Head;
1532 while (DSFptr != NULL) {
1533 DSFnext = DSFptr->next;
1534 paranoid_free(DSFptr);
1535 DSFptr = DSFnext;
1536 }
1537 DSF_Head = NULL;
1538 DSF_Tail = NULL;
1539}
1540
1541
1542/**
1543 * Creates a linked list of all of the non-NETFS mounted file systems.
1544 * We use a linked list because we don't know how many mounted file
1545 * there are (and there can be a lot).
1546 * @return 0 on success and greated than 0 on failure.
1547 */
1548static int create_list_of_non_NETFS_mounted_file_systems (void)
1549{
1550 int i = 0;
1551 int mount_cnt = 0;
1552 int lastpos = 0;
1553 char *mounted_file_system = NULL;
1554 char *command = NULL;
1555 char *token = NULL;
1556 char token_chars[] =" :\t\r\f\a\0";
1557 MOUNTED_FS_STRUCT *DSFptr = NULL;
1558
1559 free_mounted_fs_list();
1560 /********
1561 * Find the number of mounted file system entries and their respective mount points.
1562 * I can't return all of the entries as one string because it's length can be longer
1563 * than MAX_STR_LEN which is used in call_program_and_get_last_line_of_output().
1564 * So start looping and get the number of mounted file systems and query them one by one.
1565 ********/
1566 /* Get the number of mounted file systems ((those that start with "/dev/" */
1567 mr_asprintf(&command, "mount 2>/dev/null | awk '{if($1 ~ \"^/dev/\"){print $0}}'|wc -l");
1568 log_msg(5, "Running: %s", command);
1569 mr_asprintf(&mounted_file_system, "%s", call_program_and_get_last_line_of_output(command));
1570 paranoid_free(command);
1571
1572 mount_cnt = atoi(mounted_file_system);
1573 log_msg (5, "mount_cnt: %d", mount_cnt);
1574 paranoid_free(mounted_file_system);
1575
1576 for (i=mount_cnt; i > 0; i--) {
1577 mr_asprintf(&command, "mount 2>/dev/null | awk '{if($1 ~ \"^/dev/\"){print $1,$3}}'|head -n %d", i);
1578 log_msg(5, "Running: %s", command);
1579 mr_asprintf(&mounted_file_system, "%s", call_program_and_get_last_line_of_output(command));
1580 paranoid_free(command);
1581
1582 log_msg (5, "mounted_file_system: %s", mounted_file_system);
1583 if ((token = mr_strtok(mounted_file_system, token_chars, &lastpos)) == NULL) {
1584 log_msg (4, "Could not get the list of mounted file systems");
1585 paranoid_free(mounted_file_system);
1586 mr_free(token);
1587 return (1);
1588 }
1589 if (token) {
1590 log_msg (5, "token: %s", token);
1591 }
1592 while (token != NULL) {
1593 log_msg (5, "token: %s", token);
1594 if ((DSFptr = (MOUNTED_FS_STRUCT *) calloc(1, sizeof(MOUNTED_FS_STRUCT))) == NULL) {
1595 fatal_error ("Cannot allocate memory");
1596 }
1597 add_mounted_fs_struct(DSFptr);
1598 strcpy(DSFptr->device, token);
1599 mr_free(token);
1600 if ((token = mr_strtok(mounted_file_system, token_chars, &lastpos)) == NULL) {
1601 log_msg (5, "Ran out of entries on the mounted file systems list");
1602 mr_free(mounted_file_system);
1603 mr_free(token);
1604 return (1);
1605 }
1606 log_msg (5, "token: %s", token);
1607 strcpy(DSFptr->mount_point, token);
1608 mr_free(token);
1609 token = mr_strtok(mounted_file_system, token_chars, &lastpos);
1610 }
1611 mr_free(mounted_file_system);
1612 }
1613 /********
1614 * DSFptr = DSF_Head;
1615 * while (DSFptr != NULL) {
1616 * printf ("Dev: %s MP: %s Check: %d\n", DSFptr->device, DSFptr->mount_point, DSFptr->check);
1617 * DSFptr = DSFptr->next;
1618 * }
1619 ********/
1620 return (0);
1621}
1622
1623
1624
1625/**
1626 * Given a whole disk device special file, determine which mounted file systems
1627 * are on the dsf's partitions and which mounted file systems are not.
1628 * @param dsf The whole disk device special file.
1629 * @param included_dsf_list A char pointer used to hold the list of mount points
1630 * that are on the dsf. Memory for the array will be allocated within the function.
1631 * @param excluded_dsf_list A char pointer used to hold the list of mount points
1632 * that are not on the dsf. Memory for the array will be allocated within the function.
1633 * @return 0 on success, -1 if no device special file was passed in, -2 if a device
1634 * special file was passed in but it has no partitions on it, or 1 on failure
1635 */
1636static int get_dsf_mount_list (const char *dsf, char **included_dsf_list, char **excluded_dsf_list) {
1637 int i = 0;
1638 int c = 0;
1639 int lastpos = 0;
1640 char VG[MAX_STR_LEN];
1641 char *tmp = NULL;
1642 char *command = NULL;
1643 char *partition_list = NULL;
1644 char partitions[64][MAX_STR_LEN];
1645 char *mount_list = NULL;
1646 char *token = NULL;
1647 char *ndsf = NULL;
1648 char token_chars[] =" \t\r\f\a\0";
1649 MOUNTED_FS_STRUCT *DSFptr = NULL;
1650
1651 memset((char *)partitions, 0, sizeof(partitions));
1652
1653 log_msg(5, "dsf: %s", dsf);
1654
1655 /********
1656 * See if a device special file was passed in (i.e. it must start with /dev/
1657 ********/
1658 if (strncmp(dsf, "/dev/", 5)) {
1659 log_msg (4, "%s does not start with /dev/ and (probably) is not a device special file", dsf);
1660 return (-1);
1661 }
1662 log_msg(4, " %s looks like a device special file", dsf);
1663 /* Verify that the dsf exists */
1664 mr_asprintf(&command, "ls -al %s 2>/dev/null | wc -l", dsf);
1665 log_msg(5, " Executing: %s", command);
1666 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1667 paranoid_free(command);
1668
1669 log_msg(5, " Return value: %s", tmp);
1670 c = atoi(tmp);
1671 paranoid_free(tmp);
1672
1673 if (!c) {
1674 log_to_screen("Cannot find device special file %s", dsf);
1675 return (1);
1676 }
1677 log_msg(4, " %s device special file exists", dsf);
1678
1679 /* Get a list of the mounted file systems */
1680 if (create_list_of_non_NETFS_mounted_file_systems()) {
1681 log_to_screen ("Could not get the list of mounted file systems");
1682 return (1);
1683 }
1684 log_msg (5, "Processing dsf: %s", dsf);
1685 /********
1686 * Get a list of the dsf's partitions. There could be no partitions on the disk
1687 * or a dsf of a partition was passed in (e.g. /dev/sda1 instead of /dev/sda).
1688 * Either way, it's an error.
1689 ********/
1690 mr_asprintf(&command, "parted2fdisk -l %s 2>/dev/null|grep -E \"^/dev/\"|awk '{printf(\"%%s \", $1)}END{print \"\"}'", dsf);
1691 log_msg(5, "Executing: %s", command);
1692 mr_asprintf(&partition_list, "%s", call_program_and_get_last_line_of_output(command));
1693 paranoid_free(command);
1694 log_msg(4, "Partition list for %s: %s", dsf, partition_list);
1695 if (!strlen(partition_list)) {
1696 /* There were no partitions on the disk */
1697 log_msg(4, "No partitions on device special file %s", dsf);
1698 log_msg(4, "I guess it's a partition itself");
1699 strcpy(partitions[0], dsf);
1700 ndsf = truncate_to_drive_name(dsf);
1701 } else {
1702 /* Fill the partition list */
1703 i = 0;
1704 lastpos = 0;
1705 while ((token = mr_strtok(partition_list, token_chars, &lastpos)) != NULL) {
1706 log_msg (4, "Found partition: %s", token);
1707 strcpy(partitions[i++], token);
1708 mr_free(token);
1709 }
1710 mr_asprintf(&ndsf, "%s", dsf);
1711 }
1712 mr_free(partition_list);
1713
1714 /* In any case we want to exclude the dsf itself from all MondRescue activities
1715 * at restore time (LVM, fdisk, ...) so we want it in our exclude_dev list */
1716 if ((DSFptr = (MOUNTED_FS_STRUCT *) calloc(1, sizeof(MOUNTED_FS_STRUCT))) == NULL) {
1717 fatal_error ("Cannot allocate memory");
1718 }
1719 add_mounted_fs_struct(DSFptr);
1720 strcpy(DSFptr->device, dsf);
1721 DSFptr->check = 1;
1722
1723 /* For the rest ndsf is the new dsf to deal with */
1724 /********
1725 * At this point, we have a list of all of the partitions on the dsf. Now try to
1726 * see which partitions have a file system on them.
1727 *
1728 * Loop through each partition on the disk and:
1729 *
1730 * - If the partition is swap, it ignores it.
1731 *
1732 * - If the partition is mounted (e.g. /dev/sda1 is mounted on /boot), it adds an entry
1733 * to the linked list, copies to it the device name and mount point, and sets check == 1.
1734 *
1735 * - If the partition is part of a Volume Group that has Logical Volumes mounted, it adds
1736 * an entry to the linked list for each mounted Logical Volume in that Volume Group, copying
1737 * to it the device name and mount point, and sets check == 1. Note that if the Volume Group
1738 * contains more than one disk, it will still add the entry even if the Logical Volume's
1739 * extents are not on the dsf that was passed in to the function. For example, Volume Group
1740 * VolGroup00 contains the disks /dev/sda1 and /dev/sdb1, and the Logical Volumes LogVol01,
1741 * which is mounted on /var and has all of its extents on /dev/sda1, and LogVol02, which is
1742 * mounted as /usr and has all of its extents on /dev/sdb1. If you pass /dev/sda into the
1743 * function, both /var and /usr will be archived even though /usr is actually on/dev/sdb.
1744 *
1745 * - If the partition is part of a Volume Group that has Logical Volumes used in a mounted
1746 * software raid device, it adds an entry to the linked list, copies to it the software raid
1747 * device name and mount point, and sets check == 1.
1748 *
1749 * - If the partition is part of a mounted software raid device, it adds an entry to the linked
1750 * list, copies to it the software raid device name and mount point, and sets check == 1.
1751 *
1752 ********/
1753 for (i=0; strlen(partitions[i]); i++) {
1754 log_msg(4, "Processing partition: %s", partitions[i]);
1755 /* See if it's swap. If it is, ignore it. */
1756 mr_asprintf(&command, "parted2fdisk -l %s 2>/dev/null | awk '{if(($1==\"%s\")&&(toupper($0) ~ \"SWAP\")){print $1;exit}}'",
1757 ndsf, partitions[i]);
1758 log_msg(5, " Running: %s", command);
1759 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1760 paranoid_free(command);
1761 log_msg(5, " Return value: %s", tmp);
1762 c = strlen(tmp);
1763 paranoid_free(tmp);
1764 if (c) {
1765 log_msg(4, "It's swap. Ignoring partition %s", partitions[i]);
1766 continue;
1767 }
1768 /* It's not swap. See if we can find the mount point from the mount command. */
1769 mr_asprintf(&command, "mount 2>/dev/null | awk '{if((NF>0)&&($1==\"%s\")){print $3}}'", partitions[i]);
1770 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1771 paranoid_free(command);
1772 if (strlen(tmp)) {
1773 log_msg(4, " %s is mounted: %s", partitions[i], tmp);
1774 if ((DSFptr = find_mount_point_in_list(tmp)) == NULL) {
1775 log_msg (4, "Can't find mount point %s in mounted file systems list", tmp);
1776 paranoid_free(tmp);
1777 return (1);
1778 }
1779 DSFptr->check = 1;
1780 paranoid_free(tmp);
1781 continue;
1782 }
1783 paranoid_free(tmp);
1784 /* It's not swap and it's not mounted. See if it's LVM */
1785 log_msg(4, " It's not mounted. Checking to see if it's LVM...");
1786 /* Check for LVM */
1787 mr_asprintf(&command, "pvdisplay -c %s | grep '%s:' 2> /dev/null", partitions[i], partitions[i]);
1788 log_msg(5, " Running: %s", command);
1789 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1790 paranoid_free(command);
1791 if (strlen(tmp)) {
1792 log_msg(4, "Found an LVM partition at %s. Find the VG it's in...", partitions[i]);
1793 /* It's LVM: Find the VG it's in */
1794 mr_asprintf(&command, "pvdisplay -v %s 2>/dev/null|grep \"VG Name\"|awk '{print $NF}'", partitions[i]);
1795 log_msg(5, " Running: %s", command);
1796 strcpy(VG, call_program_and_get_last_line_of_output(command));
1797 paranoid_free(command);
1798 log_msg(4, " Volume Group: %s", VG);
1799 if (strlen(VG)) {
1800 /* Found the Volume Group. Now find all of the VG's mount points */
1801 log_msg(4, " Found the Volume Group. Now find all of the VG's mount points");
1802 mr_asprintf(&command, "mount 2>/dev/null|grep -E \"/dev/mapper/%s-|/dev/%s/\"|awk '{printf(\"%%s \",$3)}END{print \"\"}'", VG, VG);
1803 log_msg(5, " Running: %s", command);
1804 mr_asprintf(&mount_list, "%s", call_program_and_get_last_line_of_output(command));
1805 paranoid_free(command);
1806 log_msg(4, " VG %s mount_list: %s", VG, mount_list);
1807 lastpos = 0;
1808 while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
1809 log_msg (5, "mount point token: %s", token);
1810 if ((DSFptr = find_mount_point_in_list(token)) == NULL) {
1811 log_msg (4, "Can't find mount point %s in mounted file systems list", token);
1812 paranoid_free(tmp);
1813 mr_free(token);
1814 return (1);
1815 }
1816 DSFptr->check = 1;
1817 mr_free(token);
1818 }
1819 /********
1820 * Now we want to see if there are any software raid devices using
1821 * any of the Logical Volumes on the Volume Group.
1822 *******/
1823 paranoid_free(mount_list);
1824
1825 mr_asprintf(&command, "%s", "cat /proc/mdstat|grep -iv Personal|awk '{if($0~\"^.*[ ]+:\"){printf(\"/dev/%s \", $1)}}END{print \"\"}'");
1826 log_msg (5, "Running: %s", command);
1827 mr_asprintf(&mount_list, "%s", call_program_and_get_last_line_of_output(command));
1828 paranoid_free(command);
1829 log_msg(4, " Software raid device list: %s", mount_list);
1830 lastpos = 0;
1831 while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
1832 mr_asprintf(&command, "mdadm --detail %s 2>/dev/null | grep -c %s", token, VG);
1833 log_msg (5, "Running: %s", command);
1834 paranoid_free(tmp);
1835 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1836 paranoid_free(command);
1837 log_msg(4, "Number of Software raid device: %s", tmp);
1838 if (atoi(tmp)) {
1839 /* This device is on our disk */
1840 if ((DSFptr = find_device_in_list(token)) == NULL) {
1841 log_msg (4, "Can't find device %s in mounted file systems list", token);
1842 paranoid_free(tmp);
1843 mr_free(token);
1844 return (1);
1845 }
1846 DSFptr->check = 1;
1847 }
1848 }
1849 mr_free(token);
1850 paranoid_free(mount_list);
1851 } else {
1852 log_msg (4, "Error finding Volume Group for partition %s", partitions[i]);
1853 paranoid_free(tmp);
1854 return (1);
1855 }
1856 paranoid_free(tmp);
1857 continue;
1858 } else {
1859 log_msg (4, "Error finding partition type for the partition %s", partitions[i]);
1860 }
1861 paranoid_free(tmp);
1862 /********
1863 * It's not swap, mounted, or LVM. See if it's used in a software raid device.
1864 ********/
1865 log_msg (5, "It's not swap, mounted, or LVM. See if it's used in a software raid device.");
1866 mr_asprintf(&command, "mdadm --examine %s 2>/dev/null | awk '{if($1 == \"UUID\"){print $3}}'", partitions[i]);
1867 log_msg(4, " Running: %s", command);
1868 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1869 paranoid_free(command);
1870 if (!strlen(tmp)) {
1871 log_msg(4, " Partition %s is not used in a non-LVM software raid device", partitions[i]);
1872 paranoid_free(tmp);
1873 continue;
1874 }
1875 log_msg (5, " UUID: %s", tmp);
1876 /* Get the Software raid device list */
1877 mr_asprintf(&command, "%s", "cat /proc/mdstat|grep -iv Personal|awk '{if($0~\"^.*[ ]+:\"){printf(\"/dev/%s \", $1)}}END{print \"\"}'");
1878 log_msg (5, " Running: %s", command);
1879 mr_asprintf(&mount_list, "%s", call_program_and_get_last_line_of_output(command));
1880 paranoid_free(command);
1881 log_msg(4, " Software raid device list: %s", mount_list);
1882 /* Loop through the software raid device list to see if we can find the partition */
1883 lastpos = 0;
1884 while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
1885 mr_asprintf(&command, "mdadm --detail %s 2>/dev/null | grep -c %s", token, tmp);
1886 log_msg(4, " Running: %s", command);
1887 paranoid_free(tmp);
1888 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
1889 paranoid_free(command);
1890 if (!atoi(tmp)) {
1891 log_msg (4," Didn't find partition %s in software raid device %s", partitions[i], token);
1892 } else {
1893 if ((DSFptr = find_device_in_list(token)) == NULL) {
1894 log_msg (4, "Can't find device %s in mounted file systems list", token);
1895 paranoid_free(tmp);
1896 mr_free(token);
1897 return (1);
1898 }
1899 DSFptr->check = 1;
1900 break;
1901 }
1902 mr_free(token);
1903 }
1904 paranoid_free(tmp);
1905 paranoid_free(mount_list);
1906 }
1907
1908 /* Determine how much memory to allocate for included_dsf_list and excluded_dsf_list */
1909 i = 0;
1910 DSFptr= DSF_Head;
1911 while (DSFptr != NULL) {
1912 i += strlen(DSFptr->mount_point) + 1;
1913 DSFptr = DSFptr->next;
1914 }
1915 log_msg (5, "i: %d", i);
1916 if ((*included_dsf_list = (char *) calloc(i+100, sizeof(char))) == NULL) {
1917 fatal_error ("Cannot allocate memory");
1918 }
1919 if ((*excluded_dsf_list = (char *) calloc(i+100, sizeof(char))) == NULL) {
1920 fatal_error ("Cannot allocate memory");
1921 }
1922 DSFptr= DSF_Head;
1923 while (DSFptr != NULL) {
1924 if (DSFptr->check) {
1925 log_msg (4, "%s is mounted on %s and is on disk %s\n", DSFptr->device, DSFptr->mount_point, ndsf);
1926 strcat(*included_dsf_list, DSFptr->mount_point);
1927 strcat(*included_dsf_list, " ");
1928 } else {
1929 log_msg (4, "%s is mounted on %s and is NOT on disk %s\n", DSFptr->device, DSFptr->mount_point, ndsf);
1930 strcat(*excluded_dsf_list, DSFptr->mount_point);
1931 strcat(*excluded_dsf_list, " ");
1932 }
1933 DSFptr = DSFptr->next;
1934 }
1935 mr_free(ndsf);
1936
1937 log_msg (5, "included_dsf_list: %s", *included_dsf_list);
1938 log_msg (5, "excluded_dsf_list: %s", *excluded_dsf_list);
1939 return (0);
1940}
1941
1942
1943
1944
1945
1946/* Update the bkpinfo structure for exclude & include paths
1947 * in order to handle correctly paths corresponding to devices */
1948void mr_make_devlist_from_pathlist(char *pathlist, char mode) {
1949
1950char *token = NULL;
1951int lastpos = 0;
1952char *mounted_on_dsf = NULL;
1953char *not_mounted_on_dsf = NULL;
1954char token_chars[] =" \t\r\f\a\0\n";
1955char *tmp = NULL;
1956char *tmp1 = NULL;
1957
1958while ((token = mr_strtok(pathlist, token_chars, &lastpos)) != NULL) {
1959 switch (get_dsf_mount_list(token, &mounted_on_dsf, &not_mounted_on_dsf)) {
1960 case 1:
1961 if (mode == 'E') {
1962 log_msg(1, "WARNING ! %s doesn't exist in -E option", token);
1963 } else {
1964 log_msg(1, "ERROR ! %s doesn't exist in -I option", token);
1965 fatal_error("Error processing -I option");
1966 }
1967 break;
1968 /* Everything is OK; proceed to archive data */
1969 case 0:
1970 if (mode == 'E') {
1971 if (strlen(mounted_on_dsf)) {
1972 log_to_screen("Excluding the following file systems on %s:\n", token);
1973 log_to_screen(" %s\n", mounted_on_dsf);
1974 log_msg (5, "Adding to bkpinfo->exclude_paths due to -E option: %s", mounted_on_dsf);
1975 strcat(bkpinfo->exclude_paths, " ");
1976 strcat(bkpinfo->exclude_paths, mounted_on_dsf);
1977 strcat(bkpinfo->exclude_paths, " ");
1978 mr_strcat(bkpinfo->exclude_devs, " %s ", token);
1979 }
1980 } else {
1981 log_to_screen("Archiving only the following file systems on %s:\n", token);
1982 log_to_screen(" %s\n", mounted_on_dsf);
1983 strcpy(bkpinfo->include_paths, "/");
1984 if (strlen(not_mounted_on_dsf)) {
1985 log_msg (5, "Adding to bkpinfo->exclude_paths due to -I option: %s", not_mounted_on_dsf);
1986 log_to_screen("Not archiving the following file systems:\n");
1987 log_to_screen(" %s\n", not_mounted_on_dsf);
1988 strcat(bkpinfo->exclude_paths, " ");
1989 strcat(bkpinfo->exclude_paths, not_mounted_on_dsf);
1990 strcat(bkpinfo->exclude_paths, "");
1991 }
1992 }
1993 break;
1994 /* It's a dsf but not a whole disk dsf */
1995 case -2:
1996 log_to_screen("Could %s be a partition instead of a whole disk device special file?\nIgnored.", token);
1997 break;
1998 /* A device special file was not passed in. Process it as a path. */
1999 case -1:
2000 /* we need to add a space after token to be sure our strstr test works correctly */
2001 mr_asprintf(&tmp1,"%s ",token);
2002 if (mode == 'E') {
2003 /* Add the token if not already in the list */
2004 mr_asprintf(&tmp,"%s ",bkpinfo->exclude_paths);
2005 if (strstr(tmp,tmp1) == NULL) {
2006 strcat(bkpinfo->exclude_paths, " ");
2007 strcat(bkpinfo->exclude_paths, tmp1);
2008 }
2009 } else {
2010 /* Add the token if not already in the list */
2011 mr_asprintf(&tmp,"%s ",bkpinfo->include_paths);
2012 if (strstr(tmp,tmp1) == NULL) {
2013 strcat(bkpinfo->include_paths, " ");
2014 strcat(bkpinfo->include_paths, tmp1);
2015 }
2016 }
2017 mr_free(tmp);
2018 mr_free(tmp1);
2019 break;
2020 }
2021 mr_free(token);
2022
2023 if (bkpinfo->include_paths != NULL) {
2024 log_msg(1, "include_paths is now '%s'", bkpinfo->include_paths);
2025 }
2026 if (bkpinfo->exclude_paths != NULL) {
2027 log_msg(1, "exclude_paths is now '%s'", bkpinfo->exclude_paths);
2028 }
2029 if (bkpinfo->exclude_devs != NULL) {
2030 log_msg(1, "exclude_devs is now '%s'", bkpinfo->exclude_devs);
2031 }
2032}
2033}
2034
2035
2036
2037
2038/**
2039 * Ask user for details of backup/restore information.
2040 * Called when @c mondoarchive doesn't get any parameters.
2041 * @param bkpinfo The backup information structure to fill out with the user's data.
2042 * @param archiving_to_media TRUE if archiving, FALSE if restoring.
2043 * @return 0, always.
2044 * @bug No point of `int' return value.
2045 * @ingroup archiveGroup
2046 */
2047int interactively_obtain_media_parameters_from_user(bool archiving_to_media)
2048// archiving_to_media is TRUE if I'm being called by mondoarchive
2049// archiving_to_media is FALSE if I'm being called by mondorestore
2050{
2051 char *tmp = NULL;
2052 char *tmp1 = NULL;
2053 char *mds = NULL;
2054 char *sz_size;
2055 char *command;
2056 char *comment;
2057 char *prompt;
2058 int i;
2059 FILE *fin;
2060
2061 malloc_string(sz_size);
2062 malloc_string(command);
2063 malloc_string(comment);
2064 malloc_string(prompt);
2065 malloc_string(tmp1);
2066 assert(bkpinfo != NULL);
2067 sz_size[0] = '\0';
2068 bkpinfo->nonbootable_backup = FALSE;
2069
2070 // Tape, CD, NETFS, ...?
2071 srandom(getpid());
2072 bkpinfo->backup_media_type =
2073 (g_restoring_live_from_cd) ? cdr :
2074 which_backup_media_type(bkpinfo->restore_data);
2075 if (bkpinfo->backup_media_type == none) {
2076 log_to_screen("User has chosen not to backup the PC");
2077 finish(1);
2078 }
2079 /* Why asking to remove the media with tape ?
2080 if (bkpinfo->backup_media_type == tape && bkpinfo->restore_data) {
2081 popup_and_OK("Please remove media from drive(s)");
2082 }
2083 */
2084 log_msg(3, "media type = %s",
2085 bkptype_to_string(bkpinfo->backup_media_type));
2086 if (archiving_to_media) {
2087 sensibly_set_tmpdir_and_scratchdir();
2088 }
2089 bkpinfo->cdrw_speed = (bkpinfo->backup_media_type == cdstream) ? 2 : 4;
2090 bkpinfo->compression_level =
2091 (bkpinfo->backup_media_type == cdstream) ? 1 : 5;
2092 bkpinfo->use_lzo =
2093 (bkpinfo->backup_media_type == cdstream) ? TRUE : FALSE;
2094 mvaddstr_and_log_it(2, 0, " ");
2095
2096 // Find device's /dev (or SCSI) entry
2097 switch (bkpinfo->backup_media_type) {
2098 case cdr:
2099 case cdrw:
2100 case dvd:
2101 case usb:
2102 /* Never try to eject a USB device */
2103 if (bkpinfo->backup_media_type == usb) {
2104 bkpinfo->please_dont_eject = TRUE;
2105 }
2106 if (archiving_to_media) {
2107 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
2108 if (ask_me_yes_or_no
2109 ("Is your computer a laptop, or does the CD writer incorporate BurnProof technology?"))
2110 {
2111 bkpinfo->manual_cd_tray = TRUE;
2112 }
2113 }
2114 if ((bkpinfo->compression_level =
2115 which_compression_level()) == -1) {
2116 log_to_screen("User has chosen not to backup the PC");
2117 finish(1);
2118 }
2119 mds = media_descriptor_string(bkpinfo->backup_media_type);
2120 sprintf(comment, "What speed is your %s (re)writer?", mds);
2121 if (bkpinfo->backup_media_type == dvd) {
2122 find_dvd_device(bkpinfo->media_device, FALSE);
2123 strcpy(tmp1, "1");
2124 sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB
2125 log_msg(1, "Setting to DVD defaults");
2126 } else {
2127 strcpy(bkpinfo->media_device, VANILLA_SCSI_CDROM);
2128 strcpy(tmp1, "4");
2129 strcpy(sz_size, "650");
2130 log_msg(1, "Setting to CD defaults");
2131 }
2132 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
2133 if (!popup_and_get_string("Speed", comment, tmp1, 4)) {
2134 log_to_screen("User has chosen not to backup the PC");
2135 finish(1);
2136 }
2137 }
2138 bkpinfo->cdrw_speed = atoi(tmp1); // if DVD then this shouldn't ever be used anyway :)
2139
2140 sprintf(comment,
2141 "How much data (in Megabytes) will each %s store?", mds);
2142 mr_free(mds);
2143 if (!popup_and_get_string("Size", comment, sz_size, 5)) {
2144 log_to_screen("User has chosen not to backup the PC");
2145 finish(1);
2146 }
2147 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2148 bkpinfo->media_size[i] = atoi(sz_size);
2149 }
2150 if (bkpinfo->media_size[0] <= 0) {
2151 log_to_screen("User has chosen not to backup the PC");
2152 finish(1);
2153 }
2154 }
2155 /* No break because we continue even for usb */
2156 case cdstream:
2157 mds = media_descriptor_string(bkpinfo->backup_media_type);
2158
2159 if ((bkpinfo->disaster_recovery) && (bkpinfo->backup_media_type != usb)) {
2160 strcpy(bkpinfo->media_device, "/dev/cdrom");
2161 log_msg(2, "CD-ROM device assumed to be at %s",
2162 bkpinfo->media_device);
2163 } else if ((bkpinfo->restore_data && (bkpinfo->backup_media_type != usb))
2164 || bkpinfo->backup_media_type == dvd) {
2165 if (!bkpinfo->media_device[0]) {
2166 strcpy(bkpinfo->media_device, "/dev/cdrom");
2167 } // just for the heck of it :)
2168 log_msg(1, "bkpinfo->media_device = %s",
2169 bkpinfo->media_device);
2170 if (bkpinfo->backup_media_type == dvd
2171 || find_cdrom_device(bkpinfo->media_device, FALSE)) {
2172 log_msg(1, "bkpinfo->media_device = %s",
2173 bkpinfo->media_device);
2174 sprintf(comment,
2175 "Please specify your %s drive's /dev entry", mds);
2176 if (!popup_and_get_string
2177 ("Device?", comment, bkpinfo->media_device,
2178 MAX_STR_LEN / 4)) {
2179 log_to_screen("User has chosen not to backup the PC");
2180 finish(1);
2181 }
2182 }
2183 log_msg(2, "%s device found at %s", mds, bkpinfo->media_device);
2184 } else {
2185 if ((find_cdrw_device(bkpinfo->media_device)) && (bkpinfo->backup_media_type != usb)) {
2186 bkpinfo->media_device[0] = '\0';
2187 }
2188 if (bkpinfo->media_device[0]) {
2189 if (bkpinfo->backup_media_type == usb) {
2190 mr_asprintf(&tmp, "I think your %s media corresponds to %s. Is this correct?", mds, bkpinfo->media_device);
2191 } else {
2192 mr_asprintf(&tmp, "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.)", mds, bkpinfo->media_device);
2193 }
2194 if (!ask_me_yes_or_no(tmp)) {
2195 bkpinfo->media_device[0] = '\0';
2196 }
2197 mr_free(tmp);
2198 }
2199 if (!bkpinfo->media_device[0]) {
2200 if (bkpinfo->backup_media_type == usb) {
2201 i = popup_and_get_string("/dev entry?",
2202 "What is the /dev entry of your USB Disk/Key, please?",
2203 bkpinfo->media_device,
2204 MAX_STR_LEN / 4);
2205 } else {
2206 if (g_kernel_version < 2.6) {
2207 i = popup_and_get_string("Device node?",
2208 "What is the SCSI node of your CD (re)writer, please?",
2209 bkpinfo->media_device,
2210 MAX_STR_LEN / 4);
2211 } else {
2212 i = popup_and_get_string("/dev entry?",
2213 "What is the /dev entry of your CD (re)writer, please?",
2214 bkpinfo->media_device,
2215 MAX_STR_LEN / 4);
2216 }
2217 }
2218 if (!i) {
2219 log_to_screen("User has chosen not to backup the PC");
2220 finish(1);
2221 }
2222 }
2223 }
2224 mr_free(mds);
2225
2226 if (bkpinfo->backup_media_type == cdstream) {
2227 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2228 bkpinfo->media_size[i] = 650;
2229 }
2230 }
2231 break;
2232 case udev:
2233 if (!ask_me_yes_or_no
2234 ("This option is for advanced users only. Are you sure?")) {
2235 log_to_screen("User has chosen not to backup the PC");
2236 finish(1);
2237 }
2238 case tape:
2239
2240 if ((!bkpinfo->restore_mode) && (find_tape_device_and_size(bkpinfo->media_device, sz_size))) {
2241 log_msg(3, "Ok, using vanilla scsi tape.");
2242 strcpy(bkpinfo->media_device, VANILLA_SCSI_TAPE);
2243 if ((fin = fopen(bkpinfo->media_device, "r"))) {
2244 paranoid_fclose(fin);
2245 } else {
2246 strcpy(bkpinfo->media_device, "/dev/osst0");
2247 }
2248 }
2249 if (bkpinfo->media_device[0]) {
2250 if ((fin = fopen(bkpinfo->media_device, "r"))) {
2251 paranoid_fclose(fin);
2252 } else {
2253 if (does_file_exist("/tmp/mondo-restore.cfg")) {
2254 read_cfg_var("/tmp/mondo-restore.cfg", "media-dev",
2255 bkpinfo->media_device);
2256 }
2257 }
2258 }
2259 if (bkpinfo->media_device[0]) {
2260 mr_asprintf(&tmp, "I think I've found your tape streamer at %s; am I right on the money?", bkpinfo->media_device);
2261 if (!ask_me_yes_or_no(tmp)) {
2262 bkpinfo->media_device[0] = '\0';
2263 }
2264 mr_free(tmp);
2265 }
2266 if (!bkpinfo->media_device[0]) {
2267 if (!popup_and_get_string
2268 ("Device name?",
2269 "What is the /dev entry of your tape streamer?",
2270 bkpinfo->media_device, MAX_STR_LEN / 4)) {
2271 log_to_screen("User has chosen not to backup the PC");
2272 finish(1);
2273 }
2274 }
2275 mr_asprintf(&tmp, "ls -l %s", bkpinfo->media_device);
2276 if (run_program_and_log_output(tmp, FALSE)) {
2277 log_to_screen("User has not specified a valid /dev entry");
2278 finish(1);
2279 }
2280 mr_free(tmp);
2281 log_msg(4, "sz_size = %s", sz_size);
2282 sz_size[0] = '\0';
2283
2284 bkpinfo->use_obdr = ask_me_yes_or_no
2285 ("Do you want to activate OBDR support for your tapes ?");
2286 if (sz_size[0] == '\0') {
2287 bkpinfo->media_size[0] = 0;
2288 } else {
2289 bkpinfo->media_size[0] =
2290 friendly_sizestr_to_sizelong(sz_size) / 2 - 50;
2291 }
2292 log_msg(4, "media_size[0] = %ld", bkpinfo->media_size[0]);
2293 if (bkpinfo->media_size[0] <= 0) {
2294 bkpinfo->media_size[0] = 0;
2295 }
2296 for (i = 1; i <= MAX_NOOF_MEDIA; i++) {
2297 bkpinfo->media_size[i] = bkpinfo->media_size[0];
2298 }
2299 if (archiving_to_media) {
2300 if ((bkpinfo->compression_level =
2301 which_compression_level()) == -1) {
2302 log_to_screen("User has chosen not to backup the PC");
2303 finish(1);
2304 }
2305 }
2306 break;
2307
2308
2309
2310 case netfs:
2311 /* Never try to eject a NETFS device */
2312 bkpinfo->please_dont_eject = TRUE;
2313
2314 /* Initiate bkpinfo netfs_mount path from running environment if not already done */
2315 if (!bkpinfo->netfs_mount[0]) {
2316 strcpy(bkpinfo->netfs_mount,
2317 call_program_and_get_last_line_of_output
2318 ("mount | grep \":\" | cut -d' ' -f1 | head -n1"));
2319 }
2320#ifdef __FreeBSD__
2321 if (TRUE)
2322#else
2323 if (!bkpinfo->disaster_recovery)
2324#endif
2325 {
2326 if (!popup_and_get_string
2327 ("Network shared dir.",
2328 "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.)",
2329 bkpinfo->netfs_mount, MAX_STR_LEN / 4)) {
2330 log_to_screen("User has chosen not to backup the PC");
2331 finish(1);
2332 }
2333 if (!bkpinfo->restore_data) {
2334 if ((bkpinfo->compression_level =
2335 which_compression_level()) == -1) {
2336 log_to_screen("User has chosen not to backup the PC");
2337 finish(1);
2338 }
2339 }
2340 // check whether already mounted - we better remove
2341 // surrounding spaces and trailing '/' for this
2342 strip_spaces(bkpinfo->netfs_mount);
2343 if (bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] == '/')
2344 bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] = '\0';
2345 sprintf(command, "mount | grep \"%s \" | cut -d' ' -f3",
2346 bkpinfo->netfs_mount);
2347 strcpy(bkpinfo->isodir,
2348 call_program_and_get_last_line_of_output(command));
2349
2350 if (!bkpinfo->restore_data) {
2351 sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB
2352 sprintf(comment,
2353 "How much data (in Megabytes) will each media store?");
2354 if (!popup_and_get_string("Size", comment, sz_size, 5)) {
2355 log_to_screen("User has chosen not to backup the PC");
2356 finish(1);
2357 }
2358 } else {
2359 strcpy(sz_size, "0");
2360 }
2361 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2362 bkpinfo->media_size[i] = atoi(sz_size);
2363 }
2364 if (bkpinfo->media_size[0] < 0) {
2365 log_to_screen("User has chosen not to backup the PC");
2366 finish(1);
2367 }
2368 }
2369 if (bkpinfo->disaster_recovery) {
2370 sprintf(command ,"umount %s/isodir 2> /dev/null", bkpinfo->tmpdir);
2371 (void)system(command);
2372 /* Force NFS to be the protocol by default */
2373 if (bkpinfo->netfs_proto == NULL) {
2374 mr_asprintf(&(bkpinfo->netfs_proto), "nfs");
2375 }
2376 strcpy(tmp1, bkpinfo->netfs_proto);
2377 if (!popup_and_get_string
2378 ("Network protocol", "Which protocol should I use (nfs/sshfs) ?",
2379 tmp1, MAX_STR_LEN)) {
2380 log_to_screen("User has chosen not to backup the PC");
2381 finish(1);
2382 }
2383 mr_free(bkpinfo->netfs_proto);
2384 mr_asprintf(&(bkpinfo->netfs_proto), "%s", tmp1);
2385 if (!popup_and_get_string
2386 ("Network share", "Which remote share should I mount?",
2387 bkpinfo->netfs_mount, MAX_STR_LEN)) {
2388 log_to_screen("User has chosen not to backup the PC");
2389 finish(1);
2390 }
2391 }
2392 /* Initiate bkpinfo isodir path from running environment if mount already done */
2393 if (is_this_device_mounted(bkpinfo->netfs_mount)) {
2394 strcpy(bkpinfo->isodir,
2395 call_program_and_get_last_line_of_output
2396 ("mount | grep \":\" | cut -d' ' -f3 | head -n1"));
2397 } else {
2398 sprintf(bkpinfo->isodir, "%s/netfsdir", bkpinfo->tmpdir);
2399 sprintf(command, "mkdir -p %s", bkpinfo->isodir);
2400 run_program_and_log_output(command, 5);
2401 if (bkpinfo->restore_data) {
2402 if (strstr(bkpinfo->netfs_proto, "sshfs")) {
2403 mr_asprintf(&tmp, "sshfs -o ro %s %s", bkpinfo->netfs_mount, bkpinfo->isodir);
2404 } else {
2405 mr_asprintf(&tmp, "mount -t %s -o nolock,ro %s %s", bkpinfo->netfs_proto, bkpinfo->netfs_mount, bkpinfo->isodir);
2406 }
2407 } else {
2408 if (strstr(bkpinfo->netfs_proto, "sshfs")) {
2409 mr_asprintf(&tmp, "sshfs %s %s", bkpinfo->netfs_mount, bkpinfo->isodir);
2410 } else {
2411 mr_asprintf(&tmp, "mount -t %s -o nolock %s %s", bkpinfo->netfs_proto, bkpinfo->netfs_mount, bkpinfo->isodir);
2412 }
2413 }
2414 run_program_and_log_output(tmp, 3);
2415 mr_free(tmp);
2416
2417 malloc_string(g_selfmounted_isodir);
2418 strcpy(g_selfmounted_isodir, bkpinfo->isodir);
2419 }
2420 if (!is_this_device_mounted(bkpinfo->netfs_mount)) {
2421 popup_and_OK
2422 ("Please mount that partition before you try to backup to or restore from it.");
2423 finish(1);
2424 }
2425 strcpy(tmp1, bkpinfo->netfs_remote_dir);
2426 if (!popup_and_get_string
2427 ("Directory", "Which directory within that mountpoint?", tmp1,
2428 MAX_STR_LEN)) {
2429 log_to_screen("User has chosen not to backup the PC");
2430 finish(1);
2431 }
2432 strcpy(bkpinfo->netfs_remote_dir, tmp1);
2433
2434 // check whether writable - we better remove surrounding spaces for this
2435 strip_spaces(bkpinfo->netfs_remote_dir);
2436
2437 if (!popup_and_get_string
2438 ("Prefix.",
2439 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
2440 bkpinfo->prefix, MAX_STR_LEN / 4)) {
2441 log_to_screen("User has chosen not to backup the PC");
2442 finish(1);
2443 }
2444 log_msg(3, "prefix set to %s", bkpinfo->prefix);
2445
2446 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2447 bkpinfo->media_size[i] = 650;
2448 }
2449 log_msg(3, "Just set netfs_remote_dir to %s",
2450 bkpinfo->netfs_remote_dir);
2451 log_msg(3, "isodir is still %s", bkpinfo->isodir);
2452 break;
2453
2454 case iso:
2455 if (!bkpinfo->disaster_recovery) {
2456 if (!popup_and_get_string
2457 ("Storage dir.",
2458 "Please enter the full path name to the directory for your ISO images. Example: /mnt/raid0_0",
2459 bkpinfo->isodir, MAX_STR_LEN / 4)) {
2460 log_to_screen("User has chosen not to backup the PC");
2461 finish(1);
2462 }
2463 if (archiving_to_media) {
2464 if ((bkpinfo->compression_level =
2465 which_compression_level()) == -1) {
2466 log_to_screen("User has chosen not to backup the PC");
2467 finish(1);
2468 }
2469 sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB
2470 if (!popup_and_get_string
2471 ("ISO size.",
2472 "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 (700) or DVD's (4480) you plan to backup to.",
2473 sz_size, 16)) {
2474 log_to_screen("User has chosen not to backup the PC");
2475 finish(1);
2476 }
2477 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2478 bkpinfo->media_size[i] = atoi(sz_size);
2479 }
2480 } else {
2481 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2482 bkpinfo->media_size[i] = 650;
2483 }
2484 }
2485 }
2486 if (!popup_and_get_string
2487 ("Prefix.",
2488 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
2489 bkpinfo->prefix, MAX_STR_LEN / 4)) {
2490 log_to_screen("User has chosen not to backup the PC");
2491 finish(1);
2492 }
2493 log_msg(3, "prefix set to %s", bkpinfo->prefix);
2494 break;
2495 default:
2496 fatal_error
2497 ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
2498 }
2499
2500 if (archiving_to_media) {
2501
2502#ifdef __FreeBSD__
2503 strcpy(bkpinfo->boot_device,
2504 call_program_and_get_last_line_of_output
2505 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
2506#else
2507 strcpy(bkpinfo->boot_device,
2508 call_program_and_get_last_line_of_output
2509 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
2510#endif
2511 i = which_boot_loader(bkpinfo->boot_device);
2512 if (i == 'U') // unknown
2513 {
2514
2515#ifdef __FreeBSD__
2516 if (!popup_and_get_string
2517 ("Boot device",
2518 "What is your boot device? (e.g. /dev/ad0)",
2519 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2520 log_to_screen("User has chosen not to backup the PC");
2521 finish(1);
2522 }
2523 i = which_boot_loader(bkpinfo->boot_device);
2524#else
2525 if (!popup_and_get_string
2526 ("Boot device",
2527 "What is your boot device? (e.g. /dev/hda)",
2528 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2529 log_to_screen("User has chosen not to backup the PC");
2530 finish(1);
2531 }
2532 if (does_string_exist_in_boot_block
2533 (bkpinfo->boot_device, "LILO")) {
2534 i = 'L';
2535 } else
2536 if (does_string_exist_in_boot_block
2537 (bkpinfo->boot_device, "ELILO")) {
2538 i = 'E';
2539 } else
2540 if (does_string_exist_in_boot_block
2541 (bkpinfo->boot_device, "GRUB")) {
2542 i = 'G';
2543 } else {
2544 i = 'U';
2545 }
2546#endif
2547 if (i == 'U') {
2548 if (ask_me_yes_or_no
2549 ("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?"))
2550 {
2551 i = 'R'; // raw
2552 } else {
2553 log_to_screen
2554 ("I cannot find your boot loader. Please run mondoarchive with parameters.");
2555 finish(1);
2556 }
2557 }
2558 }
2559 bkpinfo->boot_loader = i;
2560 strcpy(bkpinfo->include_paths, "/");
2561 if (!popup_and_get_string
2562 ("Backup paths",
2563 "Please enter paths which you want me to backup. The default is '/' (i.e. everything).",
2564 bkpinfo->include_paths, MAX_STR_LEN)) {
2565 log_to_screen("User has chosen not to backup the PC");
2566 finish(1);
2567 }
2568 mr_asprintf(&tmp, "%s", list_of_NETFS_mounts_only());
2569 if (strlen(tmp) > 2) {
2570 if (bkpinfo->exclude_paths[0]) {
2571 strcat(bkpinfo->exclude_paths, " ");
2572 }
2573 strncpy(bkpinfo->exclude_paths, tmp, MAX_STR_LEN);
2574 }
2575 mr_free(tmp);
2576// NTFS
2577 strcpy(tmp1, call_program_and_get_last_line_of_output("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'"));
2578 if (strlen(tmp1) > 2) {
2579 if (!popup_and_get_string
2580 ("NTFS partitions",
2581 "Please enter/confirm the NTFS partitions you wish to backup as well.",
2582 tmp1, MAX_STR_LEN / 4)) {
2583 log_to_screen("User has chosen not to backup the PC");
2584 finish(1);
2585 }
2586 strncpy(bkpinfo->image_devs, tmp1, MAX_STR_LEN / 4);
2587 }
2588
2589
2590 if (!popup_and_get_string
2591 ("Exclude paths",
2592 "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.",
2593 bkpinfo->exclude_paths, (4*MAX_STR_LEN)-1)) {
2594 log_to_screen("User has chosen not to backup the PC");
2595 finish(1);
2596 }
2597 /* Always needs to be finished by a space */
2598 if (bkpinfo->exclude_paths[0]) {
2599 strcat(bkpinfo->exclude_paths, " ");
2600 }
2601 if (!popup_and_get_string
2602 ("Temporary directory",
2603 "Please enter your temporary directory.",
2604 bkpinfo->tmpdir, (4*MAX_STR_LEN)-1)) {
2605 log_to_screen("User has chosen not to backup the PC");
2606 finish(1);
2607 }
2608 if (!popup_and_get_string
2609 ("Scratch directory",
2610 "Please enter your scratch directory.",
2611 bkpinfo->scratchdir, (4*MAX_STR_LEN)-1)) {
2612 log_to_screen("User has chosen not to backup the PC");
2613 finish(1);
2614 }
2615// Interactive mode:
2616#ifdef __IA64__
2617 bkpinfo->make_cd_use_lilo = TRUE;
2618#else
2619 bkpinfo->make_cd_use_lilo = FALSE;
2620#endif
2621 bkpinfo->backup_data = TRUE;
2622 bkpinfo->verify_data =
2623 ask_me_yes_or_no
2624 ("Will you want to verify your backups after Mondo has created them?");
2625
2626#ifndef __FreeBSD__
2627 if (!ask_me_yes_or_no
2628 ("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."))
2629#endif
2630 {
2631 strcpy(bkpinfo->kernel_path, "FAILSAFE");
2632 }
2633
2634 if (!ask_me_yes_or_no
2635 ("Are you sure you want to proceed? Hit 'no' to abort.")) {
2636 log_to_screen("User has chosen not to backup the PC");
2637 finish(1);
2638 }
2639 } else {
2640 bkpinfo->restore_data = TRUE; // probably...
2641 }
2642
2643 if (bkpinfo->backup_media_type == iso
2644 || bkpinfo->backup_media_type == netfs) {
2645 g_ISO_restore_mode = TRUE;
2646 }
2647#ifdef __FreeSD__
2648// skip
2649#else
2650 if (bkpinfo->backup_media_type == netfs) {
2651 log_msg(3, "I think the Remote mount is mounted at %s",
2652 bkpinfo->isodir);
2653 }
2654 log_it("isodir = %s", bkpinfo->isodir);
2655 log_it("netfs_mount = '%s'", bkpinfo->netfs_mount);
2656 log_it("netfs_proto = '%s'", bkpinfo->netfs_proto);
2657 if (bkpinfo->netfs_user) {
2658 log_it("netfs_user = '%s'", bkpinfo->netfs_user);
2659 }
2660#endif
2661
2662 log_it("media device = %s", bkpinfo->media_device);
2663 log_it("media size = %ld", bkpinfo->media_size[1]);
2664 log_it("media type = %s",
2665 bkptype_to_string(bkpinfo->backup_media_type));
2666 log_it("prefix = %s", bkpinfo->prefix);
2667 log_it("compression = %ld", bkpinfo->compression_level);
2668 log_it("exclude_path = %s", bkpinfo->exclude_paths);
2669 log_it("include_path = %s", bkpinfo->include_paths);
2670
2671 /* Handle devices passed in bkpinfo and print result */
2672 /* the mr_make_devlist_from_pathlist function appends
2673 * to the *_paths variables so copy before */
2674 mr_asprintf(&tmp, "%s ", bkpinfo->exclude_paths);
2675 mr_make_devlist_from_pathlist(tmp, 'E');
2676 mr_free(tmp);
2677 mr_asprintf(&tmp, "%s ", bkpinfo->include_paths);
2678 mr_make_devlist_from_pathlist(tmp, 'I');
2679 mr_free(tmp);
2680
2681 log_it("scratchdir = '%s'", bkpinfo->scratchdir);
2682 log_it("tmpdir = '%s'", bkpinfo->tmpdir);
2683 log_it("image_devs = '%s'", bkpinfo->image_devs);
2684 log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device,
2685 bkpinfo->boot_loader);
2686 if (bkpinfo->media_size[0] < 0) {
2687 if (archiving_to_media) {
2688 fatal_error("Media size is less than zero.");
2689 } else {
2690 log_msg(2, "Warning - media size is less than zero.");
2691 bkpinfo->media_size[0] = 0;
2692 }
2693 }
2694 paranoid_free(sz_size);
2695 paranoid_free(tmp1);
2696 paranoid_free(command);
2697 paranoid_free(comment);
2698 paranoid_free(prompt);
2699 return (0);
2700}
2701
2702
2703
2704
2705/**
2706 * @addtogroup utilityGroup
2707 * @{
2708 */
2709/**
2710 * Get a space-separated list of NETFS devices and mounts.
2711 * @return The list created.
2712 * @note The return value points to static data that will be overwritten with each call.
2713 */
2714char *list_of_NETFS_devices_and_mounts(void)
2715{
2716 char *exclude_these_devices = NULL;
2717 char *exclude_these_directories = NULL;
2718 static char result_sz[1024];
2719
2720 mr_asprintf(&exclude_these_directories,"%s",list_of_NETFS_mounts_only());
2721 mr_asprintf(&exclude_these_devices,"%s", call_program_and_get_last_line_of_output("tr -s '\t' ' ' < /etc/fstab | grep -E '( (coda|ncpfs|sshfs|nfs|nfs4|smbfs|cifs|afs|gfs|ocfs|ocfs2|mvfs|nsspool|nsvol) )' | cut -d' ' -f1 | tr -s '\n' ' ' | awk '{print $0;}'"));
2722 snprintf(result_sz, 1023, "%s %s", exclude_these_directories, exclude_these_devices);
2723 mr_free(exclude_these_devices);
2724 mr_free(exclude_these_directories);
2725 return (result_sz);
2726}
2727
2728
2729
2730
2731/**
2732 * Get a space-separated list of NETFS mounts.
2733 * @return The list created.
2734 * @note The return value points to static data that will be overwritten with each call.
2735 * @bug Even though we only want the mounts, the devices are still checked.
2736 */
2737char *list_of_NETFS_mounts_only(void)
2738{
2739 char *exclude_these_directories = NULL;
2740 static char result_sz[512];
2741
2742 mr_asprintf(&exclude_these_directories,"%s", call_program_and_get_last_line_of_output("mount -t coda,ncpfs,fuse.sshfs,nfs,nfs4,smbfs,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' ' ' | awk '{print $0;}'"));
2743 snprintf(result_sz, 511, "%s", exclude_these_directories);
2744 mr_free(exclude_these_directories);
2745 return (result_sz);
2746}
2747
2748/* @} - end of utilityGroup */
2749
2750
2751
2752
2753
2754/**
2755 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
2756 * [random] is a random number between 1 and 32767.
2757 * @param store_name_here Where to store the new filename.
2758 * @param stub A random number will be appended to this to make the FIFO's name.
2759 * @ingroup deviceGroup
2760 */
2761void make_fifo(char *store_name_here, char *stub)
2762{
2763 char *tmp;
2764
2765 malloc_string(tmp);
2766 assert_string_is_neither_NULL_nor_zerolength(stub);
2767
2768 sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
2769 (int) (random() % 32768));
2770 make_hole_for_file(store_name_here);
2771 mkfifo(store_name_here, S_IRWXU | S_IRWXG);
2772 sprintf(tmp, "chmod 770 %s", store_name_here);
2773 paranoid_system(tmp);
2774 paranoid_free(tmp);
2775}
2776
2777
2778
2779
2780
2781
2782/**
2783 * Set the tmpdir and scratchdir to reside on the partition with the most free space.
2784 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
2785 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set.
2786 * @ingroup utilityGroup
2787 */
2788void sensibly_set_tmpdir_and_scratchdir()
2789{
2790 char *tmp = NULL;
2791 char *command = NULL;
2792 char *sz = NULL;
2793
2794 assert(bkpinfo != NULL);
2795
2796#ifdef __FreeBSD__
2797 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output("LANGUAGE=C df -m -P -t nonfs,msdosfs,ntfs,ntfs-3g,smbfs,smb,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol | grep -vE \"none|Filesystem\" | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -nr | awk '{print $NF;}' | while read x ; do test -w $x && echo $x && break ; done"));
2798#else
2799 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output("LANGUAGE=C df -m -P -x nfs -x nfs4 -x fuse.sshfs -x fuse -x vfat -x ntfs -x ntfs-3g -x smbfs -x smb -x cifs -x afs -x gfs -x ocfs -x ocfs2 -x mvfs -x nsspool -x nssvol -x iso9660 | grep -vE \"none|Filesystem|/dev/shm\" | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -nr | awk '{print $NF;}' | while read x ; do test -w $x && echo $x && break ; done"));
2800#endif
2801
2802 if (tmp[0] != '/') {
2803 mr_asprintf(&sz, "%s", tmp);
2804 paranoid_free(tmp);
2805 mr_asprintf(&tmp, "/%s", sz);
2806 mr_free(sz);
2807 }
2808 if (!tmp[0]) {
2809 fatal_error("I couldn't figure out the tempdir!");
2810 }
2811 setup_tmpdir(tmp);
2812 log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir);
2813
2814 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%d", tmp,
2815 (int) (random() % 32768));
2816 log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
2817
2818 mr_asprintf(&command, "rm -Rf %s/tmp.mondo.* %s/mondo.scratch.*", tmp, tmp);
2819 paranoid_free(tmp);
2820
2821 paranoid_system(command);
2822 mr_free(command);
2823}
2824
2825
2826
2827
2828
2829
2830/**
2831 * @addtogroup deviceGroup
2832 * @{
2833 */
2834/**
2835 * If we can read @p dev, set @p output to it.
2836 * If @p dev cannot be read, set @p output to "".
2837 * @param dev The device to check for.
2838 * @param output Set to @p dev if @p dev exists, "" otherwise.
2839 * @return TRUE if @p dev exists, FALSE if it doesn't.
2840 */
2841bool set_dev_to_this_if_rx_OK(char *output, char *dev)
2842{
2843 char *command;
2844
2845 malloc_string(command);
2846 if (!dev || dev[0] == '\0') {
2847 output[0] = '\0';
2848 return (FALSE);
2849 }
2850// assert_string_is_neither_NULL_nor_zerolength(dev);
2851 log_msg(10, "Injecting %s", dev);
2852 inject_device(dev);
2853 if (!does_file_exist(dev)) {
2854 log_msg(10, "%s doesn't exist. Returning FALSE.", dev);
2855 return (FALSE);
2856 }
2857 sprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null",
2858 512L, dev);
2859 if (!run_program_and_log_output(command, FALSE)
2860 && !run_program_and_log_output(command, FALSE)) {
2861 strcpy(output, dev);
2862 log_msg(4, "Found it - %s", dev);
2863 return (TRUE);
2864 } else {
2865 output[0] = '\0';
2866 log_msg(4, "It's not %s", dev);
2867 return (FALSE);
2868 }
2869}
2870
2871
2872
2873
2874
2875/**
2876 * Find out what number CD is in the drive.
2877 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
2878 * @return The current CD number, or -1 if it could not be found.
2879 * @note If the CD is not mounted, it will be mounted
2880 * (and remain mounted after this function returns).
2881 */
2882int what_number_cd_is_this()
2883{
2884 int cd_number = -1;
2885 char *mountdev = NULL;
2886 char *tmp = NULL;
2887
2888 assert(bkpinfo != NULL);
2889// log_it("Asking what_number_cd_is_this");
2890 if (g_ISO_restore_mode) {
2891 mr_asprintf(&tmp, "mount | grep iso9660 | awk '{print $3;}'");
2892
2893 mr_asprintf(&mountdev, "%s%s", call_program_and_get_last_line_of_output(tmp), "/archives/THIS-CD-NUMBER");
2894 cd_number = atoi(last_line_of_file(mountdev));
2895 paranoid_free(mountdev);
2896 paranoid_free(tmp);
2897
2898 return (cd_number);
2899 }
2900
2901 mr_asprintf(&mountdev, "%s", bkpinfo->media_device);
2902 if (!mountdev[0]) {
2903 log_it
2904 ("(what_number_cd_is_this) Warning - media_device unknown. Finding out...");
2905 find_cdrom_device(bkpinfo->media_device, FALSE);
2906 }
2907 if (!is_this_device_mounted(MNT_CDROM)) {
2908 if (bkpinfo->backup_media_type == usb) {
2909 mount_USB_here(mountdev, MNT_CDROM);
2910 } else {
2911 mount_CDROM_here(mountdev, MNT_CDROM);
2912 }
2913 }
2914 paranoid_free(mountdev);
2915
2916 cd_number = atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
2917 return (cd_number);
2918}
2919
2920
2921
2922
2923
2924
2925
2926/**
2927 * Find out what device is mounted as root (/).
2928 * @return Root device.
2929 * @note The returned string points to static storage and will be overwritten with every call.
2930 * @bug A bit of a misnomer; it's actually finding out the root device.
2931 * The mountpoint (where it's mounted) will obviously be '/'.
2932 */
2933char *where_is_root_mounted()
2934{
2935 /*@ buffers **************** */
2936 static char tmp[MAX_STR_LEN];
2937
2938
2939#ifdef __FreeBSD__
2940 strcpy(tmp, call_program_and_get_last_line_of_output
2941 ("mount | grep \" on / \" | cut -d' ' -f1"));
2942#else
2943 strcpy(tmp, call_program_and_get_last_line_of_output
2944 ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"));
2945 if (strstr(tmp, "/dev/cciss/")) {
2946 strcpy(tmp, call_program_and_get_last_line_of_output
2947 ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"));
2948 }
2949 if (strstr(tmp, "/dev/md")) {
2950 strcpy(tmp,
2951 call_program_and_get_last_line_of_output
2952 ("mount | grep \" on / \" | cut -d' ' -f1"));
2953 }
2954#endif
2955
2956 return (tmp);
2957}
2958
2959
2960/**
2961 * Find out which boot loader is in use.
2962 * @param which_device Device to look for the boot loader on.
2963 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
2964 * @note Under Linux, all drives are examined, not just @p which_device.
2965 */
2966#ifdef __FreeBSD__
2967char which_boot_loader(char *which_device)
2968{
2969 int count_lilos = 0;
2970 int count_grubs = 0;
2971 int count_boot0s = 0;
2972 int count_dangerouslydedicated = 0;
2973
2974 log_it("looking at drive %s's MBR", which_device);
2975 if (does_string_exist_in_boot_block(which_device, "GRUB")) {
2976 count_grubs++;
2977 }
2978 if (does_string_exist_in_boot_block(which_device, "LILO")) {
2979 count_lilos++;
2980 }
2981 if (does_string_exist_in_boot_block(which_device, "Drive")) {
2982 count_boot0s++;
2983 }
2984 if (does_string_exist_in_first_N_blocks
2985 (which_device, "FreeBSD/i386", 17)) {
2986 count_dangerouslydedicated++;
2987 }
2988 log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
2989 count_grubs, count_lilos, count_elilos, count_boot0s,
2990 count_dangerouslydedicated);
2991
2992 if (count_grubs && !count_lilos) {
2993 return ('G');
2994 } else if (count_lilos && !count_grubs) {
2995 return ('L');
2996 } else if (count_grubs == 1 && count_lilos == 1) {
2997 log_it("I'll bet you used to use LILO but switched to GRUB...");
2998 return ('G');
2999 } else if (count_boot0s == 1) {
3000 return ('B');
3001 } else if (count_dangerouslydedicated) {
3002 return ('D');
3003 } else {
3004 log_it("Unknown boot loader");
3005 return ('U');
3006 }
3007}
3008
3009#else
3010
3011char which_boot_loader(char *which_device)
3012{
3013 /*@ buffer ***************************************************** */
3014 char *list_drives_cmd = NULL;
3015 char *current_drive;
3016
3017 /*@ pointers *************************************************** */
3018 FILE *pdrives;
3019
3020 /*@ int ******************************************************** */
3021 int count_lilos = 0;
3022 int count_grubs = 0;
3023
3024 /*@ end vars *************************************************** */
3025
3026 malloc_string(current_drive);
3027
3028#ifdef __IA64__
3029 /* No choice for it */
3030 return ('E');
3031#endif
3032 assert(which_device != NULL);
3033
3034 mr_asprintf(&list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s", where_is_root_mounted());
3035 log_it("list_drives_cmd = %s", list_drives_cmd);
3036
3037 if (!(pdrives = popen(list_drives_cmd, "r"))) {
3038 log_OS_error("Unable to open list of drives");
3039 mr_free(list_drives_cmd);
3040 paranoid_free(current_drive);
3041 return ('\0');
3042 }
3043 mr_free(list_drives_cmd);
3044
3045 for ((void)fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
3046 (void)fgets(current_drive, MAX_STR_LEN, pdrives)) {
3047 strip_spaces(current_drive);
3048 log_it("looking at drive %s's MBR", current_drive);
3049 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
3050 count_grubs++;
3051 strcpy(which_device, current_drive);
3052 break;
3053 }
3054 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
3055 count_lilos++;
3056 strcpy(which_device, current_drive);
3057 break;
3058 }
3059 }
3060 if (pclose(pdrives)) {
3061 log_OS_error("Cannot pclose pdrives");
3062 }
3063 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
3064 if (count_grubs && !count_lilos) {
3065 paranoid_free(current_drive);
3066 return ('G');
3067 } else if (count_lilos && !count_grubs) {
3068 paranoid_free(current_drive);
3069 return ('L');
3070 } else if (count_grubs == 1 && count_lilos == 1) {
3071 log_it("I'll bet you used to use LILO but switched to GRUB...");
3072 paranoid_free(current_drive);
3073 return ('G');
3074 } else {
3075 // We need to look on each partition then
3076 mr_asprintf(&list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep -E \"^/dev/\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/");
3077 log_it("list_drives_cmd = %s", list_drives_cmd);
3078
3079 if (!(pdrives = popen(list_drives_cmd, "r"))) {
3080 log_OS_error("Unable to open list of drives");
3081 mr_free(list_drives_cmd);
3082 paranoid_free(current_drive);
3083 return ('\0');
3084 }
3085 mr_free(list_drives_cmd);
3086
3087 for ((void)fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
3088 (void)fgets(current_drive, MAX_STR_LEN, pdrives)) {
3089 strip_spaces(current_drive);
3090 log_it("looking at partition %s's BR", current_drive);
3091 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
3092 count_grubs++;
3093 strcpy(which_device, current_drive);
3094 break;
3095 }
3096 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
3097 count_lilos++;
3098 strcpy(which_device, current_drive);
3099 break;
3100 }
3101 }
3102 if (pclose(pdrives)) {
3103 log_OS_error("Cannot pclose pdrives");
3104 }
3105 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
3106 paranoid_free(current_drive);
3107 if (count_grubs && !count_lilos) {
3108 return ('G');
3109 } else if (count_lilos && !count_grubs) {
3110 return ('L');
3111 } else if (count_grubs == 1 && count_lilos == 1) {
3112 log_it("I'll bet you used to use LILO but switched to GRUB...");
3113 return ('G');
3114 } else {
3115 log_it("Unknown boot loader");
3116 return ('U');
3117 }
3118 }
3119}
3120#endif
3121
3122
3123
3124
3125/**
3126 * Write zeroes over the first 16K of @p device.
3127 * @param device The device to zero.
3128 * @return 0 for success, 1 for failure.
3129 */
3130int zero_out_a_device(char *device)
3131{
3132 FILE *fout;
3133 int i;
3134
3135 assert_string_is_neither_NULL_nor_zerolength(device);
3136
3137 log_it("Zeroing drive %s", device);
3138 if (!(fout = fopen(device, "w"))) {
3139 log_OS_error("Unable to open/write to device");
3140 return (1);
3141 }
3142 for (i = 0; i < 16384; i++) {
3143 fputc('\0', fout);
3144 }
3145 paranoid_fclose(fout);
3146 log_it("Device successfully zeroed.");
3147 return (0);
3148}
3149
3150/**
3151 * Return the device pointed to by @p incoming.
3152 * @param incoming The device to resolve symlinks for.
3153 * @return The path to the real device file.
3154 * @note The returned string points to static storage that will be overwritten with each call.
3155 * @bug Won't work with file v4.0; needs to be written in C.
3156 */
3157char *resolve_softlinks_to_get_to_actual_device_file(char *incoming)
3158{
3159 static char output[MAX_STR_LEN];
3160 char *command;
3161 char *curr_fname;
3162 char *scratch = NULL;
3163 char *tmp = NULL;
3164 char *p;
3165
3166 struct stat statbuf;
3167 command = malloc(1000);
3168 malloc_string(curr_fname);
3169 if (!does_file_exist(incoming)) {
3170 log_it
3171 ("resolve_softlinks_to_get_to_actual_device_file --- device not found");
3172 strcpy(output, incoming);
3173 } else {
3174 strcpy(curr_fname, incoming);
3175 lstat(curr_fname, &statbuf);
3176 while (S_ISLNK(statbuf.st_mode)) {
3177 log_msg(1, "curr_fname = %s", curr_fname);
3178 sprintf(command, "file %s", curr_fname);
3179 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
3180 for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' ';
3181 p--);
3182 p++;
3183 mr_asprintf(&scratch, "%s", p);
3184 for (p = scratch; *p != '\0' && *p != '\''; p++);
3185 *p = '\0';
3186 log_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp, scratch);
3187 mr_free(tmp);
3188
3189 if (scratch[0] == '/') {
3190 strcpy(curr_fname, scratch); // copy whole thing because it's an absolute softlink
3191 } else { // copy over the basename cos it's a relative softlink
3192 p = curr_fname + strlen(curr_fname);
3193 while (p != curr_fname && *p != '/') {
3194 p--;
3195 }
3196 if (*p == '/') {
3197 p++;
3198 }
3199 strcpy(p, scratch);
3200 }
3201 mr_free(scratch);
3202 lstat(curr_fname, &statbuf);
3203 }
3204 strcpy(output, curr_fname);
3205 log_it("resolved %s to %s", incoming, output);
3206 }
3207 paranoid_free(command);
3208 paranoid_free(curr_fname);
3209 return (output);
3210}
3211
3212/* @} - end of deviceGroup */
3213
3214/**
3215 * Return the type of partition format (GPT or MBR)
3216 */
3217char *which_partition_format(const char *drive)
3218{
3219 static char output[4];
3220 char *tmp = NULL;
3221 char *command;
3222 char *fdisk;
3223#ifdef __IA64__
3224 struct stat buf;
3225#endif
3226 malloc_string(command);
3227 malloc_string(fdisk);
3228 sprintf(fdisk, "/sbin/parted2fdisk");
3229 sprintf(command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
3230 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
3231 if (strstr(tmp, "GPT") == NULL) {
3232 strcpy(output, "MBR");
3233 } else {
3234 strcpy(output, "GPT");
3235 }
3236 mr_free(tmp);
3237
3238 log_msg(0, "Found %s partition table format type", output);
3239 paranoid_free(command);
3240 paranoid_free(fdisk);
3241 return (output);
3242}
3243/* @} - end of deviceGroup */
Note: See TracBrowser for help on using the repository browser.