source: MondoRescue/branches/stable/mondo/mondo/common/libmondo-devices.c@ 501

Last change on this file since 501 was 501, checked in by bcornec, 18 years ago
  • Internationalization follow up
  • X11 remaining files suppressed
  • Property svn:keywords set to Id
File size: 79.3 KB
Line 
1/* libmondo-devices.c Subroutines for handling devices
2 $Id: libmondo-devices.c 501 2006-04-29 18:59:08Z 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 "libmondo-string-EXT.h"
235#include "libmondo-tools-EXT.h"
236#include "newt-specific-EXT.h"
237#include "libmondo-fork-EXT.h"
238#include "libmondo-stream-EXT.h"
239
240#include <sys/types.h>
241#ifdef __FreeBSD__
242#define DKTYPENAMES
243#define FSTYPENAMES
244#include <sys/disklabel.h>
245#include <sys/disk.h>
246#elif linux
247#define u64 unsigned long long
248#include <linux/fs.h> /* for BLKGETSIZE64 */
249#include <linux/hdreg.h>
250#endif
251
252/*@unused@*/
253//static char cvsid[] = "$Id: libmondo-devices.c 501 2006-04-29 18:59:08Z bcornec $";
254
255extern int g_current_media_number;
256extern double g_kernel_version;
257
258extern bool g_ISO_restore_mode;
259extern struct s_bkpinfo *g_bkpinfo_DONTUSETHIS;
260extern char *g_erase_tmpdir_and_scratchdir;
261extern char *g_selfmounted_isodir;
262
263static char g_cdrw_drive_is_here[MAX_STR_LEN / 4] = "";
264static char g_cdrom_drive_is_here[MAX_STR_LEN / 4] = "";
265static char g_dvd_drive_is_here[MAX_STR_LEN / 4] = "";
266
267
268/**
269 * ????? @bug ?????
270 * @ingroup globalGroup
271 */
272bool g_restoring_live_from_cd = FALSE;
273
274extern t_bkptype g_backup_media_type; // set by main()
275
276
277
278
279void set_g_cdrom_and_g_dvd_to_bkpinfo_value(struct s_bkpinfo *bkpinfo)
280{
281 strcpy(g_cdrom_drive_is_here, bkpinfo->media_device); // just in case
282 strcpy(g_dvd_drive_is_here, bkpinfo->media_device); // just in case
283}
284
285
286
287/**
288 * Retract all CD trays and wait for autorun to complete.
289 * @ingroup deviceGroup
290 */
291void retract_CD_tray_and_defeat_autorun(void)
292{
293// log_it("rctada: Retracting all CD trays", __LINE__);
294 if (strlen(g_cdrom_drive_is_here) > 0) {
295 inject_device(g_cdrom_drive_is_here);
296 }
297 if (strlen(g_dvd_drive_is_here) > 0) {
298 inject_device(g_dvd_drive_is_here);
299 }
300 if (strlen(g_cdrw_drive_is_here) > 0) {
301 inject_device(g_cdrw_drive_is_here);
302 }
303// log_it("rctada: killing autorun");
304// run_program_and_log_output("killall autorun", TRUE);
305 if (!run_program_and_log_output("ps | grep autorun | grep -v grep", 5)) {
306 log_it("autorun detected; sleeping for 2 seconds");
307 sleep(2);
308 }
309 log_it("rctada: Unmounting all CD drives", __LINE__);
310 run_program_and_log_output("umount /dev/cdr* /dev/dvd*", 5);
311}
312
313
314
315/**
316 * Determine whether we're booted off a ramdisk.
317 * @return @c TRUE (we are) or @c FALSE (we aren't).
318 * @ingroup utilityGroup
319 */
320bool am_I_in_disaster_recovery_mode(void)
321{
322 char *tmp, *comment;
323 bool is_this_a_ramdisk = FALSE;
324
325 malloc_string(tmp);
326 malloc_string(comment);
327 strcpy(tmp, where_is_root_mounted());
328 sprintf(comment, "root is mounted at %s\n", tmp);
329 log_msg(0, comment);
330 log_msg(0,
331 "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().",
332 tmp);
333
334#ifdef __FreeBSD__
335 if (strstr(tmp, "/dev/md")) {
336 is_this_a_ramdisk = TRUE;
337 }
338#else
339 if (!strncmp(tmp, "/dev/ram", 8)
340 || (!strncmp(tmp, "/dev/rd", 7) && !strcmp(tmp, "/dev/rd/")
341 && strncmp(tmp, "/dev/rd/cd", 10)) || strstr(tmp, "rootfs")
342 || !strcmp(tmp, "/dev/root")) {
343 is_this_a_ramdisk = TRUE;
344 } else {
345 is_this_a_ramdisk = FALSE;
346 }
347#endif
348
349 if (is_this_a_ramdisk) {
350 if (!does_file_exist("/THIS-IS-A-RAMDISK")
351 && !does_file_exist("/tmp/mountlist.txt.sample")) {
352 log_to_screen
353 (_("Using /dev/root is stupid of you but I'll forgive you."));
354 is_this_a_ramdisk = FALSE;
355 }
356 }
357 if (does_file_exist("/THIS-IS-A-RAMDISK")) {
358 is_this_a_ramdisk = TRUE;
359 }
360 paranoid_free(tmp);
361 paranoid_free(comment);
362 log_msg(1, "Is this a ramdisk? result = %d", is_this_a_ramdisk);
363 return (is_this_a_ramdisk);
364}
365
366
367
368
369
370/**
371 * Turn @c bkpinfo->backup_media_type into a human-readable string.
372 * @return The human readable string (e.g. @c cdr becomes <tt>"cdr"</tt>).
373 * @note The returned string points to static storage that will be overwritten with each call.
374 * @ingroup stringGroup
375 */
376static char *bkptype_to_string(t_bkptype bt)
377{
378 static char output[MAX_STR_LEN / 4];
379 switch (bt) {
380 case none:
381 strcpy(output, _("none"));
382 break;
383 case iso:
384 strcpy(output, _("iso"));
385 break;
386 case cdr:
387 strcpy(output, _("cdr"));
388 break;
389 case cdrw:
390 strcpy(output, _("cdrw"));
391 break;
392 case cdstream:
393 strcpy(output, _("cdstream"));
394 break;
395 case nfs:
396 strcpy(output, _("nfs"));
397 break;
398 case tape:
399 strcpy(output, _("tape"));
400 break;
401 case udev:
402 strcpy(output, _("udev"));
403 break;
404 default:
405 strcpy(output, _("default"));
406 }
407 return (output);
408}
409
410
411
412/**
413 * @addtogroup deviceGroup
414 * @{
415 */
416/**
417 * Eject the tray of the specified CD device.
418 * @param dev The device to eject.
419 * @return the return value of the @c eject command. (0=success, nonzero=failure)
420 */
421int eject_device(char *dev)
422{
423 char *command;
424 int res1 = 0, res2 = 0;
425
426 malloc_string(command);
427
428 if (IS_THIS_A_STREAMING_BACKUP(g_backup_media_type)
429 && g_backup_media_type != udev) {
430 sprintf(command, "mt -f %s offline", dev);
431 res1 = run_program_and_log_output(command, 1);
432 } else {
433 res1 = 0;
434 }
435
436#ifdef __FreeBSD__
437 if (strstr(dev, "acd")) {
438 sprintf(command, "cdcontrol -f %s eject", dev);
439 } else {
440 sprintf(command, "camcontrol eject `echo %s | sed 's|/dev/||'`",
441 dev);
442 }
443#else
444 sprintf(command, "eject %s", dev);
445#endif
446
447 log_msg(3, "Ejecting %s", dev);
448 res2 = run_program_and_log_output(command, 1);
449 paranoid_free(command);
450 if (res1 && res2) {
451 return (1);
452 } else {
453 return (0);
454 }
455}
456
457/**
458 * Load (inject) the tray of the specified CD device.
459 * @param dev The device to load/inject.
460 * @return 0 for success, nonzero for failure.
461 */
462int inject_device(char *dev)
463{
464 char *command;
465 int i;
466
467 malloc_string(command);
468
469
470#ifdef __FreeBSD__
471 if (strstr(dev, "acd")) {
472 sprintf(command, "cdcontrol -f %s close", dev);
473 } else {
474 sprintf(command, "camcontrol load `echo %s | sed 's|/dev/||'`",
475 dev);
476 }
477#else
478 sprintf(command, "eject -t %s", dev);
479#endif
480 i = run_program_and_log_output(command, FALSE);
481 paranoid_free(command);
482 return (i);
483}
484
485
486/**
487 * Determine whether the specified @p device (really, you can use any file)
488 * exists.
489 * @return TRUE if it exists, FALSE if it doesn't.
490 */
491bool does_device_exist(char *device)
492{
493
494 /*@ buffers *********************************************************** */
495 char *tmp;
496 bool ret;
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 if (system(tmp)) {
504 ret = FALSE;
505 } else {
506 ret = TRUE;
507 }
508 paranoid_free(tmp);
509 return (ret);
510}
511
512
513/**
514 * Determine whether a non-Microsoft partition exists on any connected hard drive.
515 * @return TRUE (there's a Linux/FreeBSD partition) or FALSE (Microsoft has taken over yet another innocent PC).
516 */
517bool does_nonMS_partition_exist(void)
518{
519#if __FreeBSD__
520 return
521 !system
522 ("for drive in /dev/ad? /dev/da?; do fdisk $drive | grep -q FreeBSD && exit 0; done; false");
523#else
524 return
525 !system
526 ("parted2fdisk -l 2>/dev/null | grep '^/dev/' | egrep -qv '(MS|DOS|FAT|NTFS)'");
527#endif
528}
529
530/**
531 * Determine whether the specified @p partno exists on the specified @p drive.
532 * @param drive The drive to search for the partition in.
533 * @param partno The partition number to look for.
534 * @return 0 if it exists, nonzero otherwise.
535 */
536int does_partition_exist(const char *drive, int partno)
537{
538 /*@ buffers **************************************************** */
539 char *program;
540 char *incoming;
541 char *searchstr;
542 char *tmp;
543
544 /*@ ints ******************************************************* */
545 int res = 0;
546
547 /*@ pointers *************************************************** */
548 FILE *fin;
549
550
551 /*@ end vars *************************************************** */
552 assert_string_is_neither_NULL_nor_zerolength(drive);
553 assert(partno >= 0 && partno < 999);
554
555 malloc_string(program);
556 malloc_string(incoming);
557 malloc_string(searchstr);
558 malloc_string(tmp);
559
560#ifdef __FreeBSD__
561 // We assume here that this is running from mondorestore. (It is.)
562 sprintf(program, "ls %s >/dev/null 2>&1", drive,
563 build_partition_name(tmp, drive, partno));
564 return system(program);
565#else
566 tmp[0] = '\0';
567#endif
568
569 sprintf(program, "parted2fdisk -l %s 2> /dev/null", drive);
570 fin = popen(program, "r");
571 if (!fin) {
572 log_it("program=%s", program);
573 log_OS_error("Cannot popen-in program");
574 return (0);
575 }
576 (void) build_partition_name(searchstr, drive, partno);
577 strcat(searchstr, " ");
578 for (res = 0; !res && fgets(incoming, MAX_STR_LEN - 1, fin);) {
579 if (strstr(incoming, searchstr)) {
580 res = 1;
581 }
582 }
583 if (pclose(fin)) {
584 log_OS_error("Cannot pclose fin");
585 }
586 paranoid_free(program);
587 paranoid_free(incoming);
588 paranoid_free(searchstr);
589 paranoid_free(tmp);
590 return (res);
591}
592
593
594
595
596
597/**
598 * Determine whether given NULL-terminated @p str exists in the MBR of @p dev.
599 * @param dev The device to look in.
600 * @param str The string to look for.
601 * @return TRUE if it exists, FALSE if it doesn't.
602 */
603bool does_string_exist_in_boot_block(char *dev, char *str)
604{
605 /*@ buffers **************************************************** */
606 char *command;
607
608 /*@ end vars *************************************************** */
609 int i;
610
611 assert_string_is_neither_NULL_nor_zerolength(dev);
612 assert_string_is_neither_NULL_nor_zerolength(str);
613
614 malloc_string(command);
615 sprintf(command,
616 "dd if=%s bs=446 count=1 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null",
617 dev, str);
618 i = system(command);
619 paranoid_free(command);
620 if (i) {
621 return (FALSE);
622 } else {
623 return (TRUE);
624 }
625}
626
627/**
628 * Determine whether specified @p str exists in the first @p n sectors of
629 * @p dev.
630 * @param dev The device to look in.
631 * @param str The string to look for.
632 * @param n The number of 512-byte sectors to search.
633 */
634bool does_string_exist_in_first_N_blocks(char *dev, char *str, int n)
635{
636 /*@ buffers **************************************************** */
637 char *command;
638 /*@ end vars *************************************************** */
639 int i;
640
641 malloc_string(command);
642 sprintf(command,
643 "dd if=%s bs=512 count=%i 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null",
644 dev, n, str);
645 i = system(command);
646 paranoid_free(command);
647 if (i) {
648 return (FALSE);
649 } else {
650 return (TRUE);
651 }
652}
653
654
655
656/**
657 * Try to mount CD-ROM at @p mountpoint. If the CD-ROM is not found or has
658 * not been specified, call find_cdrom_device() to find it.
659 * @param bkpinfo The backup information structure. The only field used is @c bkpinfo->media_device.
660 * @param mountpoint Where to mount the CD-ROM.
661 * @return 0 for success, nonzero for failure.
662 * @see mount_CDROM_here
663 */
664int find_and_mount_actual_cd(struct s_bkpinfo *bkpinfo, char *mountpoint)
665{
666 /*@ buffers ***************************************************** */
667
668 /*@ int's ****************************************************** */
669 int res;
670 char *dev;
671
672 /*@ end vars **************************************************** */
673
674 malloc_string(dev);
675 assert(bkpinfo != NULL);
676 assert_string_is_neither_NULL_nor_zerolength(mountpoint);
677
678 if (g_backup_media_type == dvd) {
679 strcpy(dev, g_dvd_drive_is_here);
680 if (!dev[0]) {
681 find_dvd_device(dev, FALSE);
682 }
683 } else {
684 strcpy(dev, g_cdrom_drive_is_here);
685 if (!dev[0]) {
686 find_cdrom_device(dev, FALSE);
687 }
688 }
689
690 if (bkpinfo->backup_media_type != iso) {
691 retract_CD_tray_and_defeat_autorun();
692 }
693
694 if (!dev[0] || (res = mount_CDROM_here(dev, mountpoint))) {
695 if (!popup_and_get_string
696 (_("CD-ROM device"), _("Please enter your CD-ROM's /dev device"),
697 dev, MAX_STR_LEN / 4)) {
698 res = 1;
699 } else {
700 res = mount_CDROM_here(dev, mountpoint);
701 }
702 }
703 if (res) {
704 log_msg(1, _("mount failed"));
705 } else {
706 log_msg(1, _("mount succeeded with %s"), dev);
707 }
708 paranoid_free(dev);
709 return (res);
710}
711
712
713
714
715
716/**
717 * Locate a CD-R/W writer's SCSI node.
718 * @param cdrw_device SCSI node will be placed here.
719 * @return 0 for success, nonzero for failure.
720 */
721
722
723/**
724 * Locate a CD-R/W writer's SCSI node.
725 * @param cdrw_device SCSI node will be placed here.
726 * @return 0 for success, nonzero for failure.
727 */
728int find_cdrw_device(char *cdrw_device)
729{
730 /*@ buffers ************************ */
731 char *comment;
732 char *tmp;
733 char *cdr_exe;
734 char *command;
735
736 malloc_string(comment);
737 malloc_string(tmp);
738 malloc_string(cdr_exe);
739 malloc_string(command);
740 if (g_cdrw_drive_is_here[0]) {
741 strcpy(cdrw_device, g_cdrw_drive_is_here);
742 log_msg(3, "Been there, done that. Returning %s", cdrw_device);
743 paranoid_free(comment);
744 paranoid_free(tmp);
745 paranoid_free(cdr_exe);
746 paranoid_free(command);
747 return (0);
748 }
749 if (g_backup_media_type == dvd) {
750 log_msg(1,
751 "This is dumb. You're calling find_cdrw_device() but you're backing up to DVD. WTF?");
752 paranoid_free(comment);
753 paranoid_free(tmp);
754 paranoid_free(cdr_exe);
755 paranoid_free(command);
756 return (1);
757 }
758 run_program_and_log_output("insmod ide-scsi", -1);
759 if (find_home_of_exe("cdrecord")) {
760 strcpy(cdr_exe, "cdrecord");
761 } else {
762 strcpy(cdr_exe, "dvdrecord");
763 }
764 tmp[0] = '\0';
765 if (find_home_of_exe(cdr_exe)) {
766 sprintf(command,
767 "%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",
768 cdr_exe);
769 strcpy(tmp, call_program_and_get_last_line_of_output(command));
770 }
771 if (strlen(tmp) < 2) {
772 paranoid_free(comment);
773 paranoid_free(tmp);
774 paranoid_free(cdr_exe);
775 paranoid_free(command);
776 return 1;
777 } else {
778 strcpy(cdrw_device, tmp);
779 sprintf(comment, "Found CDRW device - %s", cdrw_device);
780 log_it(comment);
781 strcpy(g_cdrw_drive_is_here, cdrw_device);
782 paranoid_free(comment);
783 paranoid_free(tmp);
784 paranoid_free(cdr_exe);
785 paranoid_free(command);
786 return (0);
787 }
788}
789
790
791
792
793/**
794 * Attempt to locate a CD-ROM device's /dev entry.
795 * Several different methods may be used to find the device, including
796 * calling @c cdrecord, searching @c dmesg, and trial-and-error.
797 * @param output Where to put the located /dev entry.
798 * @param try_to_mount Whether to mount the CD as part of the test; if mount
799 * fails then return failure.
800 * @return 0 for success, nonzero for failure.
801 */
802int find_cdrom_device(char *output, bool try_to_mount)
803{
804 /*@ pointers **************************************************** */
805 FILE *fin;
806 char *p;
807 char *q;
808 char *r;
809 int retval = 0;
810
811 /*@ bool's ****************************************************** */
812 bool found_it = FALSE;
813
814 /*@ buffers ***************************************************** */
815 char *tmp;
816 char *cdr_exe;
817 char *phrase_one;
818 char *phrase_two;
819 char *command;
820 char *dvd_last_resort;
821 char *mountpoint;
822 static char the_last_place_i_found_it[MAX_STR_LEN] = "";
823
824 /*@ intialize *************************************************** */
825 malloc_string(tmp);
826 malloc_string(cdr_exe);
827 malloc_string(phrase_one);
828 malloc_string(phrase_two);
829 malloc_string(command);
830 malloc_string(dvd_last_resort);
831 malloc_string(mountpoint);
832
833 output[0] = '\0';
834 phrase_one[0] = '\0';
835 phrase_two[0] = '\0';
836 dvd_last_resort[0] = '\0';
837
838 /*@ end vars **************************************************** */
839
840 if (g_cdrom_drive_is_here[0] && !isdigit(g_cdrom_drive_is_here[0])) {
841 strcpy(output, g_cdrom_drive_is_here);
842 log_msg(3, "Been there, done that. Returning %s", output);
843 retval = 0;
844 goto end_of_find_cdrom_device;
845 }
846 if (the_last_place_i_found_it[0] != '\0' && !try_to_mount) {
847 strcpy(output, the_last_place_i_found_it);
848 log_msg(3,
849 "find_cdrom_device() --- returning last found location - '%s'",
850 output);
851 retval = 0;
852 goto end_of_find_cdrom_device;
853 }
854
855 sprintf(mountpoint, "/tmp/cd.%d", (int) (random() % 32767));
856 make_hole_for_dir(mountpoint);
857
858 if (find_home_of_exe("cdrecord")) {
859 strcpy(cdr_exe, "cdrecord");
860 } else {
861 strcpy(cdr_exe, "dvdrecord");
862 }
863 tmp[0] = '\0';
864 if (!find_home_of_exe(cdr_exe)) {
865 strcpy(output, "/dev/cdrom");
866 log_msg(4, "Can't find cdrecord; assuming %s", output);
867 if (!does_device_exist(output)) {
868 log_msg(4, "That didn't work. Sorry.");
869 retval = 1;
870 goto end_of_find_cdrom_device;
871 } else {
872 retval = 0;
873 goto end_of_find_cdrom_device;
874 }
875 }
876
877 sprintf(command, "%s -scanbus 2> /dev/null", cdr_exe);
878 fin = popen(command, "r");
879 if (!fin) {
880 log_msg(4, "command=%s", command);
881 log_OS_error("Cannot popen command");
882 return (1);
883 }
884 for (fgets(tmp, MAX_STR_LEN, fin); !feof(fin);
885 fgets(tmp, MAX_STR_LEN, fin)) {
886 p = strchr(tmp, '\'');
887 if (p) {
888 q = strchr(++p, '\'');
889 if (q) {
890 for (r = q; *(r - 1) == ' '; r--);
891 *r = '\0';
892 strcpy(phrase_one, p);
893 p = strchr(++q, '\'');
894 if (p) {
895 q = strchr(++p, '\'');
896 if (q) {
897 while (*(q - 1) == ' ') {
898 q--;
899 }
900 *q = '\0';
901 strcpy(phrase_two, p);
902 }
903 }
904 }
905 }
906 }
907 paranoid_pclose(fin);
908
909#ifndef __FreeBSD__
910 if (strlen(phrase_two) == 0) {
911 log_msg(4, "Not running phase two. String is empty.");
912 } else {
913 sprintf(command, "dmesg | grep \"%s\" 2> /dev/null", phrase_two);
914 fin = popen(command, "r");
915 if (!fin) {
916 log_msg(4, "Cannot run 2nd command - non-fatal, fortunately");
917 } else {
918 for (fgets(tmp, MAX_STR_LEN, fin); !feof(fin);
919 fgets(tmp, MAX_STR_LEN, fin)) {
920 log_msg(5, "--> '%s'", tmp);
921 if (tmp[0] != ' ' && tmp[1] != ' ') {
922 p = strchr(tmp, ':');
923 if (p) {
924 *p = '\0';
925 if (strstr(tmp, "DVD")) {
926 sprintf(dvd_last_resort, "/dev/%s", tmp);
927 log_msg(4,
928 "Ignoring '%s' because it's a DVD drive",
929 tmp);
930 } else {
931 sprintf(output, "/dev/%s", tmp);
932 found_it = TRUE;
933 }
934 }
935 }
936 }
937 paranoid_pclose(fin);
938 }
939 }
940
941#endif
942#ifdef __FreeBSD__
943 if (!found_it) {
944 log_msg(4, "OK, approach 2");
945 if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/cdrom"))) {
946 if (!
947 (found_it =
948 set_dev_to_this_if_rx_OK(output, "/dev/cdrom1"))) {
949 if (!
950 (found_it =
951 set_dev_to_this_if_rx_OK(output, "/dev/dvd"))) {
952 if (!
953 (found_it =
954 set_dev_to_this_if_rx_OK(output, "/dev/acd0"))) {
955 if (!
956 (found_it =
957 set_dev_to_this_if_rx_OK(output,
958 "/dev/cd01"))) {
959 if (!
960 (found_it =
961 set_dev_to_this_if_rx_OK(output,
962 "/dev/acd1"))) {
963 if (!
964 (found_it =
965 set_dev_to_this_if_rx_OK(output,
966 "/dev/cd1")))
967 {
968 retval = 1;
969 goto end_of_find_cdrom_device;
970 }
971 }
972 }
973 }
974 }
975 }
976 }
977 }
978#else
979 if (!found_it && strlen(dvd_last_resort) > 0) {
980 log_msg(4, "Well, I'll use the DVD - %s - as a last resort",
981 dvd_last_resort);
982 strcpy(output, dvd_last_resort);
983 found_it = TRUE;
984 }
985 if (found_it) {
986 sprintf(tmp, "grep \"%s=ide-scsi\" /proc/cmdline &> /dev/null",
987 strrchr(output, '/') + 1);
988 if (system(tmp) == 0) {
989 log_msg(4,
990 "%s is not right. It's being SCSI-emulated. Continuing.",
991 output);
992 found_it = FALSE;
993 output[0] = '\0';
994 }
995 }
996
997 if (found_it) {
998 log_msg(4, "(find_cdrom_device) --> '%s'", output);
999 if (!does_device_exist(output)) {
1000 found_it = FALSE;
1001 log_msg(4, "OK, I was wrong, I haven't found it... yet.");
1002 }
1003 }
1004
1005 if (!found_it) {
1006 log_msg(4, "OK, approach 2");
1007 if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/scd0"))) {
1008 if (!(found_it = set_dev_to_this_if_rx_OK(output, "/dev/sr0"))) {
1009 if (!
1010 (found_it =
1011 set_dev_to_this_if_rx_OK(output, "/dev/cdrom"))) {
1012 if (!
1013 (found_it =
1014 set_dev_to_this_if_rx_OK(output,
1015 "/dev/cdrom0"))) {
1016 if (!
1017 (found_it =
1018 set_dev_to_this_if_rx_OK(output,
1019 "/dev/cdrom1"))) {
1020 if (!
1021 (found_it =
1022 set_dev_to_this_if_rx_OK(output,
1023 "/dev/sr1"))) {
1024 if (!
1025 (found_it =
1026 set_dev_to_this_if_rx_OK(output,
1027 "/dev/dvd")))
1028 {
1029 if (!
1030 (found_it =
1031 set_dev_to_this_if_rx_OK(output,
1032 g_cdrw_drive_is_here)))
1033 {
1034 retval = 1;
1035 goto end_of_find_cdrom_device;
1036 }
1037 }
1038 }
1039 }
1040 }
1041 }
1042 }
1043 }
1044 }
1045#endif
1046
1047 if (found_it && try_to_mount) {
1048 if (mount_CDROM_here(output, mountpoint)) {
1049 log_msg(4, "[Cardigans] I've changed my mind");
1050 found_it = FALSE;
1051 } else {
1052 sprintf(tmp, "%s/archives", mountpoint);
1053 if (!does_file_exist(tmp)) {
1054 log_msg(4, "[Cardigans] I'll take it back");
1055 found_it = FALSE;
1056 } else {
1057 sprintf(command, "umount %s", output);
1058 paranoid_system(command);
1059 log_msg(4, "I'm confident the Mondo CD is in %s", output);
1060 }
1061 }
1062 }
1063 unlink(mountpoint);
1064
1065 if (found_it) {
1066 if (!does_file_exist(output)) {
1067 log_msg(3, "I still haven't found it.");
1068 return (1);
1069 }
1070 log_msg(3, "(find_cdrom_device) --> '%s'", output);
1071 strcpy(the_last_place_i_found_it, output);
1072 strcpy(g_cdrom_drive_is_here, output);
1073 retval = 0;
1074 goto end_of_find_cdrom_device;
1075 }
1076
1077 sprintf(command,
1078 "%s -scanbus | grep \"[0-9],[0-9],[0-9]\" | grep \"[D|C][V|D]\" | grep -n \"\" | grep \"%s\" | cut -d':' -f2",
1079 cdr_exe, g_cdrw_drive_is_here);
1080 log_msg(1, "command=%s", command);
1081 strcpy(tmp, call_program_and_get_last_line_of_output(command));
1082 if (tmp[0]) {
1083 strcpy(output, tmp);
1084 log_msg(4, "Finally found it at %s", output);
1085 retval = 0;
1086 goto end_of_find_cdrom_device;
1087 } else {
1088 log_msg(4, "Still couldn't find it.");
1089 retval = 1;
1090 goto end_of_find_cdrom_device;
1091 }
1092 end_of_find_cdrom_device:
1093 paranoid_free(tmp);
1094 paranoid_free(cdr_exe);
1095 paranoid_free(phrase_one);
1096 paranoid_free(phrase_two);
1097 paranoid_free(command);
1098 paranoid_free(dvd_last_resort);
1099 paranoid_free(mountpoint);
1100 return (retval);
1101}
1102
1103
1104
1105
1106
1107int find_dvd_device(char *output, bool try_to_mount)
1108{
1109 char *command;
1110 char *tmp;
1111 int retval = 0, devno = -1;
1112
1113 malloc_string(command);
1114 malloc_string(tmp);
1115
1116 if (g_dvd_drive_is_here[0]) {
1117 strcpy(output, g_dvd_drive_is_here);
1118 log_msg(3, "Been there, done that. Returning %s", output);
1119 return (0);
1120 }
1121
1122 sprintf(tmp, call_program_and_get_last_line_of_output
1123 ("dvdrecord -scanbus 2> /dev/null | grep \") '\" | grep -n \"\" | grep DVD | cut -d':' -f1")
1124 );
1125 log_msg(5, "tmp = '%s'", tmp);
1126 if (!tmp[0])
1127 sprintf(tmp, call_program_and_get_last_line_of_output
1128 ("cdrecord -scanbus 2> /dev/null | grep \") '\" | grep -n \"\" | grep DVD | cut -d':' -f1")
1129 );
1130 if (tmp[0]) {
1131 devno = atoi(tmp) - 1;
1132 }
1133 if (devno >= 0) {
1134 retval = 0;
1135 sprintf(output, "/dev/scd%d", devno);
1136 strcpy(g_dvd_drive_is_here, output);
1137 log_msg(2, "I think DVD is at %s", output);
1138 } else {
1139 log_msg(2, "I cannot find DVD");
1140 retval = 1;
1141 }
1142
1143 if (try_to_mount) {
1144 log_msg(1, "Ignoring the fact that try_to_mount==TRUE");
1145 }
1146 return (retval);
1147}
1148
1149
1150
1151
1152
1153#include <sys/ioctl.h>
1154
1155/**
1156 * Find the size of the specified @p drive, in megabytes. Uses @c ioctl calls
1157 * and @c dmesg.
1158 * @param drive The device to find the size of.
1159 * @return size in megabytes.
1160 */
1161long get_phys_size_of_drive(char *drive)
1162{
1163 int fd;
1164#if linux
1165 unsigned long long s = 0;
1166 int fileid, cylinders = 0, cylindersleft = 0;
1167 int cylindersize = 0;
1168 int gotgeo = 0;
1169
1170
1171 struct hd_geometry hdgeo;
1172#elif __FreeBSD__
1173 off_t s;
1174#endif
1175
1176 long outvalA = -1;
1177 long outvalB = -1;
1178 long outvalC = -1;
1179
1180 if ((fd = open(drive, O_RDONLY)) != -1) {
1181 if (ioctl(fd,
1182#if linux
1183#ifdef BLKGETSIZE64
1184 BLKGETSIZE64,
1185#else
1186 BLKGETSIZE,
1187#endif
1188#elif __FreeBSD__
1189 DIOCGMEDIASIZE,
1190#endif
1191 &s) != -1) {
1192 close(fd);
1193 // s>>11 works for older disks but not for newer ones
1194 outvalB =
1195#if linux
1196#ifdef BLKGETSIZE64
1197 s >> 20
1198#else
1199 s >> 11
1200#endif
1201#else
1202 s >> 20
1203#endif
1204 ;
1205 }
1206 }
1207
1208 if (outvalB <= 0) {
1209 log_msg(1, "Error getting size of %s: %s", drive, strerror(errno));
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 "grep -v nodev /proc/filesystems | 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 sprintf(comment,
2115 _("How much data (in Megabytes) will each media store?"));
2116 if (!popup_and_get_string(_("Size"), comment, sz_size, 5)) {
2117 log_to_screen(_("User has chosen not to backup the PC"));
2118 finish(1);
2119 }
2120 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2121 bkpinfo->media_size[i] = atoi(sz_size);
2122 }
2123 if (bkpinfo->media_size[0] <= 0) {
2124 log_to_screen(_("User has chosen not to backup the PC"));
2125 finish(1);
2126 }
2127 }
2128 if (bkpinfo->disaster_recovery) {
2129 system("umount /tmp/isodir 2> /dev/null");
2130 if (!popup_and_get_string
2131 (_("NFS share"), _("Which remote NFS share should I mount?"),
2132 bkpinfo->nfs_mount, MAX_STR_LEN)) {
2133 log_to_screen(_("User has chosen not to backup the PC"));
2134 finish(1);
2135 }
2136 }
2137 if (!is_this_device_mounted(bkpinfo->nfs_mount)) {
2138 sprintf(bkpinfo->isodir, "/tmp/isodir.mondo.%d",
2139 (int) (random() % 32768));
2140 sprintf(command, "mkdir -p %s", bkpinfo->isodir);
2141 run_program_and_log_output(command, 5);
2142 sprintf(tmp, "mount -t nfs -o nolock %s %s", bkpinfo->nfs_mount,
2143 bkpinfo->isodir);
2144 run_program_and_log_output(tmp, 5);
2145 malloc_string(g_selfmounted_isodir);
2146 strcpy(g_selfmounted_isodir, bkpinfo->isodir);
2147 }
2148 if (!is_this_device_mounted(bkpinfo->nfs_mount)) {
2149 popup_and_OK
2150 (_("Please mount that partition before you try to backup to or restore from it."));
2151 finish(1);
2152 }
2153 strcpy(tmp, bkpinfo->nfs_remote_dir);
2154 if (!popup_and_get_string
2155 (_("Directory"), _("Which directory within that mountpoint?"), tmp,
2156 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 sprintf(command, "echo hi > %s/%s/.dummy.txt", bkpinfo->isodir,
2164 bkpinfo->nfs_remote_dir);
2165 while (run_program_and_log_output(command, FALSE)) {
2166 strcpy(tmp, bkpinfo->nfs_remote_dir);
2167 sprintf(prompt,
2168 _("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."),
2169 bkpinfo->nfs_remote_dir, bkpinfo->isodir);
2170 if (!popup_and_get_string
2171 (_("Directory"), prompt, tmp, MAX_STR_LEN)) {
2172 log_to_screen(_("User has chosen not to backup the PC"));
2173 finish(1);
2174 }
2175 strcpy(bkpinfo->nfs_remote_dir, tmp);
2176 // check whether writable - we better remove surrounding space s for this
2177 strip_spaces(bkpinfo->nfs_remote_dir);
2178 sprintf(command, "echo hi > %s/%s/.dummy.txt", bkpinfo->isodir,
2179 bkpinfo->nfs_remote_dir);
2180 }
2181 if (!popup_and_get_string
2182 (_("Prefix."),
2183 _("Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files"),
2184 bkpinfo->prefix, MAX_STR_LEN / 4)) {
2185 log_to_screen(_("User has chosen not to backup the PC"));
2186 finish(1);
2187 }
2188 log_msg(3, "prefix set to %s", bkpinfo->prefix);
2189
2190 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2191 bkpinfo->media_size[i] = 650;
2192 }
2193 log_msg(3, "Just set nfs_remote_dir to %s",
2194 bkpinfo->nfs_remote_dir);
2195 log_msg(3, "isodir is still %s", bkpinfo->isodir);
2196 break;
2197
2198 case iso:
2199 if (!bkpinfo->disaster_recovery) {
2200 if (!popup_and_get_string
2201 (_("Storage dir."),
2202 _("Please enter the full path that contains your ISO images. Example: /mnt/raid0_0"),
2203 bkpinfo->isodir, MAX_STR_LEN / 4)) {
2204 log_to_screen(_("User has chosen not to backup the PC"));
2205 finish(1);
2206 }
2207 if (archiving_to_media) {
2208 if ((bkpinfo->compression_level =
2209 which_compression_level()) == -1) {
2210 log_to_screen(_("User has chosen not to backup the PC"));
2211 finish(1);
2212 }
2213 if (!popup_and_get_string
2214 (_("ISO size."),
2215 _("Please enter how big you want each ISO image to be (in megabytes). This should be less than or equal to the size of the CD-R[W]'s or DVD's you plan to backup to."),
2216 sz_size, 16)) {
2217 log_to_screen(_("User has chosen not to backup the PC"));
2218 finish(1);
2219 }
2220 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2221 bkpinfo->media_size[i] = atoi(sz_size);
2222 }
2223 if (!popup_and_get_string
2224 (_("Prefix."),
2225 _("Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files"),
2226 bkpinfo->prefix, MAX_STR_LEN / 4)) {
2227 log_to_screen("User has chosen not to backup the PC");
2228 finish(1);
2229 }
2230 log_msg(3, "prefix set to %s", bkpinfo->prefix);
2231 } else {
2232 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
2233 bkpinfo->media_size[i] = 650;
2234 }
2235 }
2236 }
2237 break;
2238 default:
2239 fatal_error
2240 ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
2241 }
2242
2243 if (archiving_to_media) {
2244
2245#ifdef __FreeBSD__
2246 strcpy(bkpinfo->boot_device,
2247 call_program_and_get_last_line_of_output
2248 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'"));
2249#else
2250 strcpy(bkpinfo->boot_device,
2251 call_program_and_get_last_line_of_output
2252 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'"));
2253#endif
2254 i = which_boot_loader(bkpinfo->boot_device);
2255 if (i == 'U') // unknown
2256 {
2257
2258#ifdef __FreeBSD__
2259 if (!popup_and_get_string
2260 (_("Boot device"),
2261 _("What is your boot device? (e.g. /dev/ad0)"),
2262 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2263 log_to_screen(_("User has chosen not to backup the PC"));
2264 finish(1);
2265 }
2266 i = which_boot_loader(bkpinfo->boot_device);
2267#else
2268 if (!popup_and_get_string
2269 (_("Boot device"),
2270 _("What is your boot device? (e.g. /dev/hda)"),
2271 bkpinfo->boot_device, MAX_STR_LEN / 4)) {
2272 log_to_screen(_("User has chosen not to backup the PC"));
2273 finish(1);
2274 }
2275 if (does_string_exist_in_boot_block
2276 (bkpinfo->boot_device, "LILO")) {
2277 i = 'L';
2278 } else
2279 if (does_string_exist_in_boot_block
2280 (bkpinfo->boot_device, "ELILO")) {
2281 i = 'E';
2282 } else
2283 if (does_string_exist_in_boot_block
2284 (bkpinfo->boot_device, "GRUB")) {
2285 i = 'G';
2286 } else {
2287 i = 'U';
2288 }
2289#endif
2290 if (i == 'U') {
2291 if (ask_me_yes_or_no
2292 (_("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?")))
2293 {
2294 i = 'R'; // raw
2295 } else {
2296 log_to_screen
2297 (_("I cannot find your boot loader. Please run mondoarchive with parameters."));
2298 finish(1);
2299 }
2300 }
2301 }
2302 bkpinfo->boot_loader = i;
2303 strcpy(bkpinfo->include_paths, "/");
2304 if (!popup_and_get_string
2305 (_("Backup paths"),
2306 _("Please enter paths which you want me to backup. The default is '/' (i.e. everything)."),
2307 bkpinfo->include_paths, MAX_STR_LEN)) {
2308 log_to_screen(_("User has chosen not to backup the PC"));
2309 finish(1);
2310 }
2311 strcpy(tmp, list_of_NFS_mounts_only());
2312 if (strlen(tmp) > 2) {
2313 if (bkpinfo->exclude_paths[0]) {
2314 strcat(bkpinfo->exclude_paths, " ");
2315 }
2316 strncpy(bkpinfo->exclude_paths, tmp, MAX_STR_LEN);
2317 }
2318// NTFS
2319 strcpy(tmp,
2320 call_program_and_get_last_line_of_output
2321 ("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'"));
2322 if (strlen(tmp) > 2) {
2323 if (!popup_and_get_string
2324 (_("NTFS partitions"),
2325 _("Please enter/confirm the NTFS partitions you wish to backup as well."),
2326 tmp, MAX_STR_LEN / 4)) {
2327 log_to_screen(_("User has chosen not to backup the PC"));
2328 finish(1);
2329 }
2330 strncpy(bkpinfo->image_devs, tmp, MAX_STR_LEN / 4);
2331 }
2332
2333
2334 if (!popup_and_get_string
2335 (_("Exclude paths"),
2336 _("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."),
2337 bkpinfo->exclude_paths, MAX_STR_LEN)) {
2338 log_to_screen(_("User has chosen not to backup the PC"));
2339 finish(1);
2340 }
2341 bkpinfo->make_cd_use_lilo = FALSE;
2342 bkpinfo->backup_data = TRUE;
2343 bkpinfo->verify_data =
2344 ask_me_yes_or_no
2345 (_("Will you want to verify your backups after Mondo has created them?"));
2346
2347#ifndef __FreeBSD__
2348 if (!ask_me_yes_or_no
2349 (_("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.")))
2350#endif
2351 {
2352 strcpy(bkpinfo->kernel_path, "FAILSAFE");
2353 }
2354
2355 if (!ask_me_yes_or_no
2356 (_("Are you sure you want to proceed? Hit 'no' to abort."))) {
2357 log_to_screen(_("User has chosen not to backup the PC"));
2358 finish(1);
2359 }
2360 } else {
2361 bkpinfo->restore_data = TRUE; // probably...
2362 }
2363
2364 if (bkpinfo->backup_media_type == iso
2365 || bkpinfo->backup_media_type == nfs) {
2366 g_ISO_restore_mode = TRUE;
2367 }
2368#ifdef __FreeSD__
2369// skip
2370#else
2371 if (bkpinfo->backup_media_type == nfs) {
2372 sprintf(tmp, "mount | grep \"%s\" | cut -d' ' -f3",
2373 bkpinfo->nfs_mount);
2374// strcpy(bkpinfo->isodir, call_program_and_get_last_line_of_output(tmp));
2375 log_msg(3, "I think the NFS mount is mounted at %s",
2376 bkpinfo->isodir);
2377 }
2378 log_it("isodir = %s", bkpinfo->isodir);
2379 log_it("nfs_mount = '%s'", bkpinfo->nfs_mount);
2380#endif
2381
2382 log_it("media device = %s", bkpinfo->media_device);
2383 log_it("media size = %ld", bkpinfo->media_size[1]);
2384 log_it("media type = %s",
2385 bkptype_to_string(bkpinfo->backup_media_type));
2386 log_it("prefix = %s", bkpinfo->prefix);
2387 log_it("compression = %ld", bkpinfo->compression_level);
2388 log_it("include_paths = '%s'", bkpinfo->include_paths);
2389 log_it("exclude_paths = '%s'", bkpinfo->exclude_paths);
2390 log_it("scratchdir = '%s'", bkpinfo->scratchdir);
2391 log_it("tmpdir = '%s'", bkpinfo->tmpdir);
2392 log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device,
2393 bkpinfo->boot_loader);
2394 if (bkpinfo->media_size[0] < 0) {
2395 if (archiving_to_media) {
2396 fatal_error("Media size is less than zero.");
2397 } else {
2398 log_msg(2, "Warning - media size is less than zero.");
2399 bkpinfo->media_size[0] = 0;
2400 }
2401 }
2402 paranoid_free(tmp);
2403 paranoid_free(sz_size);
2404 paranoid_free(command);
2405 paranoid_free(comment);
2406 paranoid_free(prompt);
2407 return (0);
2408}
2409
2410
2411
2412
2413/**
2414 * @addtogroup utilityGroup
2415 * @{
2416 */
2417/**
2418 * Get a space-separated list of NFS devices and mounts.
2419 * @return The list created.
2420 * @note The return value points to static data that will be overwritten with each call.
2421 */
2422char *list_of_NFS_devices_and_mounts(void)
2423{
2424 char *exclude_these_devices;
2425 char *exclude_these_directories;
2426 static char result_sz[512];
2427
2428 malloc_string(exclude_these_devices);
2429 malloc_string(exclude_these_directories);
2430 strcpy(exclude_these_directories,
2431 call_program_and_get_last_line_of_output
2432 ("mount -t coda,ncpfs,nfs,smbfs,cifs | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' ' ' | awk '{print $0;}'"));
2433 strcpy(exclude_these_devices,
2434 call_program_and_get_last_line_of_output
2435 ("tr -s '\t' ' ' < /etc/fstab | grep -E '( (coda|ncpfs|nfs|smbfs|cifs) )' | cut -d' ' -f1 | tr -s '\n' ' ' | awk '{print $0;}'"));
2436 sprintf(result_sz, "%s %s", exclude_these_directories,
2437 exclude_these_devices);
2438 paranoid_free(exclude_these_devices);
2439 paranoid_free(exclude_these_directories);
2440 return (result_sz);
2441}
2442
2443
2444
2445
2446/**
2447 * Get a space-separated list of NFS mounts.
2448 * @return The list created.
2449 * @note The return value points to static data that will be overwritten with each call.
2450 * @bug Even though we only want the mounts, the devices are still checked.
2451 */
2452char *list_of_NFS_mounts_only(void)
2453{
2454 char *exclude_these_devices;
2455 char *exclude_these_directories;
2456 static char result_sz[512];
2457
2458 malloc_string(exclude_these_devices);
2459 malloc_string(exclude_these_directories);
2460 strcpy(exclude_these_directories,
2461 call_program_and_get_last_line_of_output
2462 ("mount -t coda,ncpfs,nfs,smbfs,cifs | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' ' ' | awk '{print $0;}'"));
2463 strcpy(exclude_these_devices,
2464 call_program_and_get_last_line_of_output
2465 ("tr -s '\t' ' ' < /etc/fstab | grep -E '( (coda|ncpfs|nfs|smbfs|cifs) )' | cut -d' ' -f1 | tr -s '\n' ' ' | awk '{print $0;}'"));
2466 sprintf(result_sz, "%s", exclude_these_directories);
2467 paranoid_free(exclude_these_devices);
2468 paranoid_free(exclude_these_directories);
2469 return (result_sz);
2470}
2471
2472/* @} - end of utilityGroup */
2473
2474
2475
2476
2477
2478/**
2479 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
2480 * [random] is a random number between 1 and 32767.
2481 * @param store_name_here Where to store the new filename.
2482 * @param stub A random number will be appended to this to make the FIFO's name.
2483 * @ingroup deviceGroup
2484 */
2485void make_fifo(char *store_name_here, char *stub)
2486{
2487 char *tmp;
2488
2489 malloc_string(tmp);
2490 assert_string_is_neither_NULL_nor_zerolength(stub);
2491
2492 sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
2493 (int) (random() % 32768));
2494 make_hole_for_file(store_name_here);
2495 mkfifo(store_name_here, S_IRWXU | S_IRWXG);
2496 sprintf(tmp, "chmod 770 %s", store_name_here);
2497 paranoid_system(tmp);
2498 paranoid_free(tmp);
2499}
2500
2501
2502
2503
2504
2505
2506/**
2507 * Set the tmpdir and scratchdir to reside on the partition with the most free space.
2508 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
2509 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set.
2510 * @ingroup utilityGroup
2511 */
2512void sensibly_set_tmpdir_and_scratchdir(struct s_bkpinfo *bkpinfo)
2513{
2514 char *tmp, *command, *sz;
2515
2516 malloc_string(tmp);
2517 malloc_string(command);
2518 malloc_string(sz);
2519 assert(bkpinfo != NULL);
2520
2521#ifdef __FreeBSD__
2522 strcpy(tmp,
2523 call_program_and_get_last_line_of_output
2524 ("df -m -P -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;}'"));
2525#else
2526 strcpy(tmp,
2527 call_program_and_get_last_line_of_output
2528 ("df -m -P -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;}'"));
2529#endif
2530
2531 if (tmp[0] != '/') {
2532 strcpy(sz, tmp);
2533 strcpy(tmp, "/");
2534 strcat(tmp, sz);
2535 }
2536 if (!tmp[0]) {
2537 fatal_error("I couldn't figure out the tempdir!");
2538 }
2539 sprintf(bkpinfo->tmpdir, "%s/tmp.mondo.%d", tmp,
2540 (int) (random() % 32768));
2541 log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir);
2542
2543 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%d", tmp,
2544 (int) (random() % 32768));
2545 log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
2546
2547 sprintf(g_erase_tmpdir_and_scratchdir, "rm -Rf %s %s", bkpinfo->tmpdir,
2548 bkpinfo->scratchdir);
2549
2550 sprintf(command, "rm -Rf %s/tmp.mondo.* %s/mondo.scratch.*", tmp, tmp);
2551 paranoid_system(command);
2552 paranoid_free(tmp);
2553 paranoid_free(command);
2554 paranoid_free(sz);
2555}
2556
2557
2558
2559
2560
2561
2562/**
2563 * @addtogroup deviceGroup
2564 * @{
2565 */
2566/**
2567 * If we can read @p dev, set @p output to it.
2568 * If @p dev cannot be read, set @p output to "".
2569 * @param dev The device to check for.
2570 * @param output Set to @p dev if @p dev exists, "" otherwise.
2571 * @return TRUE if @p dev exists, FALSE if it doesn't.
2572 */
2573bool set_dev_to_this_if_rx_OK(char *output, char *dev)
2574{
2575 char *command;
2576
2577 malloc_string(command);
2578 if (!dev || dev[0] == '\0') {
2579 output[0] = '\0';
2580 return (FALSE);
2581 }
2582// assert_string_is_neither_NULL_nor_zerolength(dev);
2583 log_msg(10, "Injecting %s", dev);
2584 inject_device(dev);
2585 if (!does_file_exist(dev)) {
2586 log_msg(10, "%s doesn't exist. Returning FALSE.", dev);
2587 return (FALSE);
2588 }
2589 sprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null",
2590 512L, dev);
2591 if (!run_program_and_log_output(command, FALSE)
2592 && !run_program_and_log_output(command, FALSE)) {
2593 strcpy(output, dev);
2594 log_msg(4, "Found it - %s", dev);
2595 return (TRUE);
2596 } else {
2597 output[0] = '\0';
2598 log_msg(4, "It's not %s", dev);
2599 return (FALSE);
2600 }
2601}
2602
2603
2604
2605
2606
2607/**
2608 * Find out what number CD is in the drive.
2609 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
2610 * @return The current CD number, or -1 if it could not be found.
2611 * @note If the CD is not mounted, it will be mounted
2612 * (and remain mounted after this function returns).
2613 */
2614int what_number_cd_is_this(struct s_bkpinfo *bkpinfo)
2615{
2616 int cd_number = -1;
2617 char *mountdev;
2618 char *tmp;
2619
2620 malloc_string(mountdev);
2621 malloc_string(tmp);
2622 assert(bkpinfo != NULL);
2623// log_it("Asking what_number_cd_is_this");
2624 if (g_ISO_restore_mode) {
2625 sprintf(tmp, "mount | grep iso9660 | awk '{print $3;}'");
2626// log_it("tmp = %s", tmp);
2627
2628 strcpy(mountdev, call_program_and_get_last_line_of_output(tmp));
2629 strcat(mountdev, "/archives/THIS-CD-NUMBER");
2630// log_it("mountdev = %s", mountdev);
2631 cd_number = atoi(last_line_of_file(mountdev));
2632// log_it("cd_number = %d", cd_number);
2633 paranoid_free(mountdev);
2634 paranoid_free(tmp);
2635 return (cd_number);
2636 }
2637
2638 strcpy(mountdev, bkpinfo->media_device);
2639 if (!mountdev[0]) {
2640 log_it
2641 ("(what_number_cd_is_this) Warning - media_device unknown. Finding out...");
2642 find_cdrom_device(bkpinfo->media_device, FALSE);
2643 }
2644 if (!is_this_device_mounted(MNT_CDROM)) {
2645 mount_CDROM_here(mountdev, MNT_CDROM);
2646 }
2647 cd_number =
2648 atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
2649// log_it("cd_number..later.. = %d", cd_number);
2650 paranoid_free(mountdev);
2651 paranoid_free(tmp);
2652 return (cd_number);
2653}
2654
2655
2656
2657
2658
2659
2660
2661/**
2662 * Find out what device is mounted as root (/).
2663 * @return Root device.
2664 * @note The returned string points to static storage and will be overwritten with every call.
2665 * @bug A bit of a misnomer; it's actually finding out the root device.
2666 * The mountpoint (where it's mounted) will obviously be '/'.
2667 */
2668char *where_is_root_mounted()
2669{
2670 /*@ buffers **************** */
2671 static char tmp[MAX_STR_LEN];
2672
2673
2674#ifdef __FreeBSD__
2675 strcpy(tmp, call_program_and_get_last_line_of_output
2676 ("mount | grep \" on / \" | cut -d' ' -f1"));
2677#else
2678 strcpy(tmp, call_program_and_get_last_line_of_output
2679 ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//"));
2680 if (strstr(tmp, "/dev/cciss/")) {
2681 strcpy(tmp, call_program_and_get_last_line_of_output
2682 ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1"));
2683 }
2684 if (strstr(tmp, "/dev/md")) {
2685 strcpy(tmp,
2686 call_program_and_get_last_line_of_output
2687 ("mount | grep \" on / \" | cut -d' ' -f1"));
2688 }
2689#endif
2690
2691 return (tmp);
2692}
2693
2694
2695/**
2696 * Find out which boot loader is in use.
2697 * @param which_device Device to look for the boot loader on.
2698 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
2699 * @note Under Linux, all drives are examined, not just @p which_device.
2700 */
2701#ifdef __FreeBSD__
2702char which_boot_loader(char *which_device)
2703{
2704 int count_lilos = 0;
2705 int count_grubs = 0;
2706 int count_boot0s = 0;
2707 int count_dangerouslydedicated = 0;
2708
2709 log_it("looking at drive %s's MBR", which_device);
2710 if (does_string_exist_in_boot_block(which_device, "GRUB")) {
2711 count_grubs++;
2712 }
2713 if (does_string_exist_in_boot_block(which_device, "LILO")) {
2714 count_lilos++;
2715 }
2716 if (does_string_exist_in_boot_block(which_device, "Drive")) {
2717 count_boot0s++;
2718 }
2719 if (does_string_exist_in_first_N_blocks
2720 (which_device, "FreeBSD/i386", 17)) {
2721 count_dangerouslydedicated++;
2722 }
2723 log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
2724 count_grubs, count_lilos, count_elilos, count_boot0s,
2725 count_dangerouslydedicated);
2726
2727 if (count_grubs && !count_lilos) {
2728 return ('G');
2729 } else if (count_lilos && !count_grubs) {
2730 return ('L');
2731 } else if (count_grubs == 1 && count_lilos == 1) {
2732 log_it("I'll bet you used to use LILO but switched to GRUB...");
2733 return ('G');
2734 } else if (count_boot0s == 1) {
2735 return ('B');
2736 } else if (count_dangerouslydedicated) {
2737 return ('D');
2738 } else {
2739 log_it("Unknown boot loader");
2740 return ('U');
2741 }
2742}
2743
2744#else
2745
2746char which_boot_loader(char *which_device)
2747{
2748 /*@ buffer ***************************************************** */
2749 char *list_drives_cmd;
2750 char *current_drive;
2751
2752 /*@ pointers *************************************************** */
2753 FILE *pdrives;
2754
2755 /*@ int ******************************************************** */
2756 int count_lilos = 0;
2757 int count_grubs = 0;
2758
2759 /*@ end vars *************************************************** */
2760
2761 malloc_string(list_drives_cmd);
2762 malloc_string(current_drive);
2763
2764#ifdef __IA64__
2765 /* No choice for it */
2766 return ('E');
2767#endif
2768 assert(which_device != NULL);
2769 // sprintf (list_drives_cmd,
2770 // "fdisk -l | grep /dev | grep cyl | tr ':' ' ' | cut -d' ' -f2");
2771
2772 sprintf(list_drives_cmd,
2773 "parted2fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s",
2774 where_is_root_mounted());
2775 log_it("list_drives_cmd = %s", list_drives_cmd);
2776
2777 if (!(pdrives = popen(list_drives_cmd, "r"))) {
2778 log_OS_error("Unable to open list of drives");
2779 paranoid_free(list_drives_cmd);
2780 paranoid_free(current_drive);
2781 return ('\0');
2782 }
2783 for (fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives);
2784 fgets(current_drive, MAX_STR_LEN, pdrives)) {
2785 strip_spaces(current_drive);
2786 log_it("looking at drive %s's MBR", current_drive);
2787 if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
2788 count_grubs++;
2789 strcpy(which_device, current_drive);
2790 break;
2791 }
2792 if (does_string_exist_in_boot_block(current_drive, "LILO")) {
2793 count_lilos++;
2794 strcpy(which_device, current_drive);
2795 break;
2796 }
2797 }
2798 if (pclose(pdrives)) {
2799 log_OS_error("Cannot pclose pdrives");
2800 }
2801 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
2802 paranoid_free(list_drives_cmd);
2803 paranoid_free(current_drive);
2804 if (count_grubs && !count_lilos) {
2805 return ('G');
2806 } else if (count_lilos && !count_grubs) {
2807 return ('L');
2808 } else if (count_grubs == 1 && count_lilos == 1) {
2809 log_it("I'll bet you used to use LILO but switched to GRUB...");
2810 return ('G');
2811 } else {
2812 log_it("Unknown boot loader");
2813 return ('U');
2814 }
2815}
2816#endif
2817
2818
2819
2820
2821/**
2822 * Write zeroes over the first 16K of @p device.
2823 * @param device The device to zero.
2824 * @return 0 for success, 1 for failure.
2825 */
2826int zero_out_a_device(char *device)
2827{
2828 FILE *fout;
2829 int i;
2830
2831 assert_string_is_neither_NULL_nor_zerolength(device);
2832
2833 log_it("Zeroing drive %s", device);
2834 if (!(fout = fopen(device, "w"))) {
2835 log_OS_error("Unable to open/write to device");
2836 return (1);
2837 }
2838 for (i = 0; i < 16384; i++) {
2839 fputc('\0', fout);
2840 }
2841 paranoid_fclose(fout);
2842 log_it("Device successfully zeroed.");
2843 return (0);
2844}
2845
2846/**
2847 * Return the device pointed to by @p incoming.
2848 * @param incoming The device to resolve symlinks for.
2849 * @return The path to the real device file.
2850 * @note The returned string points to static storage that will be overwritten with each call.
2851 * @bug Won't work with file v4.0; needs to be written in C.
2852 */
2853char *resolve_softlinks_to_get_to_actual_device_file(char *incoming)
2854{
2855 static char output[MAX_STR_LEN];
2856 char *command;
2857 char *curr_fname;
2858 char *scratch;
2859 char *tmp;
2860 char *p;
2861
2862 struct stat statbuf;
2863 command = malloc(1000);
2864 malloc_string(tmp);
2865 malloc_string(scratch);
2866 malloc_string(curr_fname);
2867 if (!does_file_exist(incoming)) {
2868 log_it
2869 ("resolve_softlinks_to_get_to_actual_device_file --- device not found");
2870 strcpy(output, incoming);
2871 } else {
2872 strcpy(curr_fname, incoming);
2873 lstat(curr_fname, &statbuf);
2874 while (S_ISLNK(statbuf.st_mode)) {
2875 log_msg(1, "curr_fname = %s", curr_fname);
2876 sprintf(command, "file %s", curr_fname);
2877 strcpy(tmp, call_program_and_get_last_line_of_output(command));
2878 for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' ';
2879 p--);
2880 p++;
2881 strcpy(scratch, p);
2882 for (p = scratch; *p != '\0' && *p != '\''; p++);
2883 *p = '\0';
2884 log_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp,
2885 scratch);
2886 if (scratch[0] == '/') {
2887 strcpy(curr_fname, scratch); // copy whole thing because it's an absolute softlink
2888 } else { // copy over the basename cos it's a relative softlink
2889 p = curr_fname + strlen(curr_fname);
2890 while (p != curr_fname && *p != '/') {
2891 p--;
2892 }
2893 if (*p == '/') {
2894 p++;
2895 }
2896 strcpy(p, scratch);
2897 }
2898 lstat(curr_fname, &statbuf);
2899 }
2900 strcpy(output, curr_fname);
2901 log_it("resolved %s to %s", incoming, output);
2902 }
2903 paranoid_free(command);
2904 paranoid_free(curr_fname);
2905 paranoid_free(tmp);
2906 return (output);
2907}
2908
2909/* @} - end of deviceGroup */
2910
2911
2912/**
2913 * Return the type of partition format (GPT or MBR)
2914 */
2915char *which_partition_format(const char *drive)
2916{
2917 static char output[4];
2918 char *tmp;
2919 char *command;
2920 char *fdisk;
2921#ifdef __IA64__
2922 struct stat buf;
2923#endif
2924 malloc_string(tmp);
2925 malloc_string(command);
2926 malloc_string(fdisk);
2927 log_msg(0, "Looking for partition table format type");
2928 sprintf(fdisk, "/sbin/parted2fdisk");
2929 log_msg(1, "Using %s", fdisk);
2930 sprintf(command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
2931 strcpy(tmp, call_program_and_get_last_line_of_output(command));
2932 if (strstr(tmp, "GPT") == NULL) {
2933 strcpy(output, "MBR");
2934 } else {
2935 strcpy(output, "GPT");
2936 }
2937 log_msg(0, "Found %s partition table format type", output);
2938 paranoid_free(command);
2939 paranoid_free(tmp);
2940 paranoid_free(fdisk);
2941 return (output);
2942}
2943
2944/* @} - end of deviceGroup */
Note: See TracBrowser for help on using the repository browser.