source: MondoRescue/branches/2.2.5/mondo/src/common/libmondo-devices.c@ 1687

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

First attempt to integrate USB support in mondoarchive (may not compile)

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