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

Last change on this file since 89 was 89, checked in by bcornec, 18 years ago

merge r87:88 of the 2.04_berlios branch
indent some files

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