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

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

merge -r193:196 $SVN_M/branches/2.05

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