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

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

Fix a linker error

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