source: MondoRescue/branches/2.2.10/mondo/src/common/libmondo-devices.c@ 2508

Last change on this file since 2508 was 2508, checked in by Bruno Cornec, 14 years ago

r3287@localhost (orig r2285): bruno | 2009-07-20 11:36:47 +0200

r3285@localhost: bruno | 2009-07-20 11:17:35 +0200
Apply fix in 2.2.10 around multi USB device handling to 2.2.9 as well


r3291@localhost (orig r2288): bruno | 2009-07-21 16:48:31 +0200
Copy 2.2.10 test script in to 2.2.9 for memory problm analysis


r3293@localhost (orig r2290): bruno | 2009-07-22 14:03:44 +0200

  • Fix a printing error in mindi for the tar command
  • Fix all mr_asprintf which had no second param as a string


r3295@localhost (orig r2292): bruno | 2009-07-22 16:55:00 +0200

  • Fix #160 and #346 by rewriting the message.txt file with more valid information gathered in mindi


r3300@localhost (orig r2294): bruno | 2009-07-23 01:58:08 +0200

Man pages patch from Joe Ross (joe.ross_at_gmail.com)


r3303@localhost (orig r2297): bruno | 2009-07-23 17:43:49 +0200
Fix a remaining display error for 2.2.9. That version has been tested OK in a lab.


r3304@localhost (orig r2298): bruno | 2009-07-23 18:18:27 +0200

  • Remove memory leak for the last modification


r3308@localhost (orig r2302): bruno | 2009-07-24 21:18:50 +0200
Improve logging of mountlist.txt


r3310@localhost (orig r2304): bruno | 2009-07-27 19:45:10 +0200

  • popup_and_get_string needs an allocated buffer for the moment so fixing the calls with dyn. ones
  • Fix a bug in mem.c for mr_strcat, which wasn't modifying the right pointer level


r3311@localhost (orig r2305): bruno | 2009-07-27 19:49:35 +0200
Avoid a memory leak in the previous patch


r3314@localhost (orig r2308): bruno | 2009-07-27 20:59:06 +0200
Fix a bug in mr_strcat backported from 2.2.10. Should solve our seg faults.


r3315@localhost (orig r2309): bruno | 2009-07-28 02:14:23 +0200
Cosmetic changes to allow for quality to not giv false positive


r3343@localhost (orig r2311): bruno | 2009-08-18 02:13:43 +0200
Fix for initramfs detection with 2.6.30 (Hugo Vanwoerkom hvw59601_at_care2.com)


r3367@localhost (orig r2333): bruno | 2009-08-18 16:26:26 +0200
Adds a precision for -U option in man page on raw device usage and not partition name


r3373@localhost (orig r2336): bruno | 2009-08-20 17:37:41 +0200

  • Precise the combined usage of -E and -I in mondoarchive (Case 4601017223)


r3379@localhost (orig r2342): bruno | 2009-08-21 16:27:10 +0200


r3383@localhost (orig r2344): bruno | 2009-08-24 13:37:09 +0200

r3382@localhost: bruno | 2009-08-24 13:30:25 +0200
In NFS mode also propose access to expert, interactive, ... entry at boot prompt


r3388@localhost (orig r2346): bruno | 2009-08-27 11:41:16 +0200
Adds fdisk -l result in Log File at restore time


r3389@localhost (orig r2347): bruno | 2009-08-27 13:51:00 +0200

  • Solve tmp dir creation which sometimes was trying to create /%xx dirs. Should fix #293 for good


r3390@localhost (orig r2348): bruno | 2009-08-27 13:54:25 +0200
Improve logging (minor)


r3394@localhost (orig r2350): bruno | 2009-08-28 02:24:19 +0200
Change inerface of evaluate_mountlist and spread_flaws_across_three_lines in order to solve bugs linked to strings management in these functions. May fix a restoration crash seen by some customers


r3397@localhost (orig r2353): bruno | 2009-08-28 19:03:45 +0200

  • Addition of a nomd option to avoid starting mdadm
  • mpath is now already started if there was a mpath entry in mountlist


