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

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

log_msg => mr_msg for common files

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