source: MondoRescue/branches/2.05/mondo/mondo/common/libmondo-devices.c@ 101

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

Apply patch from Andree Leidenfrost <aleidenf_AT_bigpond.net.au>
(-r72:75 of trunk) for :
+ correcting NFS handling in interactive mode
+ growisofs and sudo pb

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