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

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

Render bkpinfo global (potential issue on thread, but should not be a problem as that structure is indeed static during archive)
Should solve the tmpdir issue from previous rev.
May still not compile

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