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

Last change on this file since 75 was 75, checked in by andree, 19 years ago

Various changes to get archiving to NFS work in interactive mode. It
wasn't really like were were bugs, it appeared more like it was simply
not finished.

Side note: I believe that bkpinfo->isodir and bkpinfo->prefix were the
wrong way round in libmondo-archive.c and I've swapped them.

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