source: MondoRescue/branches/2.2.8/mondo/src/common/libmondo-devices.c@ 2050

Last change on this file since 2050 was 2050, checked in by Bruno Cornec, 15 years ago
  • Do not try to create the dummy file on the NFS share when in DR mode as now the NFS share is mounted ro !
  • Property svn:keywords set to Id
File size: 76.0 KB
Line 
1/* libmondo-devices.c Subroutines for handling devices
2 $Id: libmondo-devices.c 2050 2008-10-23 12:38:39Z 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 2050 2008-10-23 12:38:39Z 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 if (! bkpinfo->disaster_recovery) {
2013 asprintf(&tmp1,"%s/%s/.dummy.txt", bkpinfo->isodir,bkpinfo->nfs_remote_dir);
2014 sprintf(command, "echo hi > %s", tmp1);
2015 while (run_program_and_log_output(command, FALSE)) {
2016 strcpy(tmp, bkpinfo->nfs_remote_dir);
2017 sprintf(prompt,
2018 "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.",
2019 bkpinfo->nfs_remote_dir, bkpinfo->isodir);
2020 if (!popup_and_get_string
2021 ("Directory", prompt, tmp, MAX_STR_LEN)) {
2022 log_to_screen("User has chosen not to backup the PC");
2023 finish(1);
2024 }
2025 strcpy(bkpinfo->nfs_remote_dir, tmp);
2026 // check whether writable - we better remove surrounding space s for this
2027 strip_spaces(bkpinfo->nfs_remote_dir);
2028 paranoid_free(tmp1);
2029 asprintf(&tmp1,"%s/%s/.dummy.txt", bkpinfo->isodir,bkpinfo->nfs_remote_dir);
2030 sprintf(command, "echo hi > %s", tmp1);
2031 }
2032 unlink(tmp1);
2033 paranoid_free(tmp1);
2034 }
2035
2036 if (!popup_and_get_string
2037 ("Prefix.",
2038 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
2039 bkpinfo->prefix, MAX_STR_LEN / 4)) {
2040 log_to_screen("User has chosen not to backup the PC");
2041 finish(1);
2042 }
2043 log_msg(3, "prefix set to %s", bkpinfo->prefix);
2044
2045 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2046 bkpinfo->media_size[i] = 650;
2047 }
2048 log_msg(3, "Just set nfs_remote_dir to %s",
2049 bkpinfo->nfs_remote_dir);
2050 log_msg(3, "isodir is still %s", bkpinfo->isodir);
2051 break;
2052
2053 case iso:
2054 if (!bkpinfo->disaster_recovery) {
2055 if (!popup_and_get_string
2056 ("Storage dir.",
2057 "Please enter the full path name to the directory for your ISO images. Example: /mnt/raid0_0",
2058 bkpinfo->isodir, MAX_STR_LEN / 4)) {
2059 log_to_screen("User has chosen not to backup the PC");
2060 finish(1);
2061 }
2062 if (archiving_to_media) {
2063 if ((bkpinfo->compression_level =
2064 which_compression_level()) == -1) {
2065 log_to_screen("User has chosen not to backup the PC");
2066 finish(1);
2067 }
2068 if (!popup_and_get_string
2069 ("ISO size.",
2070 "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.",
2071 sz_size, 16)) {
2072 log_to_screen("User has chosen not to backup the PC");
2073 finish(1);
2074 }
2075 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2076 bkpinfo->media_size[i] = atoi(sz_size);
2077 }
2078 } else {
2079 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2080 bkpinfo->media_size[i] = 650;
2081 }
2082 }
2083 }
2084 if (!popup_and_get_string
2085 ("Prefix.",
2086 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
2087 bkpinfo->prefix, MAX_STR_LEN / 4)) {
2088 log_to_screen("User has chosen not to backup the PC");
2089 finish(1);
2090 }
2091 log_msg(3, "prefix set to %s", bkpinfo->prefix);
2092 break;
2093 default:
2094 fatal_error
2095 ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
2096 }
2097
2098 if (archiving_to_media) {
2099
2100#ifdef __FreeBSD__
2101 strcpy(bkpinfo->boot_device,
2102 call_program_and_get_last_line_of_output
2103 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
2104#else
2105 strcpy(bkpinfo->boot_device,
2106 call_program_and_get_last_line_of_output
2107 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
2108#endif
2109 i = which_boot_loader(bkpinfo->boot_device);
2110 if (i == 'U') // unknown
2111 {
2112
2113#ifdef __FreeBSD__
2114 if (!popup_and_get_string
2115 ("Boot device",
2116 "What is your boot device? (e.g. /dev/ad0)",
2117 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2118 log_to_screen("User has chosen not to backup the PC");
2119 finish(1);
2120 }
2121 i = which_boot_loader(bkpinfo->boot_device);
2122#else
2123 if (!popup_and_get_string
2124 ("Boot device",
2125 "What is your boot device? (e.g. /dev/hda)",
2126 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2127 log_to_screen("User has chosen not to backup the PC");
2128 finish(1);
2129 }
2130 if (does_string_exist_in_boot_block
2131 (bkpinfo->boot_device, "LILO")) {
2132 i = 'L';
2133 } else
2134 if (does_string_exist_in_boot_block
2135 (bkpinfo->boot_device, "ELILO")) {
2136 i = 'E';
2137 } else
2138 if (does_string_exist_in_boot_block
2139 (bkpinfo->boot_device, "GRUB")) {
2140 i = 'G';
2141 } else {
2142 i = 'U';
2143 }
2144#endif
2145 if (i == 'U') {
2146 if (ask_me_yes_or_no
2147 ("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?"))
2148 {
2149 i = 'R'; // raw
2150 } else {
2151 log_to_screen
2152 ("I cannot find your boot loader. Please run mondoarchive with parameters.");
2153 finish(1);
2154 }
2155 }
2156 }
2157 bkpinfo->boot_loader = i;
2158 strcpy(bkpinfo->include_paths, "/");
2159 if (!popup_and_get_string
2160 ("Backup paths",
2161 "Please enter paths which you want me to backup. The default is '/' (i.e. everything).",
2162 bkpinfo->include_paths, MAX_STR_LEN)) {
2163 log_to_screen("User has chosen not to backup the PC");
2164 finish(1);
2165 }
2166 strcpy(tmp, list_of_NFS_mounts_only());
2167 if (strlen(tmp) > 2) {
2168 if (bkpinfo->exclude_paths[0]) {
2169 strcat(bkpinfo->exclude_paths, " ");
2170 }
2171 strncpy(bkpinfo->exclude_paths, tmp, MAX_STR_LEN);
2172 }
2173// NTFS
2174 strcpy(tmp,
2175 call_program_and_get_last_line_of_output
2176 ("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'"));
2177 if (strlen(tmp) > 2) {
2178 if (!popup_and_get_string
2179 ("NTFS partitions",
2180 "Please enter/confirm the NTFS partitions you wish to backup as well.",
2181 tmp, MAX_STR_LEN / 4)) {
2182 log_to_screen("User has chosen not to backup the PC");
2183 finish(1);
2184 }
2185 strncpy(bkpinfo->image_devs, tmp, MAX_STR_LEN / 4);
2186 }
2187
2188
2189 if (!popup_and_get_string
2190 ("Exclude paths",
2191 "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.",
2192 bkpinfo->exclude_paths, (4*MAX_STR_LEN)-1)) {
2193 log_to_screen("User has chosen not to backup the PC");
2194 finish(1);
2195 }
2196// Interactive mode:
2197#ifdef __IA64__
2198 bkpinfo->make_cd_use_lilo = TRUE;
2199#else
2200 bkpinfo->make_cd_use_lilo = FALSE;
2201#endif
2202 bkpinfo->backup_data = TRUE;
2203 bkpinfo->verify_data =
2204 ask_me_yes_or_no
2205 ("Will you want to verify your backups after Mondo has created them?");
2206
2207#ifndef __FreeBSD__
2208 if (!ask_me_yes_or_no
2209 ("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."))
2210#endif
2211 {
2212 strcpy(bkpinfo->kernel_path, "FAILSAFE");
2213 }
2214
2215 if (!ask_me_yes_or_no
2216 ("Are you sure you want to proceed? Hit 'no' to abort.")) {
2217 log_to_screen("User has chosen not to backup the PC");
2218 finish(1);
2219 }
2220 } else {
2221 bkpinfo->restore_data = TRUE; // probably...
2222 }
2223
2224 if (bkpinfo->backup_media_type == iso
2225 || bkpinfo->backup_media_type == nfs) {
2226 g_ISO_restore_mode = TRUE;
2227 }
2228#ifdef __FreeSD__
2229// skip
2230#else
2231 if (bkpinfo->backup_media_type == nfs) {
2232 sprintf(tmp, "mount | grep \"%s\" | cut -d' ' -f3",
2233 bkpinfo->nfs_mount);
2234// strcpy(bkpinfo->isodir, call_program_and_get_last_line_of_output(tmp));
2235 log_msg(3, "I think the NFS mount is mounted at %s",
2236 bkpinfo->isodir);
2237 }
2238 log_it("isodir = %s", bkpinfo->isodir);
2239 log_it("nfs_mount = '%s'", bkpinfo->nfs_mount);
2240#endif
2241
2242 log_it("media device = %s", bkpinfo->media_device);
2243 log_it("media size = %ld", bkpinfo->media_size[1]);
2244 log_it("media type = %s",
2245 bkptype_to_string(bkpinfo->backup_media_type));
2246 log_it("prefix = %s", bkpinfo->prefix);
2247 log_it("compression = %ld", bkpinfo->compression_level);
2248 log_it("include_paths = '%s'", bkpinfo->include_paths);
2249 log_it("exclude_paths = '%s'", bkpinfo->exclude_paths);
2250 log_it("scratchdir = '%s'", bkpinfo->scratchdir);
2251 log_it("tmpdir = '%s'", bkpinfo->tmpdir);
2252 log_it("image_devs = '%s'", bkpinfo->image_devs);
2253 log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device,
2254 bkpinfo->boot_loader);
2255 if (bkpinfo->media_size[0] < 0) {
2256 if (archiving_to_media) {
2257 fatal_error("Media size is less than zero.");
2258 } else {
2259 log_msg(2, "Warning - media size is less than zero.");
2260 bkpinfo->media_size[0] = 0;
2261 }
2262 }
2263 paranoid_free(tmp);
2264 paranoid_free(sz_size);
2265 paranoid_free(command);
2266 paranoid_free(comment);
2267 paranoid_free(prompt);
2268 return (0);
2269}
2270
2271
2272
2273
2274/**
2275 * @addtogroup utilityGroup
2276 * @{
2277 */
2278/**
2279 * Get a space-separated list of NFS devices and mounts.
2280 * @return The list created.
2281 * @note The return value points to static data that will be overwritten with each call.
2282 */
2283char *list_of_NFS_devices_and_mounts(void)
2284{
2285 char *exclude_these_devices;
2286 char *exclude_these_directories;
2287 static char result_sz[512];
2288
2289 malloc_string(exclude_these_devices);
2290 malloc_string(exclude_these_directories);
2291 strcpy(exclude_these_directories,
2292 call_program_and_get_last_line_of_output
2293 ("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;}'"));
2294 strcpy(exclude_these_devices,
2295 call_program_and_get_last_line_of_output
2296 ("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;}'"));
2297 sprintf(result_sz, "%s %s", exclude_these_directories,
2298 exclude_these_devices);
2299 paranoid_free(exclude_these_devices);
2300 paranoid_free(exclude_these_directories);
2301 return (result_sz);
2302}
2303
2304
2305
2306
2307/**
2308 * Get a space-separated list of NFS mounts.
2309 * @return The list created.
2310 * @note The return value points to static data that will be overwritten with each call.
2311 * @bug Even though we only want the mounts, the devices are still checked.
2312 */
2313char *list_of_NFS_mounts_only(void)
2314{
2315 char *exclude_these_devices;
2316 char *exclude_these_directories;
2317 static char result_sz[512];
2318
2319 malloc_string(exclude_these_devices);
2320 malloc_string(exclude_these_directories);
2321 strcpy(exclude_these_directories,
2322 call_program_and_get_last_line_of_output
2323 ("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;}'"));
2324 strcpy(exclude_these_devices,
2325 call_program_and_get_last_line_of_output
2326 ("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;}'"));
2327 sprintf(result_sz, "%s", exclude_these_directories);
2328 paranoid_free(exclude_these_devices);
2329 paranoid_free(exclude_these_directories);
2330 return (result_sz);
2331}
2332
2333/* @} - end of utilityGroup */
2334
2335
2336
2337
2338
2339/**
2340 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
2341 * [random] is a random number between 1 and 32767.
2342 * @param store_name_here Where to store the new filename.
2343 * @param stub A random number will be appended to this to make the FIFO's name.
2344 * @ingroup deviceGroup
2345 */
2346void make_fifo(char *store_name_here, char *stub)
2347{
2348 char *tmp;
2349
2350 malloc_string(tmp);
2351 assert_string_is_neither_NULL_nor_zerolength(stub);
2352
2353 sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
2354 (int) (random() % 32768));
2355 make_hole_for_file(store_name_here);
2356 mkfifo(store_name_here, S_IRWXU | S_IRWXG);
2357 sprintf(tmp, "chmod 770 %s", store_name_here);
2358 paranoid_system(tmp);
2359 paranoid_free(tmp);
2360}
2361
2362
2363
2364
2365
2366
2367/**
2368 * Set the tmpdir and scratchdir to reside on the partition with the most free space.
2369 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
2370 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set.
2371 * @ingroup utilityGroup
2372 */
2373void sensibly_set_tmpdir_and_scratchdir()
2374{
2375 char *tmp, *command, *sz;
2376
2377 malloc_string(tmp);
2378 malloc_string(command);
2379 malloc_string(sz);
2380 assert(bkpinfo != NULL);
2381
2382#ifdef __FreeBSD__
2383 strcpy(tmp,
2384 call_program_and_get_last_line_of_output
2385 ("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;}'"));
2386#else
2387 strcpy(tmp,
2388 call_program_and_get_last_line_of_output
2389 ("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;}'"));
2390#endif
2391
2392 if (tmp[0] != '/') {
2393 strcpy(sz, tmp);
2394 strcpy(tmp, "/");
2395 strcat(tmp, sz);
2396 }
2397 if (!tmp[0]) {
2398 fatal_error("I couldn't figure out the tempdir!");
2399 }
2400 setup_tmpdir(tmp);
2401 log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir);
2402
2403 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%d", tmp,
2404 (int) (random() % 32768));
2405 log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
2406
2407 sprintf(command, "rm -Rf %s/tmp.mondo.* %s/mondo.scratch.*", tmp, tmp);
2408 paranoid_system(command);
2409 paranoid_free(tmp);
2410 paranoid_free(command);
2411 paranoid_free(sz);
2412}
2413
2414
2415
2416
2417
2418
2419/**
2420 * @addtogroup deviceGroup
2421 * @{
2422 */
2423/**
2424 * If we can read @p dev, set @p output to it.
2425 * If @p dev cannot be read, set @p output to "".
2426 * @param dev The device to check for.
2427 * @param output Set to @p dev if @p dev exists, "" otherwise.
2428 * @return TRUE if @p dev exists, FALSE if it doesn't.
2429 */
2430bool set_dev_to_this_if_rx_OK(char *output, char *dev)
2431{
2432 char *command;
2433
2434 malloc_string(command);
2435 if (!dev || dev[0] == '\0') {
2436 output[0] = '\0';
2437 return (FALSE);
2438 }
2439// assert_string_is_neither_NULL_nor_zerolength(dev);
2440 log_msg(10, "Injecting %s", dev);
2441 inject_device(dev);
2442 if (!does_file_exist(dev)) {
2443 log_msg(10, "%s doesn't exist. Returning FALSE.", dev);
2444 return (FALSE);
2445 }
2446 sprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null",
2447 512L, dev);
2448 if (!run_program_and_log_output(command, FALSE)
2449 && !run_program_and_log_output(command, FALSE)) {
2450 strcpy(output, dev);
2451 log_msg(4, "Found it - %s", dev);
2452 return (TRUE);
2453 } else {
2454 output[0] = '\0';
2455 log_msg(4, "It's not %s", dev);
2456 return (FALSE);
2457 }
2458}
2459
2460
2461
2462
2463
2464/**
2465 * Find out what number CD is in the drive.
2466 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
2467 * @return The current CD number, or -1 if it could not be found.
2468 * @note If the CD is not mounted, it will be mounted
2469 * (and remain mounted after this function returns).
2470 */
2471int what_number_cd_is_this()
2472{
2473 int cd_number = -1;
2474 char *mountdev;
2475 char *tmp;
2476
2477 malloc_string(mountdev);
2478 malloc_string(tmp);
2479 assert(bkpinfo != NULL);
2480// log_it("Asking what_number_cd_is_this");
2481 if (g_ISO_restore_mode) {
2482 sprintf(tmp, "mount | grep iso9660 | awk '{print $3;}'");
2483// log_it("tmp = %s", tmp);
2484
2485 strcpy(mountdev, call_program_and_get_last_line_of_output(tmp));
2486 strcat(mountdev, "/archives/THIS-CD-NUMBER");
2487// log_it("mountdev = %s", mountdev);
2488 cd_number = atoi(last_line_of_file(mountdev));
2489// log_it("cd_number = %d", cd_number);
2490 paranoid_free(mountdev);
2491 paranoid_free(tmp);
2492 return (cd_number);
2493 }
2494
2495 strcpy(mountdev, bkpinfo->media_device);
2496 if (!mountdev[0]) {
2497 log_it
2498 ("(what_number_cd_is_this) Warning - media_device unknown. Finding out...");
2499 find_cdrom_device(bkpinfo->media_device, FALSE);
2500 }
2501 if (!is_this_device_mounted(MNT_CDROM)) {
2502 if (bkpinfo->backup_media_type == usb) {
2503 mount_USB_here(mountdev, MNT_CDROM);
2504 } else {
2505 mount_CDROM_here(mountdev, MNT_CDROM);
2506 }
2507 }
2508 cd_number =
2509 atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
2510// log_it("cd_number..later.. = %d", cd_number);
2511 paranoid_free(mountdev);
2512 paranoid_free(tmp);
2513 return (cd_number);
2514}
2515
2516
2517
2518
2519
2520
2521
2522/**
2523 * Find out what device is mounted as root (/).
2524 * @return Root device.
2525 * @note The returned string points to static storage and will be overwritten with every call.
2526 * @bug A bit of a misnomer; it's actually finding out the root device.
2527 * The mountpoint (where it's mounted) will obviously be '/'.
2528 */
2529char *where_is_root_mounted()
2530{
2531 /*@ buffers **************** */
2532 static char tmp[MAX_STR_LEN];
2533
2534
2535#ifdef __FreeBSD__
2536 strcpy(tmp, call_program_and_get_last_line_of_output
2537 ("mount | grep \" on / \" | cut -d' ' -f1"));
2538#else
2539 strcpy(tmp, call_program_and_get_last_line_of_output
2540 ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"));
2541 if (strstr(tmp, "/dev/cciss/")) {
2542 strcpy(tmp, call_program_and_get_last_line_of_output
2543 ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"));
2544 }
2545 if (strstr(tmp, "/dev/md")) {
2546 strcpy(tmp,
2547 call_program_and_get_last_line_of_output
2548 ("mount | grep \" on / \" | cut -d' ' -f1"));
2549 }
2550#endif
2551
2552 return (tmp);
2553}
2554
2555
2556/**
2557 * Find out which boot loader is in use.
2558 * @param which_device Device to look for the boot loader on.
2559 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
2560 * @note Under Linux, all drives are examined, not just @p which_device.
2561 */
2562#ifdef __FreeBSD__
2563char which_boot_loader(char *which_device)
2564{
2565 int count_lilos = 0;
2566 int count_grubs = 0;
2567 int count_boot0s = 0;
2568 int count_dangerouslydedicated = 0;
2569
2570 log_it("looking at drive %s's MBR", which_device);
2571 if (does_string_exist_in_boot_block(which_device, "GRUB")) {
2572 count_grubs++;
2573 }
2574 if (does_string_exist_in_boot_block(which_device, "LILO")) {
2575 count_lilos++;
2576 }
2577 if (does_string_exist_in_boot_block(which_device, "Drive")) {
2578 count_boot0s++;
2579 }
2580 if (does_string_exist_in_first_N_blocks
2581 (which_device, "FreeBSD/i386", 17)) {
2582 count_dangerouslydedicated++;
2583 }
2584 log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
2585 count_grubs, count_lilos, count_elilos, count_boot0s,
2586 count_dangerouslydedicated);
2587
2588 if (count_grubs && !count_lilos) {
2589 return ('G');
2590 } else if (count_lilos && !count_grubs) {
2591 return ('L');
2592 } else if (count_grubs == 1 && count_lilos == 1) {
2593 log_it("I'll bet you used to use LILO but switched to GRUB...");
2594 return ('G');
2595 } else if (count_boot0s == 1) {
2596 return ('B');
2597 } else if (count_dangerouslydedicated) {
2598 return ('D');
2599 } else {
2600 log_it("Unknown boot loader");
2601 return ('U');
2602 }
2603}
2604
2605#else
2606
2607char which_boot_loader(char *which_device)
2608{
2609 /*@ buffer ***************************************************** */
2610 char *list_drives_cmd;
2611 char *current_drive;
2612
2613 /*@ pointers *************************************************** */
2614 FILE *pdrives;
2615
2616 /*@ int ******************************************************** */
2617 int count_lilos = 0;
2618 int count_grubs = 0;
2619
2620 /*@ end vars *************************************************** */
2621
2622 malloc_string(list_drives_cmd);
2623 malloc_string(current_drive);
2624
2625#ifdef __IA64__
2626 /* No choice for it */
2627 return ('E');
2628#endif
2629 assert(which_device != NULL);
2630 // sprintf (list_drives_cmd,
2631 // "fdisk -l | grep /dev | grep cyl | tr ':' ' ' | cut -d' ' -f2");
2632
2633 sprintf(list_drives_cmd,
2634 "parted2fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s",
2635 where_is_root_mounted());
2636 log_it("list_drives_cmd = %s", list_drives_cmd);
2637
2638 if (!(pdrives = popen(list_drives_cmd, "r"))) {
2639 log_OS_error("Unable to open list of drives");
2640 paranoid_free(list_drives_cmd);
2641 paranoid_free(current_drive);
2642 return ('\0');
2643 }
2644 for (fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
2645 fgets(current_drive, MAX_STR_LEN, pdrives)) {
2646 strip_spaces(current_drive);
2647 log_it("looking at drive %s's MBR", current_drive);
2648 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
2649 count_grubs++;
2650 strcpy(which_device, current_drive);
2651 break;
2652 }
2653 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
2654 count_lilos++;
2655 strcpy(which_device, current_drive);
2656 break;
2657 }
2658 }
2659 if (pclose(pdrives)) {
2660 log_OS_error("Cannot pclose pdrives");
2661 }
2662 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
2663 if (count_grubs && !count_lilos) {
2664 return ('G');
2665 } else if (count_lilos && !count_grubs) {
2666 return ('L');
2667 } else if (count_grubs == 1 && count_lilos == 1) {
2668 log_it("I'll bet you used to use LILO but switched to GRUB...");
2669 return ('G');
2670 } else {
2671 // We need to look on each partition then
2672 sprintf(list_drives_cmd,
2673 "parted2fdisk -l 2>/dev/null | grep -E \"^/dev/\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/");
2674 log_it("list_drives_cmd = %s", list_drives_cmd);
2675
2676 if (!(pdrives = popen(list_drives_cmd, "r"))) {
2677 log_OS_error("Unable to open list of drives");
2678 paranoid_free(list_drives_cmd);
2679 paranoid_free(current_drive);
2680 return ('\0');
2681 }
2682 for (fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
2683 fgets(current_drive, MAX_STR_LEN, pdrives)) {
2684 strip_spaces(current_drive);
2685 log_it("looking at partition %s's BR", current_drive);
2686 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
2687 count_grubs++;
2688 strcpy(which_device, current_drive);
2689 break;
2690 }
2691 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
2692 count_lilos++;
2693 strcpy(which_device, current_drive);
2694 break;
2695 }
2696 }
2697 if (pclose(pdrives)) {
2698 log_OS_error("Cannot pclose pdrives");
2699 }
2700 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
2701 paranoid_free(list_drives_cmd);
2702 paranoid_free(current_drive);
2703 if (count_grubs && !count_lilos) {
2704 return ('G');
2705 } else if (count_lilos && !count_grubs) {
2706 return ('L');
2707 } else if (count_grubs == 1 && count_lilos == 1) {
2708 log_it("I'll bet you used to use LILO but switched to GRUB...");
2709 return ('G');
2710 } else {
2711 log_it("Unknown boot loader");
2712 return ('U');
2713 }
2714 }
2715}
2716#endif
2717
2718
2719
2720
2721/**
2722 * Write zeroes over the first 16K of @p device.
2723 * @param device The device to zero.
2724 * @return 0 for success, 1 for failure.
2725 */
2726int zero_out_a_device(char *device)
2727{
2728 FILE *fout;
2729 int i;
2730
2731 assert_string_is_neither_NULL_nor_zerolength(device);
2732
2733 log_it("Zeroing drive %s", device);
2734 if (!(fout = fopen(device, "w"))) {
2735 log_OS_error("Unable to open/write to device");
2736 return (1);
2737 }
2738 for (i = 0; i < 16384; i++) {
2739 fputc('\0', fout);
2740 }
2741 paranoid_fclose(fout);
2742 log_it("Device successfully zeroed.");
2743 return (0);
2744}
2745
2746/**
2747 * Return the device pointed to by @p incoming.
2748 * @param incoming The device to resolve symlinks for.
2749 * @return The path to the real device file.
2750 * @note The returned string points to static storage that will be overwritten with each call.
2751 * @bug Won't work with file v4.0; needs to be written in C.
2752 */
2753char *resolve_softlinks_to_get_to_actual_device_file(char *incoming)
2754{
2755 static char output[MAX_STR_LEN];
2756 char *command;
2757 char *curr_fname;
2758 char *scratch;
2759 char *tmp;
2760 char *p;
2761
2762 struct stat statbuf;
2763 command = malloc(1000);
2764 malloc_string(tmp);
2765 malloc_string(scratch);
2766 malloc_string(curr_fname);
2767 if (!does_file_exist(incoming)) {
2768 log_it
2769 ("resolve_softlinks_to_get_to_actual_device_file --- device not found");
2770 strcpy(output, incoming);
2771 } else {
2772 strcpy(curr_fname, incoming);
2773 lstat(curr_fname, &statbuf);
2774 while (S_ISLNK(statbuf.st_mode)) {
2775 log_msg(1, "curr_fname = %s", curr_fname);
2776 sprintf(command, "file %s", curr_fname);
2777 strcpy(tmp, call_program_and_get_last_line_of_output(command));
2778 for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' ';
2779 p--);
2780 p++;
2781 strcpy(scratch, p);
2782 for (p = scratch; *p != '\0' && *p != '\''; p++);
2783 *p = '\0';
2784 log_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp,
2785 scratch);
2786 if (scratch[0] == '/') {
2787 strcpy(curr_fname, scratch); // copy whole thing because it's an absolute softlink
2788 } else { // copy over the basename cos it's a relative softlink
2789 p = curr_fname + strlen(curr_fname);
2790 while (p != curr_fname && *p != '/') {
2791 p--;
2792 }
2793 if (*p == '/') {
2794 p++;
2795 }
2796 strcpy(p, scratch);
2797 }
2798 lstat(curr_fname, &statbuf);
2799 }
2800 strcpy(output, curr_fname);
2801 log_it("resolved %s to %s", incoming, output);
2802 }
2803 paranoid_free(command);
2804 paranoid_free(curr_fname);
2805 paranoid_free(tmp);
2806 return (output);
2807}
2808
2809/* @} - end of deviceGroup */
2810
2811
2812/**
2813 * Return the type of partition format (GPT or MBR)
2814 */
2815char *which_partition_format(const char *drive)
2816{
2817 static char output[4];
2818 char *tmp;
2819 char *command;
2820 char *fdisk;
2821#ifdef __IA64__
2822 struct stat buf;
2823#endif
2824 malloc_string(tmp);
2825 malloc_string(command);
2826 malloc_string(fdisk);
2827 log_msg(0, "Looking for partition table format type");
2828 sprintf(fdisk, "/sbin/parted2fdisk");
2829 log_msg(1, "Using %s", fdisk);
2830 sprintf(command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
2831 strcpy(tmp, call_program_and_get_last_line_of_output(command));
2832 if (strstr(tmp, "GPT") == NULL) {
2833 strcpy(output, "MBR");
2834 } else {
2835 strcpy(output, "GPT");
2836 }
2837 log_msg(0, "Found %s partition table format type", output);
2838 paranoid_free(command);
2839 paranoid_free(tmp);
2840 paranoid_free(fdisk);
2841 return (output);
2842}
2843
2844/* @} - end of deviceGroup */
Note: See TracBrowser for help on using the repository browser.