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

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

Fix a seg fault introduced by last patch

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