source: MondoRescue/branches/stable/mondo/src/common/libmondo-devices.c@ 1663

Last change on this file since 1663 was 1663, checked in by Bruno Cornec, 17 years ago
  • Fix bug #197 (based on an initial patch of Scott Cummings)
  • Fix a bug where df was using locale to print messages and wasn't filtered correctly
  • mkdtemp checked in configure
  • reset_bkpinfo called as early as possible by both main program.
  • It creates a tmpdir cleanly with mkdtemp in setup_tmpdir subfunction, which takes in account TMPIR and TMP env var. Remains to see what tmpfs does and tests
  • configure.in should also be filtered.
  • Remove g_bkpinfo_DONTUSETHIS
  • remove bkpinfo also from header files
  • Render bkpinfo global (potential issue on thread, but should not be a problem as that structure is indeed static during archive)
  • Apply patch from Andree Leidenfrost, modified a bit to use bkpinfo->tmpdir instead of /tmp or MINDI_CACHE when appropriate. Fix security issues in mondo. Thanks al ot Andree for catching all those issues.
  • /tmp => /var/log for mondorestore.log in mindi
  • Update linux terminfo to fix a color issue (Andree Leidenfrost)
  • Removes useless log file (Andree Leidenfrost)
  • replace vi with find_my_editor during restore (Andree Leidenfrost)
  • sync in bg in mindi (VMWare issue to look at)
  • mindi/mindi-busybox have a different version than mondo for pb
  • PB-SUF also added to spec file
  • Fix a bug for pb build (omission of PB-SUF declaration)

(merge -r1631:1662 $SVN_M/branches/2.2.5)

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