source: MondoRescue/branches/stable/mondo/src/mondoarchive/mondo-cli.c@ 1770

Last change on this file since 1770 was 1770, checked in by Bruno Cornec, 16 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

  • Property svn:keywords set to Id
File size: 26.3 KB
Line 
1/***************************************************************************
2$Id: mondo-cli.c 1770 2007-11-06 10:01:53Z 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 "my-stuff.h"
13#include "mondostructures.h"
14#include "mondo-cli-EXT.h"
15#include "libmondo.h"
16#include <pthread.h>
17
18#include "mr_mem.h"
19#include "mr_msg.h"
20#include "mr_gettext.h"
21#include "mr_conf.h"
22
23//static char cvsid[] = "$Id: mondo-cli.c 1770 2007-11-06 10:01:53Z bruno $";
24
25extern bool g_text_mode;
26extern char g_startdir[MAX_STR_LEN]; ///< ????? @bug ?????
27extern char g_tmpfs_mountpt[MAX_STR_LEN];
28extern bool g_sigpipe;
29
30extern struct mr_ar_conf *mr_conf;
31
32/*@ file pointer **************************************************/
33extern FILE *g_tape_stream;
34
35/*@ long long *****************************************************/
36extern long long g_tape_posK;
37
38/*@ long **********************************************************/
39extern long g_noof_sets;
40
41/*@ bool******** **************************************************/
42bool g_debugging = FALSE; ///< ????? @bug ????? @ingroup globalGroup
43bool g_running_live = FALSE; ///< ????? @bug ????? @ingroup globalGroup
44extern bool g_cd_recovery;
45
46extern void setup_tmpdir(char *path);
47
48/**
49 * Whether we're restoring from ISOs. Obviously not, since this is the
50 * backup program.
51 * @note You @b MUST declare this variable somewhere in your program if
52 * you use libmondo. Otherwise the link will fail.
53 * @ingroup globalGroup
54 */
55bool g_ISO_restore_mode = FALSE;
56
57extern double g_kernel_version;
58extern int g_current_media_number;
59extern pid_t g_main_pid;
60extern char *resolve_softlinks_to_get_to_actual_device_file(char *);
61
62/* Do we use extended attributes and acl ?
63 * By default no, use --acl & --attr options to force their usage */
64char *g_getfacl = NULL;
65char *g_getfattr = NULL;
66
67/* Reference to global bkpinfo */
68extern struct s_bkpinfo *bkpinfo;
69
70/**
71 * @addtogroup cliGroup
72 * @{
73 */
74/**
75 * Populate @p bkpinfo from the command-line parameters stored in @p argc and @p argv.
76 * @param argc The argument count, including the program name; @p argc passed to main().
77 * @param argv The argument vector; @p argv passed to main().
78 * @param bkpinfo The backup information structure to populate.
79 * @return The number of problems with the command line (0 for success).
80 */
81int
82handle_incoming_parameters(int argc, char *argv[])
83{
84 /*@ int *** */
85 int res = 0;
86 int retval = 0;
87 int i = 0;
88
89 /*@ buffers *************** */
90 char *tmp = NULL;
91 char flag_val[128][MAX_STR_LEN];
92 bool flag_set[128];
93
94 sensibly_set_tmpdir_and_scratchdir();
95
96 for (i = 0; i < 128; i++) {
97 flag_val[i][0] = '\0';
98 flag_set[i] = FALSE;
99 }
100 res = retrieve_switches_from_command_line(argc, argv, flag_val,
101 flag_set);
102 retval += res;
103 if (!retval) {
104 res = process_switches(flag_val, flag_set);
105 retval += res;
106 }
107/*
108 if (!retval)
109 {
110*/
111 mr_msg(3, "Switches:-");
112 for (i = 0; i < 128; i++) {
113 if (flag_set[i]) {
114 mr_msg(3, "-%c %s", i, flag_val[i]);
115 }
116 }
117// }
118 mr_asprintf(&tmp, "rm -Rf %s/tmp.mondo.*", bkpinfo->tmpdir);
119 paranoid_system(tmp);
120 mr_free(tmp);
121
122 mr_asprintf(&tmp, "rm -Rf %s/mondo.scratch.*", bkpinfo->scratchdir);
123 paranoid_system(tmp);
124 mr_free(tmp);
125
126 sprintf(bkpinfo->scratchdir + strlen(bkpinfo->scratchdir),
127 "/mondo.scratch.%ld", random() % 32767);
128
129 mr_asprintf(&tmp, "mkdir -p %s/tmpfs", bkpinfo->tmpdir);
130 paranoid_system(tmp);
131 mr_free(tmp);
132
133 mr_asprintf(&tmp, "mkdir -p %s", bkpinfo->scratchdir);
134 paranoid_system(tmp);
135 mr_free(tmp);
136 return (retval);
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 char *tmp = NULL;
150 char *q = NULL;
151
152 assert(bkpinfo != NULL);
153 assert(value != NULL);
154
155 mr_asprintf(&tmp, value);
156 q = strchr(tmp, ',');
157 if (q != NULL) {
158 *q = '\0';
159 }
160 bkpinfo->media_size = friendly_sizestr_to_sizelong(tmp);
161 mr_free(tmp);
162
163 mr_msg(3, "media_size = %ld", bkpinfo->media_size);
164 if (bkpinfo->media_size <= 0L) {
165 mr_msg(1, "You gave media an invalid size\n");
166 return (-1);
167 }
168 return (0);
169}
170
171
172/**
173 * Process mondoarchive's command-line switches.
174 * @param bkpinfo The backup information structure to populate.
175 * @param flag_val An array of the argument passed to each switch (the letter is the index).
176 * If a switch is not set or has no argument, the field in @p flag_val doesn't matter.
177 * @param flag_set An array of <tt>bool</tt>s indexed by switch letter: TRUE if it's set,
178 * FALSE if it's not.
179 * @return The number of problems with the switches, or 0 for success.
180 * @bug Maybe include a list of all switches (inc. intentionally undocumented ones not in the manual!) here?
181 */
182int
183process_switches(char flag_val[128][MAX_STR_LEN], bool flag_set[128])
184{
185
186 /*@ ints *** */
187 int i = 0;
188 int retval = 0;
189 int percent = 0;
190
191 /*@ buffers ** */
192 char *tmp = NULL;
193 char *tmp1 = NULL;
194 char *tmp2 = NULL;
195 char *psz = NULL;
196 char *p = NULL;
197 char *q = NULL;
198
199 long itbs = 0L;
200
201 struct stat buf;
202
203 malloc_string(tmp);
204
205 assert(bkpinfo != NULL);
206 assert(flag_val != NULL);
207 assert(flag_set != NULL);
208
209 bkpinfo->internal_tape_block_size = mr_conf->internal_tape_blocksize;
210
211 /* compulsory */
212 i = flag_set['i'] + flag_set['n'] +
213 flag_set['t'] + flag_set['u'] + flag_set['r'] +
214 flag_set['w'] + flag_set['C'] + flag_set['U'];
215 if (i == 0) {
216 retval++;
217 log_to_screen(_("You must specify the media type\n"));
218 }
219 if (i > 1) {
220 retval++;
221 log_to_screen(_("Please specify only one media type\n"));
222 }
223 if (flag_set['K']) {
224 mr_conf->log_level = atoi(flag_val['K']);
225 if (mr_conf->log_level < 3) {
226 mr_conf->log_level = 3;
227 }
228 }
229 if (flag_set['L'] && flag_set['0']) {
230 retval++;
231 log_to_screen(_("You cannot have 'no compression' _and_ LZOP.\n"));
232 }
233 bkpinfo->backup_data = flag_set['O'];
234 bkpinfo->verify_data = flag_set['V'];
235 if (flag_set['I'] && !bkpinfo->backup_data) {
236 log_to_screen(_("-I switch is ignored if just verifying"));
237 }
238 if (flag_set['E'] && !bkpinfo->backup_data) {
239 log_to_screen(_("-E switch is ignored if just verifying"));
240 }
241
242 if (!find_home_of_exe("afio")) {
243 if (find_home_of_exe("star")) {
244 flag_set['R'] = TRUE;
245 mr_msg(1, "Using star instead of afio");
246 } else {
247 fatal_error
248 ("Neither afio nor star is installed. Please install at least one.");
249 }
250 }
251
252 if (flag_set['R']) {
253 bkpinfo->use_star = TRUE;
254 if (flag_set['L']) {
255 fatal_error("You may not use star and lzop at the same time.");
256 }
257 if (!find_home_of_exe("star")) {
258 fatal_error
259 ("Please install 'star' RPM or tarball if you are going to use -R. Thanks.");
260 }
261 }
262 if (flag_set['W']) {
263 bkpinfo->nonbootable_backup = TRUE;
264 log_to_screen("Warning - you have opted for non-bootable backup");
265 if (flag_set['f'] || flag_set['l']) {
266 log_to_screen
267 (_("You don't need to specify bootloader or bootdevice"));
268 }
269 }
270 if (flag_set['t'] && flag_set['H']) {
271 fatal_error
272 ("Sorry, you may not nuke w/o warning from tape. Drop -H, please.");
273 }
274 if (flag_set['I']) {
275 if (!strcmp(bkpinfo->include_paths, "/")) {
276 mr_msg(2, "'/' is pleonastic.");
277 bkpinfo->include_paths[0] = '\0';
278 }
279 if (bkpinfo->include_paths[0]) {
280 strcat(bkpinfo->include_paths, " ");
281 }
282 mr_asprintf(&tmp1, flag_val['I']);
283 p = tmp1;
284 q = tmp1;
285
286 /* Cut the flag_val['I'] in parts containing all paths to test them */
287 while (p != NULL) {
288 q = strchr(p, ' ');
289 if (q != NULL) {
290 *q = '\0';
291 if (stat(p, &buf) != 0) {
292 mr_msg(1, "ERROR ! %s doesn't exist", p);
293 fatal_error("ERROR ! You specified a directory to include which doesn't exist");
294 }
295 p = q+1 ;
296 } else {
297 if (stat(p, &buf) != 0) {
298 mr_msg(1, "ERROR ! %s doesn't exist", p);
299 fatal_error("ERROR ! You specified a directory to include which doesn't exist");
300 }
301 p = NULL;
302 }
303 }
304 mr_free(tmp1);
305
306 strncpy(bkpinfo->include_paths + strlen(bkpinfo->include_paths),
307 flag_val['I'],
308 4*MAX_STR_LEN - strlen(bkpinfo->include_paths));
309 mr_msg(1, "include_paths is now '%s'", bkpinfo->include_paths);
310 if (bkpinfo->include_paths[0] == '-') {
311 retval++;
312 log_to_screen(_("Please supply a sensible value with '-I'\n"));
313 }
314 }
315
316 if (g_kernel_version >= 2.6 && !flag_set['d']
317 && flag_set['w']) {
318 fatal_error
319 ("If you are using the 2.6.x kernel, please specify the CD-R(W) device.");
320 }
321
322 if (flag_set['J']) {
323 if (flag_set['I']) {
324 retval++;
325 log_to_screen
326 (_("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 combine -J with -I. Thanks. :-)"));
327 }
328 bkpinfo->make_filelist = FALSE;
329 strcpy(bkpinfo->include_paths, flag_val['J']);
330 }
331
332 if (flag_set['w'] || flag_set['C'] || flag_set['r']) {
333 if (!flag_set['r'] && g_kernel_version <= 2.5
334 && strstr(flag_val['d'], "/dev/")) {
335 fatal_error
336 ("Please don't give a /dev entry. Give a SCSI node for the parameter of the -d flag.");
337 }
338 if (flag_set['r'] && g_kernel_version <= 2.5
339 && !strstr(flag_val['d'], "/dev/")) {
340 fatal_error
341 ("Please give a /dev entry, not a SCSI node, as the parameter of the -d flag.");
342 }
343 if (g_kernel_version >= 2.6 && !strstr(flag_val['d'], "/dev/")) {
344 log_to_screen
345 (_("Linus says 2.6 has a broken ide-scsi module. Proceed at your own risk..."));
346 }
347
348 if (system("which cdrecord > /dev/null 2> /dev/null")
349 && system("which dvdrecord > /dev/null 2> /dev/null")) {
350 fatal_error
351 ("Please install dvdrecord/cdrecord and try again.");
352 }
353 if (flag_set['w']) {
354 mr_msg(3, "flag_val['w'] = %s", flag_val['w']);
355 bkpinfo->writer_speed = atoi(flag_val['w']);
356 }
357
358 if (bkpinfo->writer_speed < 1) {
359 fatal_error
360 ("You specified a silly speed for a burner");
361 }
362 }
363
364 if (flag_set['t'] && !flag_set['d']) {
365 log_it("Hmm! No tape drive specified. Let's see what we can do.");
366 if (find_tape_device_and_size(flag_val['d'], tmp)) {
367 log_to_screen
368 ("Tape device not specified. I had problems to find it either");
369 }
370 flag_set['d'] = TRUE;
371 mr_asprintf(&tmp2,
372 _("You didn't specify a tape streamer device. I'm assuming %s"),
373 flag_val['d']);
374 log_to_screen(tmp2);
375 mr_free(tmp2);
376 percent = 0;
377 }
378
379 if (flag_set['U']) // USB
380 {
381 if (! flag_set['d']) {
382 fatal_error
383 ("You need to specify a device file with -d for bootable USB device creation");
384 }
385 if (!flag_set['s']) {
386 fatal_error("You did not specify a size (-s) for your USB device. Aborting");
387 }
388 }
389
390 if (flag_set['r']) // DVD
391 {
392 if (flag_set['m']) {
393 fatal_error
394 ("Manual CD tray (-m) not yet supported in conjunction w/ DVD drives. Drop -m.");
395 }
396 if (!flag_set['d']) {
397 if (!find_dvd_device(flag_val['d'], FALSE)) {
398 flag_set['d'] = TRUE;
399 log_to_screen(_("I guess DVD drive is at %s"), flag_val['d']);
400 }
401 }
402 if (!find_home_of_exe("growisofs")) {
403 fatal_error
404 ("Please install growisofs (probably part of dvd+rw-tools). If you want DVD support, you need it.");
405 }
406 if (!find_home_of_exe("dvd+rw-format")) {
407 fatal_error
408 ("Please install dvd+rw-format (probably part of dvd+rw-tools). If you want DVD support, you need it.");
409 }
410 if (strchr(flag_val['d'], ',')) {
411 fatal_error
412 ("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag.");
413 }
414 }
415
416 if (flag_set['t'] || flag_set['u']) { /* tape size */
417 if (strchr(flag_val['d'], ',')) {
418 fatal_error
419 ("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag.");
420 }
421 if (flag_set['O']) {
422 if (flag_set['s']) {
423 if (flag_set['t']) {
424 fatal_error
425 ("For the moment, please don't specify a tape size. Mondo should handle end-of-tape gracefully anyway.");
426 }
427 if (process_the_s_switch(flag_val['s'])) {
428 fatal_error("Bad -s switch");
429 }
430 } else if (flag_set['u'] || flag_set['t']) {
431 /* Force autodetection */
432 bkpinfo->media_size = 0L;
433 } else {
434 retval++;
435 log_to_screen("Tape size not specified.\n");
436 }
437 }
438 } else { /* CD|USB size */
439 if (flag_set['s']) {
440 if (process_the_s_switch(flag_val['s'])) {
441 fatal_error("Bad -s switch");
442 }
443 }
444 if (flag_set['w']) {
445 bkpinfo->wipe_media_first = TRUE;
446 } /* CD-RW */
447 }
448 if (flag_set['n']) {
449 strncpy(bkpinfo->nfs_mount, flag_val['n'], MAX_STR_LEN);
450 if (!flag_set['d']) {
451 strncpy(bkpinfo->nfs_remote_dir, "/", MAX_STR_LEN);
452 }
453 mr_asprintf(&tmp2, "mount | grep -E '^%s .*$' | cut -d' ' -f3",
454 bkpinfo->nfs_mount);
455 strncpy(bkpinfo->isodir,
456 call_program_and_get_last_line_of_output(tmp2),
457 MAX_STR_LEN / 4);
458 mr_free(tmp2);
459 if (strlen(bkpinfo->isodir) < 3) {
460 retval++;
461 log_to_screen(_("NFS share is not mounted. Please mount it.\n"));
462 }
463 mr_msg(3, "mount = %s", bkpinfo->nfs_mount);
464 mr_msg(3, "isodir= %s", bkpinfo->isodir);
465 }
466
467 if (flag_set['C']) {
468 bkpinfo->backup_media_type = cdstream;
469 }
470 if (flag_set['i']) {
471 bkpinfo->backup_media_type = iso;
472 }
473 if (flag_set['n']) {
474 bkpinfo->backup_media_type = nfs;
475 }
476 if (flag_set['r']) {
477 bkpinfo->backup_media_type = dvd;
478 }
479 if (flag_set['t']) {
480 bkpinfo->backup_media_type = tape;
481 }
482 if (flag_set['u']) {
483 bkpinfo->backup_media_type = udev;
484 }
485 if (flag_set['w']) {
486 bkpinfo->backup_media_type = cdrw;
487 }
488 if (flag_set['U']) {
489 bkpinfo->backup_media_type = usb;
490 /* Never try to eject a USB device */
491 bkpinfo->please_dont_eject = TRUE;
492 }
493 if (flag_set['z']) {
494 if (find_home_of_exe("getfattr")) {
495 mr_asprintf(&g_getfattr,"getfattr");
496 }
497 if (find_home_of_exe("getfacl")) {
498 mr_asprintf(&g_getfacl,"getfacl");
499 }
500 }
501
502 /* optional, popular */
503 if (flag_set['g']) {
504 g_text_mode = FALSE;
505 }
506
507 if (flag_set['E']) {
508 if (bkpinfo->exclude_paths[0]) {
509 strcat(bkpinfo->exclude_paths, " ");
510 }
511 mr_asprintf(&tmp1, flag_val['E']);
512 p = tmp1;
513 q = tmp1;
514
515 /* Cut the flag_val['E'] in parts containing all paths to test them */
516 while (p != NULL) {
517 q = strchr(p, ' ');
518 if (q != NULL) {
519 *q = '\0';
520 /* Fix bug 14 where ending / cause a problem later
521 * so handled here for the moment */
522 q--;
523 if (*q == '/') {
524 *q = '\0';
525 }
526 q++;
527 /* End of bug fix */
528 if (stat(p, &buf) != 0) {
529 mr_msg(1, "WARNING ! %s doesn't exist", p);
530 }
531 p = q+1 ;
532 } else {
533 if (stat(p, &buf) != 0) {
534 mr_msg(1, "WARNING ! %s doesn't exist", p);
535 }
536 p = NULL;
537 }
538 }
539 mr_free(tmp1);
540
541 strncpy(bkpinfo->exclude_paths + strlen(bkpinfo->exclude_paths),
542 flag_val['E'],
543 4*MAX_STR_LEN - strlen(bkpinfo->exclude_paths));
544 }
545 if (flag_set['e']) {
546 bkpinfo->please_dont_eject = TRUE;
547 }
548 if (flag_set['N']) // exclude NFS mounts & devices
549 {
550 mr_asprintf(&psz, list_of_NFS_mounts_only());
551 if (bkpinfo->exclude_paths[0]) {
552 strncat(bkpinfo->exclude_paths, " ", 4*MAX_STR_LEN);
553 }
554 strncat(bkpinfo->exclude_paths, psz, 4*MAX_STR_LEN);
555 mr_free(psz);
556 mr_msg(3, "-N means we're now excluding %s",
557 bkpinfo->exclude_paths);
558 }
559 if (strlen(bkpinfo->exclude_paths) >= 4*MAX_STR_LEN) {
560 fatal_error
561 ("Your '-E' parameter is too long. Increase MAX_STR_LEN");
562 }
563 if (flag_set['b']) {
564 mr_asprintf(&psz, flag_val['b']);
565 mr_msg(1, "psz = '%s'", psz);
566 if (psz[strlen(psz) - 1] == 'k') {
567 psz[strlen(psz) - 1] = '\0';
568 itbs = atol(psz) * 1024L;
569 } else {
570 itbs = atol(psz);
571 }
572 mr_free(psz);
573
574 mr_msg(1, "'%s' --> %ld", flag_val['b'], itbs);
575 mr_msg(1, "Internal tape block size is now %ld bytes", itbs);
576 if (itbs % 512 != 0 || itbs < 256 || itbs > 1024L * 1024) {
577 fatal_error
578 ("Are you nuts? Silly, your internal tape block size is. Abort, I shall.");
579 }
580 bkpinfo->internal_tape_block_size = itbs;
581 }
582
583 if (flag_set['D']) {
584 bkpinfo->differential = TRUE;
585 } else {
586 bkpinfo->differential = mr_conf->differential;
587 }
588
589 if (flag_set['x']) {
590 strncpy(bkpinfo->image_devs, flag_val['x'], MAX_STR_LEN / 4);
591 if (run_program_and_log_output("which ntfsclone", 2)) {
592 fatal_error("Please install ntfsprogs package/tarball.");
593 }
594 }
595 if (flag_set['m']) {
596 bkpinfo->manual_tray = TRUE;
597 }
598 if (flag_set['k']) {
599 mr_allocstr(bkpinfo->kernel_path, flag_val['k']);
600 if (!strcmp(bkpinfo->kernel_path, "failsafe")) {
601 mr_allocstr(bkpinfo->kernel_path, "FAILSAFE");
602 }
603 if (strcmp(bkpinfo->kernel_path, "FAILSAFE")
604 && !does_file_exist(bkpinfo->kernel_path)) {
605 retval++;
606 mr_asprintf(&tmp2,
607 _("You specified kernel '%s', which does not exist\n"),
608 bkpinfo->kernel_path);
609 log_to_screen(tmp2);
610 mr_free(tmp2);
611 }
612 }
613
614 if (flag_set['p']) {
615 mr_allocstr(bkpinfo->prefix, flag_val['p']);
616 }
617
618 if (flag_set['d']) { /* backup directory (if ISO/NFS/USB) */
619 if (flag_set['i']) {
620 strncpy(bkpinfo->isodir, flag_val['d'], MAX_STR_LEN / 4);
621 mr_asprintf(&tmp2, "ls -l %s", bkpinfo->isodir);
622 if (run_program_and_log_output(tmp2, 2)) {
623 fatal_error
624 ("output folder does not exist - please create it");
625 }
626 mr_free(tmp2);
627 } else if (flag_set['n']) {
628 strncpy(bkpinfo->nfs_remote_dir, flag_val['d'], MAX_STR_LEN);
629 } else { /* backup device (if tape/CD-R/CD-RW) */
630 mr_asprintf(&tmp2,flag_val['d']);
631 mr_free(bkpinfo->media_device);
632 bkpinfo->media_device = tmp2;
633 }
634 }
635
636 if (flag_set['n']) {
637 mr_asprintf(&tmp1,"%s/%s/.dummy.txt", bkpinfo->isodir,bkpinfo->nfs_remote_dir);
638 mr_asprintf(&tmp2, "echo hi > %s", tmp1);
639 if (run_program_and_log_output(tmp2, 2)) {
640 retval++;
641 mr_free(tmp2);
642 mr_asprintf(&tmp2,
643 _("Are you sure directory '%s' exists in remote dir '%s'?\nIf so, do you have rights to write to it?\n"),
644 bkpinfo->nfs_remote_dir, bkpinfo->nfs_mount);
645 log_to_screen(tmp2);
646 }
647 mr_free(tmp2);
648 unlink(tmp1);
649 mr_free(tmp1);
650 }
651
652 if (!flag_set['d']
653 && (flag_set['w'] || flag_set['C'] || flag_set['U'])) {
654 if (bkpinfo->media_device) {
655 mr_msg(4, "Using device %s", bkpinfo->media_device);
656 strncpy(flag_val['d'], bkpinfo->media_device, MAX_STR_LEN / 4);
657 flag_set['d'] = TRUE;
658 } else {
659 fatal_error(_("No device provided either on command line or in the configuration file"));
660 }
661 }
662
663 if (!flag_set['d'] && !flag_set['n'] && !flag_set['C']) {
664 retval++;
665 log_to_screen(_("Please specify the backup device/directory.\n"));
666 fatal_error
667 ("You didn't use -d to specify the backup device/directory.");
668 }
669
670 /* optional, obscure */
671 for (i = '0'; i <= '9'; i++) {
672 if (flag_set[i]) {
673 bkpinfo->compression_level = i - '0';
674 } /* not '\0' but '0' */
675 }
676 if (flag_set['S']) {
677 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%ld", flag_val['S'],
678 random() % 32768);
679 }
680 if (flag_set['T']) {
681 setup_tmpdir(flag_val['T']);
682 mr_asprintf(&tmp2, "touch %s/.foo.dat", flag_val['T']);
683 if (run_program_and_log_output(tmp2, 1)) {
684 retval++;
685 log_to_screen
686 (_("Please specify a tempdir which I can write to. :)"));
687 fatal_error("I cannot write to the tempdir you specified.");
688 }
689 mr_free(tmp2);
690
691 mr_asprintf(&tmp2, "ln -sf %s/.foo.dat %s/.bar.dat", bkpinfo->tmpdir, bkpinfo->tmpdir);
692 if (run_program_and_log_output(tmp2, 1)) {
693 retval++;
694 log_to_screen
695 (_("Please don't specify a SAMBA or VFAT or NFS tmpdir."));
696 fatal_error("I cannot write to the tempdir you specified.");
697 }
698 mr_free(tmp2);
699 }
700
701 if (flag_set['A']) {
702 strncpy(bkpinfo->call_after_iso, flag_val['A'], MAX_STR_LEN);
703 }
704 if (flag_set['B']) {
705 strncpy(bkpinfo->call_before_iso, flag_val['B'], MAX_STR_LEN);
706 }
707 if (flag_set['H']) {
708 g_cd_recovery = TRUE;
709 }
710 if (flag_set['l']) {
711#ifdef __FreeBSD__
712# define BOOT_LOADER_CHARS "GLBMR"
713#else
714# ifdef __IA64__
715# define BOOT_LOADER_CHARS "GER"
716# else
717# define BOOT_LOADER_CHARS "GLR"
718# endif
719#endif
720 if (!strchr
721 (BOOT_LOADER_CHARS,
722 (bkpinfo->boot_loader = flag_val['l'][0]))) {
723 mr_msg(1, "%c? What is %c? I need G, L, E or R.",
724 bkpinfo->boot_loader, bkpinfo->boot_loader);
725 fatal_error
726 ("Please specify GRUB, LILO, ELILO or RAW with the -l switch");
727 }
728#undef BOOT_LOADER_CHARS
729 }
730
731 if (flag_set['f']) {
732 strncpy(bkpinfo->boot_device,
733 resolve_softlinks_to_get_to_actual_device_file(flag_val
734 ['f']),
735 MAX_STR_LEN / 4);
736 }
737
738 if (flag_set['Q']) {
739 if (bkpinfo->boot_device == NULL) {
740 fatal_error("-f option required when using -Q\n");
741 }
742 i = which_boot_loader(bkpinfo->boot_device);
743 mr_msg(3, "boot loader is %c, residing at %s", i, bkpinfo->boot_device);
744 log_to_screen(_("boot loader is %c, residing at %s\n"), i, tmp);
745 finish(0);
746 }
747
748 if (flag_set['P']) {
749 strncpy(bkpinfo->postnuke_tarball, flag_val['P'], MAX_STR_LEN);
750 }
751
752 if (!flag_set['o']
753 &&
754 !run_program_and_log_output
755 ("grep -Ei suse /etc/issue.net | grep -E '9.0' | grep 64", 2)) {
756 bkpinfo->make_cd_use_lilo = TRUE;
757 log_to_screen
758 (_("Forcing you to use LILO. SuSE 9.0 (64-bit) has a broken mkfs.vfat binary."));
759 }
760
761 if (flag_set['o']) {
762 bkpinfo->make_cd_use_lilo = TRUE;
763 }
764#ifndef __FreeBSD__
765 else {
766 if (!is_this_a_valid_disk_format("vfat")) {
767 bkpinfo->make_cd_use_lilo = TRUE;
768 log_to_screen
769 (_("Your kernel appears not to support vfat filesystems. I am therefore"));
770 log_to_screen
771 (_("using LILO instead of SYSLINUX as the CD's boot loader."));
772 }
773 if (run_program_and_log_output("which mkfs.vfat", 2)) {
774 bkpinfo->make_cd_use_lilo = TRUE;
775#ifdef __IA32__
776 log_to_screen
777 (_("Your filesystem is missing 'mkfs.vfat', so I cannot use SYSLINUX as"));
778 log_to_screen
779 (_("your boot loader. I shall therefore use LILO instead."));
780#endif
781#ifdef __IA64__
782 log_to_screen
783 (_("Your filesystem is missing 'mkfs.vfat', so I cannot prepare the EFI"));
784 log_to_screen(_("environment correctly. Please install it."));
785 fatal_error("Aborting");
786#endif
787 }
788#ifdef __IA64__
789 /* We force ELILO usage on IA64 */
790 bkpinfo->make_cd_use_lilo = TRUE;
791#endif
792 }
793#endif
794
795 if (bkpinfo->make_cd_use_lilo && !does_file_exist("/boot/boot.b")) {
796 paranoid_system("touch /boot/boot.b");
797 }
798
799 i = flag_set['O'] + flag_set['V'];
800 if (i == 0) {
801 retval++;
802 log_to_screen(_("Specify backup (-O), verify (-V) or both (-OV).\n"));
803 }
804
805/* and finally... */
806
807 mr_free(tmp);
808 return (retval);
809}
810
811
812/**
813 * Get the switches from @p argc and @p argv using getopt() and place them in
814 * @p flag_set and @p flag_val.
815 * @param argc The argument count (@p argc passed to main()).
816 * @param argv The argument vector (@p argv passed to main()).
817 * @param flag_val An array indexed by switch letter - if a switch is set and
818 * has an argument then set flag_val[switch] to that argument.
819 * @param flag_set An array indexed by switch letter - if a switch is set then
820 * set flag_set[switch] to TRUE, else set it to FALSE.
821 * @return The number of problems with the command line (0 for success).
822 */
823int
824retrieve_switches_from_command_line(int argc, char *argv[],
825 char flag_val[128][MAX_STR_LEN],
826 bool flag_set[128])
827{
828 /*@ ints ** */
829 int opt = 0;
830 char *tmp = NULL;
831 int i = 0;
832 int len = 0;
833
834 /*@ bools *** */
835 bool bad_switches = FALSE;
836
837 assert(flag_val != NULL);
838 assert(flag_set != NULL);
839
840 for (i = 0; i < 128; i++) {
841 flag_val[i][0] = '\0';
842 flag_set[i] = FALSE;
843 }
844 while ((opt =
845 getopt(argc, argv,
846 "0123456789A:B:C:DE:FGHI:J:K:LNOP:QRS:T:UVWb:c:d:ef:gik:l:mn:op:rs:tuw:x:z"))
847 != -1) {
848 if (opt == '?') {
849 bad_switches = TRUE;
850 /*log_it("Invalid option: %c\n",optopt); */
851 } else {
852 if (flag_set[optopt]) {
853 bad_switches = TRUE;
854 mr_asprintf(&tmp, _("Switch -%c previously defined as %s\n"), opt,
855 flag_val[i]);
856 log_to_screen(tmp);
857 mr_free(tmp);
858 } else {
859 flag_set[opt] = TRUE;
860 if (optarg) {
861 len = strlen(optarg);
862 if (optarg[0] != '/' && optarg[len - 1] == '/') {
863 optarg[--len] = '\0';
864 log_to_screen
865 (_("Warning - param '%s' should not have trailing slash!"),
866 optarg);
867 }
868 if (opt == 'd') {
869 if (strchr(flag_val[opt], '/')
870 && flag_val[opt][0] != '/') {
871 mr_asprintf(&tmp,
872 _("-%c flag --- must be absolute path --- '%s' isn't absolute"),
873 opt, flag_val[opt]);
874 log_to_screen(tmp);
875 mr_free(tmp);
876 bad_switches = TRUE;
877 }
878 }
879 strcpy(flag_val[opt], optarg);
880 }
881 }
882 }
883 }
884 for (i = optind; i < argc; i++) {
885 bad_switches = TRUE;
886 mr_asprintf(&tmp, _("Invalid arg -- %s\n"), argv[i]);
887 log_to_screen(tmp);
888 mr_free(tmp);
889 }
890 return (bad_switches);
891}
892
893
894/**
895 * Terminate Mondo in response to a signal.
896 * @param sig The signal number received.
897 */
898void terminate_daemon(int sig)
899{
900 char *tmp = NULL;
901 char *tmp2 = NULL;
902
903 switch (sig) {
904 case SIGINT:
905 mr_asprintf(&tmp, _("SIGINT signal received from OS"));
906 mr_asprintf(&tmp2, _("You interrupted me :-)"));
907 break;
908 case SIGKILL:
909 mr_asprintf(&tmp, _("SIGKILL signal received from OS"));
910 mr_asprintf(&tmp2,
911 _("I seriously have no clue how this signal even got to me. Something's wrong with your system."));
912 break;
913 case SIGTERM:
914 mr_asprintf(&tmp, _("SIGTERM signal received from OS"));
915 mr_asprintf(&tmp2, _("Got terminate signal"));
916 break;
917 case SIGHUP:
918 mr_asprintf(&tmp, _("SIGHUP signal received from OS"));
919 mr_asprintf(&tmp2, _("Hangup on line"));
920 break;
921 case SIGSEGV:
922 mr_asprintf(&tmp, _("SIGSEGV signal received from OS"));
923 mr_asprintf(&tmp2,
924 _("Internal programming error. Please send a backtrace as well as your log."));
925 break;
926 case SIGPIPE:
927 mr_asprintf(&tmp, _("SIGPIPE signal received from OS"));
928 mr_asprintf(&tmp2, _("Pipe was broken"));
929 break;
930 case SIGABRT:
931 mr_asprintf(&tmp, _("SIGABRT signal received from OS"));
932 mr_asprintf(&tmp2,
933 _("Abort - probably failed assertion. I'm sleeping for a few seconds so you can read the message."));
934 break;
935 default:
936 mr_asprintf(&tmp, _("(Unknown)"));
937 mr_asprintf(&tmp2, _("(Unknown)"));
938 }
939
940 log_to_screen(tmp);
941 log_to_screen(tmp2);
942 mr_free(tmp);
943 mr_free(tmp2);
944 if (sig == SIGABRT) {
945 sleep(10);
946 }
947 kill_buffer();
948 fatal_error
949 ("Mondoarchive is terminating in response to a signal from the OS");
950 finish(254); // just in case
951}
952
953
954/**
955 * Turn signal-trapping on or off.
956 * @param on If TRUE, turn it on; if FALSE, turn it off (we still trap it, just don't do as much).
957 */
958void set_signals(int on)
959{
960 int signals[] =
961 { SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT, SIGKILL, SIGSTOP, 0 };
962 int i;
963
964 signal(SIGPIPE, sigpipe_occurred);
965 for (i = 0; signals[i]; i++) {
966 if (on) {
967 signal(signals[i], terminate_daemon);
968 } else {
969 signal(signals[i], termination_in_progress);
970 }
971 }
972}
973
974
975/**
976 * Exit immediately without cleaning up.
977 * @param sig The signal we are exiting due to.
978 */
979void termination_in_progress(int sig)
980{
981 mr_msg(1, "Termination in progress");
982 usleep(1000);
983 pthread_exit(0);
984}
985
986/* @} - end of cliGroup */
Note: See TracBrowser for help on using the repository browser.