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

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

busybox under /usr/lib shouldn't be put on the boot disk as it breaks the /usr/lib* build. Use only the /bin/busybox bin.

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