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

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

memory management going on (libmondo-verify.c, libmondo-devices.c, libmondo-string.c, libmondo-stream.c)

  • 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 122 2005-11-14 23:01:12Z 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 122 2005-11-14 23:01:12Z 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 assert(bkpinfo != NULL);
1832 sz_size[0] = '\0';
1833 bkpinfo->nonbootable_backup = FALSE;
1834
1835// Tape, CD, NFS, ...?
1836 srandom(getpid());
1837 bkpinfo->backup_media_type =
1838 (g_restoring_live_from_cd) ? cdr :
1839 which_backup_media_type(bkpinfo->restore_data);
1840 if (bkpinfo->backup_media_type == none) {
1841 log_to_screen("User has chosen not to backup the PC");
1842 finish(1);
1843 }
1844 if (bkpinfo->backup_media_type == tape && bkpinfo->restore_data) {
1845 popup_and_OK("Please remove CD/floppy from drive(s)");
1846 }
1847 log_msg(3, "media type = %s",
1848 bkptype_to_string(bkpinfo->backup_media_type));
1849 if (archiving_to_media) {
1850 sensibly_set_tmpdir_and_scratchdir(bkpinfo);
1851 }
1852 bkpinfo->cdrw_speed = (bkpinfo->backup_media_type == cdstream) ? 2 : 4;
1853 bkpinfo->compression_level =
1854 (bkpinfo->backup_media_type == cdstream) ? 1 : 5;
1855 bkpinfo->use_lzo =
1856 (bkpinfo->backup_media_type == cdstream) ? TRUE : FALSE;
1857
1858/*
1859 if (find_home_of_exe("star") && (!find_home_of_exe("afio") || find_home_of_exe("selinuxenabled")))
1860 {
1861 bkpinfo->use_star = FALSE;
1862 bkpinfo->use_lzo = FALSE;
1863 log_to_screen("Using star, not afio");
1864 if (!find_home_of_exe("afio"))
1865 { log_to_screen("...because afio not found"); }
1866 if (find_home_of_exe("selinuxenabled"))
1867 { log_to_screen("...because SELINUX found"); }
1868 }
1869*/
1870
1871 mvaddstr_and_log_it(2, 0, " ");
1872
1873// Find device's /dev (or SCSI) entry
1874 switch (bkpinfo->backup_media_type) {
1875 case cdr:
1876 case cdrw:
1877 case dvd:
1878 if (archiving_to_media) {
1879 if (ask_me_yes_or_no
1880 ("Is your computer a laptop, or does the CD writer incorporate BurnProof technology?"))
1881 {
1882 bkpinfo->manual_cd_tray = TRUE;
1883 }
1884 if ((bkpinfo->compression_level =
1885 which_compression_level()) == -1) {
1886 log_to_screen("User has chosen not to backup the PC");
1887 finish(1);
1888 }
1889 sprintf(comment, "What speed is your %s (re)writer?",
1890 media_descriptor_string(bkpinfo->backup_media_type));
1891 if (bkpinfo->backup_media_type == dvd) {
1892 find_dvd_device(bkpinfo->media_device, FALSE);
1893 strcpy(tmp, "1");
1894 sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4582 MB
1895 log_msg(1, "Setting to DVD defaults");
1896 } else {
1897 strcpy(bkpinfo->media_device, VANILLA_SCSI_CDROM);
1898 strcpy(tmp, "4");
1899 strcpy(sz_size, "650");
1900 log_msg(1, "Setting to CD defaults");
1901 }
1902 if (bkpinfo->backup_media_type != dvd) {
1903 if (!popup_and_get_string("Speed", comment, tmp, 4)) {
1904 log_to_screen("User has chosen not to backup the PC");
1905 finish(1);
1906 }
1907 }
1908 bkpinfo->cdrw_speed = atoi(tmp); // if DVD then this shouldn't ever be used anyway :)
1909 sprintf(comment,
1910 "How much data (in Megabytes) will each %s store?",
1911 media_descriptor_string(bkpinfo->backup_media_type));
1912 if (!popup_and_get_string("Size", comment, sz_size, 5)) {
1913 log_to_screen("User has chosen not to backup the PC");
1914 finish(1);
1915 }
1916 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1917 bkpinfo->media_size[i] = atoi(sz_size);
1918 }
1919 if (bkpinfo->media_size[0] <= 0) {
1920 log_to_screen("User has chosen not to backup the PC");
1921 finish(1);
1922 }
1923 }
1924 case cdstream:
1925 if (bkpinfo->disaster_recovery) {
1926 strcpy(bkpinfo->media_device, "/dev/cdrom");
1927 log_msg(2, "CD-ROM device assumed to be at %s",
1928 bkpinfo->media_device);
1929 } else if (bkpinfo->restore_data
1930 || bkpinfo->backup_media_type == dvd) {
1931 if (!bkpinfo->media_device[0]) {
1932 strcpy(bkpinfo->media_device, "/dev/cdrom");
1933 } // just for the heck of it :)
1934 log_msg(1, "bkpinfo->media_device = %s",
1935 bkpinfo->media_device);
1936 if (bkpinfo->backup_media_type == dvd
1937 || find_cdrom_device(bkpinfo->media_device, FALSE)) {
1938 log_msg(1, "bkpinfo->media_device = %s",
1939 bkpinfo->media_device);
1940 sprintf(comment,
1941 "Please specify your %s drive's /dev entry",
1942 media_descriptor_string(bkpinfo->
1943 backup_media_type));
1944 if (!popup_and_get_string
1945 ("Device?", comment, bkpinfo->media_device,
1946 MAX_STR_LEN / 4)) {
1947 log_to_screen("User has chosen not to backup the PC");
1948 finish(1);
1949 }
1950 }
1951 log_msg(2, "%s device found at %s",
1952 media_descriptor_string(bkpinfo->backup_media_type),
1953 bkpinfo->media_device);
1954 } else {
1955 if (find_cdrw_device(bkpinfo->media_device)) {
1956 bkpinfo->media_device[0] = '\0';
1957 }
1958 if (bkpinfo->media_device[0]) {
1959 sprintf(tmp,
1960 "I think I've found your %s burner at SCSI node %s; am I right on the money?",
1961 media_descriptor_string(bkpinfo->
1962 backup_media_type),
1963 bkpinfo->media_device);
1964 if (!ask_me_yes_or_no(tmp)) {
1965 bkpinfo->media_device[0] = '\0';
1966 }
1967 }
1968 if (!bkpinfo->media_device[0]) {
1969 if (g_kernel_version < 2.6) {
1970 i = popup_and_get_string("Device node?",
1971 "What is the SCSI node of your CD (re)writer, please?",
1972 bkpinfo->media_device,
1973 MAX_STR_LEN / 4);
1974 } else {
1975 i = popup_and_get_string("/dev entry?",
1976 "What is the /dev entry of your CD (re)writer, please?",
1977 bkpinfo->media_device,
1978 MAX_STR_LEN / 4);
1979 }
1980 if (!i) {
1981 log_to_screen("User has chosen not to backup the PC");
1982 finish(1);
1983 }
1984 }
1985 }
1986 if (bkpinfo->backup_media_type == cdstream) {
1987 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
1988 bkpinfo->media_size[i] = 650;
1989 }
1990 }
1991 break;
1992 case udev:
1993 if (!ask_me_yes_or_no
1994 ("This option is for advanced users only. Are you sure?")) {
1995 log_to_screen("User has chosen not to backup the PC");
1996 finish(1);
1997 }
1998 case tape:
1999
2000 if (find_tape_device_and_size(bkpinfo->media_device, sz_size)) {
2001 log_msg(3, "Ok, using vanilla scsi tape.");
2002 strcpy(bkpinfo->media_device, VANILLA_SCSI_TAPE);
2003 if ((fin = fopen(bkpinfo->media_device, "r"))) {
2004 paranoid_fclose(fin);
2005 } else {
2006 strcpy(bkpinfo->media_device, "/dev/osst0");
2007 }
2008 }
2009 if (bkpinfo->media_device[0]) {
2010 if ((fin = fopen(bkpinfo->media_device, "r"))) {
2011 paranoid_fclose(fin);
2012 } else {
2013 if (does_file_exist("/tmp/mondo-restore.cfg")) {
2014 read_cfg_var("/tmp/mondo-restore.cfg", "media-dev",
2015 bkpinfo->media_device);
2016 }
2017 }
2018 sprintf(tmp,
2019 "I think I've found your tape streamer at %s; am I right on the money?",
2020 bkpinfo->media_device);
2021 }
2022 if (bkpinfo->media_device[0]) {
2023 sprintf(tmp,
2024 "I think I've found your tape streamer at %s; am I right on the money?",
2025 bkpinfo->media_device);
2026 if (!ask_me_yes_or_no(tmp)) {
2027 bkpinfo->media_device[0] = '\0';
2028 }
2029 }
2030 if (!bkpinfo->media_device[0]) {
2031 if (!popup_and_get_string
2032 ("Device name?",
2033 "What is the /dev entry of your tape streamer?",
2034 bkpinfo->media_device, MAX_STR_LEN / 4)) {
2035 log_to_screen("User has chosen not to backup the PC");
2036 finish(1);
2037 }
2038 }
2039 sprintf(tmp, "ls -l %s", bkpinfo->media_device);
2040 if (run_program_and_log_output(tmp, FALSE)) {
2041 log_to_screen("User has not specified a valid /dev entry");
2042 finish(1);
2043 }
2044 log_msg(4, "sz_size = %s", sz_size);
2045 sz_size[0] = '\0';
2046/*
2047 if ((size_sz[0]=='\0' || atol(size_sz)==0) && archiving_to_media)
2048 {
2049 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))
2050 { log_to_screen("User has chosen not to backup the PC"); finish(1); }
2051 }
2052*/
2053 if (sz_size[0] == '\0') {
2054 bkpinfo->media_size[0] = 0;
2055 } else {
2056 bkpinfo->media_size[0] =
2057 friendly_sizestr_to_sizelong(sz_size) / 2 - 50;
2058 }
2059 log_msg(4, "media_size[0] = %ld", bkpinfo->media_size[0]);
2060 if (bkpinfo->media_size[0] <= 0) {
2061 bkpinfo->media_size[0] = 0;
2062 }
2063 for (i = 1; i <= MAX_NOOF_MEDIA; i++) {
2064 bkpinfo->media_size[i] = bkpinfo->media_size[0];
2065 }
2066 if (archiving_to_media) {
2067 if ((bkpinfo->compression_level =
2068 which_compression_level()) == -1) {
2069 log_to_screen("User has chosen not to backup the PC");
2070 finish(1);
2071 }
2072 }
2073 break;
2074
2075
2076
2077 case nfs:
2078 if (!bkpinfo->nfs_mount[0]) {
2079 strcpy(bkpinfo->nfs_mount,
2080 call_program_and_get_last_line_of_output
2081 ("mount | grep \":\" | cut -d' ' -f1 | head -n1"));
2082 }
2083#ifdef __FreeBSD__
2084 if (TRUE)
2085#else
2086 if (!bkpinfo->disaster_recovery)
2087#endif
2088 {
2089 if (!popup_and_get_string
2090 ("NFS dir.",
2091 "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.)",
2092 bkpinfo->nfs_mount, MAX_STR_LEN / 4)) {
2093 log_to_screen("User has chosen not to backup the PC");
2094 finish(1);
2095 }
2096 if (!bkpinfo->restore_data) {
2097 if ((bkpinfo->compression_level =
2098 which_compression_level()) == -1) {
2099 log_to_screen("User has chosen not to backup the PC");
2100 finish(1);
2101 }
2102 }
2103 // check whether already mounted - we better remove
2104 // surrounding spaces and trailing '/' for this
2105 strip_spaces(bkpinfo->nfs_mount);
2106 if (bkpinfo->nfs_mount[strlen(bkpinfo->nfs_mount) - 1] == '/')
2107 bkpinfo->nfs_mount[strlen(bkpinfo->nfs_mount) - 1] = '\0';
2108 sprintf(command, "mount | grep \"%s \" | cut -d' ' -f3",
2109 bkpinfo->nfs_mount);
2110 strcpy(bkpinfo->isodir,
2111 call_program_and_get_last_line_of_output(command));
2112 }
2113 if (bkpinfo->disaster_recovery) {
2114 system("umount /tmp/isodir 2> /dev/null");
2115 if (!popup_and_get_string
2116 ("NFS share", "Which remote NFS share should I mount?",
2117 bkpinfo->nfs_mount, MAX_STR_LEN)) {
2118 log_to_screen("User has chosen not to backup the PC");
2119 finish(1);
2120 }
2121 }
2122 if (!is_this_device_mounted(bkpinfo->nfs_mount)) {
2123 sprintf(bkpinfo->isodir, "/tmp/isodir.mondo.%d",
2124 (int) (random() % 32768));
2125 sprintf(command, "mkdir -p %s", bkpinfo->isodir);
2126 run_program_and_log_output(command, 5);
2127 sprintf(tmp, "mount %s -t nfs %s", bkpinfo->nfs_mount,
2128 bkpinfo->isodir);
2129 run_program_and_log_output(tmp, 5);
2130 malloc_string(g_selfmounted_isodir);
2131 strcpy(g_selfmounted_isodir, bkpinfo->isodir);
2132 }
2133 if (!is_this_device_mounted(bkpinfo->nfs_mount)) {
2134 popup_and_OK
2135 ("Please mount that partition before you try to backup to or restore from it.");
2136 finish(1);
2137 }
2138 strcpy(tmp, bkpinfo->nfs_remote_dir);
2139 if (!popup_and_get_string
2140 ("Directory", "Which directory within that mountpoint?", tmp,
2141 MAX_STR_LEN)) {
2142 log_to_screen("User has chosen not to backup the PC");
2143 finish(1);
2144 }
2145 strcpy(bkpinfo->nfs_remote_dir, tmp);
2146 // check whether writable - we better remove surrounding spaces for this
2147 strip_spaces(bkpinfo->nfs_remote_dir);
2148 sprintf(command, "echo hi > %s/%s/.dummy.txt", bkpinfo->isodir,
2149 bkpinfo->nfs_remote_dir);
2150 while (run_program_and_log_output(command, FALSE)) {
2151 strcpy(tmp, bkpinfo->nfs_remote_dir);
2152 asprintf(&prompt,
2153 "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.",
2154 bkpinfo->nfs_remote_dir, bkpinfo->isodir);
2155 if (!popup_and_get_string
2156 ("Directory", prompt, tmp, MAX_STR_LEN)) {
2157 log_to_screen("User has chosen not to backup the PC");
2158 finish(1);
2159 }
2160 strcpy(bkpinfo->nfs_remote_dir, tmp);
2161 // check whether writable - we better remove surrounding spaces for this */
2162 strip_spaces(bkpinfo->nfs_remote_dir);
2163 asprintf(&command, "echo hi > %s/%s/.dummy.txt",
2164 bkpinfo->isodir, bkpinfo->nfs_remote_dir);
2165 }
2166 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2167 bkpinfo->media_size[i] = 650;
2168 }
2169 log_msg(3, "Just set nfs_remote_dir to %s",
2170 bkpinfo->nfs_remote_dir);
2171 log_msg(3, "isodir is still %s", bkpinfo->isodir);
2172 break;
2173
2174 case iso:
2175 if (!bkpinfo->disaster_recovery) {
2176 if (!popup_and_get_string
2177 ("Storage dir.",
2178 "Please enter the full path that contains your ISO images. Example: /mnt/raid0_0",
2179 bkpinfo->isodir, MAX_STR_LEN / 4)) {
2180 log_to_screen("User has chosen not to backup the PC");
2181 finish(1);
2182 }
2183 if (archiving_to_media) {
2184 if ((bkpinfo->compression_level =
2185 which_compression_level()) == -1) {
2186 log_to_screen("User has chosen not to backup the PC");
2187 finish(1);
2188 }
2189 if (!popup_and_get_string
2190 ("ISO size.",
2191 "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.",
2192 sz_size, 16)) {
2193 log_to_screen("User has chosen not to backup the PC");
2194 finish(1);
2195 }
2196 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2197 bkpinfo->media_size[i] = atoi(sz_size);
2198 }
2199 if (!popup_and_get_string
2200 ("Prefix.",
2201 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files",
2202 bkpinfo->prefix, MAX_STR_LEN / 4)) {
2203 log_to_screen("User has chosen not to backup the PC");
2204 finish(1);
2205 }
2206 } else {
2207 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2208 bkpinfo->media_size[i] = 650;
2209 }
2210 }
2211 }
2212 break;
2213 default:
2214 fatal_error
2215 ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
2216 }
2217 if (archiving_to_media) {
2218
2219#ifdef __FreeBSD__
2220 strcpy(bkpinfo->boot_device,
2221 call_program_and_get_last_line_of_output
2222 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
2223#else
2224 strcpy(bkpinfo->boot_device,
2225 call_program_and_get_last_line_of_output
2226 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
2227#endif
2228 i = which_boot_loader(bkpinfo->boot_device);
2229 if (i == 'U') // unknown
2230 {
2231
2232#ifdef __FreeBSD__
2233 if (!popup_and_get_string
2234 ("Boot device",
2235 "What is your boot device? (e.g. /dev/ad0)",
2236 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2237 log_to_screen("User has chosen not to backup the PC");
2238 finish(1);
2239 }
2240 i = which_boot_loader(bkpinfo->boot_device);
2241#else
2242 if (!popup_and_get_string
2243 ("Boot device",
2244 "What is your boot device? (e.g. /dev/hda)",
2245 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2246 log_to_screen("User has chosen not to backup the PC");
2247 finish(1);
2248 }
2249 if (does_string_exist_in_boot_block
2250 (bkpinfo->boot_device, "LILO")) {
2251 i = 'L';
2252 } else
2253 if (does_string_exist_in_boot_block
2254 (bkpinfo->boot_device, "ELILO")) {
2255 i = 'E';
2256 } else
2257 if (does_string_exist_in_boot_block
2258 (bkpinfo->boot_device, "GRUB")) {
2259 i = 'G';
2260 } else {
2261 i = 'U';
2262 }
2263#endif
2264 if (i == 'U') {
2265 if (ask_me_yes_or_no
2266 ("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?"))
2267 {
2268 i = 'R'; // raw
2269 } else {
2270 log_to_screen
2271 ("I cannot find your boot loader. Please run mondoarchive with parameters.");
2272 finish(1);
2273 }
2274 }
2275 }
2276 bkpinfo->boot_loader = i;
2277 strcpy(bkpinfo->include_paths, "/");
2278 if (!popup_and_get_string
2279 ("Backup paths",
2280 "Please enter paths which you want me to backup. The default is '/' (i.e. everything).",
2281 bkpinfo->include_paths, MAX_STR_LEN)) {
2282 log_to_screen("User has chosen not to backup the PC");
2283 finish(1);
2284 }
2285 strcpy(tmp, list_of_NFS_mounts_only());
2286 if (strlen(tmp) > 2) {
2287 if (bkpinfo->exclude_paths[0]) {
2288 strcat(bkpinfo->exclude_paths, " ");
2289 }
2290 strncpy(bkpinfo->exclude_paths, tmp, MAX_STR_LEN);
2291 }
2292// NTFS
2293 strcpy(tmp,
2294 call_program_and_get_last_line_of_output
2295 ("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'"));
2296 if (strlen(tmp) > 2) {
2297 if (!popup_and_get_string
2298 ("NTFS partitions",
2299 "Please enter/confirm the NTFS partitions you wish to backup as well.",
2300 tmp, MAX_STR_LEN / 4)) {
2301 log_to_screen("User has chosen not to backup the PC");
2302 finish(1);
2303 }
2304 strncpy(bkpinfo->image_devs, tmp, MAX_STR_LEN / 4);
2305 }
2306
2307
2308 if (!popup_and_get_string
2309 ("Exclude paths",
2310 "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.",
2311 bkpinfo->exclude_paths, MAX_STR_LEN)) {
2312 log_to_screen("User has chosen not to backup the PC");
2313 finish(1);
2314 }
2315 bkpinfo->make_cd_use_lilo = FALSE;
2316 bkpinfo->backup_data = TRUE;
2317 bkpinfo->verify_data =
2318 ask_me_yes_or_no
2319 ("Will you want to verify your backups after Mondo has created them?");
2320
2321#ifndef __FreeBSD__
2322 if (!ask_me_yes_or_no
2323 ("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."))
2324#endif
2325 {
2326 strcpy(bkpinfo->kernel_path, "FAILSAFE");
2327 }
2328
2329 if (!ask_me_yes_or_no
2330 ("Are you sure you want to proceed? Hit 'no' to abort.")) {
2331 log_to_screen("User has chosen not to backup the PC");
2332 finish(1);
2333 }
2334 } else {
2335 bkpinfo->restore_data = TRUE; // probably...
2336 }
2337
2338 if (bkpinfo->backup_media_type == iso
2339 || bkpinfo->backup_media_type == nfs) {
2340 g_ISO_restore_mode = TRUE;
2341 }
2342#ifdef __FreeSD__
2343// skip
2344#else
2345 if (bkpinfo->backup_media_type == nfs) {
2346 sprintf(tmp, "mount | grep \"%s\" | cut -d' ' -f3",
2347 bkpinfo->nfs_mount);
2348// strcpy(bkpinfo->isodir, call_program_and_get_last_line_of_output(tmp));
2349 log_msg(3, "I think the NFS mount is mounted at %s",
2350 bkpinfo->isodir);
2351 }
2352 log_it("isodir = %s", bkpinfo->isodir);
2353 log_it("nfs_mount = '%s'", bkpinfo->nfs_mount);
2354#endif
2355
2356 log_it("media device = %s", bkpinfo->media_device);
2357 log_it("media size = %ld", bkpinfo->media_size[1]);
2358 log_it("media type = %s",
2359 bkptype_to_string(bkpinfo->backup_media_type));
2360 log_it("compression = %ld", bkpinfo->compression_level);
2361 log_it("include_paths = '%s'", bkpinfo->include_paths);
2362 log_it("exclude_paths = '%s'", bkpinfo->exclude_paths);
2363 log_it("scratchdir = '%s'", bkpinfo->scratchdir);
2364 log_it("tmpdir = '%s'", bkpinfo->tmpdir);
2365 log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device,
2366 bkpinfo->boot_loader);
2367 log_it("prefix = %s", bkpinfo->prefix);
2368 if (bkpinfo->media_size[0] < 0) {
2369 if (archiving_to_media) {
2370 fatal_error("Media size is less than zero.");
2371 } else {
2372 log_msg(2, "Warning - media size is less than zero.");
2373 bkpinfo->media_size[0] = 0;
2374 }
2375 }
2376 paranoid_free(tmp);
2377 paranoid_free(sz_size);
2378 paranoid_free(command);
2379 paranoid_free(comment);
2380 paranoid_free(prompt);
2381 return (0);
2382}
2383
2384
2385
2386
2387/**
2388 * @addtogroup utilityGroup
2389 * @{
2390 */
2391/**
2392 * Get a space-separated list of NFS devices and mounts.
2393 * @return The list created.
2394 * @note The return value points to static data that will be overwritten with each call.
2395 */
2396char *list_of_NFS_devices_and_mounts(void)
2397{
2398 char *exclude_these_devices;
2399 char *exclude_these_directories;
2400 static char result_sz[512];
2401
2402 malloc_string(exclude_these_devices);
2403 malloc_string(exclude_these_directories);
2404 strcpy(exclude_these_directories,
2405 call_program_and_get_last_line_of_output
2406 ("mount -t coda,ncpfs,nfs,smbfs | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' ' ' | awk '{print $0;}'"));
2407 strcpy(exclude_these_devices,
2408 call_program_and_get_last_line_of_output
2409 ("cat /etc/fstab | tr -s '\t' ' ' | grep -E '( (coda|ncpfs|nfs|smbfs) )' | cut -d' ' -f1 | tr -s '\n' ' ' | awk '{print $0;}'"));
2410 sprintf(result_sz, "%s %s", exclude_these_directories,
2411 exclude_these_devices);
2412 paranoid_free(exclude_these_devices);
2413 paranoid_free(exclude_these_directories);
2414 return (result_sz);
2415}
2416
2417
2418
2419
2420/**
2421 * Get a space-separated list of NFS mounts.
2422 * @return The list created.
2423 * @note The return value points to static data that will be overwritten with each call.
2424 * @bug Even though we only want the mounts, the devices are still checked.
2425 */
2426char *list_of_NFS_mounts_only(void)
2427{
2428 char *exclude_these_devices;
2429 char *exclude_these_directories;
2430 static char result_sz[512];
2431
2432 malloc_string(exclude_these_devices);
2433 malloc_string(exclude_these_directories);
2434 strcpy(exclude_these_directories,
2435 call_program_and_get_last_line_of_output
2436 ("mount -t coda,ncpfs,nfs,smbfs | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' ' ' | awk '{print $0;}'"));
2437 strcpy(exclude_these_devices,
2438 call_program_and_get_last_line_of_output
2439 ("cat /etc/fstab | tr -s '\t' ' ' | grep -E '( (coda|ncpfs|nfs|smbfs) )' | cut -d' ' -f1 | tr -s '\n' ' ' | awk '{print $0;}'"));
2440 sprintf(result_sz, "%s", exclude_these_directories);
2441 paranoid_free(exclude_these_devices);
2442 paranoid_free(exclude_these_directories);
2443 return (result_sz);
2444}
2445
2446/* @} - end of utilityGroup */
2447
2448
2449
2450
2451
2452/**
2453 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
2454 * [random] is a random number between 1 and 32767.
2455 * @param store_name_here Where to store the new filename.
2456 * @param stub A random number will be appended to this to make the FIFO's name.
2457 * @ingroup deviceGroup
2458 */
2459void make_fifo(char *store_name_here, char *stub)
2460{
2461 char *tmp;
2462
2463 malloc_string(tmp);
2464 assert_string_is_neither_NULL_nor_zerolength(stub);
2465
2466 sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
2467 (int) (random() % 32768));
2468 make_hole_for_file(store_name_here);
2469 mkfifo(store_name_here, S_IRWXU | S_IRWXG);
2470 sprintf(tmp, "chmod 770 %s", store_name_here);
2471 paranoid_system(tmp);
2472 paranoid_free(tmp);
2473}
2474
2475
2476
2477
2478
2479
2480/**
2481 * Set the tmpdir and scratchdir to reside on the partition with the most free space.
2482 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
2483 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set.
2484 * @ingroup utilityGroup
2485 */
2486void sensibly_set_tmpdir_and_scratchdir(struct s_bkpinfo *bkpinfo)
2487{
2488 char *tmp, *command, *sz;
2489
2490 malloc_string(tmp);
2491 malloc_string(command);
2492 malloc_string(sz);
2493 assert(bkpinfo != NULL);
2494
2495#ifdef __FreeBSD__
2496 strcpy(tmp,
2497 call_program_and_get_last_line_of_output
2498 ("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;}'"));
2499#else
2500 strcpy(tmp,
2501 call_program_and_get_last_line_of_output
2502 ("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;}'"));
2503#endif
2504
2505 if (tmp[0] != '/') {
2506 strcpy(sz, tmp);
2507 strcpy(tmp, "/");
2508 strcat(tmp, sz);
2509 }
2510 if (!tmp[0]) {
2511 fatal_error("I couldn't figure out the tempdir!");
2512 }
2513 sprintf(bkpinfo->tmpdir, "%s/tmp.mondo.%d", tmp,
2514 (int) (random() % 32768));
2515 log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir);
2516
2517 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%d", tmp,
2518 (int) (random() % 32768));
2519 log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
2520
2521 sprintf(g_erase_tmpdir_and_scratchdir, "rm -Rf %s %s", bkpinfo->tmpdir,
2522 bkpinfo->scratchdir);
2523
2524 sprintf(command, "rm -Rf %s/tmp.mondo.* %s/mondo.scratch.*", tmp, tmp);
2525 paranoid_system(command);
2526 paranoid_free(tmp);
2527 paranoid_free(command);
2528 paranoid_free(sz);
2529}
2530
2531
2532
2533
2534
2535
2536/**
2537 * @addtogroup deviceGroup
2538 * @{
2539 */
2540/**
2541 * If we can read @p dev, set @p output to it.
2542 * If @p dev cannot be read, set @p output to "".
2543 * @param dev The device to check for.
2544 * @param output Set to @p dev if @p dev exists, "" otherwise.
2545 * @return TRUE if @p dev exists, FALSE if it doesn't.
2546 */
2547bool set_dev_to_this_if_rx_OK(char *output, char *dev)
2548{
2549 char *command;
2550
2551 malloc_string(command);
2552 if (!dev || dev[0] == '\0') {
2553 output[0] = '\0';
2554 return (FALSE);
2555 }
2556// assert_string_is_neither_NULL_nor_zerolength(dev);
2557 log_msg(10, "Injecting %s", dev);
2558 inject_device(dev);
2559 if (!does_file_exist(dev)) {
2560 log_msg(10, "%s doesn't exist. Returning FALSE.", dev);
2561 return (FALSE);
2562 }
2563 sprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null",
2564 512L, dev);
2565 if (!run_program_and_log_output(command, FALSE)
2566 && !run_program_and_log_output(command, FALSE)) {
2567 strcpy(output, dev);
2568 log_msg(4, "Found it - %s", dev);
2569 return (TRUE);
2570 } else {
2571 output[0] = '\0';
2572 log_msg(4, "It's not %s", dev);
2573 return (FALSE);
2574 }
2575}
2576
2577
2578
2579
2580
2581/**
2582 * Find out what number CD is in the drive.
2583 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
2584 * @return The current CD number, or -1 if it could not be found.
2585 * @note If the CD is not mounted, it will be mounted
2586 * (and remain mounted after this function returns).
2587 */
2588int what_number_cd_is_this(struct s_bkpinfo *bkpinfo)
2589{
2590 int cd_number = -1;
2591 char *mountdev;
2592 char *tmp;
2593
2594 malloc_string(mountdev);
2595 malloc_string(tmp);
2596 assert(bkpinfo != NULL);
2597// log_it("Asking what_number_cd_is_this");
2598 if (g_ISO_restore_mode) {
2599 sprintf(tmp, "mount | grep iso9660 | awk '{print $3;}'");
2600// log_it("tmp = %s", tmp);
2601
2602 strcpy(mountdev, call_program_and_get_last_line_of_output(tmp));
2603 strcat(mountdev, "/archives/THIS-CD-NUMBER");
2604// log_it("mountdev = %s", mountdev);
2605 cd_number = atoi(last_line_of_file(mountdev));
2606// log_it("cd_number = %d", cd_number);
2607 paranoid_free(mountdev);
2608 paranoid_free(tmp);
2609 return (cd_number);
2610 }
2611
2612 strcpy(mountdev, bkpinfo->media_device);
2613 if (!mountdev[0]) {
2614 log_it
2615 ("(what_number_cd_is_this) Warning - media_device unknown. Finding out...");
2616 find_cdrom_device(bkpinfo->media_device, FALSE);
2617 }
2618 if (!is_this_device_mounted(MNT_CDROM)) {
2619 mount_CDROM_here(mountdev, MNT_CDROM);
2620 }
2621 cd_number =
2622 atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
2623// log_it("cd_number..later.. = %d", cd_number);
2624 paranoid_free(mountdev);
2625 paranoid_free(tmp);
2626 return (cd_number);
2627}
2628
2629
2630
2631
2632
2633
2634
2635/**
2636 * Find out what device is mounted as root (/).
2637 * @return Root device.
2638 * @note The returned string points to static storage and will be overwritten with every call.
2639 * @bug A bit of a misnomer; it's actually finding out the root device.
2640 * The mountpoint (where it's mounted) will obviously be '/'.
2641 */
2642char *where_is_root_mounted()
2643{
2644 /*@ buffers **************** */
2645 static char tmp[MAX_STR_LEN];
2646
2647
2648#ifdef __FreeBSD__
2649 strcpy(tmp, call_program_and_get_last_line_of_output
2650 ("mount | grep \" on / \" | cut -d' ' -f1"));
2651#else
2652 strcpy(tmp, call_program_and_get_last_line_of_output
2653 ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"));
2654 if (strstr(tmp, "/dev/cciss/")) {
2655 strcpy(tmp, call_program_and_get_last_line_of_output
2656 ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"));
2657 }
2658 if (strstr(tmp, "/dev/md")) {
2659 strcpy(tmp,
2660 call_program_and_get_last_line_of_output
2661 ("mount | grep \" on / \" | cut -d' ' -f1"));
2662 }
2663#endif
2664
2665 return (tmp);
2666}
2667
2668
2669/**
2670 * Find out which boot loader is in use.
2671 * @param which_device Device to look for the boot loader on.
2672 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
2673 * @note Under Linux, all drives are examined, not just @p which_device.
2674 */
2675#ifdef __FreeBSD__
2676char which_boot_loader(char *which_device)
2677{
2678 int count_lilos = 0;
2679 int count_grubs = 0;
2680 int count_boot0s = 0;
2681 int count_dangerouslydedicated = 0;
2682
2683 log_it("looking at drive %s's MBR", which_device);
2684 if (does_string_exist_in_boot_block(which_device, "GRUB")) {
2685 count_grubs++;
2686 }
2687 if (does_string_exist_in_boot_block(which_device, "LILO")) {
2688 count_lilos++;
2689 }
2690 if (does_string_exist_in_boot_block(which_device, "Drive")) {
2691 count_boot0s++;
2692 }
2693 if (does_string_exist_in_first_N_blocks
2694 (which_device, "FreeBSD/i386", 17)) {
2695 count_dangerouslydedicated++;
2696 }
2697 log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
2698 count_grubs, count_lilos, count_elilos, count_boot0s,
2699 count_dangerouslydedicated);
2700
2701 if (count_grubs && !count_lilos) {
2702 return ('G');
2703 } else if (count_lilos && !count_grubs) {
2704 return ('L');
2705 } else if (count_grubs == 1 && count_lilos == 1) {
2706 log_it("I'll bet you used to use LILO but switched to GRUB...");
2707 return ('G');
2708 } else if (count_boot0s == 1) {
2709 return ('B');
2710 } else if (count_dangerouslydedicated) {
2711 return ('D');
2712 } else {
2713 log_it("Unknown boot loader");
2714 return ('U');
2715 }
2716}
2717
2718#else
2719
2720char which_boot_loader(char *which_device)
2721{
2722 /*@ buffer ***************************************************** */
2723 char *list_drives_cmd;
2724 char *current_drive;
2725
2726 /*@ pointers *************************************************** */
2727 FILE *pdrives;
2728
2729 /*@ int ******************************************************** */
2730 int count_lilos = 0;
2731 int count_grubs = 0;
2732
2733 /*@ end vars *************************************************** */
2734
2735 malloc_string(list_drives_cmd);
2736 malloc_string(current_drive);
2737
2738#ifdef __IA64__
2739 /* No choice for it */
2740 return ('E');
2741#endif
2742 assert(which_device != NULL);
2743 // sprintf (list_drives_cmd,
2744 // "fdisk -l | grep /dev | grep cyl | tr ':' ' ' | cut -d' ' -f2");
2745
2746 sprintf(list_drives_cmd,
2747 // "parted2fdisk
2748 "fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s",
2749 where_is_root_mounted());
2750 log_it("list_drives_cmd = %s", list_drives_cmd);
2751
2752 if (!(pdrives = popen(list_drives_cmd, "r"))) {
2753 log_OS_error("Unable to open list of drives");
2754 paranoid_free(list_drives_cmd);
2755 paranoid_free(current_drive);
2756 return ('\0');
2757 }
2758 for (fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
2759 fgets(current_drive, MAX_STR_LEN, pdrives)) {
2760 strip_spaces(current_drive);
2761 log_it("looking at drive %s's MBR", current_drive);
2762 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
2763 count_grubs++;
2764 strcpy(which_device, current_drive);
2765 break;
2766 }
2767 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
2768 count_lilos++;
2769 strcpy(which_device, current_drive);
2770 break;
2771 }
2772 }
2773 if (pclose(pdrives)) {
2774 log_OS_error("Cannot pclose pdrives");
2775 }
2776 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
2777 paranoid_free(list_drives_cmd);
2778 paranoid_free(current_drive);
2779 if (count_grubs && !count_lilos) {
2780 return ('G');
2781 } else if (count_lilos && !count_grubs) {
2782 return ('L');
2783 } else if (count_grubs == 1 && count_lilos == 1) {
2784 log_it("I'll bet you used to use LILO but switched to GRUB...");
2785 return ('G');
2786 } else {
2787 log_it("Unknown boot loader");
2788 return ('U');
2789 }
2790}
2791#endif
2792
2793
2794
2795
2796/**
2797 * Write zeroes over the first 16K of @p device.
2798 * @param device The device to zero.
2799 * @return 0 for success, 1 for failure.
2800 */
2801int zero_out_a_device(char *device)
2802{
2803 FILE *fout;
2804 int i;
2805
2806 assert_string_is_neither_NULL_nor_zerolength(device);
2807
2808 log_it("Zeroing drive %s", device);
2809 if (!(fout = fopen(device, "w"))) {
2810 log_OS_error("Unable to open/write to device");
2811 return (1);
2812 }
2813 for (i = 0; i < 16384; i++) {
2814 fputc('\0', fout);
2815 }
2816 paranoid_fclose(fout);
2817 log_it("Device successfully zeroed.");
2818 return (0);
2819}
2820
2821/**
2822 * Return the device pointed to by @p incoming.
2823 * @param incoming The device to resolve symlinks for.
2824 * @return The path to the real device file.
2825 * @note The returned string points to static storage that will be overwritten with each call.
2826 * @bug Won't work with file v4.0; needs to be written in C.
2827 */
2828char *resolve_softlinks_to_get_to_actual_device_file(char *incoming)
2829{
2830 static char output[MAX_STR_LEN];
2831 char *command;
2832 char *curr_fname;
2833 char *scratch;
2834 char *tmp;
2835 char *p;
2836
2837 struct stat statbuf;
2838 command = malloc(1000);
2839 malloc_string(tmp);
2840 malloc_string(scratch);
2841 malloc_string(curr_fname);
2842 if (!does_file_exist(incoming)) {
2843 log_it
2844 ("resolve_softlinks_to_get_to_actual_device_file --- device not found");
2845 strcpy(output, incoming);
2846 } else {
2847 strcpy(curr_fname, incoming);
2848 lstat(curr_fname, &statbuf);
2849 while (S_ISLNK(statbuf.st_mode)) {
2850 log_msg(1, "curr_fname = %s", curr_fname);
2851 sprintf(command, "file %s", curr_fname);
2852 strcpy(tmp, call_program_and_get_last_line_of_output(command));
2853 for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' ';
2854 p--);
2855 p++;
2856 strcpy(scratch, p);
2857 for (p = scratch; *p != '\0' && *p != '\''; p++);
2858 *p = '\0';
2859 log_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp,
2860 scratch);
2861 if (scratch[0] == '/') {
2862 strcpy(curr_fname, scratch); // copy whole thing because it's an absolute softlink
2863 } else { // copy over the basename cos it's a relative softlink
2864 p = curr_fname + strlen(curr_fname);
2865 while (p != curr_fname && *p != '/') {
2866 p--;
2867 }
2868 if (*p == '/') {
2869 p++;
2870 }
2871 strcpy(p, scratch);
2872 }
2873 lstat(curr_fname, &statbuf);
2874 }
2875 strcpy(output, curr_fname);
2876 log_it("resolved %s to %s", incoming, output);
2877 }
2878 paranoid_free(command);
2879 paranoid_free(curr_fname);
2880 paranoid_free(tmp);
2881 return (output);
2882}
2883
2884/* @} - end of deviceGroup */
2885
2886
2887/**
2888 * Return the type of partition format (GPT or MBR)
2889 */
2890char *which_partition_format(const char *drive)
2891{
2892 static char output[4];
2893 char *tmp;
2894 char *command;
2895 char *fdisk;
2896
2897 malloc_string(tmp);
2898 malloc_string(command);
2899 malloc_string(fdisk);
2900 log_msg(0, "Looking for partition table format type");
2901// BERLIOS: Do that temporarily: we need to put back parted2fdisk everywhere
2902#ifdef __IA64__
2903 struct stat buf;
2904
2905 sprintf(fdisk, "/usr/local/bin/fdisk");
2906 if (stat(fdisk, &buf) != 0) {
2907#endif
2908 sprintf(fdisk, "/sbin/fdisk");
2909#ifdef __IA64__
2910 }
2911#endif
2912 log_msg(1, "Using %s", fdisk);
2913 sprintf(command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
2914 strcpy(tmp, call_program_and_get_last_line_of_output(command));
2915 if (strstr(tmp, "GPT") == NULL) {
2916 strcpy(output, "MBR");
2917 } else {
2918 strcpy(output, "GPT");
2919 }
2920 log_msg(0, "Found %s partition table format type", output);
2921 paranoid_free(command);
2922 paranoid_free(tmp);
2923 paranoid_free(fdisk);
2924 return (output);
2925}
2926
2927/* @} - end of deviceGroup */
Note: See TracBrowser for help on using the repository browser.