source: MondoRescue/branches/2.2.7/mondo/src/common/libmondo-devices.c@ 1988

Last change on this file since 1988 was 1988, checked in by Bruno Cornec, 16 years ago

Fix for #261 nsspool and nssvol support (thanks sprobst for report and proposal of ptch)

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