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

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

Handle part of #250

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