source: MondoRescue/branches/3.1/mondo/src/common/libmondo-cli.c@ 3190

Last change on this file since 3190 was 3190, checked in by Bruno Cornec, 11 years ago
  • Modification to 3.1 branch to make it extremely similar to 3.0. What remains are function rewrite with allocation in the function and desallocation outside of the function. Will be next step
  • Property svn:keywords set to Id
File size: 32.4 KB
Line 
1/***************************************************************************
2$Id: libmondo-cli.c 3190 2013-09-25 06:55:43Z 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_str.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 bool g_fail_immediately;
23extern char g_startdir[MAX_STR_LEN]; ///< ????? @bug ?????
24extern char *MONDO_OPTIONS;
25
26/*@ file pointer **************************************************/
27extern FILE *g_tape_stream;
28
29/*@ long long *****************************************************/
30extern long long g_tape_posK;
31
32/*@ long **********************************************************/
33extern long g_noof_sets;
34
35/*@ bool******** **************************************************/
36bool g_debugging = FALSE; ///< ????? @bug ????? @ingroup globalGroup
37bool g_running_live = FALSE; ///< ????? @bug ????? @ingroup globalGroup
38extern bool g_cd_recovery;
39
40extern void setup_tmpdir(char *path);
41extern void setup_scratchdir(char *path);
42void mr_make_devlist_from_pathlist(char *pathlist, char mode);
43extern double g_kernel_version;
44extern int g_current_media_number;
45extern pid_t g_main_pid;
46extern char *resolve_softlinks_to_get_to_actual_device_file(char *);
47
48/* Do we use extended attributes and acl ?
49 * By default no, use -z option to force their usage */
50extern char *g_getfacl;
51extern char *g_getfattr;
52
53/* Reference to global bkpinfo */
54extern struct s_bkpinfo *bkpinfo;
55
56extern void free_MR_global_filenames(void);
57
58long g_max_biggie_size = BIGGIEMAXSIZE;
59
60/**
61 * @addtogroup cliGroup
62 * @{
63 */
64/**
65 * Populate @p bkpinfo from the command-line parameters stored in @p argc and @p argv.
66 * @param argc The argument count, including the program name; @p argc passed to main().
67 * @param argv The argument vector; @p argv passed to main().
68 * @param bkpinfo The backup information structure to populate.
69 * @return The number of problems with the command line (0 for success).
70 */
71int
72handle_incoming_parameters(int argc, char *argv[])
73{
74 /*@ int *** */
75 int res = 0;
76 int retval = 0;
77 int i = 0, j;
78
79 /*@ buffers *************** */
80 char *tmp = NULL;
81 char flag_val[128][MAX_STR_LEN];
82 bool flag_set[128];
83
84 for (i = 0; i < 128; i++) {
85 flag_val[i][0] = '\0';
86 flag_set[i] = FALSE;
87 }
88 bkpinfo->media_size = 650; /* default */
89 res = retrieve_switches_from_command_line(argc, argv, flag_val, flag_set);
90 retval += res;
91 if (!retval) {
92 res = process_switches(flag_val, flag_set);
93 retval += res;
94 }
95
96 log_msg(3, "Switches:-");
97 for (i = 0; i < 128; i++) {
98 if (flag_set[i]) {
99 log_msg(3, "-%c %s", i, flag_val[i]);
100 }
101 }
102
103 return (retval);
104}
105
106
107/**
108 * Store the sizespec(s) stored in @p value into @p bkpinfo.
109 * @param bkpinfo The backup information structure; the @c bkpinfo->media_size field will be populated.
110 * @param value The sizespec (e.g. "2g", "40m").
111 * @return 0, always.
112 * @bug Return code not needed.
113 */
114int process_the_s_switch(char *value)
115{
116 assert(bkpinfo != NULL);
117 assert(value != NULL);
118
119 bkpinfo->media_size = -1; /* dummy value */
120 bkpinfo->media_size = friendly_sizestr_to_sizelong(value);
121 log_msg(3, "media_size = %ld", bkpinfo->media_size);
122 if (bkpinfo->media_size <= 0) {
123 log_msg(1, "You gave media an invalid size %s\n", value);
124 return (-1);
125 }
126 return (0);
127}
128
129/**
130 * Process mondoarchive's command-line switches.
131 * @param bkpinfo The backup information structure to populate.
132 * @param flag_val An array of the argument passed to each switch (the letter is the index).
133 * If a switch is not set or has no argument, the field in @p flag_val doesn't matter.
134 * @param flag_set An array of <tt>bool</tt>s indexed by switch letter: TRUE if it's set,
135 * FALSE if it's not.
136 * @return The number of problems with the switches, or 0 for success.
137 * @bug Maybe include a list of all switches (inc. intentionally undocumented ones not in the manual!) here?
138 */
139int
140process_switches(char flag_val[128][MAX_STR_LEN], bool flag_set[128])
141{
142
143 /*@ ints *** */
144 int i = 0;
145 int retval = 0;
146
147 /*@ buffers ** */
148 char *tmp1 = NULL;
149 char *tmp2 = NULL;
150 char *psz = NULL;
151 char *p = NULL;
152 char *q = NULL;
153
154 long itbs = 0L;
155
156 struct stat buf;
157
158 assert(bkpinfo != NULL);
159 assert(flag_val != NULL);
160 assert(flag_set != NULL);
161
162 bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
163
164 /* compulsory */
165 i = flag_set['c'] + flag_set['i'] + flag_set['n'] +
166 flag_set['t'] + flag_set['u'] + flag_set['r'] +
167 flag_set['w'] + flag_set['C'] + flag_set['U'];
168 if ((i == 0) && (! bkpinfo->restore_data)) {
169 retval++;
170 log_to_screen("You must specify the media type\n");
171 }
172 if (i > 1) {
173 retval++;
174 log_to_screen("Please specify only one media type\n");
175 }
176
177 if (flag_set['K']) {
178 g_loglevel = atoi(flag_val['K']);
179 log_msg(1,"Loglevel forced to %d",g_loglevel);
180 if (g_loglevel < 3) {
181 g_loglevel = 3;
182 }
183 }
184
185 if ((flag_set['L'] && flag_set['0']) && (! bkpinfo->restore_data)) {
186 retval++;
187 log_to_screen("You cannot have 'no compression' _and_ LZOP.\n");
188 }
189 if (! bkpinfo->restore_data) {
190 bkpinfo->backup_data = flag_set['O'];
191 }
192 bkpinfo->verify_data = flag_set['V'];
193
194 if (flag_set['I'] && !bkpinfo->backup_data) {
195 log_to_screen("-I switch is ignored if just verifying");
196 }
197 if (flag_set['E'] && !bkpinfo->backup_data) {
198 log_to_screen("-E switch is ignored if just verifying");
199 }
200
201 tmp1 = find_home_of_exe("afio");
202 if (!tmp1) {
203 mr_free(tmp1);
204 tmp1 = find_home_of_exe("star");
205 if (tmp1) {
206 mr_free(tmp1);
207 flag_set['R'] = TRUE;
208 log_msg(1, "Using star instead of afio");
209 } else {
210 mr_free(tmp1);
211 fatal_error("Neither afio nor star is installed. Please install at least one.");
212 }
213 }
214 mr_free(tmp1);
215
216 if (flag_set['R']) {
217 bkpinfo->use_star = TRUE;
218 if (flag_set['L']) {
219 fatal_error("You may not use star and lzop at the same time.");
220 }
221 tmp1 = find_home_of_exe("star");
222 if (!tmp1) {
223 mr_free(tmp1);
224 fatal_error("Please install 'star' RPM or tarball if you are going to use -R. Thanks.");
225 }
226 mr_free(tmp1);
227 }
228
229 if ((flag_set['W']) && (! bkpinfo->restore_data)) {
230 bkpinfo->nonbootable_backup = TRUE;
231 log_to_screen("Warning - you have opted for non-bootable backup");
232 if (flag_set['f'] || flag_set['l']) {
233 log_to_screen
234 ("You don't need to specify bootloader or bootdevice");
235 }
236 }
237
238 if (flag_set['I']) {
239 if (bkpinfo->include_paths && bkpinfo->include_paths[0] == '-') {
240 retval++;
241 log_to_screen("Please supply a sensible value with '-I'\n");
242 }
243 if (!strcmp(bkpinfo->include_paths, "/")) {
244 log_msg(2, "'/' is pleonastic.");
245 bkpinfo->include_paths[0] = '\0';
246 }
247 if (bkpinfo->include_paths[0]) {
248 strcat(bkpinfo->include_paths, "|");
249 }
250
251 mr_asprintf(tmp1, "%s", flag_val['I']);
252 p = tmp1;
253 q = tmp1;
254
255 /* Cut the flag_val['I'] in parts containing all paths to test them */
256 while (p != NULL) {
257 q = strchr(p, '|');
258 if (q != NULL) {
259 *q = '\0';
260 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
261 log_msg(1, "ERROR ! %s doesn't exist", p);
262 fatal_error("ERROR ! You specified a directory to include which doesn't exist");
263 }
264 p = q+1 ;
265 } else {
266 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
267 log_msg(1, "ERROR ! %s doesn't exist", p);
268 fatal_error("ERROR ! You specified a directory to include which doesn't exist");
269 }
270 p = NULL;
271 }
272 }
273 mr_free(tmp1);
274 mr_make_devlist_from_pathlist(flag_val['I'], 'I');
275 log_msg(4, "Finished with the -I option");
276 }
277
278 if (g_kernel_version >= 2.6 && !flag_set['d'] && (flag_set['c'] || flag_set['w']) && (! bkpinfo->restore_data)) {
279 fatal_error("If you are using the 2.6.x kernel, please specify the CD-R(W) device.");
280 }
281
282
283 if (flag_set['J']) {
284 if (flag_set['I']) {
285 retval++;
286 log_to_screen("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. :-)");
287 }
288 bkpinfo->make_filelist = FALSE;
289 mr_asprintf(bkpinfo->include_paths, "%s", flag_val['J']);
290 }
291
292 if ((flag_set['c'] || flag_set['w'] || flag_set['C'] || flag_set['r']) && (! bkpinfo->restore_data)) {
293 if (!flag_set['r'] && g_kernel_version <= 2.5 && strstr(flag_val['d'], "/dev/")) {
294 fatal_error("Please don't give a /dev entry. Give a SCSI node for the parameter of the -d flag.");
295 }
296 if (flag_set['r'] && g_kernel_version <= 2.5 && !strstr(flag_val['d'], "/dev/")) {
297 fatal_error("Please give a /dev entry, not a SCSI node, as the parameter of the -d flag.");
298 }
299 if (g_kernel_version >= 2.6 && !strstr(flag_val['d'], "/dev/")) {
300 log_to_screen("Linus says 2.6 has a broken ide-scsi module. Proceed at your own risk...");
301 }
302
303 if (system("which cdrecord > /dev/null 2> /dev/null") && system("which dvdrecord > /dev/null 2> /dev/null")) {
304 fatal_error("Please install dvdrecord/cdrecord and try again.");
305 }
306 if (flag_set['C']) {
307 bkpinfo->cdrw_speed = atoi(flag_val['C']);
308 if (bkpinfo->cdrw_speed < 1) {
309 fatal_error("You specified a silly speed for a CD-R[W] drive");
310 }
311 if (!flag_set['L']) {
312 log_to_screen("You must use -L with -C. Therefore I am setting it for you.");
313 flag_set['L'] = 1;
314 flag_val['L'][0] = '\0';
315 }
316 } else {
317 log_msg(3, "flag_val['c'] = %s", flag_val['c']);
318 log_msg(3, "flag_val['w'] = %s", flag_val['w']);
319 if (flag_set['c']) {
320 bkpinfo->cdrw_speed = atoi(flag_val['c']);
321 } else if (flag_set['w']) {
322 bkpinfo->cdrw_speed = atoi(flag_val['w']);
323 } else if (flag_set['r']) {
324 bkpinfo->cdrw_speed = 1; /*atoi(flag_val['r']); */
325 }
326
327 if (bkpinfo->cdrw_speed < 1) {
328 fatal_error("You specified a silly speed for a CD-R[W] drive");
329 }
330 }
331 }
332
333 if ((flag_set['t'] && !flag_set['d']) && (! bkpinfo->restore_data)) {
334 log_it("Hmm! No tape drive specified. Let's see what we can do.");
335 if ((tmp1 = mr_find_tape_device()) == NULL) {
336 fatal_error("Tape device not specified. I couldn't find it either.");
337 }
338 strcpy(flag_val['d'], tmp1);
339 mr_free(tmp1);
340 flag_set['d'] = TRUE;
341 log_to_screen("You didn't specify a tape streamer device. I'm assuming %s", flag_val['d']);
342 }
343
344 if (flag_set['U']) // USB
345 {
346 if (! flag_set['d']) {
347 fatal_error("You need to specify a device file with -d for bootable USB device usage");
348 }
349 if ((!flag_set['s']) && (! bkpinfo->restore_data)) {
350 fatal_error("You did not specify a size (-s) for your USB device. Aborting");
351 }
352 }
353
354 if (flag_set['r']) // DVD
355 {
356 if (flag_set['m']) {
357 fatal_error("Manual CD tray (-m) not yet supported in conjunction w/ DVD drives. Drop -m.");
358 }
359 if (!flag_set['d']) {
360 if ((tmp1 = find_dvd_device(flag_val['d'])) != NULL) {
361 strcpy(flag_val['d'],tmp1);
362 mr_free(tmp1);
363 flag_set['d'] = TRUE;
364 log_to_screen("I guess DVD drive is at %s", flag_val['d']);
365 }
366 }
367 if (strchr(flag_val['d'], ',')) {
368 fatal_error("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag.");
369 }
370 if (! bkpinfo->restore_data) {
371 tmp1 = find_home_of_exe("growisofs");
372 if (!tmp1) {
373 mr_free(tmp1);
374 fatal_error("Please install growisofs (probably part of dvd+rw-tools). If you want DVD support, you need it.");
375 }
376 mr_free(tmp1);
377
378 tmp1 = find_home_of_exe("dvd+rw-format");
379 if (!tmp1) {
380 mr_free(tmp1);
381 fatal_error("Please install dvd+rw-format (probably part of dvd+rw-tools). If you want DVD support, you need it.");
382 }
383 mr_free(tmp1);
384
385 if (!flag_set['s']) {
386 sprintf(flag_val['s'], "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4582 MB
387 strcat(flag_val['s'], "m");
388 log_to_screen("You did not specify a size (-s) for DVD. I'm guessing %s.", flag_val['s']);
389 flag_set['s'] = 1;
390 }
391 }
392 }
393
394 if (flag_set['t'] || flag_set['u']) { /* tape size */
395 if (strchr(flag_val['d'], ',')) {
396 fatal_error("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag.");
397 }
398 if ((flag_set['O']) && (! bkpinfo->restore_data)) {
399 if (flag_set['s']) {
400 if (flag_set['t']) {
401 fatal_error("For the moment, please don't specify a tape size. Mondo should handle end-of-tape gracefully anyway.");
402 }
403 if (process_the_s_switch(flag_val['s'])) {
404 fatal_error("Bad -s switch");
405 }
406 } else if (flag_set['u'] || flag_set['t']) {
407 bkpinfo->media_size = 0;
408 } else {
409 retval++;
410 log_to_screen("Tape size not specified.\n");
411 }
412 }
413 } else if (! bkpinfo->restore_data) { /* CD|USB size */
414 if (flag_set['s']) {
415 if (process_the_s_switch(flag_val['s'])) {
416 fatal_error("Bad -s switch");
417 }
418 }
419 if (flag_set['w']) {
420 bkpinfo->wipe_media_first = TRUE;
421 } /* CD-RW */
422 }
423
424 if (flag_set['n']) {
425 mr_free(bkpinfo->netfs_mount);
426 mr_asprintf(bkpinfo->netfs_mount, "%s", flag_val['n']);
427 if (!flag_set['d']) {
428 mr_free(bkpinfo->netfs_remote_dir);
429 mr_asprintf(bkpinfo->netfs_remote_dir, "/");
430 }
431 /* test for protocol */
432 p = strstr(bkpinfo->netfs_mount, "://");
433 if (p == NULL) {
434 /* protocol not found assuming NFS for compatibility */
435 mr_asprintf(q,"nfs");
436
437 p = strchr(bkpinfo->netfs_mount, ':');
438 if (p == NULL) {
439 fatal_error("No protocol specified for remote share mount, nor any old NFS syntax found.\nPlease do man mondoarchive as syntax changed");
440 }
441 /* p points on to the string server:/path */
442 p = bkpinfo->netfs_mount;
443
444 } else {
445 /* Isolate the protocol */
446 *p = '\0';
447 mr_asprintf(q,"%s",bkpinfo->netfs_mount);
448
449 /* Skip proto now */
450 p++;
451 p++;
452 p++;
453 }
454 /* whatever done before proto is pointed to by q */
455 bkpinfo->netfs_proto = q;
456
457 /* p points on to the string server:/path */
458 /* Store the 2 values */
459 /* using memmove instead of strcpy as per #584 */
460 /* memmove(bkpinfo->netfs_mount, p, MAX_STR_LEN); */
461 bkpinfo->netfs_mount = p;
462
463 /* test if we specified a user */
464 p = strchr(bkpinfo->netfs_mount, '@');
465 if (p != NULL) {
466 /* User found. Store the 2 values */
467 bkpinfo->netfs_user = bkpinfo->netfs_mount;
468 p++;
469 /* new netfs mount */
470 mr_asprintf(bkpinfo->netfs_mount, "%s", p);
471 /* now that user is computed, create the right value by removing end of string */
472 p--;
473 *p = '\0';
474 }
475 mr_asprintf(tmp1, "mount | grep -E \"^[a-z]*#*[%s@]*%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_user, bkpinfo->netfs_mount);
476 mr_free(bkpinfo->isodir);
477 bkpinfo->isodir = call_program_and_get_last_line_of_output(tmp1,TRUE);
478 mr_free(tmp1);
479
480 if (strlen(bkpinfo->isodir) < 3) {
481 log_to_screen("Network share is not mounted. Trying to mount it for you.\n");
482 if (bkpinfo->netfs_user) {
483 if (strstr(bkpinfo->netfs_proto, "sshfs")) {
484 mr_asprintf(tmp1, "sshfs %s@%s", bkpinfo->netfs_user, bkpinfo->netfs_mount);
485 } else if (strstr(bkpinfo->netfs_proto, "smbfs")) {
486 mr_asprintf(tmp1, "mount -t cifs %s -o user=%s", bkpinfo->netfs_mount, bkpinfo->netfs_user);
487 } else if (strstr(bkpinfo->netfs_proto, "nfs")) {
488 mr_asprintf(tmp1, "mount %s@%s", bkpinfo->netfs_user, bkpinfo->netfs_mount);
489 } else {
490 log_to_screen("Protocol %s not supported yet for network backups.\n", bkpinfo->netfs_proto);
491 fatal_error("Bad Protocol\n");
492 }
493 } else {
494 if (strstr(bkpinfo->netfs_proto, "sshfs")) {
495 mr_asprintf(tmp1, "sshfs %s", bkpinfo->netfs_mount);
496 } else if (strstr(bkpinfo->netfs_proto, "smbfs")) {
497 mr_asprintf(tmp1, "mount -t cifs %s", bkpinfo->netfs_mount);
498 } else if (strstr(bkpinfo->netfs_proto, "nfs")) {
499 mr_asprintf(tmp1, "mount %s", bkpinfo->netfs_mount);
500 } else {
501 log_to_screen("Protocol %s not supported yet for network backups.\n", bkpinfo->netfs_proto);
502 fatal_error("Bad Protocol\n");
503 }
504 }
505 i = system(tmp1);
506 mr_free(tmp1);
507
508 if (i) {
509 log_to_screen("Unable to mount Network share %s. Please mount manually.\n", bkpinfo->netfs_mount);
510 retval++;
511 } else {
512 if (bkpinfo->netfs_user) {
513 mr_asprintf(tmp1, "mount | grep -E \"^[%s@]*%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_user, bkpinfo->netfs_mount);
514 } else {
515 mr_asprintf(tmp1, "mount | grep -E \"^%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_mount);
516 }
517 mr_free(bkpinfo->isodir);
518 bkpinfo->isodir = call_program_and_get_last_line_of_output(tmp1,TRUE);
519 mr_free(tmp1);
520
521 if (strlen(bkpinfo->isodir) < 3) {
522 retval++;
523 log_to_screen("Network share %s is strangely not mounted. Please mount manually...\n", bkpinfo->netfs_mount);
524 }
525 }
526 }
527 log_msg(3, "proto = %s", bkpinfo->netfs_proto);
528 log_msg(3, "mount = %s", bkpinfo->netfs_mount);
529 if (bkpinfo->netfs_user) {
530 log_msg(3, "user = %s", bkpinfo->netfs_user);
531 }
532 log_msg(3, "isodir= %s", bkpinfo->isodir);
533 }
534
535 if (flag_set['c']) {
536 bkpinfo->backup_media_type = cdr;
537 }
538 if (flag_set['C']) {
539 bkpinfo->backup_media_type = cdstream;
540 }
541 if (flag_set['i']) {
542 bkpinfo->backup_media_type = iso;
543 }
544 if (flag_set['n']) {
545 bkpinfo->backup_media_type = netfs;
546 /* Never try to eject a Network device */
547 bkpinfo->please_dont_eject = TRUE;
548 }
549 if (flag_set['r']) {
550 bkpinfo->backup_media_type = dvd;
551 }
552 if (flag_set['t']) {
553 bkpinfo->backup_media_type = tape;
554 }
555 if (flag_set['u']) {
556 bkpinfo->backup_media_type = udev;
557 }
558 if (flag_set['w']) {
559 bkpinfo->backup_media_type = cdrw;
560 }
561 if (flag_set['U']) {
562 bkpinfo->backup_media_type = usb;
563 /* Never try to eject a USB device */
564 bkpinfo->please_dont_eject = TRUE;
565 }
566 if (flag_set['z']) {
567 tmp1 = find_home_of_exe("getfattr");
568 if (tmp1) {
569 mr_asprintf(g_getfattr,"getfattr");
570 }
571 mr_free(tmp1);
572
573 tmp1 = find_home_of_exe("getfacl");
574 if (tmp1) {
575 mr_asprintf(g_getfacl,"getfacl");
576 }
577 mr_free(tmp1);
578 }
579
580 /* optional, popular */
581 if (flag_set['g']) {
582 g_text_mode = FALSE;
583 }
584
585 if (flag_set['E']) {
586 if (bkpinfo->exclude_paths && (bkpinfo->exclude_paths[0] == '-')) {
587 retval++;
588 log_to_screen("Please supply a sensible value with '-E'\n");
589 }
590 mr_asprintf(tmp1, "%s", flag_val['E']);
591
592 p = tmp1;
593 q = tmp1;
594
595 /* Cut the flag_val['E'] in parts containing all paths to test them */
596 while (p != NULL) {
597 q = strchr(p, '|');
598 if (q != NULL) {
599 *q = '\0';
600 /* Fix bug 14 where ending / cause a problem later
601 * so handled here for the moment */
602 q--;
603 if (*q == '/') {
604 *q = '\0';
605 }
606 q++;
607 /* End of bug fix */
608 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
609 log_msg(1, "WARNING ! %s doesn't exist", p);
610 }
611 p = q+1 ;
612 } else {
613 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
614 log_msg(1, "WARNING ! %s doesn't exist", p);
615 }
616 p = NULL;
617 }
618 }
619 mr_free(tmp1);
620
621 mr_make_devlist_from_pathlist(flag_val['E'], 'E');
622 log_msg(4, "Finished with the -E option");
623 }
624
625 if (flag_set['e']) {
626 bkpinfo->please_dont_eject = TRUE;
627 }
628
629 if (flag_set['M']) {
630 g_max_biggie_size = atol(flag_val['M']);
631 log_msg(1, "Max size for biggie file is now %ld KB", g_max_biggie_size);
632 }
633
634 if ((flag_set['N']) && (! bkpinfo->restore_data)) // exclude Network mounts & devices
635 {
636 psz = list_of_NETFS_mounts_only();
637 log_msg(5, "-N means we'll exclude %s", psz);
638 if (bkpinfo->exclude_paths) {
639 mr_strcat(bkpinfo->exclude_paths, "|%s", psz);
640 mr_free(psz);
641 } else {
642 bkpinfo->exclude_paths = psz;
643 }
644
645 if (bkpinfo->exclude_paths != NULL) {
646 log_msg(3, "-N means we're now excluding %s", bkpinfo->exclude_paths);
647 }
648 }
649
650 if (flag_set['b']) {
651 mr_asprintf(psz, "%s", flag_val['b']);
652 log_msg(1, "psz = '%s'", psz);
653 if (psz[strlen(psz) - 1] == 'k') {
654 psz[strlen(psz) - 1] = '\0';
655 itbs = atol(psz) * 1024L;
656 } else {
657 itbs = atol(psz);
658 }
659 mr_free(psz);
660 log_msg(1, "'%s' --> %ld", flag_val['b'], itbs);
661 log_msg(1, "Internal tape block size is now %ld bytes", itbs);
662 if (itbs % 512 != 0 || itbs < 256 || itbs > 1024L * 1024) {
663 fatal_error("Are you nuts? Silly, your internal tape block size is. Abort, I shall.");
664 }
665 bkpinfo->internal_tape_block_size = itbs;
666 }
667
668 if ((flag_set['D']) && (! bkpinfo->restore_data)) {
669 bkpinfo->differential = 1;
670// bkpinfo->differential = atoi (flag_val['D']);
671 if ((bkpinfo->differential < 1) || (bkpinfo->differential > 9)) {
672 fatal_error("The D option should be between 1 and 9 inclusive");
673 }
674 }
675
676 if (flag_set['x']) {
677 mr_asprintf(bkpinfo->image_devs, "%s", flag_val['x']);
678 if ((run_program_and_log_output("which ntfsclone", 2)) && (! bkpinfo->restore_data)) {
679 fatal_error("Please install ntfsprogs package/tarball.");
680 }
681 }
682
683 if (flag_set['m']) {
684 bkpinfo->manual_cd_tray = TRUE;
685 }
686
687 if ((flag_set['k']) && (! bkpinfo->restore_data)) {
688 mr_free(bkpinfo->kernel_path);
689 mr_asprintf(bkpinfo->kernel_path, "%s", flag_val['k']);
690 if (!does_file_exist(bkpinfo->kernel_path)) {
691 retval++;
692 log_to_screen("You specified kernel '%s', which does not exist\n", bkpinfo->kernel_path);
693 }
694 }
695
696 if (flag_set['p']) {
697 mr_free(bkpinfo->prefix);
698 mr_asprintf(bkpinfo->prefix, "%s", flag_val['p']);
699 log_msg(1,"Prefix forced to %s",bkpinfo->prefix);
700 }
701
702 if (flag_set['d']) { /* backup directory (if ISO/NETFS) */
703 if (flag_set['i']) {
704 mr_free(bkpinfo->isodir);
705 mr_asprintf(bkpinfo->isodir, "%s", flag_val['d']);
706 mr_asprintf(tmp1, "ls -l %s", bkpinfo->isodir);
707 if (run_program_and_log_output(tmp1, 2)) {
708 mr_free(tmp1);
709 fatal_error("output folder does not exist - please create it");
710 }
711 mr_free(tmp1);
712 } else if (flag_set['n']) {
713 mr_free(bkpinfo->netfs_remote_dir);
714 mr_asprintf(bkpinfo->netfs_remote_dir, "%s", flag_val['d']);
715 } else { /* backup device (if tape/CD-R/CD-RW) */
716 mr_free(bkpinfo->media_device);
717 mr_asprintf(bkpinfo->media_device, "%s", flag_val['d']);
718 }
719 }
720
721 if ((flag_set['n']) && (! bkpinfo->restore_data)) {
722 mr_asprintf(tmp1,"%s/%s/.dummy.txt", bkpinfo->isodir,bkpinfo->netfs_remote_dir);
723 if ((bkpinfo->netfs_user) && (strstr(bkpinfo->netfs_proto,"nfs"))) {
724 mr_asprintf(tmp2, "su - %s -c \"echo hi > %s\"", bkpinfo->netfs_user, tmp1);
725 } else {
726 mr_asprintf(tmp2, "echo hi > %s", tmp1);
727 }
728 i = run_program_and_log_output(tmp2, 2);
729 mr_free(tmp2);
730
731 if (i) {
732 retval++;
733 log_to_screen("Are you sure directory '%s' exists in remote dir '%s'?\nIf so, do you have rights to write to it?\n", bkpinfo->netfs_remote_dir, bkpinfo->netfs_mount);
734 }
735 unlink(tmp1);
736 mr_free(tmp1);
737 }
738
739 if (!flag_set['d'] && (flag_set['c'] || flag_set['w'] || flag_set['C'])) {
740 if (g_kernel_version >= 2.6) {
741 tmp2 = popup_and_get_string("Device", "Please specify the device", bkpinfo->media_device);
742 if (tmp2 == NULL) {
743 fatal_error("User opted to cancel.");
744 }
745 bkpinfo->media_device = tmp2;
746 } else {
747 bkpinfo->media_device = find_cdrw_device();
748 if (bkpinfo->media_device == NULL) {
749 retval++;
750 log_to_screen("Tried and failed to find CD-R[W] drive automatically.\n");
751 } else {
752 flag_set['d'] = TRUE;
753 strncpy(flag_val['d'], bkpinfo->media_device, MAX_STR_LEN / 4);
754 }
755 }
756 }
757
758 if ((!flag_set['d'] && !flag_set['n'] && !flag_set['C']) && (! bkpinfo->restore_data)) {
759 retval++;
760 log_to_screen("Please specify the backup device/directory.\n");
761 fatal_error("You didn't use -d to specify the backup device/directory.");
762 }
763
764 for (i = '0'; i <= '9'; i++) {
765 if (flag_set[i]) {
766 bkpinfo->compression_level = i - '0';
767 } /* not '\0' but '0' */
768 }
769
770 if (flag_set['S']) {
771 /* Before changing remove old ones if any */
772 if (bkpinfo->scratchdir) {
773 if (chdir("/tmp")) {
774 // FIXME
775 }
776 mr_asprintf(tmp1, "rm -Rf %s", bkpinfo->scratchdir);
777 paranoid_system(tmp1);
778 mr_free(tmp1);
779 }
780
781 mr_asprintf(tmp1, "ln -sf %s/.foo.dat %s/.bar.dat", bkpinfo->scratchdir, bkpinfo->scratchdir);
782 if (run_program_and_log_output(tmp1, 1)) {
783 retval++;
784 mr_free(tmp1);
785 log_to_screen("Please don't specify a SAMBA or VFAT or NFS scratchdir.");
786 fatal_error("I cannot write to the scratchdir you specified.");
787 }
788 mr_free(tmp1);
789 }
790
791 if (flag_set['T']) {
792 setup_tmpdir(flag_val['T']);
793 mr_asprintf(tmp1, "touch %s/.foo.dat", bkpinfo->tmpdir);
794 i = run_program_and_log_output(tmp1, 1);
795 mr_free(tmp1);
796
797 if (i) {
798 retval++;
799 log_to_screen("Please specify a tempdir which I can write to. :)");
800 fatal_error("I cannot write to the tempdir you specified.");
801 }
802 mr_asprintf(tmp1, "ln -sf %s/.foo.dat %s/.bar.dat", bkpinfo->tmpdir, bkpinfo->tmpdir);
803 i = run_program_and_log_output(tmp1, 1);
804 mr_free(tmp1);
805
806 if (i) {
807 retval++;
808 log_to_screen("Please don't specify a SAMBA or VFAT or NFS tmpdir.");
809 fatal_error("I cannot write to the tempdir you specified.");
810 }
811 }
812
813 if ((flag_set['A']) && (! bkpinfo->restore_data)) {
814 mr_asprintf(bkpinfo->call_after_iso, "%s", flag_val['A']);
815 }
816
817 if ((flag_set['B']) && (! bkpinfo->restore_data)) {
818 mr_asprintf(bkpinfo->call_before_iso, "%s", flag_val['B']);
819 }
820
821 if ((flag_set['H']) && (! bkpinfo->restore_data)) {
822 g_cd_recovery = TRUE;
823 }
824
825 if ((flag_set['l']) && (! bkpinfo->restore_data)) {
826#ifdef __FreeBSD__
827# define BOOT_LOADER_CHARS "GLBMR"
828#else
829# ifdef __IA64__
830# define BOOT_LOADER_CHARS "GER"
831# else
832# define BOOT_LOADER_CHARS "GLR"
833# endif
834#endif
835 if (!strchr(BOOT_LOADER_CHARS, (bkpinfo->boot_loader = flag_val['l'][0]))) {
836 log_msg(1, "%c? What is %c? I need G, L, E or R.", bkpinfo->boot_loader, bkpinfo->boot_loader);
837 fatal_error("Please specify GRUB, LILO, ELILO or RAW with the -l switch");
838 }
839#undef BOOT_LOADER_CHARS
840 }
841
842 if (flag_set['f']) {
843 mr_free(bkpinfo->boot_device);
844 bkpinfo->boot_device = resolve_softlinks_to_get_to_actual_device_file(flag_val['f']);
845 }
846
847 if ((flag_set['P']) && (! bkpinfo->restore_data)) {
848 mr_free(bkpinfo->postnuke_tarball);
849 mr_asprintf(bkpinfo->postnuke_tarball, "%s", flag_val['P']);
850 }
851
852 if (flag_set['Q']) {
853 i = which_boot_loader(NULL);
854 log_msg(3, "boot loader is %c", i);
855 printf("boot loader is %c\n", i);
856 finish(0);
857 }
858
859 if ((flag_set['L']) && (! bkpinfo->restore_data)) {
860 bkpinfo->use_lzo = TRUE;
861 if (run_program_and_log_output("which lzop", 2)) {
862 retval++;
863 log_to_screen("Please install LZOP. You can't use '-L' until you do.\n");
864 }
865 }
866
867 if (flag_set['F']) {
868 log_msg(3, "-F means we will fail immediately at the first interaction request");
869 g_fail_immediately = TRUE;
870 }
871
872 if ((flag_set['G']) && (! bkpinfo->restore_data)) {
873 bkpinfo->use_gzip = TRUE;
874 if (run_program_and_log_output("which gzip", 2)) {
875 retval++;
876 log_to_screen("Please install gzip. You can't use '-G' until you do.\n");
877 }
878 }
879
880 if ((flag_set['Y']) && (! bkpinfo->restore_data)) {
881 bkpinfo->use_lzma = TRUE;
882 if (run_program_and_log_output("which lzma", 2)) {
883 retval++;
884 log_to_screen("Please install lzma. You can't use '-Y' until you do.\n");
885 }
886 }
887
888 bkpinfo->use_obdr = FALSE;
889 if (flag_set['o']) {
890 if ((!flag_set['t']) && (! bkpinfo->restore_data)) {
891 log_to_screen("OBDR support is only available for tapes. Use the -t option");
892 fatal_error("Aborting");
893 }
894 bkpinfo->use_obdr = TRUE;
895 }
896
897#ifndef __FreeBSD__
898 if ((!is_this_a_valid_disk_format("vfat")) && (! bkpinfo->restore_data)) {
899 bkpinfo->make_cd_use_lilo = TRUE;
900 log_to_screen("Your kernel appears not to support vfat filesystems. I am therefore");
901 log_to_screen("using LILO instead of SYSLINUX as the media boot loader.");
902 }
903 if ((run_program_and_log_output("which mkfs.vfat", 2)) && (! bkpinfo->restore_data)) {
904 bkpinfo->make_cd_use_lilo = TRUE;
905#ifdef __IA32__
906 log_to_screen("Your filesystem is missing 'mkfs.vfat', so I cannot use SYSLINUX as");
907 log_to_screen("your boot loader. I shall therefore use LILO instead.");
908#endif
909#ifdef __IA64__
910 log_to_screen("Your filesystem is missing 'mkfs.vfat', so I cannot prepare the EFI");
911 log_to_screen("environment correctly. Please install it.");
912 fatal_error("Aborting");
913#endif
914 }
915#ifdef __IA64__
916 /* We force ELILO usage on IA64 */
917 bkpinfo->make_cd_use_lilo = TRUE;
918#endif
919#endif
920
921 if (! bkpinfo->restore_data) {
922 i = flag_set['O'] + flag_set['V'];
923 if (i == 0) {
924 retval++;
925 log_to_screen("Specify backup (-O), verify (-V) or both (-OV).\n");
926 }
927 }
928
929 if ((! bkpinfo->restore_data) && (flag_set['Z'])) {
930 fatal_error("The -Z switch is only valid in restore mode");
931 }
932
933 if (flag_set['Z']) {
934 if (! strcmp(flag_val['Z'], "nuke")) {
935 bkpinfo->restore_mode = nuke;
936 } else if (! strcmp(flag_val['Z'], "interactive")) {
937 bkpinfo->restore_mode = interactive;
938 } else if (! strcmp(flag_val['Z'], "compare")) {
939 bkpinfo->restore_mode = compare;
940 } else if (! strcmp(flag_val['Z'], "mbr")) {
941 bkpinfo->restore_mode = mbr;
942 } else if (! strcmp(flag_val['Z'], "iso")) {
943 bkpinfo->restore_mode = isoonly;
944 } else if (! strcmp(flag_val['Z'], "isonuke")) {
945 bkpinfo->restore_mode = isonuke;
946 } else {
947 bkpinfo->restore_mode = interactive;
948 }
949 }
950
951/* and finally... */
952
953 return (retval);
954}
955
956
957
958/**
959 * Get the switches from @p argc and @p argv using getopt() and place them in
960 * @p flag_set and @p flag_val.
961 * @param argc The argument count (@p argc passed to main()).
962 * @param argv The argument vector (@p argv passed to main()).
963 * @param flag_val An array indexed by switch letter - if a switch is set and
964 * has an argument then set flag_val[switch] to that argument.
965 * @param flag_set An array indexed by switch letter - if a switch is set then
966 * set flag_set[switch] to TRUE, else set it to FALSE.
967 * @return The number of problems with the command line (0 for success).
968 */
969int retrieve_switches_from_command_line(int argc, char *argv[], char flag_val[128][MAX_STR_LEN], bool flag_set[128])
970{
971 /*@ ints ** */
972 int opt = 0;
973 int i = 0;
974 int len;
975
976 /*@ bools *** */
977 bool bad_switches = FALSE;
978
979 assert(flag_val != NULL);
980 assert(flag_set != NULL);
981
982 for (i = 0; i < 128; i++) {
983 flag_val[i][0] = '\0';
984 flag_set[i] = FALSE;
985 }
986 while ((opt = getopt(argc, argv, MONDO_OPTIONS)) != -1) {
987 if (opt == '?') {
988 bad_switches = TRUE;
989 } else {
990 if (flag_set[opt]) {
991 bad_switches = TRUE;
992 log_to_screen("Switch -%c previously defined as %s\n", opt, flag_val[opt]);
993 } else {
994 flag_set[opt] = TRUE;
995 if (optarg) {
996 len = strlen(optarg);
997 if (optarg[0] != '/' && optarg[len - 1] == '/') {
998 optarg[--len] = '\0';
999 log_to_screen
1000 ("Warning - param '%s' should not have trailing slash!",
1001 optarg);
1002 }
1003 if (opt == 'd') {
1004 if (strchr(flag_val[opt], '/')
1005 && flag_val[opt][0] != '/') {
1006 log_to_screen("-%c flag --- must be absolute path --- '%s' isn't absolute", opt, flag_val[opt]);
1007 bad_switches = TRUE;
1008 }
1009 }
1010 strcpy(flag_val[opt], optarg);
1011 }
1012 }
1013 }
1014 }
1015 for (i = optind; i < argc; i++) {
1016 bad_switches = TRUE;
1017 log_to_screen("Invalid arg -- %s\n", argv[i]);
1018 }
1019 return (bad_switches);
1020}
1021
1022
1023
1024
1025/**
1026 * Print a not-so-helpful help message and exit.
1027 */
1028void help_screen()
1029{
1030 log_msg(1, "Type 'man mondoarchive' for more information\n");
1031 exit(1);
1032}
1033
1034
1035/**
1036 * Terminate Mondo in response to a signal.
1037 * @param sig The signal number received.
1038 */
1039void terminate_daemon(int sig)
1040{
1041 char *tmp = NULL;
1042 char *tmp2 = NULL;
1043
1044 switch (sig) {
1045 case SIGINT:
1046 mr_asprintf(tmp, "SIGINT");
1047 mr_asprintf(tmp2, "You interrupted me :-)");
1048 break;
1049 case SIGKILL:
1050 mr_asprintf(tmp, "SIGKILL");
1051 mr_asprintf(tmp2, "I seriously have no clue how this signal even got to me. Something's wrong with your system.");
1052 break;
1053 case SIGTERM:
1054 mr_asprintf(tmp, "SIGTERM");
1055 mr_asprintf(tmp2, "Got terminate signal");
1056 break;
1057 case SIGHUP:
1058 mr_asprintf(tmp, "SIGHUP");
1059 mr_asprintf(tmp2, "Hangup on line");
1060 break;
1061 case SIGSEGV:
1062 mr_asprintf(tmp, "SIGSEGV");
1063 mr_asprintf(tmp2, "Internal programming error. Please send a backtrace as well as your log.");
1064 break;
1065 case SIGPIPE:
1066 mr_asprintf(tmp, "SIGPIPE");
1067 mr_asprintf(tmp2, "Pipe was broken");
1068 break;
1069 case SIGABRT:
1070 mr_asprintf(tmp, "SIGABRT");
1071 mr_asprintf(tmp2, "Abort - probably failed assertion. I'm sleeping for a few seconds so you can read the message.");
1072 break;
1073 default:
1074 mr_asprintf(tmp, "(Unknown)");
1075 mr_asprintf(tmp2, "(Unknown)");
1076 }
1077
1078 mr_strcat(tmp, " signal received from OS");
1079 log_to_screen(tmp);
1080 mr_free(tmp);
1081
1082 log_to_screen(tmp2);
1083 mr_free(tmp2);
1084 if (sig == SIGABRT) {
1085 sleep(10);
1086 }
1087 kill_buffer();
1088
1089 free_MR_global_filenames();
1090
1091 fatal_error("MondoRescue is terminating in response to a signal from the OS");
1092 finish(254); // just in case
1093}
1094
1095
1096
1097
1098/**
1099 * Turn signal-trapping on or off.
1100 * @param on If TRUE, turn it on; if FALSE, turn it off (we still trap it, just don't do as much).
1101 */
1102void set_signals(int on)
1103{
1104 int signals[] = { SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT, SIGKILL, SIGSTOP, 0 };
1105 int i;
1106
1107 signal(SIGPIPE, sigpipe_occurred);
1108 for (i = 0; signals[i]; i++) {
1109 if (on) {
1110 signal(signals[i], terminate_daemon);
1111 } else {
1112 signal(signals[i], termination_in_progress);
1113 }
1114 }
1115}
1116
1117
1118
1119
1120/**
1121 * Exit immediately without cleaning up.
1122 * @param sig The signal we are exiting due to.
1123 */
1124void termination_in_progress(int sig)
1125{
1126 log_msg(1, "Termination in progress");
1127 usleep(1000);
1128 pthread_exit(0);
1129}
1130
1131/* @} - end of cliGroup */
Note: See TracBrowser for help on using the repository browser.