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

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

Fix a bug where df was using locale to print messages and wasn't filtered correctly
Improve setup of tmpdir again

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