source: MondoRescue/trunk/mondo/mondo/common/libmondo-devices.c@ 147

Last change on this file since 147 was 147, checked in by bcornec, 18 years ago

Quality errors handled

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