source: MondoRescue/branches/2.2.9/mondo/src/common/libmondo-cli.c@ 2223

Last change on this file since 2223 was 2223, checked in by Bruno Cornec, 15 years ago

mount the NFS dir in mondoarchive, if not already mounted, but present in fstab. Also avoids issue with trailing /. Should fix #304.

  • Property svn:keywords set to Id
File size: 50.1 KB
RevLine 
[1]1/***************************************************************************
[2085]2$Id: libmondo-cli.c 2223 2009-06-17 01:38:48Z bruno $
[1]3*******************************************************************/
4
5/**
6 * @file
7 * Functions for handling command-line arguments passed to mondoarchive.
8 */
9
10/** @def BOOT_LOADER_CHARS The characters allowed for boot loader on this platform. */
11
12#include <pthread.h>
[1917]13#include "my-stuff.h"
[2211]14#include "mr_mem.h"
15#include "mr_string.h"
[1917]16#include "mondostructures.h"
17#include "libmondo-cli-EXT.h"
18#include "libmondo.h"
[1]19
20extern int g_loglevel;
21extern bool g_text_mode;
[116]22extern char g_startdir[MAX_STR_LEN]; ///< ????? @bug ?????
[1917]23extern char *MONDO_OPTIONS;
[1]24
25/*@ file pointer **************************************************/
26extern FILE *g_tape_stream;
27
28/*@ long long *****************************************************/
29extern long long g_tape_posK;
30
31/*@ long **********************************************************/
32extern long g_noof_sets;
33
34/*@ bool******** **************************************************/
[116]35bool g_debugging = FALSE; ///< ????? @bug ????? @ingroup globalGroup
36bool g_running_live = FALSE; ///< ????? @bug ????? @ingroup globalGroup
[1]37extern bool g_cd_recovery;
38
[1656]39extern void setup_tmpdir(char *path);
[1]40extern double g_kernel_version;
41extern int g_current_media_number;
42extern pid_t g_main_pid;
[116]43extern char *resolve_softlinks_to_get_to_actual_device_file(char *);
[1]44
[2007]45/* Stuff that handles the -I and -E option when a whole disk DSF is used */
46typedef struct mounted_fs_struct {
47 char device[MAX_STR_LEN]; /* The name of the device */
48 char mount_point[MAX_STR_LEN]; /* The devices mount point */
49 unsigned char check; /* 1 == included on DSF */
50 struct mounted_fs_struct *next;
51} MOUNTED_FS_STRUCT;
52static MOUNTED_FS_STRUCT *DSF_Head = NULL; /* Points to the first entry of mounted_fs_struct list */
53static MOUNTED_FS_STRUCT *DSF_Tail = NULL; /* Points to the last entry of mounted_fs_struct list */
54static void add_mounted_fs_struct (MOUNTED_FS_STRUCT *DSFptr);
55static void free_mounted_fs_list (void);
56static int get_dsf_mount_list (const char *dsf, char **included_dsf_list, char **excluded_dsf_list);
57static int create_list_of_non_NFS_mounted_file_systems (void);
58static MOUNTED_FS_STRUCT *find_mount_point_in_list (char *mount_point);
59static MOUNTED_FS_STRUCT *find_device_in_list (char *device);
60
[948]61/* Do we use extended attributes and acl ?
62 * By default no, use --acl & --attr options to force their usage */
[1917]63extern char *g_getfacl;
64extern char *g_getfattr;
[1]65
[1645]66/* Reference to global bkpinfo */
67extern struct s_bkpinfo *bkpinfo;
68
[1967]69extern void free_MR_global_filenames(void);
70
[1]71/**
72 * @addtogroup cliGroup
73 * @{
74 */
75/**
76 * Populate @p bkpinfo from the command-line parameters stored in @p argc and @p argv.
77 * @param argc The argument count, including the program name; @p argc passed to main().
78 * @param argv The argument vector; @p argv passed to main().
79 * @param bkpinfo The backup information structure to populate.
80 * @return The number of problems with the command line (0 for success).
81 */
82int
[1645]83handle_incoming_parameters(int argc, char *argv[])
[1]84{
[116]85 /*@ int *** */
86 int res = 0;
87 int retval = 0;
88 int i = 0, j;
[1]89
[116]90 /*@ buffers *************** */
91 char *tmp;
92 char flag_val[128][MAX_STR_LEN];
93 bool flag_set[128];
[1]94
[1702]95 tmp = malloc(9*MAX_STR_LEN);
[116]96 for (i = 0; i < 128; i++) {
97 flag_val[i][0] = '\0';
98 flag_set[i] = FALSE;
99 }
100 for (j = 1; j <= MAX_NOOF_MEDIA; j++) {
101 bkpinfo->media_size[j] = 650;
102 } /* default */
103 res =
104 retrieve_switches_from_command_line(argc, argv, flag_val,
105 flag_set);
106 retval += res;
107 if (!retval) {
[1645]108 res = process_switches(flag_val, flag_set);
[116]109 retval += res;
110 }
[1]111/*
112 if (!retval)
113 {
114*/
[116]115 log_msg(3, "Switches:-");
116 for (i = 0; i < 128; i++) {
117 if (flag_set[i]) {
118 sprintf(tmp, "-%c %s", i, flag_val[i]);
119 log_msg(3, tmp);
120 }
[1]121 }
122// }
[116]123 sprintf(tmp, "rm -Rf %s/tmp.mondo.*", bkpinfo->tmpdir);
124 paranoid_system(tmp);
125 sprintf(tmp, "rm -Rf %s/mondo.scratch.*", bkpinfo->scratchdir);
126 paranoid_system(tmp);
127 sprintf(bkpinfo->scratchdir + strlen(bkpinfo->scratchdir),
128 "/mondo.scratch.%ld", random() % 32767);
129 sprintf(tmp, "mkdir -p %s/tmpfs", bkpinfo->tmpdir);
130 paranoid_system(tmp);
131 sprintf(tmp, "mkdir -p %s", bkpinfo->scratchdir);
132 paranoid_system(tmp);
133 paranoid_free(tmp);
134 return (retval);
[1]135}
136
137
138
139
140/**
141 * Store the sizespec(s) stored in @p value into @p bkpinfo.
142 * @param bkpinfo The backup information structure; the @c bkpinfo->media_size field will be populated.
143 * @param value The sizespec (e.g. "2g", "40m").
144 * @return 0, always.
145 * @bug Return code not needed.
146 */
[1645]147int process_the_s_switch(char *value)
[1]148{
[116]149 int j;
150 char tmp[MAX_STR_LEN], *p, comment[MAX_STR_LEN];
[1]151
[116]152 assert(bkpinfo != NULL);
153 assert(value != NULL);
[1]154
[116]155 bkpinfo->media_size[0] = -1; /* dummy value */
156 for (j = 1, p = value; j < MAX_NOOF_MEDIA && strchr(p, ',');
157 j++, p = strchr(p, ',') + 1) {
158 strncpy(tmp, p, MAX_STR_LEN);
159 *(strchr(tmp, ',')) = '\0';
160 bkpinfo->media_size[j] = friendly_sizestr_to_sizelong(tmp);
161 sprintf(comment, "media_size[%d] = %ld", j,
162 bkpinfo->media_size[j]);
163 log_msg(3, comment);
[1]164 }
[116]165 for (; j <= MAX_NOOF_MEDIA; j++) {
166 bkpinfo->media_size[j] = friendly_sizestr_to_sizelong(p);
[1]167 }
168// bkpinfo->media_size[0] = bkpinfo->media_size[MAX_NOOF_MEDIA];
[116]169 for (j = 1; j <= MAX_NOOF_MEDIA; j++) {
170 if (bkpinfo->media_size[j] <= 0) {
171 log_msg(1, "You gave media #%d an invalid size\n", j);
172 return (-1);
173 }
174 }
175 return (0);
[1]176}
177
[2007]178/**
179 * Frees the memory for all of the structures on the linked list of
180 * all of the non-NFS mounted file systems.
181 */
182static void free_mounted_fs_list (void) {
183 MOUNTED_FS_STRUCT *DSFptr = NULL;
184 MOUNTED_FS_STRUCT *DSFnext = NULL;
185
186 DSFptr = DSF_Head;
187 while (DSFptr != NULL) {
188 DSFnext = DSFptr->next;
189 paranoid_free(DSFptr);
190 DSFptr = DSFnext;
191 }
192 DSF_Head = NULL;
193 DSF_Tail = NULL;
194}
[1]195
[2007]196/**
197 * Creates a singly linked list of all of the non-NFS mounted file systems.
198 * @param DSFptr A pointer to the structure MOUNTED_FS_STRUCT used to hold
199 * the list of mounted file systems.
200 * @return None.
201 */
202static void add_mounted_fs_struct (MOUNTED_FS_STRUCT *DSFptr)
203{
204 assert (DSFptr);
205 if (DSF_Head == NULL) {
206 DSF_Head = DSFptr;
207 } else {
208 DSF_Tail->next = DSFptr;
209 }
210 DSFptr->next = NULL;
211 DSF_Tail = DSFptr;
212}
[1]213
214/**
[2007]215 * Find the structure, in the singly linked list of all of the non-NFS
216 * mounted file systems, that contains the specified device.
217 * @param device The device to find
218 * @return NULL if it didn't find the device, a pointer to the
219 * structure if it did.
220 */
221static MOUNTED_FS_STRUCT *find_device_in_list (char *device)
222{
223 MOUNTED_FS_STRUCT *DSFptr = NULL;
224
225 DSFptr = DSF_Head;
226 while (DSFptr != NULL) {
227 if (!strcmp(DSFptr->device, device)) {
228 break;
229 }
230 DSFptr = DSFptr->next;
231 }
232 return (DSFptr);
233}
234
235/**
236 * Find the structure, in the singly linked list of all of the non-NFS
237 * mounted file systems, that contains the specified mount point.
238 * @param mount_point The mount point to find
239 * @return NULL is it didn't find the mount point, a pointer to the
240 * structure if it did.
241 */
242static MOUNTED_FS_STRUCT *find_mount_point_in_list (char *mount_point)
243{
244 MOUNTED_FS_STRUCT *DSFptr = NULL;
245
246 DSFptr = DSF_Head;
247 while (DSFptr != NULL) {
248 if (!strcmp(DSFptr->mount_point, mount_point)) {
249 break;
250 }
251 DSFptr = DSFptr->next;
252 }
253 return (DSFptr);
254}
255
256/**
257 * Creates a linked list of all of the non-NFS mounted file systems.
258 * We use a linked list because we don't know how many mounted file
259 * there are (and there can be a lot).
260 * @return 0 on success and greated than 0 on failure.
261 */
262static int create_list_of_non_NFS_mounted_file_systems (void)
263{
264 int i = 0;
265 int mount_cnt = 0;
266 char *mounted_file_system = NULL;
267 char *command = NULL;
268 char *token = NULL;
269 char token_chars[] =" :\t\r\f\a\0";
270 MOUNTED_FS_STRUCT *DSFptr = NULL;
271
272 free_mounted_fs_list();
273 /********
274 * Find the number of mounted file system entries and their respective mount points.
275 * I can't return all of the entries as one string because it's length can be longer
276 * than MAX_STR_LEN which is used in call_program_and_get_last_line_of_output().
277 * So start looping and get the number of mounted file systems and query them one by one.
278 ********/
279 /* Get the number of mounted file systems ((those that start with "/dev/" */
[2211]280 mr_asprintf(&command, "mount 2>/dev/null | awk '{if($1 ~ \"^/dev/\"){print $0}}'|wc -l");
[2007]281 log_msg(5, "Running: %s", command);
[2211]282 mr_asprintf(&mounted_file_system, "%s", call_program_and_get_last_line_of_output(command));
[2007]283 paranoid_free(command);
284
285 mount_cnt = atoi(mounted_file_system);
286 log_msg (5, "mount_cnt: %d", mount_cnt);
287 paranoid_free(mounted_file_system);
288
289 for (i=mount_cnt; i > 0; i--) {
[2211]290 mr_asprintf(&command, "mount 2>/dev/null | awk '{if($1 ~ \"^/dev/\"){print $1,$3}}'|head -n %d", i);
[2007]291 log_msg(5, "Running: %s", command);
[2211]292 mr_asprintf(&mounted_file_system, "%s", call_program_and_get_last_line_of_output(command));
[2007]293 paranoid_free(command);
294
295 log_msg (5, "mounted_file_system: %s", mounted_file_system);
296 if ((token = strtok(mounted_file_system, token_chars)) == NULL) {
297 log_msg (4, "Could not get the list of mounted file systems");
298 paranoid_free(mounted_file_system);
299 return (1);
300 }
301 log_msg (5, "token: %s", token);
302 while (token != NULL) {
303 log_msg (5, "token: %s", token);
304 if ((DSFptr = (MOUNTED_FS_STRUCT *) calloc(1, sizeof(MOUNTED_FS_STRUCT))) == NULL) {
305 fatal_error ("Cannot allocate memory");
306 }
307 add_mounted_fs_struct(DSFptr);
308 strcpy(DSFptr->device, token);
309 if ((token = strtok(NULL, token_chars)) == NULL) {
310 log_msg (5, "Ran out of entries on the mounted file systems list");
[2022]311 paranoid_free(mounted_file_system);
[2007]312 return (1);
313 }
314 log_msg (5, "token: %s", token);
315 strcpy(DSFptr->mount_point, token);
316 token = strtok(NULL, token_chars);
317 }
[2022]318 paranoid_free(mounted_file_system);
[2007]319 }
320 /********
321 * DSFptr = DSF_Head;
322 * while (DSFptr != NULL) {
323 * printf ("Dev: %s MP: %s Check: %d\n", DSFptr->device, DSFptr->mount_point, DSFptr->check);
324 * DSFptr = DSFptr->next;
325 * }
326 ********/
327 return (0);
328}
329
330/**
331 * Given a whole disk device special file, determine which mounted file systems
332 * are on the dsf's partitions and which mounted file systems are not.
333 * @param dsf The whole disk device special file.
334 * @param included_dsf_list A char pointer used to hold the list of mount points
335 * that are on the dsf. Memory for the array will be allocated within the function.
336 * @param excluded_dsf_list A char pointer used to hold the list of mount points
337 * that are not on the dsf. Memory for the array will be allocated within the function.
338 * @return 0 on success, -1 if no device special file was passed in, -2 if a device
339 * special file was passed in but it has no partitions on it, or 1 on failure
340 */
341static int get_dsf_mount_list (const char *dsf, char **included_dsf_list, char **excluded_dsf_list) {
342 int i = 0;
343 int c = 0;
[2022]344 int lastpos = 0;
[2007]345 char VG[MAX_STR_LEN];
346 char *tmp = NULL;
347 char *command = NULL;
348 char *partition_list = NULL;
349 char partitions[64][MAX_STR_LEN];
350 char *mount_list = NULL;
351 char *token = NULL;
352 char token_chars[] =" \t\r\f\a\0";
353 MOUNTED_FS_STRUCT *DSFptr = NULL;
354
355 memset((char *)partitions, 0, sizeof(partitions));
356
[2022]357 log_msg(5, "dsf: %s", dsf);
358
359 /********
360 * See if a device special file was passed in (i.e. it must start with /dev/
361 ********/
362 if (strncmp(dsf, "/dev/", 5)) {
363 log_msg (5, "%s does not start with /dev/ and (probably) is not a device special file", dsf);
364 return (-1);
[2007]365 }
[2022]366 log_msg(5, " %s looks like a device special file", dsf);
367 /* Verify that the dsf exists */
[2211]368 mr_asprintf(&command, "ls -al %s 2>/dev/null | wc -l", dsf);
[2022]369 log_msg(5, " Executing: %s", command);
[2211]370 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
[2022]371 paranoid_free(command);
372
373 log_msg(5, " Return value: %s", tmp);
374 c = atoi(tmp);
375 paranoid_free(tmp);
376
377 if (!c) {
378 log_to_screen("Cannot find device special file %s", dsf);
379 return (1);
380 }
381 log_msg(5, " %s device special file exists", dsf);
[2007]382
383 /* Get a list of the mounted file systems */
384 if (create_list_of_non_NFS_mounted_file_systems()) {
385 log_to_screen ("Could not get the list of mounted file systems");
386 return (1);
387 }
[2022]388 log_msg (5, "Processing dsf: %s", dsf);
389 /********
390 * Get a list of the dsf's partitions. There could be no partitions on the disk
391 * or a dsf of a partition was passed in (e.g. /dev/sda1 instead of /dev/sda).
392 * Either way, it's an error.
393 ********/
[2211]394 mr_asprintf(&command,
[2222]395 "parted2fdisk -l %s 2>/dev/null|grep -E \"^/dev/\"|awk '{printf(\"%%s \", $1)}END{print \"\"}'", dsf);
[2022]396 log_msg(4, "Executing: %s", command);
[2211]397 mr_asprintf(&partition_list, "%s", call_program_and_get_last_line_of_output(command));
[2022]398 paranoid_free(command);
399 log_msg(4, "Partition list for %s: %s", dsf, partition_list);
400 if (!strlen(partition_list)) {
401 /* There were no partitions on the disk */
402 log_msg(4, "Cannot find any partitions on device special file %s", dsf);
403 return (-2);
404 }
[2007]405
[2022]406 /* Fill the partition list */
407 i = 0;
408 lastpos = 0;
[2053]409 while ((token = mr_strtok(partition_list, token_chars, &lastpos)) != NULL) {
[2022]410 log_msg (5, "Found partition: %s", token);
411 strcpy(partitions[i++], token);
412 }
413 paranoid_free(partition_list);
[2007]414
[2022]415 /********
416 * At this point, we have a list of all of the partitions on the dsf. Now try to
417 * see which partitions have a file system on them.
418 *
419 * Loop through each partition on the disk and:
420 *
421 * - If the partition is swap, it ignores it.
422 *
423 * - If the partition is mounted (e.g. /dev/sda1 is mounted on /boot), it adds an entry
424 * to the linked list, copies to it the device name and mount point, and sets check == 1.
425 *
426 * - If the partition is part of a Volume Group that has Logical Volumes mounted, it adds
427 * an entry to the linked list for each mounted Logical Volume in that Volume Group, copying
428 * to it the device name and mount point, and sets check == 1. Note that if the Volume Group
429 * contains more than one disk, it will still add the entry even if the Logical Volume's
430 * extents are not on the dsf that was passed in to the function. For example, Volume Group
431 * VolGroup00 contains the disks /dev/sda1 and /dev/sdb1, and the Logical Volumes LogVol01,
432 * which is mounted on /var and has all of its extents on /dev/sda1, and LogVol02, which is
433 * mounted as /usr and has all of its extents on /dev/sdb1. If you pass /dev/sda into the
434 * function, both /var and /usr will be archived even though /usr is actually on/dev/sdb.
435 *
436 * - If the partition is part of a Volume Group that has Logical Volumes used in a mounted
437 * software raid device, it adds an entry to the linked list, copies to it the software raid
438 * device name and mount point, and sets check == 1.
439 *
440 * - If the partition is part of a mounted software raid device, it adds an entry to the linked
441 * list, copies to it the software raid device name and mount point, and sets check == 1.
442 *
443 ********/
444 for (i=0; strlen(partitions[i]); i++) {
445 log_msg(4, "Processing partition: %s", partitions[i]);
446 /* See if it's swap. If it is, ignore it. */
[2211]447 mr_asprintf(&command,
[2222]448 "parted2fdisk -l %s 2>/dev/null | awk '{if(($1==\"%s\")&&(toupper($0) ~ \"SWAP\")){print $1;exit}}'",
[2022]449 dsf, partitions[i]);
450 log_msg(4, " Running: %s", command);
[2211]451 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
[2022]452 paranoid_free(command);
453 log_msg(4, " Return value: %s", tmp);
454 c = strlen(tmp);
455 paranoid_free(tmp);
456 if (c) {
457 log_msg(4, "It's swap. Ignoring partition %s", partitions[i]);
458 continue;
459 }
460 /* It's not swap. See if we can find the mount point from the mount command. */
[2211]461 mr_asprintf(&command, "mount 2>/dev/null | awk '{if((NF>0)&&($1==\"%s\")){print $3}}'", partitions[i]);
462 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
[2022]463 paranoid_free(command);
464 if (strlen(tmp)) {
465 log_msg(4, " %s is mounted: %s", partitions[i], tmp);
466 if ((DSFptr = find_mount_point_in_list(tmp)) == NULL) {
467 log_msg (4, "Can't find mount point %s in mounted file systems list", tmp);
[2007]468 paranoid_free(tmp);
[2022]469 return (1);
[2007]470 }
[2022]471 DSFptr->check = 1;
[2007]472 paranoid_free(tmp);
[2022]473 continue;
474 }
475 paranoid_free(tmp);
476 /* It's not swap and it's not mounted. See if it's LVM */
477 log_msg(4, " It's not mounted. Checking to see if it's LVM...");
478 /* Get the partition ID; 8e for LVM */
[2222]479 mr_asprintf(&command, "parted2fdisk -l %s |awk '{if($1 ~ \"^%s\"){print $5}}'", dsf, partitions[i]);
[2022]480 log_msg(4, " Running: %s", command);
[2211]481 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
[2022]482 paranoid_free(command);
483 if (strlen(tmp)) {
484 log_msg(4, " Partition ID: %s", tmp);
485 if (!strcasecmp(tmp, "8e")) {
486 /* It's LVM: Find the VG it's in */
487 log_msg(4, " It's LVM: Find the VG it's in...");
[2211]488 mr_asprintf(&command, "pvdisplay -v %s 2>/dev/null|grep \"VG Name\"|awk '{print $NF}'", partitions[i]);
[2022]489 log_msg(4, " Running: %s", command);
490 strcpy(VG, call_program_and_get_last_line_of_output(command));
491 paranoid_free(command);
492 log_msg(4, " Volume Group: %s", VG);
493 if (strlen(VG)) {
494 /* Found the Volume Group. Now find all of the VG's mount points */
495 log_msg(4, " Found the Volume Group. Now find all of the VG's mount points");
[2211]496 mr_asprintf(&command,
[2022]497 "mount 2>/dev/null|grep -E \"/dev/mapper/%s-|/dev/%s/\"|awk '{printf(\"%%s \",$3)}END{print \"\"}'",
498 VG, VG);
[2007]499 log_msg(4, " Running: %s", command);
[2211]500 mr_asprintf(&mount_list, "%s", call_program_and_get_last_line_of_output(command));
[2007]501 paranoid_free(command);
[2022]502 log_msg(4, " VG %s mount_list: %s", VG, mount_list);
503 lastpos = 0;
[2053]504 while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
[2022]505 log_msg (5, "mount point token: %s", token);
506 if ((DSFptr = find_mount_point_in_list(token)) == NULL) {
507 log_msg (4, "Can't find mount point %s in mounted file systems list", token);
508 paranoid_free(tmp);
509 return (1);
510 }
511 DSFptr->check = 1;
512 }
513 /********
514 * Now we want to see if there are any software raid devices using
515 * any of the Logical Volumes on the Volume Group.
516 *******/
517 paranoid_free(mount_list);
[2211]518 mr_asprintf(&command, "%s",
[2022]519 "cat /proc/mdstat|grep -iv Personal|awk '{if($0~\"^.*[ ]+:\"){printf(\"/dev/%s \", $1)}}END{print \"\"}'");
520 log_msg (5, "Running: %s", command);
[2211]521 mr_asprintf(&mount_list, "%s", call_program_and_get_last_line_of_output(command));
[2022]522 paranoid_free(command);
523 log_msg(4, " Software raid device list: %s", mount_list);
524 lastpos = 0;
[2053]525 while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
[2211]526 mr_asprintf(&command, "mdadm --detail %s 2>/dev/null | grep -c %s", token, VG);
[2022]527 log_msg (5, "Running: %s", command);
528 paranoid_free(tmp);
[2211]529 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
[2007]530 paranoid_free(command);
[2022]531 log_msg(4, "Number of Software raid device: %s", tmp);
532 if (atoi(tmp)) {
533 /* This device is on our disk */
534 if ((DSFptr = find_device_in_list(token)) == NULL) {
535 log_msg (4, "Can't find device %s in mounted file systems list", token);
[2007]536 paranoid_free(tmp);
537 return (1);
538 }
539 DSFptr->check = 1;
540 }
541 }
[2022]542 paranoid_free(mount_list);
543 } else {
544 log_msg (4, "Error finding Volume Group for partition %s", partitions[i]);
[2007]545 paranoid_free(tmp);
[2022]546 return (1);
[2007]547 }
[2022]548 paranoid_free(tmp);
549 continue;
[2007]550 }
[2022]551 } else {
552 log_msg (4, "Error finding partition type for the partition %s", partitions[i]);
553 }
554 paranoid_free(tmp);
555 /********
556 * It's not swap, mounted, or LVM. See if it's used in a software raid device.
557 ********/
558 log_msg (5, "It's not swap, mounted, or LVM. See if it's used in a software raid device.");
[2211]559 mr_asprintf(&command, "mdadm --examine %s 2>/dev/null | awk '{if($1 == \"UUID\"){print $3}}'", partitions[i]);
[2022]560 log_msg(4, " Running: %s", command);
[2211]561 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
[2022]562 paranoid_free(command);
563 if (!strlen(tmp)) {
564 log_msg(4, " Partition %s is not used in a non-LVM software raid device", partitions[i]);
[2007]565 paranoid_free(tmp);
[2022]566 continue;
567 }
568 log_msg (5, " UUID: %s", tmp);
569 /* Get the Software raid device list */
[2211]570 mr_asprintf(&command, "%s",
[2022]571 "cat /proc/mdstat|grep -iv Personal|awk '{if($0~\"^.*[ ]+:\"){printf(\"/dev/%s \", $1)}}END{print \"\"}'");
572 log_msg (5, " Running: %s", command);
[2211]573 mr_asprintf(&mount_list, "%s", call_program_and_get_last_line_of_output(command));
[2022]574 paranoid_free(command);
575 log_msg(4, " Software raid device list: %s", mount_list);
576 /* Loop through the software raid device list to see if we can find the partition */
577 lastpos = 0;
[2053]578 while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
[2211]579 mr_asprintf(&command, "mdadm --detail %s 2>/dev/null | grep -c %s", token, tmp);
[2007]580 log_msg(4, " Running: %s", command);
[2022]581 paranoid_free(tmp);
[2211]582 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
[2007]583 paranoid_free(command);
[2022]584 if (!atoi(tmp)) {
585 log_msg (4," Didn't find partition %s in software raid device %s", partitions[i], token);
586 } else {
587 if ((DSFptr = find_device_in_list(token)) == NULL) {
588 log_msg (4, "Can't find device %s in mounted file systems list", token);
589 paranoid_free(tmp);
590 return (1);
[2007]591 }
[2022]592 DSFptr->check = 1;
593 break;
[2007]594 }
595 }
[2022]596 paranoid_free(tmp);
[2007]597 }
598 paranoid_free(partition_list);
599 paranoid_free(mount_list);
600
601 /* Determine how much memory to allocate for included_dsf_list and excluded_dsf_list */
602 i = 0;
603 DSFptr= DSF_Head;
604 while (DSFptr != NULL) {
605 i += strlen(DSFptr->mount_point) + 1;
606 DSFptr = DSFptr->next;
607 }
608 log_msg (5, "i: %d", i);
609 if ((*included_dsf_list = (char *) calloc(i+100, sizeof(char))) == NULL) {
610 fatal_error ("Cannot allocate memory");
611 }
612 if ((*excluded_dsf_list = (char *) calloc(i+100, sizeof(char))) == NULL) {
613 fatal_error ("Cannot allocate memory");
614 }
615 DSFptr= DSF_Head;
616 while (DSFptr != NULL) {
617 if (DSFptr->check) {
618 log_msg (5, "%s is mounted on %s and is on disk %s\n", DSFptr->device, DSFptr->mount_point, dsf);
619 strcat(*included_dsf_list, DSFptr->mount_point);
620 strcat(*included_dsf_list, " ");
621 } else {
622 log_msg (4, "%s is mounted on %s and is NOT on disk %s\n", DSFptr->device, DSFptr->mount_point, dsf);
623 strcat(*excluded_dsf_list, DSFptr->mount_point);
624 strcat(*excluded_dsf_list, " ");
625 }
626 DSFptr = DSFptr->next;
627 }
628 log_msg (5, "included_dsf_list: %s", *included_dsf_list);
629 log_msg (5, "excluded_dsf_list: %s", *excluded_dsf_list);
630 return (0);
631}
632
633
634/**
[1]635 * Process mondoarchive's command-line switches.
636 * @param bkpinfo The backup information structure to populate.
637 * @param flag_val An array of the argument passed to each switch (the letter is the index).
638 * If a switch is not set or has no argument, the field in @p flag_val doesn't matter.
639 * @param flag_set An array of <tt>bool</tt>s indexed by switch letter: TRUE if it's set,
640 * FALSE if it's not.
641 * @return The number of problems with the switches, or 0 for success.
642 * @bug Maybe include a list of all switches (inc. intentionally undocumented ones not in the manual!) here?
643 */
644int
[1645]645process_switches(char flag_val[128][MAX_STR_LEN], bool flag_set[128])
[1]646{
647
[116]648 /*@ ints *** */
649 int i = 0;
650 int retval = 0;
651 int percent = 0;
[2022]652 int lastpos = 0;
[1]653
[116]654 /*@ buffers ** */
[2022]655 char *tmp = NULL;
656 char *tmp1 = NULL;
657 char *psz = NULL;
658 char *p = NULL;
659 char *q = NULL;
660 char *token = NULL;
[2007]661 char *mounted_on_dsf = NULL;
662 char *not_mounted_on_dsf = NULL;
[2022]663 char token_chars[] =" \t\r\f\a\0";
[1]664
[949]665 long itbs = 0L;
[1]666
[289]667 struct stat buf;
668
[116]669 malloc_string(tmp);
[1]670
[116]671 assert(bkpinfo != NULL);
672 assert(flag_val != NULL);
673 assert(flag_set != NULL);
[1]674
[116]675 bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
[1]676
[1967]677 /* compulsory */
[116]678 i = flag_set['c'] + flag_set['i'] + flag_set['n'] +
679 flag_set['t'] + flag_set['u'] + flag_set['r'] +
[1690]680 flag_set['w'] + flag_set['C'] + flag_set['U'];
[1967]681 if ((i == 0) && (! bkpinfo->restore_data)) {
[116]682 retval++;
[541]683 log_to_screen("You must specify the media type\n");
[1]684 }
[116]685 if (i > 1) {
686 retval++;
[541]687 log_to_screen("Please specify only one media type\n");
[1]688 }
[1967]689
[116]690 if (flag_set['K']) {
691 g_loglevel = atoi(flag_val['K']);
[1945]692 log_msg(1,"Loglevel forced to %d",g_loglevel);
[116]693 if (g_loglevel < 3) {
694 g_loglevel = 3;
695 }
[1]696 }
[1967]697
698 if ((flag_set['L'] && flag_set['0']) && (! bkpinfo->restore_data)) {
[116]699 retval++;
[541]700 log_to_screen("You cannot have 'no compression' _and_ LZOP.\n");
[1]701 }
[1967]702 if (! bkpinfo->restore_data) {
703 bkpinfo->backup_data = flag_set['O'];
704 }
[116]705 bkpinfo->verify_data = flag_set['V'];
[1967]706
[116]707 if (flag_set['I'] && !bkpinfo->backup_data) {
[541]708 log_to_screen("-I switch is ignored if just verifying");
[116]709 }
710 if (flag_set['E'] && !bkpinfo->backup_data) {
[541]711 log_to_screen("-E switch is ignored if just verifying");
[116]712 }
[1]713
[116]714 if (!find_home_of_exe("afio")) {
715 if (find_home_of_exe("star")) {
716 flag_set['R'] = TRUE;
717 log_msg(1, "Using star instead of afio");
718 } else {
719 fatal_error
720 ("Neither afio nor star is installed. Please install at least one.");
721 }
[1]722 }
723
[116]724 if (flag_set['R']) {
725 bkpinfo->use_star = TRUE;
726 if (flag_set['L']) {
727 fatal_error("You may not use star and lzop at the same time.");
728 }
729 if (!find_home_of_exe("star")) {
730 fatal_error
731 ("Please install 'star' RPM or tarball if you are going to use -R. Thanks.");
732 }
[1]733 }
[1967]734
735 if ((flag_set['W']) && (! bkpinfo->restore_data)) {
[116]736 bkpinfo->nonbootable_backup = TRUE;
737 log_to_screen("Warning - you have opted for non-bootable backup");
738 if (flag_set['f'] || flag_set['l']) {
739 log_to_screen
[541]740 ("You don't need to specify bootloader or bootdevice");
[116]741 }
[1]742 }
[1967]743
[116]744 if (flag_set['I']) {
[2022]745 if (bkpinfo->include_paths[0] == '-') {
746 retval++;
747 log_to_screen("Please supply a sensible value with '-I'\n");
748 }
[116]749 if (!strcmp(bkpinfo->include_paths, "/")) {
750 log_msg(2, "'/' is pleonastic.");
751 bkpinfo->include_paths[0] = '\0';
752 }
753 if (bkpinfo->include_paths[0]) {
754 strcat(bkpinfo->include_paths, " ");
755 }
[2022]756
[2211]757 mr_asprintf(&tmp1, "%s", flag_val['I']);
[2022]758 p = tmp1;
759 q = tmp1;
760
761 /* Cut the flag_val['I'] in parts containing all paths to test them */
762 while (p != NULL) {
763 q = strchr(p, ' ');
764 if (q != NULL) {
765 *q = '\0';
766 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
767 log_msg(1, "ERROR ! %s doesn't exist", p);
768 fatal_error("ERROR ! You specified a directory to include which doesn't exist");
769 }
770 p = q+1 ;
771 } else {
772 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
773 log_msg(1, "ERROR ! %s doesn't exist", p);
774 fatal_error("ERROR ! You specified a directory to include which doesn't exist");
775 }
776 p = NULL;
777 }
778 }
779 paranoid_free(tmp1);
[2053]780 while ((token = mr_strtok(flag_val['I'], token_chars, &lastpos)) != NULL) {
[2022]781 switch (get_dsf_mount_list(token, &mounted_on_dsf, &not_mounted_on_dsf)) {
[2007]782 /* It's a dsf but not a whole disk dsf */
783 case -2:
[2022]784 log_to_screen("Could %s be a partition instead of a whole disk device special file?\n Ignored.", token);
[2007]785 break;
786 /* Fatal error; exit */
787 case 1:
788 fatal_error("Error processing -I option");
789 /* Everything is OK; process to archive data */
790 case 0:
[2022]791 log_to_screen("Archiving only the following file systems on %s:\n", token);
[2007]792 log_to_screen(" %s\n", mounted_on_dsf);
793 strcpy(bkpinfo->include_paths, "/");
794 if (strlen(not_mounted_on_dsf)) {
795 log_msg (5, "Adding to bkpinfo->exclude_paths due to -I option: %s", not_mounted_on_dsf);
796 log_to_screen("Not archiving the following file systems:\n");
797 log_to_screen(" %s\n", not_mounted_on_dsf);
798 strcat(bkpinfo->exclude_paths, not_mounted_on_dsf);
799 strcat(bkpinfo->exclude_paths, "");
800 }
801 break;
802 /* A device special file was not passed in. Process it as a path. */
803 case -1:
[2022]804 strcat(bkpinfo->include_paths, token);
805 strcat(bkpinfo->include_paths, " ");
[2007]806 break;
[542]807 }
[2022]808 }
809 log_msg(1, "include_paths is now '%s'", bkpinfo->include_paths);
810 if (bkpinfo->exclude_paths != NULL) {
811 log_msg(1, "exclude_paths is now '%s'", bkpinfo->exclude_paths);
812 }
813 log_msg(4, "Finished with the -I option");
[116]814 }
[1]815
[116]816 if (g_kernel_version >= 2.6 && !flag_set['d']
[1967]817 && (flag_set['c'] || flag_set['w']) && (! bkpinfo->restore_data)) {
[116]818 fatal_error
819 ("If you are using the 2.6.x kernel, please specify the CD-R(W) device.");
[1]820 }
821
[116]822
823 if (flag_set['J']) {
824 if (flag_set['I']) {
825 retval++;
826 log_to_screen
[541]827 ("Please do not use -J in combination with -I. If you want to make a list of files to backup, that's fine, use -J <filename> but please don't muddy the waters by combining -J with -I. Thanks. :-)");
[116]828 }
829 bkpinfo->make_filelist = FALSE;
830 strcpy(bkpinfo->include_paths, flag_val['J']);
[1]831 }
[1967]832
833 if ((flag_set['c'] || flag_set['w'] || flag_set['C'] || flag_set['r']) && (! bkpinfo->restore_data)) {
[116]834 if (!flag_set['r'] && g_kernel_version <= 2.5
835 && strstr(flag_val['d'], "/dev/")) {
836 fatal_error
837 ("Please don't give a /dev entry. Give a SCSI node for the parameter of the -d flag.");
838 }
839 if (flag_set['r'] && g_kernel_version <= 2.5
840 && !strstr(flag_val['d'], "/dev/")) {
841 fatal_error
842 ("Please give a /dev entry, not a SCSI node, as the parameter of the -d flag.");
843 }
844 if (g_kernel_version >= 2.6 && !strstr(flag_val['d'], "/dev/")) {
845 log_to_screen
[541]846 ("Linus says 2.6 has a broken ide-scsi module. Proceed at your own risk...");
[116]847 }
848
849 if (system("which cdrecord > /dev/null 2> /dev/null")
850 && system("which dvdrecord > /dev/null 2> /dev/null")) {
851 fatal_error
852 ("Please install dvdrecord/cdrecord and try again.");
853 }
854 if (flag_set['C']) {
855 bkpinfo->cdrw_speed = atoi(flag_val['C']);
856 if (bkpinfo->cdrw_speed < 1) {
857 fatal_error
858 ("You specified a silly speed for a CD-R[W] drive");
859 }
860 if (!flag_set['L']) {
861 log_to_screen
[541]862 ("You must use -L with -C. Therefore I am setting it for you.");
[116]863 flag_set['L'] = 1;
864 flag_val['L'][0] = '\0';
865 }
866 } else {
867 log_msg(3, "flag_val['c'] = %s", flag_val['c']);
868 log_msg(3, "flag_val['w'] = %s", flag_val['w']);
869// log_msg(3, "flag_set['r'] = %i", flag_set['r'] );
870 if (flag_set['c']) {
871 bkpinfo->cdrw_speed = atoi(flag_val['c']);
872 } else if (flag_set['w']) {
873 bkpinfo->cdrw_speed = atoi(flag_val['w']);
874 } else if (flag_set['r']) {
875 bkpinfo->cdrw_speed = 1; /*atoi(flag_val['r']); */
876 }
877
878 if (bkpinfo->cdrw_speed < 1) {
879 fatal_error
880 ("You specified a silly speed for a CD-R[W] drive");
881 }
882 }
[1]883 }
[1967]884
[1969]885 if ((flag_set['t'] && !flag_set['d']) && (! bkpinfo->restore_data)) {
[116]886 log_it("Hmm! No tape drive specified. Let's see what we can do.");
887 if (find_tape_device_and_size(flag_val['d'], tmp)) {
888 fatal_error
889 ("Tape device not specified. I couldn't find it either.");
890 }
891 flag_set['d'] = TRUE;
892 sprintf(tmp,
[541]893 "You didn't specify a tape streamer device. I'm assuming %s",
[116]894 flag_val['d']);
895 log_to_screen(tmp);
896 percent = 0;
897 }
898
[1687]899 if (flag_set['U']) // USB
900 {
901 if (! flag_set['d']) {
902 fatal_error
[1967]903 ("You need to specify a device file with -d for bootable USB device usage");
[1687]904 }
[1967]905 if ((!flag_set['s']) && (! bkpinfo->restore_data)) {
[1687]906 fatal_error("You did not specify a size (-s) for your USB device. Aborting");
907 }
908 }
909
[116]910 if (flag_set['r']) // DVD
911 {
912 if (flag_set['m']) {
913 fatal_error
914 ("Manual CD tray (-m) not yet supported in conjunction w/ DVD drives. Drop -m.");
915 }
916 if (!flag_set['d']) {
917 if (!find_dvd_device(flag_val['d'], FALSE)) {
918 flag_set['d'] = TRUE;
[541]919 log_to_screen("I guess DVD drive is at %s", flag_val['d']);
[116]920 }
921 }
922 if (strchr(flag_val['d'], ',')) {
923 fatal_error
924 ("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag.");
925 }
[1967]926 if (! bkpinfo->restore_data) {
927 if (!find_home_of_exe("growisofs")) {
928 fatal_error
929 ("Please install growisofs (probably part of dvd+rw-tools). If you want DVD support, you need it.");
930 }
931 if (!find_home_of_exe("dvd+rw-format")) {
932 fatal_error
933 ("Please install dvd+rw-format (probably part of dvd+rw-tools). If you want DVD support, you need it.");
934 }
935 if (!flag_set['s']) {
936 sprintf(flag_val['s'], "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4582 MB
937 strcat(flag_val['s'], "m");
938 log_to_screen
939 ("You did not specify a size (-s) for DVD. I'm guessing %s.",
940 flag_val['s']);
941 flag_set['s'] = 1;
942 }
[116]943 }
[1]944/*
945 if (flag_set['Z']) {
946 bkpinfo->blank_dvd_first = TRUE;
947 }
948*/
[116]949 }
[1]950
[116]951 if (flag_set['t'] || flag_set['u']) { /* tape size */
952 if (strchr(flag_val['d'], ',')) {
953 fatal_error
954 ("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag.");
955 }
[1967]956 if ((flag_set['O']) && (! bkpinfo->restore_data)) {
[116]957 if (flag_set['s']) {
958 if (flag_set['t']) {
959 fatal_error
960 ("For the moment, please don't specify a tape size. Mondo should handle end-of-tape gracefully anyway.");
961 }
[1645]962 if (process_the_s_switch(flag_val['s'])) {
[116]963 fatal_error("Bad -s switch");
964 }
965 } else if (flag_set['u'] || flag_set['t']) {
966 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
967 bkpinfo->media_size[i] = 0;
968 }
969 } else {
970 retval++;
971 log_to_screen("Tape size not specified.\n");
972 }
973 }
[1967]974 } else if (! bkpinfo->restore_data) { /* CD|USB size */
[116]975 if (flag_set['s']) {
[1645]976 if (process_the_s_switch(flag_val['s'])) {
[116]977 fatal_error("Bad -s switch");
978 }
979 }
980 if (flag_set['w']) {
981 bkpinfo->wipe_media_first = TRUE;
982 } /* CD-RW */
[1]983 }
[1967]984
[116]985 if (flag_set['n']) {
986 strncpy(bkpinfo->nfs_mount, flag_val['n'], MAX_STR_LEN);
987 if (!flag_set['d']) {
988 strncpy(bkpinfo->nfs_remote_dir, "/", MAX_STR_LEN);
989 }
[2223]990 sprintf(tmp, "mount | grep -E \"^%s[/]* .*\" | cut -d' ' -f3",
[116]991 bkpinfo->nfs_mount);
992 strncpy(bkpinfo->isodir,
993 call_program_and_get_last_line_of_output(tmp),
994 MAX_STR_LEN / 4);
995 if (strlen(bkpinfo->isodir) < 3) {
[2223]996 log_to_screen("NFS share is not mounted. Trying to mount it for you.\n");
997 sprintf(tmp, "mount %s", bkpinfo->nfs_mount);
998 if (system(tmp)) {
999 log_to_screen("Unable to mount NFS share %s. Please mount manually.\n", bkpinfo->nfs_mount);
1000 retval++;
1001 } else {
1002 sprintf(tmp, "mount | grep -E \"^%s[/]* .*\" | cut -d' ' -f3",
1003 bkpinfo->nfs_mount);
1004 strncpy(bkpinfo->isodir,
1005 call_program_and_get_last_line_of_output(tmp),
1006 MAX_STR_LEN / 4);
1007 if (strlen(bkpinfo->isodir) < 3) {
1008 retval++;
1009 log_to_screen("NFS share %s is strangely not mounted. Please mount manually...\n", bkpinfo->nfs_mount);
1010 }
1011 }
[116]1012 }
1013 log_msg(3, "mount = %s", bkpinfo->nfs_mount);
1014 log_msg(3, "isodir= %s", bkpinfo->isodir);
[1]1015 }
[1967]1016
[116]1017 if (flag_set['c']) {
1018 bkpinfo->backup_media_type = cdr;
[1]1019 }
[116]1020 if (flag_set['C']) {
1021 bkpinfo->backup_media_type = cdstream;
[1]1022 }
[116]1023 if (flag_set['i']) {
1024 bkpinfo->backup_media_type = iso;
1025 }
1026 if (flag_set['n']) {
1027 bkpinfo->backup_media_type = nfs;
[1848]1028 /* Never try to eject a NFS device */
1029 bkpinfo->please_dont_eject = TRUE;
[116]1030 }
1031 if (flag_set['r']) {
1032 bkpinfo->backup_media_type = dvd;
1033 }
1034 if (flag_set['t']) {
1035 bkpinfo->backup_media_type = tape;
1036 }
1037 if (flag_set['u']) {
1038 bkpinfo->backup_media_type = udev;
1039 }
1040 if (flag_set['w']) {
1041 bkpinfo->backup_media_type = cdrw;
1042 }
[1687]1043 if (flag_set['U']) {
1044 bkpinfo->backup_media_type = usb;
[1745]1045 /* Never try to eject a USB device */
[1746]1046 bkpinfo->please_dont_eject = TRUE;
[1687]1047 }
[948]1048 if (flag_set['z']) {
1049 if (find_home_of_exe("getfattr")) {
[2211]1050 mr_asprintf(&g_getfattr,"getfattr");
[948]1051 }
1052 if (find_home_of_exe("getfacl")) {
[2211]1053 mr_asprintf(&g_getfacl,"getfacl");
[948]1054 }
1055 }
[1]1056
[805]1057 /* optional, popular */
[116]1058 if (flag_set['g']) {
1059 g_text_mode = FALSE;
1060 }
[805]1061
[116]1062 if (flag_set['E']) {
[2022]1063 if (bkpinfo->exclude_paths[0] == '-') {
1064 retval++;
1065 log_to_screen("Please supply a sensible value with '-E'\n");
1066 }
[116]1067 if (bkpinfo->exclude_paths[0]) {
1068 strcat(bkpinfo->exclude_paths, " ");
1069 }
[2211]1070 mr_asprintf(&tmp1, "%s", flag_val['E']);
[542]1071
[2022]1072 p = tmp1;
1073 q = tmp1;
1074
1075 /* Cut the flag_val['E'] in parts containing all paths to test them */
1076 while (p != NULL) {
1077 q = strchr(p, ' ');
1078 if (q != NULL) {
1079 *q = '\0';
1080 /* Fix bug 14 where ending / cause a problem later
1081 * so handled here for the moment */
1082 q--;
1083 if (*q == '/') {
1084 *q = '\0';
1085 }
1086 q++;
1087 /* End of bug fix */
1088 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
1089 log_msg(1, "WARNING ! %s doesn't exist", p);
1090 }
1091 p = q+1 ;
1092 } else {
1093 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
1094 log_msg(1, "WARNING ! %s doesn't exist", p);
1095 }
1096 p = NULL;
1097 }
1098 }
1099 paranoid_free(tmp1);
1100 lastpos = 0;
[2053]1101 while ((token = mr_strtok(flag_val['E'], token_chars, &lastpos)) != NULL) {
[2022]1102 switch (get_dsf_mount_list(token, &mounted_on_dsf, &not_mounted_on_dsf)) {
[2007]1103 case 1:
[2036]1104 log_msg(1, "WARNING ! a path doesn't exist in -E option");
1105 break;
[2007]1106 /* Everything is OK; proceed to archive data */
1107 case 0:
1108 if (strlen(mounted_on_dsf)) {
[2022]1109 log_to_screen("Excluding the following file systems on %s:\n", token);
[2011]1110 log_to_screen(" %s\n", mounted_on_dsf);
[2007]1111 log_msg (5, "Adding to bkpinfo->exclude_paths due to -E option: %s", mounted_on_dsf);
1112 strcat(bkpinfo->exclude_paths, mounted_on_dsf);
[2022]1113 strcat(bkpinfo->exclude_paths, " ");
[805]1114 }
[2007]1115 break;
1116 /* It's a dsf but not a whole disk dsf */
1117 case -2:
[2022]1118 log_to_screen("Could %s be a partition instead of a whole disk device special file?\nIgnored.", token);
[2007]1119 break;
1120 /* A device special file was not passed in. Process it as a path. */
1121 case -1:
[2036]1122 strcat(bkpinfo->exclude_paths, token);
1123 strcat(bkpinfo->exclude_paths, " ");
1124 break;
[542]1125 }
[2022]1126 }
1127 log_msg(1, "exclude_paths is now '%s'", bkpinfo->exclude_paths);
1128 log_msg(4, "Finished with the -E option");
[116]1129 }
[1967]1130
[116]1131 if (flag_set['e']) {
1132 bkpinfo->please_dont_eject = TRUE;
1133 }
[1967]1134
1135 if ((flag_set['N']) && (! bkpinfo->restore_data)) // exclude NFS mounts & devices
[116]1136 {
[1]1137// strncpy(psz, list_of_NFS_devices_and_mounts(), MAX_STR_LEN);
[2214]1138 asprintf(&psz, "%s", list_of_NFS_mounts_only());
[116]1139 if (bkpinfo->exclude_paths[0]) {
[1540]1140 strncat(bkpinfo->exclude_paths, " ", 4*MAX_STR_LEN);
[116]1141 }
[1540]1142 strncat(bkpinfo->exclude_paths, psz, 4*MAX_STR_LEN);
[2214]1143 mr_free(psz);
1144
[116]1145 log_msg(3, "-N means we're now excluding %s",
1146 bkpinfo->exclude_paths);
1147 }
[1967]1148
[1540]1149 if (strlen(bkpinfo->exclude_paths) >= 4*MAX_STR_LEN) {
[116]1150 fatal_error
[1540]1151 ("Your '-E' parameter is too long. Increase MAX_STR_LEN");
[116]1152 }
[1967]1153
[116]1154 if (flag_set['b']) {
[2214]1155 mr_asprintf(&psz, flag_val['b']);
[116]1156 log_msg(1, "psz = '%s'", psz);
1157 if (psz[strlen(psz) - 1] == 'k') {
1158 psz[strlen(psz) - 1] = '\0';
1159 itbs = atol(psz) * 1024L;
1160 } else {
1161 itbs = atol(psz);
1162 }
[2214]1163 mr_free(psz);
[116]1164 log_msg(1, "'%s' --> %ld", flag_val['b'], itbs);
1165 log_msg(1, "Internal tape block size is now %ld bytes", itbs);
1166 if (itbs % 512 != 0 || itbs < 256 || itbs > 1024L * 1024) {
1167 fatal_error
1168 ("Are you nuts? Silly, your internal tape block size is. Abort, I shall.");
1169 }
1170 bkpinfo->internal_tape_block_size = itbs;
1171 }
[1967]1172
1173 if ((flag_set['D']) && (! bkpinfo->restore_data)) {
[116]1174 bkpinfo->differential = 1;
[1]1175// bkpinfo->differential = atoi (flag_val['D']);
[116]1176 if ((bkpinfo->differential < 1) || (bkpinfo->differential > 9)) {
1177 fatal_error
1178 ("The D option should be between 1 and 9 inclusive");
1179 }
[1]1180 }
[1967]1181
[116]1182 if (flag_set['x']) {
1183 strncpy(bkpinfo->image_devs, flag_val['x'], MAX_STR_LEN / 4);
[1967]1184 if ((run_program_and_log_output("which ntfsclone", 2)) && (! bkpinfo->restore_data)) {
[296]1185 fatal_error("Please install ntfsprogs package/tarball.");
[116]1186 }
[1]1187 }
[1967]1188
[116]1189 if (flag_set['m']) {
1190 bkpinfo->manual_cd_tray = TRUE;
[1]1191 }
[1967]1192
1193 if ((flag_set['k']) && (! bkpinfo->restore_data)) {
[116]1194 strncpy(bkpinfo->kernel_path, flag_val['k'], MAX_STR_LEN);
1195 if (!strcmp(bkpinfo->kernel_path, "failsafe")) {
1196 strcpy(bkpinfo->kernel_path, "FAILSAFE");
1197 }
1198 if (strcmp(bkpinfo->kernel_path, "FAILSAFE")
1199 && !does_file_exist(bkpinfo->kernel_path)) {
1200 retval++;
1201 sprintf(tmp,
[541]1202 "You specified kernel '%s', which does not exist\n",
[116]1203 bkpinfo->kernel_path);
1204 log_to_screen(tmp);
1205 }
1206 }
[1967]1207
[116]1208 if (flag_set['p']) {
1209 strncpy(bkpinfo->prefix, flag_val['p'], MAX_STR_LEN / 4);
[1966]1210 log_msg(1,"Prefix forced to %s",bkpinfo->prefix);
[116]1211 }
[1]1212
[116]1213 if (flag_set['d']) { /* backup directory (if ISO/NFS) */
1214 if (flag_set['i']) {
1215 strncpy(bkpinfo->isodir, flag_val['d'], MAX_STR_LEN / 4);
1216 sprintf(tmp, "ls -l %s", bkpinfo->isodir);
[1737]1217 if (run_program_and_log_output(tmp, 2)) {
[116]1218 fatal_error
1219 ("output folder does not exist - please create it");
1220 }
1221 } else if (flag_set['n']) {
1222 strncpy(bkpinfo->nfs_remote_dir, flag_val['d'], MAX_STR_LEN);
1223 } else { /* backup device (if tape/CD-R/CD-RW) */
1224 strncpy(bkpinfo->media_device, flag_val['d'], MAX_STR_LEN / 4);
1225 }
[1]1226 }
[116]1227
[1967]1228 if ((flag_set['n']) && (! bkpinfo->restore_data)) {
[2211]1229 mr_asprintf(&tmp1,"%s/%s/.dummy.txt", bkpinfo->isodir,bkpinfo->nfs_remote_dir);
[1767]1230 sprintf(tmp, "echo hi > %s", tmp1);
[1737]1231 if (run_program_and_log_output(tmp, 2)) {
[116]1232 retval++;
1233 sprintf(tmp,
[541]1234 "Are you sure directory '%s' exists in remote dir '%s'?\nIf so, do you have rights to write to it?\n",
[116]1235 bkpinfo->nfs_remote_dir, bkpinfo->nfs_mount);
1236 log_to_screen(tmp);
1237 }
[1767]1238 unlink(tmp1);
1239 paranoid_free(tmp1);
[1]1240 }
1241
[116]1242 if (!flag_set['d']
1243 && (flag_set['c'] || flag_set['w'] || flag_set['C'])) {
1244 if (g_kernel_version >= 2.6) {
1245 if (popup_and_get_string
[541]1246 ("Device", "Please specify the device",
[116]1247 bkpinfo->media_device, MAX_STR_LEN / 4)) {
1248 retval++;
[541]1249 log_to_screen("User opted to cancel.");
[116]1250 }
1251 } else if (find_cdrw_device(bkpinfo->media_device)) {
1252 retval++;
1253 log_to_screen
[541]1254 ("Tried and failed to find CD-R[W] drive automatically.\n");
[116]1255 } else {
1256 flag_set['d'] = TRUE;
1257 strncpy(flag_val['d'], bkpinfo->media_device, MAX_STR_LEN / 4);
1258 }
[1]1259 }
1260
[1967]1261 if ((!flag_set['d'] && !flag_set['n'] && !flag_set['C']) && (! bkpinfo->restore_data)) {
[116]1262 retval++;
[541]1263 log_to_screen("Please specify the backup device/directory.\n");
[116]1264 fatal_error
1265 ("You didn't use -d to specify the backup device/directory.");
[1]1266 }
[1967]1267
[116]1268 for (i = '0'; i <= '9'; i++) {
1269 if (flag_set[i]) {
1270 bkpinfo->compression_level = i - '0';
1271 } /* not '\0' but '0' */
[1]1272 }
[1967]1273
[116]1274 if (flag_set['S']) {
1275 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%ld", flag_val['S'],
1276 random() % 32768);
[1]1277 }
[1967]1278
[116]1279 if (flag_set['T']) {
[1655]1280 setup_tmpdir(flag_val['T']);
1281 sprintf(tmp, "touch %s/.foo.dat", bkpinfo->tmpdir);
[116]1282 if (run_program_and_log_output(tmp, 1)) {
1283 retval++;
1284 log_to_screen
[541]1285 ("Please specify a tempdir which I can write to. :)");
[116]1286 fatal_error("I cannot write to the tempdir you specified.");
1287 }
[1655]1288 sprintf(tmp, "ln -sf %s/.foo.dat %s/.bar.dat", bkpinfo->tmpdir, bkpinfo->tmpdir);
[116]1289 if (run_program_and_log_output(tmp, 1)) {
1290 retval++;
1291 log_to_screen
[541]1292 ("Please don't specify a SAMBA or VFAT or NFS tmpdir.");
[116]1293 fatal_error("I cannot write to the tempdir you specified.");
1294 }
[1]1295 }
[1967]1296
1297 if ((flag_set['A']) && (! bkpinfo->restore_data)) {
[116]1298 strncpy(bkpinfo->call_after_iso, flag_val['A'], MAX_STR_LEN);
1299 }
[1967]1300
1301 if ((flag_set['B']) && (! bkpinfo->restore_data)) {
[116]1302 strncpy(bkpinfo->call_before_iso, flag_val['B'], MAX_STR_LEN);
1303 }
[1967]1304
1305 if ((flag_set['H']) && (! bkpinfo->restore_data)) {
[116]1306 g_cd_recovery = TRUE;
1307 }
[1967]1308
1309 if ((flag_set['l']) && (! bkpinfo->restore_data)) {
[1]1310#ifdef __FreeBSD__
1311# define BOOT_LOADER_CHARS "GLBMR"
1312#else
1313# ifdef __IA64__
1314# define BOOT_LOADER_CHARS "GER"
1315# else
1316# define BOOT_LOADER_CHARS "GLR"
1317# endif
1318#endif
[116]1319 if (!strchr
1320 (BOOT_LOADER_CHARS,
1321 (bkpinfo->boot_loader = flag_val['l'][0]))) {
1322 log_msg(1, "%c? WTF is %c? I need G, L, E or R.",
1323 bkpinfo->boot_loader, bkpinfo->boot_loader);
1324 fatal_error
1325 ("Please specify GRUB, LILO, ELILO or RAW with the -l switch");
1326 }
[1]1327#undef BOOT_LOADER_CHARS
1328 }
[1967]1329
[116]1330 if (flag_set['f']) {
1331 strncpy(bkpinfo->boot_device,
1332 resolve_softlinks_to_get_to_actual_device_file(flag_val
1333 ['f']),
1334 MAX_STR_LEN / 4);
1335 }
[1967]1336
1337 if ((flag_set['P']) && (! bkpinfo->restore_data)) {
[116]1338 strncpy(bkpinfo->postnuke_tarball, flag_val['P'], MAX_STR_LEN);
1339 }
[1967]1340
[116]1341 if (flag_set['Q']) {
1342 i = which_boot_loader(tmp);
1343 log_msg(3, "boot loader is %c, residing at %s", i, tmp);
[541]1344 printf("boot loader is %c, residing at %s\n", i, tmp);
[116]1345 finish(0);
1346 }
[1967]1347
1348 if ((flag_set['L']) && (! bkpinfo->restore_data)) {
[116]1349 bkpinfo->use_lzo = TRUE;
[1737]1350 if (run_program_and_log_output("which lzop", 2)) {
[116]1351 retval++;
1352 log_to_screen
[541]1353 ("Please install LZOP. You can't use '-L' until you do.\n");
[116]1354 }
1355 }
[1]1356
[1967]1357 if ((flag_set['G']) && (! bkpinfo->restore_data)) {
[998]1358 bkpinfo->use_gzip = TRUE;
[1737]1359 if (run_program_and_log_output("which gzip", 2)) {
[998]1360 retval++;
1361 log_to_screen
1362 ("Please install gzip. You can't use '-G' until you do.\n");
1363 }
1364 }
1365
[1948]1366 bkpinfo->use_obdr = FALSE;
1367 if (flag_set['o']) {
[1967]1368 if ((!flag_set['t']) && (! bkpinfo->restore_data)) {
[1948]1369 log_to_screen("OBDR support is only available for tapes. Use the -t option");
1370 fatal_error("Aborting");
1371 }
1372 bkpinfo->use_obdr = TRUE;
1373 }
[1967]1374
[1948]1375#ifndef __FreeBSD__
[1967]1376 if ((!is_this_a_valid_disk_format("vfat")) && (! bkpinfo->restore_data)) {
[116]1377 bkpinfo->make_cd_use_lilo = TRUE;
1378 log_to_screen
[1948]1379 ("Your kernel appears not to support vfat filesystems. I am therefore");
1380 log_to_screen
1381 ("using LILO instead of SYSLINUX as the media boot loader.");
[116]1382 }
[1967]1383 if ((run_program_and_log_output("which mkfs.vfat", 2)) && (! bkpinfo->restore_data)) {
[116]1384 bkpinfo->make_cd_use_lilo = TRUE;
[1]1385#ifdef __IA32__
[1948]1386 log_to_screen
1387 ("Your filesystem is missing 'mkfs.vfat', so I cannot use SYSLINUX as");
1388 log_to_screen
1389 ("your boot loader. I shall therefore use LILO instead.");
[1]1390#endif
1391#ifdef __IA64__
[1948]1392 log_to_screen
1393 ("Your filesystem is missing 'mkfs.vfat', so I cannot prepare the EFI");
1394 log_to_screen("environment correctly. Please install it.");
1395 fatal_error("Aborting");
[1]1396#endif
[1948]1397 }
[1]1398#ifdef __IA64__
[1948]1399 /* We force ELILO usage on IA64 */
1400 bkpinfo->make_cd_use_lilo = TRUE;
[2085]1401#endif
1402#endif
[1]1403
[1967]1404 if (! bkpinfo->restore_data) {
[1917]1405 i = flag_set['O'] + flag_set['V'];
1406 if (i == 0) {
1407 retval++;
1408 log_to_screen("Specify backup (-O), verify (-V) or both (-OV).\n");
1409 }
[116]1410 }
[1]1411
[1967]1412 if ((! bkpinfo->restore_data) && (flag_set['Z'])) {
1413 fatal_error
1414 ("The -Z switch is only valid in restore mode");
1415 }
1416
1417 if (flag_set['Z']) {
1418 if (! strcmp(flag_val['Z'], "nuke")) {
1419 bkpinfo->restore_mode = nuke;
1420 } else if (! strcmp(flag_val['Z'], "interactive")) {
1421 bkpinfo->restore_mode = interactive;
1422 } else if (! strcmp(flag_val['Z'], "compare")) {
1423 bkpinfo->restore_mode = compare;
1424 } else if (! strcmp(flag_val['Z'], "mbr")) {
1425 bkpinfo->restore_mode = mbr;
1426 } else if (! strcmp(flag_val['Z'], "iso")) {
1427 bkpinfo->restore_mode = isoonly;
1428 } else if (! strcmp(flag_val['Z'], "isonuke")) {
1429 bkpinfo->restore_mode = isonuke;
1430 } else {
1431 bkpinfo->restore_mode = interactive;
1432 }
1433 }
1434
[1]1435/* and finally... */
1436
[116]1437 paranoid_free(tmp);
1438 return (retval);
[1]1439}
1440
1441
1442
1443/**
1444 * Get the switches from @p argc and @p argv using getopt() and place them in
1445 * @p flag_set and @p flag_val.
1446 * @param argc The argument count (@p argc passed to main()).
1447 * @param argv The argument vector (@p argv passed to main()).
1448 * @param flag_val An array indexed by switch letter - if a switch is set and
1449 * has an argument then set flag_val[switch] to that argument.
1450 * @param flag_set An array indexed by switch letter - if a switch is set then
1451 * set flag_set[switch] to TRUE, else set it to FALSE.
1452 * @return The number of problems with the command line (0 for success).
1453 */
1454int
[116]1455retrieve_switches_from_command_line(int argc, char *argv[],
1456 char flag_val[128][MAX_STR_LEN],
1457 bool flag_set[128])
[1]1458{
[116]1459 /*@ ints ** */
1460 int opt = 0;
[2202]1461 char *tmp = NULL;
[116]1462 int i = 0;
1463 int len;
[1]1464
[116]1465 /*@ bools *** */
1466 bool bad_switches = FALSE;
[1]1467
[116]1468 assert(flag_val != NULL);
1469 assert(flag_set != NULL);
[1]1470
[116]1471 for (i = 0; i < 128; i++) {
1472 flag_val[i][0] = '\0';
1473 flag_set[i] = FALSE;
[1]1474 }
[116]1475 while ((opt =
[1917]1476 getopt(argc, argv, MONDO_OPTIONS))
[116]1477 != -1) {
1478 if (opt == '?') {
1479 bad_switches = TRUE;
1480 /*log_it("Invalid option: %c\n",optopt); */
1481 } else {
1482 if (flag_set[optopt]) {
1483 bad_switches = TRUE;
[2211]1484 mr_asprintf(&tmp, "Switch -%c previously defined as %s\n", opt,
[116]1485 flag_val[i]);
1486 log_to_screen(tmp);
[2202]1487 paranoid_free(tmp);
[116]1488 } else {
1489 flag_set[opt] = TRUE;
1490 if (optarg) {
1491 len = strlen(optarg);
1492 if (optarg[0] != '/' && optarg[len - 1] == '/') {
1493 optarg[--len] = '\0';
1494 log_to_screen
[541]1495 ("Warning - param '%s' should not have trailing slash!",
[116]1496 optarg);
1497 }
1498 if (opt == 'd') {
1499 if (strchr(flag_val[opt], '/')
1500 && flag_val[opt][0] != '/') {
[2211]1501 mr_asprintf(&tmp,
[541]1502 "-%c flag --- must be absolute path --- '%s' isn't absolute",
[116]1503 opt, flag_val[opt]);
1504 log_to_screen(tmp);
[2202]1505 paranoid_free(tmp);
[116]1506 bad_switches = TRUE;
1507 }
1508 }
1509 strcpy(flag_val[opt], optarg);
1510 }
1511 }
[1]1512 }
1513 }
[116]1514 for (i = optind; i < argc; i++) {
1515 bad_switches = TRUE;
[2211]1516 mr_asprintf(&tmp, "Invalid arg -- %s\n", argv[i]);
[116]1517 log_to_screen(tmp);
[2202]1518 paranoid_free(tmp);
[116]1519 }
1520 return (bad_switches);
[1]1521}
1522
1523
1524
1525
1526/**
1527 * Print a not-so-helpful help message and exit.
1528 */
[116]1529void help_screen()
[1]1530{
[1967]1531 log_msg(1, "Type 'man mondoarchive' for more information\n");
[116]1532 exit(1);
[1]1533}
1534
1535
1536/**
1537 * Terminate Mondo in response to a signal.
1538 * @param sig The signal number received.
1539 */
1540void terminate_daemon(int sig)
1541{
[2211]1542 char *tmp = NULL;
1543 char *tmp2 = NULL;
[1]1544
[116]1545 switch (sig) {
[1]1546 case SIGINT:
[2211]1547 mr_asprintf(&tmp, "SIGINT");
1548 mr_asprintf(&tmp2, "You interrupted me :-)");
[1]1549 break;
1550 case SIGKILL:
[2211]1551 mr_asprintf(&tmp, "SIGKILL");
1552 mr_asprintf(&tmp2,
[541]1553 "I seriously have no clue how this signal even got to me. Something's wrong with your system.");
[1]1554 break;
1555 case SIGTERM:
[2211]1556 mr_asprintf(&tmp, "SIGTERM");
1557 mr_asprintf(&tmp2, "Got terminate signal");
[1]1558 break;
1559 case SIGHUP:
[2211]1560 mr_asprintf(&tmp, "SIGHUP");
1561 mr_asprintf(&tmp2, "Hangup on line");
[1]1562 break;
1563 case SIGSEGV:
[2211]1564 mr_asprintf(&tmp, "SIGSEGV");
1565 mr_asprintf(&tmp2,
[541]1566 "Internal programming error. Please send a backtrace as well as your log.");
[1]1567 break;
1568 case SIGPIPE:
[2211]1569 mr_asprintf(&tmp, "SIGPIPE");
1570 mr_asprintf(&tmp2, "Pipe was broken");
[1]1571 break;
[116]1572 case SIGABRT:
[2211]1573 mr_asprintf(&tmp, "SIGABRT");
1574 mr_asprintf(&tmp2,
[541]1575 "Abort - probably failed assertion. I'm sleeping for a few seconds so you can read the message.");
[116]1576 break;
[1]1577 default:
[2211]1578 mr_asprintf(&tmp, "(Unknown)");
1579 mr_asprintf(&tmp2, "(Unknown)");
[116]1580 }
[1]1581
[2211]1582 mr_strcat(tmp, " signal received from OS");
[116]1583 log_to_screen(tmp);
[2211]1584 paranoid_free(tmp);
1585
[116]1586 log_to_screen(tmp2);
[2211]1587 paranoid_free(tmp2);
[116]1588 if (sig == SIGABRT) {
1589 sleep(10);
1590 }
1591 kill_buffer();
[1967]1592
1593 free_MR_global_filenames();
1594
[116]1595 fatal_error
[1967]1596 ("MondoRescue is terminating in response to a signal from the OS");
[116]1597 finish(254); // just in case
[1]1598}
1599
1600
1601
1602
1603/**
1604 * Turn signal-trapping on or off.
1605 * @param on If TRUE, turn it on; if FALSE, turn it off (we still trap it, just don't do as much).
1606 */
1607void set_signals(int on)
1608{
[116]1609 int signals[] =
1610 { SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT, SIGKILL, SIGSTOP, 0 };
1611 int i;
1612
1613 signal(SIGPIPE, sigpipe_occurred);
1614 for (i = 0; signals[i]; i++) {
1615 if (on) {
1616 signal(signals[i], terminate_daemon);
1617 } else {
1618 signal(signals[i], termination_in_progress);
1619 }
1620 }
[1]1621}
1622
1623
1624
1625
1626/**
1627 * Exit immediately without cleaning up.
1628 * @param sig The signal we are exiting due to.
1629 */
1630void termination_in_progress(int sig)
1631{
[116]1632 log_msg(1, "Termination in progress");
1633 usleep(1000);
1634 pthread_exit(0);
[1]1635}
1636
1637/* @} - end of cliGroup */
Note: See TracBrowser for help on using the repository browser.