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

Last change on this file since 1120 was 1120, checked in by Bruno Cornec, 17 years ago

fix linker errors
begining of rewrite for libmondo-devices.c

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