source: MondoRescue/branches/2.2.6/mondo/src/common/libmondo-devices.c@ 1972

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

Exclude gfs type of FS from backup (should solve #135)

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