/*\ |*| Parity Archive - A way to restore missing files in a set. |*| |*| Copyright (C) 2001 Willem Monsuwe (willem@stack.nl) |*| |*| File format by Stefan Wehlus - |*| initial idea by Tobias Rieper, further suggestions by Kilroy Balore |*| |*| CommandLine User Interface \*/ #include #include "interface.h" /*\ |*| Print usage \*/ static int usage(void) { printf( "Usage:\n" " par c(heck) [options] : Check parity archive\n" " par r(ecover) [options] : Restore missing volumes\n" " par a(dd) [options] [files] : Add files to parity archive\n" " Advanced:\n" " par m(ix) [options] : Try to restore from all parity files at once\n" " par i(nteractive) [] : Interactive mode (very bare-bones)\n" "\n" "Options: (Can be turned off with '+')\n" " -m : Move existing files out of the way\n" " -f : Fix faulty filenames\n" " -p: Number of files per parity volume\n" " or -n: Number of parity volumes to create\n" " -k : Keep broken files\n" " -s : Be smart if filenames are consistently different.\n" " +i : Do not add following files to parity volumes\n" " +c : Do not create parity volumes\n" " +C : Ignore case in filename comparisons\n" " +H : Do not check control hashes\n" " -v,+v: Increase or decrease verbosity\n" " -h,-?: Display this help\n" " -- : Always treat following arguments as files\n" "\n" ); return 0; } int ui_cli(int argc, char *argv[]) { int nvolumes = 10, pervol = 1, adding = 1, makepxx = 1, smart = 0, dash = 0, plus = 0; int (* flag)(int) = par_setflags; par_setflags(PARFLAG_CTRL | PARFLAG_CASE | PARFLAG_MOVE); if (argc == 1) return usage(); for (; argc > 1; argc--, argv++) { if (((argv[1][0] == '-') || (argv[1][0] == '+')) && argv[1][1] && !dash) { for (p = argv[1]; *p; p++) switch (*p) { case '-': if (p[1] == '-') { dash = 1; } else { plus = 1; flag = par_setflags; } break; case '+': plus = 0; flag = par_unsetflags; break; case 'm': flag(PARFLAG_MOVE); break; case 'i': cmd.add = plus; break; case 'f': cmd.fix = plus; break; case 'c': cmd.pxx = plus; break; case 'v': if (plus) cmd.loglevel++; else cmd.loglevel--; break; case 'p': case 'n': pervol = (*p == 'p'); while (isspace(*++p)) ; if (!*p) { argv++; argc--; p = argv[1]; } if (!isdigit(*p)) { fprintf(stderr, "Value expected!\n"); } else { cmd.volumes = 0; do { cmd.volumes *= 10; cmd.volumes += *p - '0'; } while (isdigit(*++p)); p--; } break; case 'H': flag(PARFLAG_CTRL); break; case 'C': flag(PARFLAG_CASE); break; case 'k': flag(PARFLAG_KEEP); break; case 's': smart = plus; break; case '?': case 'h': return usage(); default: fprintf(stderr, "Unknown switch: '%c'\n", *p); break; } continue; } if (!cmd.action) { switch (argv[1][0]) { case 'c': case 'C': cmd.action = ACTION_CHECK; break; case 'm': case 'M': cmd.action = ACTION_MIX; break; case 'r': case 'R': cmd.action = ACTION_RESTORE; break; case 'a': case 'A': cmd.action = ACTION_ADD; break; case 'i': case 'I': cmd.action = ACTION_TEXT_UI; break; default: fprintf(stderr, "Unknown command: '%s'\n", argv[1]); break; } continue; } switch (cmd.action) { default: cmd.action = ACTION_CHECK; /*\ FALLTHROUGH \*/ case ACTION_CHECK: case ACTION_RESTORE: fprintf(stderr, "Checking %s\n", argv[1]); par = read_par_header(unist(argv[1]), 0, 0, 0); if (!par) { fail = 2; continue; } if (check_par(par) < 0) fail = 1; free_par(par); par = 0; break; case ACTION_ADD: fprintf(stderr, "Adding to %s\n", argv[1]); par = read_par_header(unist(argv[1]), 1, 0, 0); if (!par) return 2; cmd.action = ACTION_ADDING; break; case ACTION_ADDING: par_add_file(par, find_file_name(unist(argv[1]), 1)); break; case ACTION_MIX: fprintf(stderr, "Unknown argument: '%s'\n", argv[1]); break; case ACTION_TEXT_UI: par_load(unist(argv[1])); break; } } }