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

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

No need to use sudo for NFS user, just use su and avoid any passwd issue.

  • Property svn:keywords set to Id
File size: 50.5 KB
Line 
1/***************************************************************************
2$Id: libmondo-cli.c 2225 2009-06-17 02:47:09Z bruno $
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>
13#include "my-stuff.h"
14#include "mr_mem.h"
15#include "mr_string.h"
16#include "mondostructures.h"
17#include "libmondo-cli-EXT.h"
18#include "libmondo.h"
19
20extern int g_loglevel;
21extern bool g_text_mode;
22extern char g_startdir[MAX_STR_LEN]; ///< ????? @bug ?????
23extern char *MONDO_OPTIONS;
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******** **************************************************/
35bool g_debugging = FALSE; ///< ????? @bug ????? @ingroup globalGroup
36bool g_running_live = FALSE; ///< ????? @bug ????? @ingroup globalGroup
37extern bool g_cd_recovery;
38
39extern void setup_tmpdir(char *path);
40extern double g_kernel_version;
41extern int g_current_media_number;
42extern pid_t g_main_pid;
43extern char *resolve_softlinks_to_get_to_actual_device_file(char *);
44
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
61/* Do we use extended attributes and acl ?
62 * By default no, use --acl & --attr options to force their usage */
63extern char *g_getfacl;
64extern char *g_getfattr;
65
66/* Reference to global bkpinfo */
67extern struct s_bkpinfo *bkpinfo;
68
69extern void free_MR_global_filenames(void);
70
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
83handle_incoming_parameters(int argc, char *argv[])
84{
85 /*@ int *** */
86 int res = 0;
87 int retval = 0;
88 int i = 0, j;
89
90 /*@ buffers *************** */
91 char *tmp;
92 char flag_val[128][MAX_STR_LEN];
93 bool flag_set[128];
94
95 tmp = malloc(9*MAX_STR_LEN);
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) {
108 res = process_switches(flag_val, flag_set);
109 retval += res;
110 }
111/*
112 if (!retval)
113 {
114*/
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 }
121 }
122// }
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);
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 */
147int process_the_s_switch(char *value)
148{
149 int j;
150 char tmp[MAX_STR_LEN], *p, comment[MAX_STR_LEN];
151
152 assert(bkpinfo != NULL);
153 assert(value != NULL);
154
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);
164 }
165 for (; j <= MAX_NOOF_MEDIA; j++) {
166 bkpinfo->media_size[j] = friendly_sizestr_to_sizelong(p);
167 }
168// bkpinfo->media_size[0] = bkpinfo->media_size[MAX_NOOF_MEDIA];
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);
176}
177
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}
195
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}
213
214/**
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/" */
280 mr_asprintf(&command, "mount 2>/dev/null | awk '{if($1 ~ \"^/dev/\"){print $0}}'|wc -l");
281 log_msg(5, "Running: %s", command);
282 mr_asprintf(&mounted_file_system, "%s", call_program_and_get_last_line_of_output(command));
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--) {
290 mr_asprintf(&command, "mount 2>/dev/null | awk '{if($1 ~ \"^/dev/\"){print $1,$3}}'|head -n %d", i);
291 log_msg(5, "Running: %s", command);
292 mr_asprintf(&mounted_file_system, "%s", call_program_and_get_last_line_of_output(command));
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");
311 paranoid_free(mounted_file_system);
312 return (1);
313 }
314 log_msg (5, "token: %s", token);
315 strcpy(DSFptr->mount_point, token);
316 token = strtok(NULL, token_chars);
317 }
318 paranoid_free(mounted_file_system);
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;
344 int lastpos = 0;
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
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);
365 }
366 log_msg(5, " %s looks like a device special file", dsf);
367 /* Verify that the dsf exists */
368 mr_asprintf(&command, "ls -al %s 2>/dev/null | wc -l", dsf);
369 log_msg(5, " Executing: %s", command);
370 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
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);
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 }
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 ********/
394 mr_asprintf(&command,
395 "parted2fdisk -l %s 2>/dev/null|grep -E \"^/dev/\"|awk '{printf(\"%%s \", $1)}END{print \"\"}'", dsf);
396 log_msg(4, "Executing: %s", command);
397 mr_asprintf(&partition_list, "%s", call_program_and_get_last_line_of_output(command));
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 }
405
406 /* Fill the partition list */
407 i = 0;
408 lastpos = 0;
409 while ((token = mr_strtok(partition_list, token_chars, &lastpos)) != NULL) {
410 log_msg (5, "Found partition: %s", token);
411 strcpy(partitions[i++], token);
412 }
413 paranoid_free(partition_list);
414
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. */
447 mr_asprintf(&command,
448 "parted2fdisk -l %s 2>/dev/null | awk '{if(($1==\"%s\")&&(toupper($0) ~ \"SWAP\")){print $1;exit}}'",
449 dsf, partitions[i]);
450 log_msg(4, " Running: %s", command);
451 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
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. */
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));
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);
468 paranoid_free(tmp);
469 return (1);
470 }
471 DSFptr->check = 1;
472 paranoid_free(tmp);
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 */
479 mr_asprintf(&command, "parted2fdisk -l %s |awk '{if($1 ~ \"^%s\"){print $5}}'", dsf, partitions[i]);
480 log_msg(4, " Running: %s", command);
481 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
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...");
488 mr_asprintf(&command, "pvdisplay -v %s 2>/dev/null|grep \"VG Name\"|awk '{print $NF}'", partitions[i]);
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");
496 mr_asprintf(&command,
497 "mount 2>/dev/null|grep -E \"/dev/mapper/%s-|/dev/%s/\"|awk '{printf(\"%%s \",$3)}END{print \"\"}'",
498 VG, VG);
499 log_msg(4, " Running: %s", command);
500 mr_asprintf(&mount_list, "%s", call_program_and_get_last_line_of_output(command));
501 paranoid_free(command);
502 log_msg(4, " VG %s mount_list: %s", VG, mount_list);
503 lastpos = 0;
504 while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
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);
518 mr_asprintf(&command, "%s",
519 "cat /proc/mdstat|grep -iv Personal|awk '{if($0~\"^.*[ ]+:\"){printf(\"/dev/%s \", $1)}}END{print \"\"}'");
520 log_msg (5, "Running: %s", command);
521 mr_asprintf(&mount_list, "%s", call_program_and_get_last_line_of_output(command));
522 paranoid_free(command);
523 log_msg(4, " Software raid device list: %s", mount_list);
524 lastpos = 0;
525 while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
526 mr_asprintf(&command, "mdadm --detail %s 2>/dev/null | grep -c %s", token, VG);
527 log_msg (5, "Running: %s", command);
528 paranoid_free(tmp);
529 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
530 paranoid_free(command);
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);
536 paranoid_free(tmp);
537 return (1);
538 }
539 DSFptr->check = 1;
540 }
541 }
542 paranoid_free(mount_list);
543 } else {
544 log_msg (4, "Error finding Volume Group for partition %s", partitions[i]);
545 paranoid_free(tmp);
546 return (1);
547 }
548 paranoid_free(tmp);
549 continue;
550 }
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.");
559 mr_asprintf(&command, "mdadm --examine %s 2>/dev/null | awk '{if($1 == \"UUID\"){print $3}}'", partitions[i]);
560 log_msg(4, " Running: %s", command);
561 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
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]);
565 paranoid_free(tmp);
566 continue;
567 }
568 log_msg (5, " UUID: %s", tmp);
569 /* Get the Software raid device list */
570 mr_asprintf(&command, "%s",
571 "cat /proc/mdstat|grep -iv Personal|awk '{if($0~\"^.*[ ]+:\"){printf(\"/dev/%s \", $1)}}END{print \"\"}'");
572 log_msg (5, " Running: %s", command);
573 mr_asprintf(&mount_list, "%s", call_program_and_get_last_line_of_output(command));
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;
578 while ((token = mr_strtok(mount_list, token_chars, &lastpos)) != NULL) {
579 mr_asprintf(&command, "mdadm --detail %s 2>/dev/null | grep -c %s", token, tmp);
580 log_msg(4, " Running: %s", command);
581 paranoid_free(tmp);
582 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command));
583 paranoid_free(command);
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);
591 }
592 DSFptr->check = 1;
593 break;
594 }
595 }
596 paranoid_free(tmp);
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/**
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
645process_switches(char flag_val[128][MAX_STR_LEN], bool flag_set[128])
646{
647
648 /*@ ints *** */
649 int i = 0;
650 int retval = 0;
651 int percent = 0;
652 int lastpos = 0;
653
654 /*@ buffers ** */
655 char *tmp = NULL;
656 char *tmp1 = NULL;
657 char *psz = NULL;
658 char *p = NULL;
659 char *q = NULL;
660 char *token = NULL;
661 char *mounted_on_dsf = NULL;
662 char *not_mounted_on_dsf = NULL;
663 char token_chars[] =" \t\r\f\a\0";
664
665 long itbs = 0L;
666
667 struct stat buf;
668
669 malloc_string(tmp);
670
671 assert(bkpinfo != NULL);
672 assert(flag_val != NULL);
673 assert(flag_set != NULL);
674
675 bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
676
677 /* compulsory */
678 i = flag_set['c'] + flag_set['i'] + flag_set['n'] +
679 flag_set['t'] + flag_set['u'] + flag_set['r'] +
680 flag_set['w'] + flag_set['C'] + flag_set['U'];
681 if ((i == 0) && (! bkpinfo->restore_data)) {
682 retval++;
683 log_to_screen("You must specify the media type\n");
684 }
685 if (i > 1) {
686 retval++;
687 log_to_screen("Please specify only one media type\n");
688 }
689
690 if (flag_set['K']) {
691 g_loglevel = atoi(flag_val['K']);
692 log_msg(1,"Loglevel forced to %d",g_loglevel);
693 if (g_loglevel < 3) {
694 g_loglevel = 3;
695 }
696 }
697
698 if ((flag_set['L'] && flag_set['0']) && (! bkpinfo->restore_data)) {
699 retval++;
700 log_to_screen("You cannot have 'no compression' _and_ LZOP.\n");
701 }
702 if (! bkpinfo->restore_data) {
703 bkpinfo->backup_data = flag_set['O'];
704 }
705 bkpinfo->verify_data = flag_set['V'];
706
707 if (flag_set['I'] && !bkpinfo->backup_data) {
708 log_to_screen("-I switch is ignored if just verifying");
709 }
710 if (flag_set['E'] && !bkpinfo->backup_data) {
711 log_to_screen("-E switch is ignored if just verifying");
712 }
713
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 }
722 }
723
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 }
733 }
734
735 if ((flag_set['W']) && (! bkpinfo->restore_data)) {
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
740 ("You don't need to specify bootloader or bootdevice");
741 }
742 }
743
744 if (flag_set['I']) {
745 if (bkpinfo->include_paths[0] == '-') {
746 retval++;
747 log_to_screen("Please supply a sensible value with '-I'\n");
748 }
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 }
756
757 mr_asprintf(&tmp1, "%s", flag_val['I']);
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);
780 while ((token = mr_strtok(flag_val['I'], token_chars, &lastpos)) != NULL) {
781 switch (get_dsf_mount_list(token, &mounted_on_dsf, &not_mounted_on_dsf)) {
782 /* It's a dsf but not a whole disk dsf */
783 case -2:
784 log_to_screen("Could %s be a partition instead of a whole disk device special file?\n Ignored.", token);
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:
791 log_to_screen("Archiving only the following file systems on %s:\n", token);
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:
804 strcat(bkpinfo->include_paths, token);
805 strcat(bkpinfo->include_paths, " ");
806 break;
807 }
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");
814 }
815
816 if (g_kernel_version >= 2.6 && !flag_set['d']
817 && (flag_set['c'] || flag_set['w']) && (! bkpinfo->restore_data)) {
818 fatal_error
819 ("If you are using the 2.6.x kernel, please specify the CD-R(W) device.");
820 }
821
822
823 if (flag_set['J']) {
824 if (flag_set['I']) {
825 retval++;
826 log_to_screen
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. :-)");
828 }
829 bkpinfo->make_filelist = FALSE;
830 strcpy(bkpinfo->include_paths, flag_val['J']);
831 }
832
833 if ((flag_set['c'] || flag_set['w'] || flag_set['C'] || flag_set['r']) && (! bkpinfo->restore_data)) {
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
846 ("Linus says 2.6 has a broken ide-scsi module. Proceed at your own risk...");
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
862 ("You must use -L with -C. Therefore I am setting it for you.");
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 }
883 }
884
885 if ((flag_set['t'] && !flag_set['d']) && (! bkpinfo->restore_data)) {
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,
893 "You didn't specify a tape streamer device. I'm assuming %s",
894 flag_val['d']);
895 log_to_screen(tmp);
896 percent = 0;
897 }
898
899 if (flag_set['U']) // USB
900 {
901 if (! flag_set['d']) {
902 fatal_error
903 ("You need to specify a device file with -d for bootable USB device usage");
904 }
905 if ((!flag_set['s']) && (! bkpinfo->restore_data)) {
906 fatal_error("You did not specify a size (-s) for your USB device. Aborting");
907 }
908 }
909
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;
919 log_to_screen("I guess DVD drive is at %s", flag_val['d']);
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 }
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 }
943 }
944/*
945 if (flag_set['Z']) {
946 bkpinfo->blank_dvd_first = TRUE;
947 }
948*/
949 }
950
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 }
956 if ((flag_set['O']) && (! bkpinfo->restore_data)) {
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 }
962 if (process_the_s_switch(flag_val['s'])) {
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 }
974 } else if (! bkpinfo->restore_data) { /* CD|USB size */
975 if (flag_set['s']) {
976 if (process_the_s_switch(flag_val['s'])) {
977 fatal_error("Bad -s switch");
978 }
979 }
980 if (flag_set['w']) {
981 bkpinfo->wipe_media_first = TRUE;
982 } /* CD-RW */
983 }
984
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 }
990 /* test if we specified a user for the NFS dialog */
991 p = strchr(bkpinfo->nfs_mount, '@');
992 if (p != NULL) {
993 /* User found. Store the 2 values */
994 p++;
995 /* new NFS mount */
996 strcpy(tmp,p);
997 p--;
998 *p = '\0';
999 strcpy(bkpinfo->nfs_user,bkpinfo->nfs_mount);
1000 strcpy(bkpinfo->nfs_mount,tmp);
1001 }
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 log_to_screen("NFS share is not mounted. Trying to mount it for you.\n");
1009 sprintf(tmp, "mount %s", bkpinfo->nfs_mount);
1010 if (system(tmp)) {
1011 log_to_screen("Unable to mount NFS share %s. Please mount manually.\n", bkpinfo->nfs_mount);
1012 retval++;
1013 } else {
1014 sprintf(tmp, "mount | grep -E \"^%s[/]* .*\" | cut -d' ' -f3",
1015 bkpinfo->nfs_mount);
1016 strncpy(bkpinfo->isodir,
1017 call_program_and_get_last_line_of_output(tmp),
1018 MAX_STR_LEN / 4);
1019 if (strlen(bkpinfo->isodir) < 3) {
1020 retval++;
1021 log_to_screen("NFS share %s is strangely not mounted. Please mount manually...\n", bkpinfo->nfs_mount);
1022 }
1023 }
1024 }
1025 log_msg(3, "mount = %s", bkpinfo->nfs_mount);
1026 log_msg(3, "isodir= %s", bkpinfo->isodir);
1027 }
1028
1029 if (flag_set['c']) {
1030 bkpinfo->backup_media_type = cdr;
1031 }
1032 if (flag_set['C']) {
1033 bkpinfo->backup_media_type = cdstream;
1034 }
1035 if (flag_set['i']) {
1036 bkpinfo->backup_media_type = iso;
1037 }
1038 if (flag_set['n']) {
1039 bkpinfo->backup_media_type = nfs;
1040 /* Never try to eject a NFS device */
1041 bkpinfo->please_dont_eject = TRUE;
1042 }
1043 if (flag_set['r']) {
1044 bkpinfo->backup_media_type = dvd;
1045 }
1046 if (flag_set['t']) {
1047 bkpinfo->backup_media_type = tape;
1048 }
1049 if (flag_set['u']) {
1050 bkpinfo->backup_media_type = udev;
1051 }
1052 if (flag_set['w']) {
1053 bkpinfo->backup_media_type = cdrw;
1054 }
1055 if (flag_set['U']) {
1056 bkpinfo->backup_media_type = usb;
1057 /* Never try to eject a USB device */
1058 bkpinfo->please_dont_eject = TRUE;
1059 }
1060 if (flag_set['z']) {
1061 if (find_home_of_exe("getfattr")) {
1062 mr_asprintf(&g_getfattr,"getfattr");
1063 }
1064 if (find_home_of_exe("getfacl")) {
1065 mr_asprintf(&g_getfacl,"getfacl");
1066 }
1067 }
1068
1069 /* optional, popular */
1070 if (flag_set['g']) {
1071 g_text_mode = FALSE;
1072 }
1073
1074 if (flag_set['E']) {
1075 if (bkpinfo->exclude_paths[0] == '-') {
1076 retval++;
1077 log_to_screen("Please supply a sensible value with '-E'\n");
1078 }
1079 if (bkpinfo->exclude_paths[0]) {
1080 strcat(bkpinfo->exclude_paths, " ");
1081 }
1082 mr_asprintf(&tmp1, "%s", flag_val['E']);
1083
1084 p = tmp1;
1085 q = tmp1;
1086
1087 /* Cut the flag_val['E'] in parts containing all paths to test them */
1088 while (p != NULL) {
1089 q = strchr(p, ' ');
1090 if (q != NULL) {
1091 *q = '\0';
1092 /* Fix bug 14 where ending / cause a problem later
1093 * so handled here for the moment */
1094 q--;
1095 if (*q == '/') {
1096 *q = '\0';
1097 }
1098 q++;
1099 /* End of bug fix */
1100 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
1101 log_msg(1, "WARNING ! %s doesn't exist", p);
1102 }
1103 p = q+1 ;
1104 } else {
1105 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
1106 log_msg(1, "WARNING ! %s doesn't exist", p);
1107 }
1108 p = NULL;
1109 }
1110 }
1111 paranoid_free(tmp1);
1112 lastpos = 0;
1113 while ((token = mr_strtok(flag_val['E'], token_chars, &lastpos)) != NULL) {
1114 switch (get_dsf_mount_list(token, &mounted_on_dsf, &not_mounted_on_dsf)) {
1115 case 1:
1116 log_msg(1, "WARNING ! a path doesn't exist in -E option");
1117 break;
1118 /* Everything is OK; proceed to archive data */
1119 case 0:
1120 if (strlen(mounted_on_dsf)) {
1121 log_to_screen("Excluding the following file systems on %s:\n", token);
1122 log_to_screen(" %s\n", mounted_on_dsf);
1123 log_msg (5, "Adding to bkpinfo->exclude_paths due to -E option: %s", mounted_on_dsf);
1124 strcat(bkpinfo->exclude_paths, mounted_on_dsf);
1125 strcat(bkpinfo->exclude_paths, " ");
1126 }
1127 break;
1128 /* It's a dsf but not a whole disk dsf */
1129 case -2:
1130 log_to_screen("Could %s be a partition instead of a whole disk device special file?\nIgnored.", token);
1131 break;
1132 /* A device special file was not passed in. Process it as a path. */
1133 case -1:
1134 strcat(bkpinfo->exclude_paths, token);
1135 strcat(bkpinfo->exclude_paths, " ");
1136 break;
1137 }
1138 }
1139 log_msg(1, "exclude_paths is now '%s'", bkpinfo->exclude_paths);
1140 log_msg(4, "Finished with the -E option");
1141 }
1142
1143 if (flag_set['e']) {
1144 bkpinfo->please_dont_eject = TRUE;
1145 }
1146
1147 if ((flag_set['N']) && (! bkpinfo->restore_data)) // exclude NFS mounts & devices
1148 {
1149// strncpy(psz, list_of_NFS_devices_and_mounts(), MAX_STR_LEN);
1150 mr_asprintf(&psz, "%s", list_of_NFS_mounts_only());
1151 if (bkpinfo->exclude_paths[0]) {
1152 strncat(bkpinfo->exclude_paths, " ", 4*MAX_STR_LEN);
1153 }
1154 strncat(bkpinfo->exclude_paths, psz, 4*MAX_STR_LEN);
1155 mr_free(psz);
1156
1157 log_msg(3, "-N means we're now excluding %s",
1158 bkpinfo->exclude_paths);
1159 }
1160
1161 if (strlen(bkpinfo->exclude_paths) >= 4*MAX_STR_LEN) {
1162 fatal_error
1163 ("Your '-E' parameter is too long. Increase MAX_STR_LEN");
1164 }
1165
1166 if (flag_set['b']) {
1167 mr_asprintf(&psz, flag_val['b']);
1168 log_msg(1, "psz = '%s'", psz);
1169 if (psz[strlen(psz) - 1] == 'k') {
1170 psz[strlen(psz) - 1] = '\0';
1171 itbs = atol(psz) * 1024L;
1172 } else {
1173 itbs = atol(psz);
1174 }
1175 mr_free(psz);
1176 log_msg(1, "'%s' --> %ld", flag_val['b'], itbs);
1177 log_msg(1, "Internal tape block size is now %ld bytes", itbs);
1178 if (itbs % 512 != 0 || itbs < 256 || itbs > 1024L * 1024) {
1179 fatal_error
1180 ("Are you nuts? Silly, your internal tape block size is. Abort, I shall.");
1181 }
1182 bkpinfo->internal_tape_block_size = itbs;
1183 }
1184
1185 if ((flag_set['D']) && (! bkpinfo->restore_data)) {
1186 bkpinfo->differential = 1;
1187// bkpinfo->differential = atoi (flag_val['D']);
1188 if ((bkpinfo->differential < 1) || (bkpinfo->differential > 9)) {
1189 fatal_error
1190 ("The D option should be between 1 and 9 inclusive");
1191 }
1192 }
1193
1194 if (flag_set['x']) {
1195 strncpy(bkpinfo->image_devs, flag_val['x'], MAX_STR_LEN / 4);
1196 if ((run_program_and_log_output("which ntfsclone", 2)) && (! bkpinfo->restore_data)) {
1197 fatal_error("Please install ntfsprogs package/tarball.");
1198 }
1199 }
1200
1201 if (flag_set['m']) {
1202 bkpinfo->manual_cd_tray = TRUE;
1203 }
1204
1205 if ((flag_set['k']) && (! bkpinfo->restore_data)) {
1206 strncpy(bkpinfo->kernel_path, flag_val['k'], MAX_STR_LEN);
1207 if (!strcmp(bkpinfo->kernel_path, "failsafe")) {
1208 strcpy(bkpinfo->kernel_path, "FAILSAFE");
1209 }
1210 if (strcmp(bkpinfo->kernel_path, "FAILSAFE")
1211 && !does_file_exist(bkpinfo->kernel_path)) {
1212 retval++;
1213 sprintf(tmp,
1214 "You specified kernel '%s', which does not exist\n",
1215 bkpinfo->kernel_path);
1216 log_to_screen(tmp);
1217 }
1218 }
1219
1220 if (flag_set['p']) {
1221 strncpy(bkpinfo->prefix, flag_val['p'], MAX_STR_LEN / 4);
1222 log_msg(1,"Prefix forced to %s",bkpinfo->prefix);
1223 }
1224
1225 if (flag_set['d']) { /* backup directory (if ISO/NFS) */
1226 if (flag_set['i']) {
1227 strncpy(bkpinfo->isodir, flag_val['d'], MAX_STR_LEN / 4);
1228 sprintf(tmp, "ls -l %s", bkpinfo->isodir);
1229 if (run_program_and_log_output(tmp, 2)) {
1230 fatal_error
1231 ("output folder does not exist - please create it");
1232 }
1233 } else if (flag_set['n']) {
1234 strncpy(bkpinfo->nfs_remote_dir, flag_val['d'], MAX_STR_LEN);
1235 } else { /* backup device (if tape/CD-R/CD-RW) */
1236 strncpy(bkpinfo->media_device, flag_val['d'], MAX_STR_LEN / 4);
1237 }
1238 }
1239
1240 if ((flag_set['n']) && (! bkpinfo->restore_data)) {
1241 mr_asprintf(&tmp1,"%s/%s/.dummy.txt", bkpinfo->isodir,bkpinfo->nfs_remote_dir);
1242 if (bkpinfo->nfs_user) {
1243 sprintf(tmp, "su - %s -c \"echo hi > %s\"", bkpinfo->nfs_user, tmp1);
1244 } else {
1245 sprintf(tmp, "echo hi > %s", tmp1);
1246 }
1247 if (run_program_and_log_output(tmp, 2)) {
1248 retval++;
1249 sprintf(tmp,
1250 "Are you sure directory '%s' exists in remote dir '%s'?\nIf so, do you have rights to write to it?\n",
1251 bkpinfo->nfs_remote_dir, bkpinfo->nfs_mount);
1252 log_to_screen(tmp);
1253 }
1254 unlink(tmp1);
1255 paranoid_free(tmp1);
1256 }
1257
1258 if (!flag_set['d']
1259 && (flag_set['c'] || flag_set['w'] || flag_set['C'])) {
1260 if (g_kernel_version >= 2.6) {
1261 if (popup_and_get_string
1262 ("Device", "Please specify the device",
1263 bkpinfo->media_device, MAX_STR_LEN / 4)) {
1264 retval++;
1265 log_to_screen("User opted to cancel.");
1266 }
1267 } else if (find_cdrw_device(bkpinfo->media_device)) {
1268 retval++;
1269 log_to_screen
1270 ("Tried and failed to find CD-R[W] drive automatically.\n");
1271 } else {
1272 flag_set['d'] = TRUE;
1273 strncpy(flag_val['d'], bkpinfo->media_device, MAX_STR_LEN / 4);
1274 }
1275 }
1276
1277 if ((!flag_set['d'] && !flag_set['n'] && !flag_set['C']) && (! bkpinfo->restore_data)) {
1278 retval++;
1279 log_to_screen("Please specify the backup device/directory.\n");
1280 fatal_error
1281 ("You didn't use -d to specify the backup device/directory.");
1282 }
1283
1284 for (i = '0'; i <= '9'; i++) {
1285 if (flag_set[i]) {
1286 bkpinfo->compression_level = i - '0';
1287 } /* not '\0' but '0' */
1288 }
1289
1290 if (flag_set['S']) {
1291 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%ld", flag_val['S'],
1292 random() % 32768);
1293 }
1294
1295 if (flag_set['T']) {
1296 setup_tmpdir(flag_val['T']);
1297 sprintf(tmp, "touch %s/.foo.dat", bkpinfo->tmpdir);
1298 if (run_program_and_log_output(tmp, 1)) {
1299 retval++;
1300 log_to_screen
1301 ("Please specify a tempdir which I can write to. :)");
1302 fatal_error("I cannot write to the tempdir you specified.");
1303 }
1304 sprintf(tmp, "ln -sf %s/.foo.dat %s/.bar.dat", bkpinfo->tmpdir, bkpinfo->tmpdir);
1305 if (run_program_and_log_output(tmp, 1)) {
1306 retval++;
1307 log_to_screen
1308 ("Please don't specify a SAMBA or VFAT or NFS tmpdir.");
1309 fatal_error("I cannot write to the tempdir you specified.");
1310 }
1311 }
1312
1313 if ((flag_set['A']) && (! bkpinfo->restore_data)) {
1314 strncpy(bkpinfo->call_after_iso, flag_val['A'], MAX_STR_LEN);
1315 }
1316
1317 if ((flag_set['B']) && (! bkpinfo->restore_data)) {
1318 strncpy(bkpinfo->call_before_iso, flag_val['B'], MAX_STR_LEN);
1319 }
1320
1321 if ((flag_set['H']) && (! bkpinfo->restore_data)) {
1322 g_cd_recovery = TRUE;
1323 }
1324
1325 if ((flag_set['l']) && (! bkpinfo->restore_data)) {
1326#ifdef __FreeBSD__
1327# define BOOT_LOADER_CHARS "GLBMR"
1328#else
1329# ifdef __IA64__
1330# define BOOT_LOADER_CHARS "GER"
1331# else
1332# define BOOT_LOADER_CHARS "GLR"
1333# endif
1334#endif
1335 if (!strchr
1336 (BOOT_LOADER_CHARS,
1337 (bkpinfo->boot_loader = flag_val['l'][0]))) {
1338 log_msg(1, "%c? WTF is %c? I need G, L, E or R.",
1339 bkpinfo->boot_loader, bkpinfo->boot_loader);
1340 fatal_error
1341 ("Please specify GRUB, LILO, ELILO or RAW with the -l switch");
1342 }
1343#undef BOOT_LOADER_CHARS
1344 }
1345
1346 if (flag_set['f']) {
1347 strncpy(bkpinfo->boot_device,
1348 resolve_softlinks_to_get_to_actual_device_file(flag_val
1349 ['f']),
1350 MAX_STR_LEN / 4);
1351 }
1352
1353 if ((flag_set['P']) && (! bkpinfo->restore_data)) {
1354 strncpy(bkpinfo->postnuke_tarball, flag_val['P'], MAX_STR_LEN);
1355 }
1356
1357 if (flag_set['Q']) {
1358 i = which_boot_loader(tmp);
1359 log_msg(3, "boot loader is %c, residing at %s", i, tmp);
1360 printf("boot loader is %c, residing at %s\n", i, tmp);
1361 finish(0);
1362 }
1363
1364 if ((flag_set['L']) && (! bkpinfo->restore_data)) {
1365 bkpinfo->use_lzo = TRUE;
1366 if (run_program_and_log_output("which lzop", 2)) {
1367 retval++;
1368 log_to_screen
1369 ("Please install LZOP. You can't use '-L' until you do.\n");
1370 }
1371 }
1372
1373 if ((flag_set['G']) && (! bkpinfo->restore_data)) {
1374 bkpinfo->use_gzip = TRUE;
1375 if (run_program_and_log_output("which gzip", 2)) {
1376 retval++;
1377 log_to_screen
1378 ("Please install gzip. You can't use '-G' until you do.\n");
1379 }
1380 }
1381
1382 bkpinfo->use_obdr = FALSE;
1383 if (flag_set['o']) {
1384 if ((!flag_set['t']) && (! bkpinfo->restore_data)) {
1385 log_to_screen("OBDR support is only available for tapes. Use the -t option");
1386 fatal_error("Aborting");
1387 }
1388 bkpinfo->use_obdr = TRUE;
1389 }
1390
1391#ifndef __FreeBSD__
1392 if ((!is_this_a_valid_disk_format("vfat")) && (! bkpinfo->restore_data)) {
1393 bkpinfo->make_cd_use_lilo = TRUE;
1394 log_to_screen
1395 ("Your kernel appears not to support vfat filesystems. I am therefore");
1396 log_to_screen
1397 ("using LILO instead of SYSLINUX as the media boot loader.");
1398 }
1399 if ((run_program_and_log_output("which mkfs.vfat", 2)) && (! bkpinfo->restore_data)) {
1400 bkpinfo->make_cd_use_lilo = TRUE;
1401#ifdef __IA32__
1402 log_to_screen
1403 ("Your filesystem is missing 'mkfs.vfat', so I cannot use SYSLINUX as");
1404 log_to_screen
1405 ("your boot loader. I shall therefore use LILO instead.");
1406#endif
1407#ifdef __IA64__
1408 log_to_screen
1409 ("Your filesystem is missing 'mkfs.vfat', so I cannot prepare the EFI");
1410 log_to_screen("environment correctly. Please install it.");
1411 fatal_error("Aborting");
1412#endif
1413 }
1414#ifdef __IA64__
1415 /* We force ELILO usage on IA64 */
1416 bkpinfo->make_cd_use_lilo = TRUE;
1417#endif
1418#endif
1419
1420 if (! bkpinfo->restore_data) {
1421 i = flag_set['O'] + flag_set['V'];
1422 if (i == 0) {
1423 retval++;
1424 log_to_screen("Specify backup (-O), verify (-V) or both (-OV).\n");
1425 }
1426 }
1427
1428 if ((! bkpinfo->restore_data) && (flag_set['Z'])) {
1429 fatal_error
1430 ("The -Z switch is only valid in restore mode");
1431 }
1432
1433 if (flag_set['Z']) {
1434 if (! strcmp(flag_val['Z'], "nuke")) {
1435 bkpinfo->restore_mode = nuke;
1436 } else if (! strcmp(flag_val['Z'], "interactive")) {
1437 bkpinfo->restore_mode = interactive;
1438 } else if (! strcmp(flag_val['Z'], "compare")) {
1439 bkpinfo->restore_mode = compare;
1440 } else if (! strcmp(flag_val['Z'], "mbr")) {
1441 bkpinfo->restore_mode = mbr;
1442 } else if (! strcmp(flag_val['Z'], "iso")) {
1443 bkpinfo->restore_mode = isoonly;
1444 } else if (! strcmp(flag_val['Z'], "isonuke")) {
1445 bkpinfo->restore_mode = isonuke;
1446 } else {
1447 bkpinfo->restore_mode = interactive;
1448 }
1449 }
1450
1451/* and finally... */
1452
1453 paranoid_free(tmp);
1454 return (retval);
1455}
1456
1457
1458
1459/**
1460 * Get the switches from @p argc and @p argv using getopt() and place them in
1461 * @p flag_set and @p flag_val.
1462 * @param argc The argument count (@p argc passed to main()).
1463 * @param argv The argument vector (@p argv passed to main()).
1464 * @param flag_val An array indexed by switch letter - if a switch is set and
1465 * has an argument then set flag_val[switch] to that argument.
1466 * @param flag_set An array indexed by switch letter - if a switch is set then
1467 * set flag_set[switch] to TRUE, else set it to FALSE.
1468 * @return The number of problems with the command line (0 for success).
1469 */
1470int
1471retrieve_switches_from_command_line(int argc, char *argv[],
1472 char flag_val[128][MAX_STR_LEN],
1473 bool flag_set[128])
1474{
1475 /*@ ints ** */
1476 int opt = 0;
1477 char *tmp = NULL;
1478 int i = 0;
1479 int len;
1480
1481 /*@ bools *** */
1482 bool bad_switches = FALSE;
1483
1484 assert(flag_val != NULL);
1485 assert(flag_set != NULL);
1486
1487 for (i = 0; i < 128; i++) {
1488 flag_val[i][0] = '\0';
1489 flag_set[i] = FALSE;
1490 }
1491 while ((opt =
1492 getopt(argc, argv, MONDO_OPTIONS))
1493 != -1) {
1494 if (opt == '?') {
1495 bad_switches = TRUE;
1496 /*log_it("Invalid option: %c\n",optopt); */
1497 } else {
1498 if (flag_set[optopt]) {
1499 bad_switches = TRUE;
1500 mr_asprintf(&tmp, "Switch -%c previously defined as %s\n", opt,
1501 flag_val[i]);
1502 log_to_screen(tmp);
1503 paranoid_free(tmp);
1504 } else {
1505 flag_set[opt] = TRUE;
1506 if (optarg) {
1507 len = strlen(optarg);
1508 if (optarg[0] != '/' && optarg[len - 1] == '/') {
1509 optarg[--len] = '\0';
1510 log_to_screen
1511 ("Warning - param '%s' should not have trailing slash!",
1512 optarg);
1513 }
1514 if (opt == 'd') {
1515 if (strchr(flag_val[opt], '/')
1516 && flag_val[opt][0] != '/') {
1517 mr_asprintf(&tmp,
1518 "-%c flag --- must be absolute path --- '%s' isn't absolute",
1519 opt, flag_val[opt]);
1520 log_to_screen(tmp);
1521 paranoid_free(tmp);
1522 bad_switches = TRUE;
1523 }
1524 }
1525 strcpy(flag_val[opt], optarg);
1526 }
1527 }
1528 }
1529 }
1530 for (i = optind; i < argc; i++) {
1531 bad_switches = TRUE;
1532 mr_asprintf(&tmp, "Invalid arg -- %s\n", argv[i]);
1533 log_to_screen(tmp);
1534 paranoid_free(tmp);
1535 }
1536 return (bad_switches);
1537}
1538
1539
1540
1541
1542/**
1543 * Print a not-so-helpful help message and exit.
1544 */
1545void help_screen()
1546{
1547 log_msg(1, "Type 'man mondoarchive' for more information\n");
1548 exit(1);
1549}
1550
1551
1552/**
1553 * Terminate Mondo in response to a signal.
1554 * @param sig The signal number received.
1555 */
1556void terminate_daemon(int sig)
1557{
1558 char *tmp = NULL;
1559 char *tmp2 = NULL;
1560
1561 switch (sig) {
1562 case SIGINT:
1563 mr_asprintf(&tmp, "SIGINT");
1564 mr_asprintf(&tmp2, "You interrupted me :-)");
1565 break;
1566 case SIGKILL:
1567 mr_asprintf(&tmp, "SIGKILL");
1568 mr_asprintf(&tmp2,
1569 "I seriously have no clue how this signal even got to me. Something's wrong with your system.");
1570 break;
1571 case SIGTERM:
1572 mr_asprintf(&tmp, "SIGTERM");
1573 mr_asprintf(&tmp2, "Got terminate signal");
1574 break;
1575 case SIGHUP:
1576 mr_asprintf(&tmp, "SIGHUP");
1577 mr_asprintf(&tmp2, "Hangup on line");
1578 break;
1579 case SIGSEGV:
1580 mr_asprintf(&tmp, "SIGSEGV");
1581 mr_asprintf(&tmp2,
1582 "Internal programming error. Please send a backtrace as well as your log.");
1583 break;
1584 case SIGPIPE:
1585 mr_asprintf(&tmp, "SIGPIPE");
1586 mr_asprintf(&tmp2, "Pipe was broken");
1587 break;
1588 case SIGABRT:
1589 mr_asprintf(&tmp, "SIGABRT");
1590 mr_asprintf(&tmp2,
1591 "Abort - probably failed assertion. I'm sleeping for a few seconds so you can read the message.");
1592 break;
1593 default:
1594 mr_asprintf(&tmp, "(Unknown)");
1595 mr_asprintf(&tmp2, "(Unknown)");
1596 }
1597
1598 mr_strcat(tmp, " signal received from OS");
1599 log_to_screen(tmp);
1600 paranoid_free(tmp);
1601
1602 log_to_screen(tmp2);
1603 paranoid_free(tmp2);
1604 if (sig == SIGABRT) {
1605 sleep(10);
1606 }
1607 kill_buffer();
1608
1609 free_MR_global_filenames();
1610
1611 fatal_error
1612 ("MondoRescue is terminating in response to a signal from the OS");
1613 finish(254); // just in case
1614}
1615
1616
1617
1618
1619/**
1620 * Turn signal-trapping on or off.
1621 * @param on If TRUE, turn it on; if FALSE, turn it off (we still trap it, just don't do as much).
1622 */
1623void set_signals(int on)
1624{
1625 int signals[] =
1626 { SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT, SIGKILL, SIGSTOP, 0 };
1627 int i;
1628
1629 signal(SIGPIPE, sigpipe_occurred);
1630 for (i = 0; signals[i]; i++) {
1631 if (on) {
1632 signal(signals[i], terminate_daemon);
1633 } else {
1634 signal(signals[i], termination_in_progress);
1635 }
1636 }
1637}
1638
1639
1640
1641
1642/**
1643 * Exit immediately without cleaning up.
1644 * @param sig The signal we are exiting due to.
1645 */
1646void termination_in_progress(int sig)
1647{
1648 log_msg(1, "Termination in progress");
1649 usleep(1000);
1650 pthread_exit(0);
1651}
1652
1653/* @} - end of cliGroup */
Note: See TracBrowser for help on using the repository browser.