r3399@localhost (orig r2355): bruno | 2009-08-29 00:56:50 +0200
Remove function spread_flaws_across_three_lines and expand it at the single place where it was useful, and fix memory allocation issues in it.


r3402@localhost (orig r2358): bruno | 2009-09-01 19:02:35 +0200
P2V doc updated (Lester Wade lester.wade_at_hp.com)


r3404@localhost (orig r2360): bruno | 2009-09-01 19:26:53 +0200
Website update to refer to new P2V document


r3405@localhost (orig r2361): bruno | 2009-09-03 13:54:25 +0200

  • Fix a case where the NFS dir in restore mode was mounted rw (linked to bug #291 could create a huge problem)


r3407@localhost (orig r2363): bruno | 2009-09-03 14:46:46 +0200
More verbose at installation of additional tools


r3409@localhost (orig r2365): bruno | 2009-09-03 18:08:32 +0200

  • New update from Lester Wade (lester.wade_at_hp.com) for P2V doc


r3410@localhost (orig r2366): bruno | 2009-09-05 01:28:18 +0200
place the code of mondo_makefilelist before its call



r3411@localhost (orig r2367): bruno | 2009-09-06 01:51:26 +0200

  • Advertising for project-builder on the website added


r3412@localhost (orig r2368): bruno | 2009-09-07 15:36:23 +0200
Fix compilation issue


r3413@localhost (orig r2369): bruno | 2009-09-07 18:03:40 +0200
Another compilation issue fixed.


r3415@localhost (orig r2371): bruno | 2009-09-08 13:40:25 +0200

  • Fix a problem a error detection in evaluate_mountlist which casued nuke mode to abort. Error string should also be better now.


r3417@localhost (orig r2373): bruno | 2009-09-08 13:55:31 +0200
Avoid asking the Prefix name in NFS mode twice


r3418@localhost (orig r2374): bruno | 2009-09-08 20:04:07 +0200

  • Try to fix garbled screen progression in text mode based on 2.2.10 modifications which are working


r3424@localhost (orig r2380): bruno | 2009-09-09 20:30:47 +0200

  • Change NFS support into a NetFS support to allow for multiple protocol in addition to NFS (NEEDS TESTING)
  • Better logging to detect a potential nuke issue


r3425@localhost (orig r2381): bruno | 2009-09-10 02:05:55 +0200
Fix a missing param for sshfs call


r3428@localhost (orig r2384): bruno | 2009-09-10 13:02:56 +0200

  • Remove separate function look_for_duplicate_mountpoints used only once and whose interface created problems with caller


r3430@localhost (orig r2386): bruno | 2009-09-10 16:06:52 +0200
Be compatible on backup type by making old nfs recognized as netfs and proto forced


r3431@localhost (orig r2387): bruno | 2009-09-10 18:40:47 +0200
Fix a problem in netfs analysis in mondoarchive


r3432@localhost (orig r2388): bruno | 2009-09-10 20:25:13 +0200
Fix mondoarchive CLI analysis for NETFS type of requests


r3434@localhost (orig r2390): bruno | 2009-09-11 03:05:20 +0200

  • Adds ext3 initrd support for 2.6.30


r3437@localhost (orig r2393): bruno | 2009-09-11 11:56:52 +0200

  • Tries to add support for bzip2 and lzma initramfs (preliminary, not tested) for 2.6.30


r3438@localhost (orig r2394): bruno | 2009-09-12 02:53:02 +0200
Fix interface of evaluate_mountlist (remove 2nd param useless) and fix nuke mode which wasn't working.


r3441@localhost (orig r2397): bruno | 2009-09-14 18:54:34 +0200
Fix a format issue in text mode on percentage


r3452@localhost (orig r2398): bruno | 2009-09-15 16:00:13 +0200

  • Fix a bug where flaws_str could be NULL and wasn't tested correctly.


r3453@localhost (orig r2399): bruno | 2009-09-15 19:28:39 +0200

  • Use protocol name when displaying restore progress instead of netfs
  • Ask for network protocol name at restore time


r3455@localhost (orig r2401): bruno | 2009-09-15 19:34:19 +0200
Wrong structure member name was used


r3456@localhost (orig r2402): bruno | 2009-09-16 13:04:17 +0200
Use dir for shell related commands and dir1 for C related actions in open_and_list_dir to avoid missing some files with { in names e.g.


r3457@localhost (orig r2403): bruno | 2009-09-16 16:32:03 +0200

  • At restore time read the netfs protocol in the conf file


r3462@localhost (orig r2408): bruno | 2009-09-18 15:17:08 +0200
Remove useless script


r3463@localhost (orig r2409): bruno | 2009-09-18 15:25:35 +0200

  • Split deplist.txt into multiple conf files under deplist.d in the conf dir. This will allow to have a minimal.conf file for initrd content to analyze to improve support of new embedded feature in the future (sshfs, live install). The other conf files contain the additional commands to put in the all.tar.gz. For the moment, mindi is still working the same. THis infra will allow that support in a near future. deplist.txt is now reserved for the admin additional commands.


r3465@localhost (orig r2410): bruno | 2009-09-18 19:10:54 +0200

  • Better list of mandatory tools
  • Adds fuse and sshfs support in initrd


r3466@localhost (orig r2411): bruno | 2009-09-18 20:32:47 +0200
sshfs also needs ssh at restore time in initrd


r3478@localhost (orig r2418): bruno | 2009-09-23 23:22:39 +0200
Modify getfattr call to have all extended attributes, including non user ones. (patch from Kevin Ritzenthaler Kevin.Ritzenthaler_at_hp.com) and fix #357


r3479@localhost (orig r2419): bruno | 2009-09-23 23:50:34 +0200
star only supports ACL when used with exustar mode. Fix #356.


r3482@localhost (orig r2422): bruno | 2009-09-24 16:53:24 +0200

  • Adds support for bnx2x (BL 460 G6) and auth_rpcgss (Debian 2.6.31)


r3485@localhost (orig r2423): bruno | 2009-09-25 16:38:40 +0200
Fix an issue in is_this_device_mounted (string freed before last usage)


r3486@localhost (orig r2424): bruno | 2009-09-25 18:44:01 +0200

  • analyze-my-lvm now removes excluded devices from list coming from mondoarchive
  • new mr_make_devlist_from_pathlist which handle the new bkpinfo->exclude_devs field containing the excluded devices and remove corresponding code from libmondo-cli.c
  • Move DSF code into libmondo-devices.c for coherency, and only the previous function is made externally available
  • Remove dev_to_exclude in libmondo-archive.c which wasn't working correctly and replace it with bkpinfo->exclude_devs


r3487@localhost (orig r2425): bruno | 2009-09-25 18:58:23 +0200

  • Improving ssh support at restore time by providing a shadow file


r3489@localhost (orig r2426): bruno | 2009-09-25 19:42:09 +0200

  • Attempt to stay backward compatible without protocol for -n option


r3490@localhost (orig r2427): bruno | 2009-09-28 02:08:06 +0200
Avoids null param for excludes_devs for mindi call


r3492@localhost (orig r2429): bruno | 2009-09-28 11:46:16 +0200

  • Simplify GetInitrdFilesystemToUse which doesn't need to detect everything, but just know if it's initramfs (new mode) or a compressed FS ext2/3 (older mode) as initrd is anyway re-made by mindi. Should fix #353


r3494@localhost (orig r2431): bruno | 2009-09-28 13:16:18 +0200

  • Use only the AWK veriable everywhere and not the awk command


r3495@localhost (orig r2432): bruno | 2009-09-28 14:16:31 +0200
Warning emited in case of duplicate mountpoints or devices in fstab found


r3496@localhost (orig r2433): bruno | 2009-09-28 15:55:17 +0200
ssh in the restore env needs some dlopened libs (libnss_compat|files)


r3497@localhost (orig r2434): bruno | 2009-09-28 16:33:14 +0200
Compiler warning fixed


r3498@localhost (orig r2435): bruno | 2009-09-28 17:55:26 +0200
Improve user management for NetFS cases


r3499@localhost (orig r2436): bruno | 2009-09-29 01:48:32 +0200

  • Improve deplist.d/* files
  • adds libnss for ssh support in boot disk
  • Solve a memory management issue in DSF module (strtok => mr_strtok)
  • DSF now also supports partitions in addition to full disks
  • Adds debug in open_and_list_dir


r3500@localhost (orig r2437): bruno | 2009-09-29 10:41:56 +0200

  • Fix udev support in init for Mandriva 2009.1 (udevadm settle is blocking)


r3501@localhost (orig r2438): bruno | 2009-09-29 14:41:36 +0200

  • Improvements on sshfs/ssh management in restore mode
  • Include now all minimal requirements for sshfs


r3502@localhost (orig r2439): bruno | 2009-09-29 18:46:08 +0200

  • Avoids error message if some ssh conf files do not exist


r3503@localhost (orig r2440): bruno | 2009-09-29 18:57:13 +0200

  • Avoids comment analysis in the new code handling deplist.d


r3504@localhost (orig r2441): bruno | 2009-09-29 19:34:34 +0200

  • fuse device is needed at restore time for sshfs


r3505@localhost (orig r2442): bruno | 2009-09-29 20:02:36 +0200

  • Improves udev timeout handling


r3506@localhost (orig r2443): bruno | 2009-09-29 20:43:38 +0200

  • priority given to env var for tmpdir
  • fuse FS excluded from tmpdir computation


r3518@localhost (orig r2447): bruno | 2009-10-04 01:58:08 +0200

  • Iprove USB log in case of error by adding the conf file


r3519@localhost (orig r2448): bruno | 2009-10-05 11:06:13 +0200


r3520@localhost (orig r2449): bruno | 2009-10-06 01:10:35 +0200

  • Adds support for grub2 conf file grub.cfg in addition to menu.lst


r3521@localhost (orig r2450): bruno | 2009-10-06 01:24:02 +0200

  • Fix a mr_asprintf usage without & causing a seg fault.


r3523@localhost (orig r2452): bruno | 2009-10-06 12:47:56 +0200
CIFS mounts shouldn't be part of the mountlist analysis (should help solving #288)


r3524@localhost (orig r2453): bruno | 2009-10-07 10:17:03 +0200

  • Fix a bug in handling of -E option with real devices (bad report in function mr_make_devlist_from_pathlist of the test between -E and -I)


r3525@localhost (orig r2454): bruno | 2009-10-07 10:19:02 +0200

  • Fix an error in the test for grub conf files (or used instead of and)


r3526@localhost (orig r2455): bruno | 2009-10-07 16:14:59 +0200
afio is under /bin on Debian


r3527@localhost (orig r2456): bruno | 2009-10-07 17:31:26 +0200

  • Adds support for libcrc32c (needed by bnx2x)


r3532@localhost (orig r2457): bruno | 2009-10-09 13:33:44 +0200

  • Apply path from Matthew Cline (matt_at_nightrealms.com) in order to fix #359


r3533@localhost (orig r2458): bruno | 2009-10-09 13:41:02 +0200
Adds a conf file example for mindi and fix #360


r3535@localhost (orig r2459): bruno | 2009-10-09 15:13:01 +0200
MOde of conf file


r3546@localhost (orig r2461): bruno | 2009-10-14 01:12:24 +0200

  • umount freshly created VFAT partition on USB key as Ubunu has an automounter mounting it as soon as created (Steffen Neumann sneumann_at_ipb-halle.de)


r3566@localhost (orig r2463): bruno | 2009-10-26 01:34:16 +0100

  • Reset an error counter before blanking a DVD to avoid always returning an error (Vincent Raman vincent.raman_at_macqel.eu)


r3567@localhost (orig r2464): bruno | 2009-10-26 13:57:14 +0100
bzip2 is under /bin on Debian


r3568@localhost (orig r2465): bruno | 2009-10-28 01:46:30 +0100
some distro hold lvm commands under /usr/sbin


r3595@localhost (orig r2469): bruno | 2009-11-10 12:22:10 +0100
/dev/shm is now part of the default exclude list


r3596@localhost (orig r2470): bruno | 2009-11-10 12:32:40 +0100
Remove useless pb_log and MONDO_TRACEFILE


r3597@localhost (orig r2471): bruno | 2009-11-10 12:57:58 +0100
Improve analysis of kernel modules by printing whether it's a live or extra module which has not been found (Matthew Cline) as reported in #362


r3598@localhost (orig r2472): bruno | 2009-11-10 13:21:46 +0100

  • Default to DVD size when in iso or netfs mode


r3599@localhost (orig r2473): bruno | 2009-11-10 14:13:10 +0100

  • Fix #363 where exclude_paths was extended up to memory limit dumping core


r3600@localhost (orig r2474): bruno | 2009-11-10 14:31:14 +0100

  • Update deplist for Debian support


r3602@localhost (orig r2476): bruno | 2009-11-11 02:44:42 +0100

  • small improvement for loging in USB case


r3603@localhost (orig r2477): bruno | 2009-11-11 13:29:27 +0100

  • Adds a nolvm boot option at restore time


r3604@localhost (orig r2478): bruno | 2009-11-11 19:54:51 +0100

  • Fix #367 - the for loop doesn't make any test now, as it was computed before entering the loop, leading to an error, and was also made inside the loop anyway.


r3605@localhost (orig r2479): bruno | 2009-11-12 00:32:45 +0100

  • Add support for diskdumplib driver useful for RHEL 3 and IBM xseries 336


r3606@localhost (orig r2480): bruno | 2009-11-12 01:09:40 +0100

  • If using nolvm, mondorestore should also not nalyze and handle i-want-my-lvm


r3608@localhost (orig r2482): bruno | 2009-11-14 12:54:11 +0100
Fix bunzip2 on debian as well


r3610@localhost (orig r2484): bruno | 2009-11-15 00:44:19 +0100

  • Adds support for variable serial port console, with defalut to /dev/ttyS0, and a boot param to change it with serial=/dev/ttySx


r3615@localhost (orig r2485): bruno | 2009-11-15 01:34:33 +0100

r3614@localhost: bruno | 2009-11-15 01:34:12 +0100
Adds a space in exclude paths


r3623@localhost (orig r2487): bruno | 2009-11-18 20:41:40 +0100

r3620@localhost: bruno | 2009-11-18 10:31:36 +0100

  • Only link /dev/tty to serial port when there is indeed a serial port. If not breaks mondorestore on normal console


r3631@localhost (orig r2490): bruno | 2009-11-24 01:48:29 +0100
Put news below in the main page to make it more readable


r3648@localhost (orig r2492): bruno | 2009-11-25 23:50:13 +0100

r3647@localhost: bruno | 2009-11-25 23:49:11 +0100

  • Add warning for -f and SW Raid as in 2.2.10


r3650@localhost (orig r2493): bruno | 2009-11-26 00:19:52 +0100

r3649@localhost: bruno | 2009-11-26 00:18:27 +0100

  • Addition of the german translation made by Magnus Rasche (Magnus.rasche_at_gmx.de) and Website inclusion


r3652@localhost (orig r2495): bruno | 2009-11-27 15:55:55 +0100
cosmetic display fix
r3659@localhost (orig r2498): bruno | 2009-12-05 17:53:03 +0100
nfsopt restore boot time option added to support custom mount options for network restore


r3684@localhost (orig r2501): bruno | 2009-12-17 00:35:08 +0100
Fix #375 mondo will segfault if the partition in sensibly_set_tmpdir_and_scratchdir() is read-only (cylau)


r3685@localhost (orig r2502): bruno | 2009-12-17 01:02:47 +0100

  • Fix an issue in the function listing kernel modules when not found


r3686@localhost (orig r2503): bruno | 2009-12-17 01:15:01 +0100
Adds scsi_dump_register to mindi SCSI_MODS for RHEL3 + IBM servers


r3701@localhost (orig r2504): bruno | 2009-12-23 02:24:33 +0100

  • Addition of the Lab for Mondorescue


r3702@localhost (orig r2505): bruno | 2009-12-23 02:41:17 +0100
Web site update for Lab MondoRescue delivery


r3706@localhost (orig r2506): bruno | 2010-01-04 11:31:53 +0100

  • Fix a bug when isodir is / only when splitting it in iso_path and iso_mnt


r3707@localhost (orig r2507): bruno | 2010-01-04 13:22:49 +0100

  • Fix #377: Segfault in pause_and_ask_for_cdr() (ggeens)


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