lintian doesn't like orphan packages with uploaders...
[debian/amanda] / server-src / amadmin.c
index 7930e0bd2dc86cef8d9d700e758530d47db522dc..f51b17e7f8cc5b9eb88559e641c542039c2d6a96 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
  * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 2007-2012 Zmanda, Inc.  All Rights Reserved.
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -42,6 +43,7 @@
 #include "util.h"
 #include "timestamp.h"
 #include "server_util.h"
+#include <getopt.h>
 
 disklist_t diskq;
 
@@ -88,6 +90,13 @@ static void show_config(int argc, char **argv);
 static char *conf_tapelist = NULL;
 static char *displayunit;
 static long int unitdivisor;
+static gboolean print_default = 1;
+static gboolean print_source = 0;
+static int opt_days = -1;
+static char *opt_sort = NULL;
+static gboolean exact_match = FALSE;
+static gboolean opt_long = 0;
+static gboolean opt_outdated = 0;
 
 static const struct {
     const char *name;
@@ -143,6 +152,16 @@ static const struct {
 };
 #define        NCMDS   (int)(sizeof(cmdtab) / sizeof(cmdtab[0]))
 
+static struct option long_options[] = {
+    {"version"       , 0, NULL,  1},
+    {"no-default"    , 0, NULL,  2},
+    {"print-source"  , 0, NULL,  3},
+    {"days"          , 1, NULL,  4},
+    {"sort"          , 1, NULL,  5},
+    {"exact-match"   , 0, NULL,  6},
+    {NULL, 0, NULL, 0}
+};
+
 int
 main(
     int                argc,
@@ -176,6 +195,37 @@ main(
 
     cfg_ovr = extract_commandline_config_overrides(&argc, &argv);
 
+    while (1) {
+       int option_index = 0;
+        int c;
+        c = getopt_long(argc, argv, "ld", long_options, &option_index);
+
+       if (c == -1) {
+           break;
+       }
+
+       switch(c) {
+       case 1: printf("amadmin-%s\n", VERSION);
+               return 0;
+       case 2: print_default = 0;
+               break;
+       case 3: print_source = 1;
+               break;
+       case 4: opt_days = atoi(optarg);
+               break;
+       case 5: opt_sort = g_strdup(optarg);
+               break;
+       case 6: exact_match = TRUE;
+               break;
+       case 'l': opt_long = TRUE;
+               break;
+       case 'd': opt_outdated = TRUE;
+               break;
+       default: usage();
+       }
+    }
+    argc -= optind-1, argv += optind-1;
+
     if(argc < 3) usage();
 
     set_config_overrides(cfg_ovr);
@@ -246,7 +296,7 @@ usage(void)
 {
     int i;
 
-    g_fprintf(stderr, _("\nUsage: %s [-o configoption]* <conf> <command> {<args>} ...\n"),
+    g_fprintf(stderr, _("\nUsage: %s [--version] [--exact-match] [--no-default] [--print-source] [-o configoption]*\n               <conf> <command> {<args>} ...\n"),
            get_pname());
     g_fprintf(stderr, _("    Valid <command>s are:\n"));
     for (i = 0; i < NCMDS; i++)
@@ -324,7 +374,7 @@ diskloop(
        usage();
     }
 
-    errstr = match_disklist(&diskq, argc-3, argv+3);
+    errstr = match_disklist(&diskq, exact_match, argc-3, argv+3);
     if (errstr) {
        g_printf("%s", errstr);
        amfree(errstr);
@@ -898,8 +948,8 @@ tape(
 
 void
 balance(
-    int                argc,
-    char **    argv)
+    int                argc G_GNUC_UNUSED,
+    char **    argv G_GNUC_UNUSED)
 {
     disk_t *dp;
     struct balance_stats {
@@ -921,9 +971,10 @@ balance(
     overdue = 0;
     max_overdue = 0;
 
-    if(argc > 4 && strcmp(argv[3],"--days") == 0) {
-       later = atoi(argv[4]);
-       if(later < 0) later = conf_dumpcycle;
+    if (opt_days > 0) {
+       later = opt_days;
+    } else if (opt_days == 0) {
+       later = conf_dumpcycle;
     }
     if(later > 10000) later = 10000;
 
@@ -1118,11 +1169,11 @@ find(
 
 
     sort_order = newstralloc(sort_order, DEFAULT_SORT_ORDER);
-    if(argc > 4 && strcmp(argv[3],"--sort") == 0) {
+    if (opt_sort) {
        size_t i, valid_sort=1;
 
-       for(i = strlen(argv[4]); i > 0; i--) {
-           switch (argv[4][i - 1]) {
+       for(i = strlen(opt_sort); i > 0; i--) {
+           switch (opt_sort[i - 1]) {
            case 'h':
            case 'H':
            case 'k':
@@ -1144,16 +1195,15 @@ find(
            }
        }
        if(valid_sort) {
-           sort_order = newstralloc(sort_order, argv[4]);
+           sort_order = newstralloc(sort_order, opt_sort);
        } else {
-           g_printf(_("Invalid sort order: %s\n"), argv[4]);
+           g_printf(_("Invalid sort order: %s\n"), opt_sort);
            g_printf(_("Use default sort order: %s\n"), sort_order);
        }
-       start_argc=6;
-    } else {
-       start_argc=4;
     }
-    errstr = match_disklist(&diskq, argc-(start_argc-1), argv+(start_argc-1));
+    start_argc=4;
+    errstr = match_disklist(&diskq, exact_match, argc-(start_argc-1),
+                                                argv+(start_argc-1));
 
     /* check all log file exists */
     output_find_log = find_log();
@@ -1170,8 +1220,8 @@ find(
        disk_t *dp;
 
        amfree(errstr);
-       errstr = match_disklist(&diskq, argc-(start_argc-1),
-                                       argv+(start_argc-1));
+       errstr = match_disklist(&diskq, exact_match, argc-(start_argc-1),
+                                                    argv+(start_argc-1));
        if (errstr) {
            g_printf("%s", errstr);
            amfree(errstr);
@@ -1183,14 +1233,6 @@ find(
                afind->next = new_output_find;
                new_output_find = afind;
            } else {
-               amfree(afind->timestamp);
-               amfree(afind->write_timestamp);
-               amfree(afind->hostname);
-               amfree(afind->diskname);
-               amfree(afind->label);
-               amfree(afind->status);
-               amfree(afind->dump_status);
-               amfree(afind->message);
                amfree(afind);
            }
        }
@@ -1214,7 +1256,8 @@ static GSList *
 get_file_list(
     int argc,
     char **argv,
-    int allow_empty)
+    int allow_empty,
+    gboolean exact_match)
 {
     GSList * file_list = NULL;
     GSList * dumplist;
@@ -1222,6 +1265,7 @@ get_file_list(
 
     flags = CMDLINE_PARSE_DATESTAMP;
     if (allow_empty) flags |= CMDLINE_EMPTY_TO_WILDCARD;
+    if (exact_match) flags |= CMDLINE_EXACT_MATCH;
     dumplist = cmdline_parse_dumpspecs(argc, argv, flags);
 
     file_list = cmdline_match_holding(dumplist);
@@ -1462,22 +1506,9 @@ holding(
             return;
 
         case HOLDING_LIST:
+           long_list = opt_long;
+           outdated_list = opt_outdated;
             argc -= 4; argv += 4;
-           while (argc && argv[0][0] == '-') {
-               switch (argv[0][1]) {
-                   case 'l': 
-                       long_list = 1; 
-                       break;
-                   case 'd': /* have to use '-d', and not '-o', because of parse_config */
-                       outdated_list = 1;
-                       break;
-                   default:
-                       g_fprintf(stderr, _("Unknown option -%c\n"), argv[0][1]);
-                       usage();
-                       return;
-               }
-               argc--; argv++;
-           }
 
            /* header */
             if (long_list) {
@@ -1485,7 +1516,7 @@ holding(
                    _("size (kB)"), _("lv"), _("outd"), _("dump specification"));
             }
 
-            file_list = get_file_list(argc, argv, 1);
+            file_list = get_file_list(argc, argv, 1, exact_match);
             for (li = file_list; li != NULL; li = li->next) {
                 char *dumpstr;
                int is_outdated;
@@ -1520,7 +1551,7 @@ holding(
         case HOLDING_DELETE:
             argc -= 4; argv += 4;
 
-            file_list = get_file_list(argc, argv, 0);
+            file_list = get_file_list(argc, argv, 0, exact_match);
             for (li = file_list; li != NULL; li = li->next) {
                 g_fprintf(stderr, _("Deleting '%s'\n"), (char *)li->data);
                 /* remove it from the catalog */
@@ -1547,7 +1578,7 @@ int
 bump_thresh(
     int                level)
 {
-    int bump = getconf_int(CNF_BUMPSIZE);
+    gint64 bump = getconf_int64(CNF_BUMPSIZE);
     double mult = getconf_real(CNF_BUMPMULT);
 
     while(--level)
@@ -1569,8 +1600,8 @@ bumpsize(
 
     g_printf(_("Current bump parameters:\n"));
     if(conf_bumppercent == 0) {
-       g_printf(_("  bumpsize %5d KB\t- minimum savings (threshold) to bump level 1 -> 2\n"),
-              getconf_int(CNF_BUMPSIZE));
+       g_printf(_("  bumpsize %5jd KB\t- minimum savings (threshold) to bump level 1 -> 2\n"),
+              (intmax_t)getconf_int64(CNF_BUMPSIZE));
        g_printf(_("  bumpdays %5d\t- minimum days at each level\n"),
               getconf_int(CNF_BUMPDAYS));
        g_printf(_("  bumpmult %5.5lg\t- threshold = bumpsize * bumpmult**(level-1)\n\n"),
@@ -1644,13 +1675,16 @@ export_one(
 {
     info_t info;
     int i,l;
+    char *qhost, *qdisk;
 
     if(get_info(dp->host->hostname, dp->name, &info)) {
        g_fprintf(stderr, _("Warning: no curinfo record for %s:%s\n"),
                dp->host->hostname, dp->name);
        return;
     }
-    g_printf(_("host: %s\ndisk: %s\n"), dp->host->hostname, dp->name);
+    qhost = quote_string(dp->host->hostname);
+    qdisk = quote_string(dp->name);
+    g_printf(_("host: %s\ndisk: %s\n"), qhost, qdisk);
     g_printf(_("command: %u\n"), info.command);
     g_printf(_("last_level: %d\n"),info.last_level);
     g_printf(_("consecutive_runs: %d\n"),info.consecutive_runs);
@@ -1682,6 +1716,8 @@ export_one(
               (intmax_t)info.history[l].date);
     }
     g_printf("//\n");
+    amfree(qhost);
+    amfree(qdisk);
 }
 
 /* ----------------------------------------------- */
@@ -1726,7 +1762,10 @@ import_db(
     skip_whitespace(s, ch);
     if(ch == '\0'
        || sscanf(s - 1, "%d.%d.%d", &vers_maj, &vers_min, &vers_patch) != 3) {
-       goto bad_header;
+       vers_patch = -1;
+       if (sscanf(s - 1, "%d.%d", &vers_maj, &vers_min) != 2) {
+           goto bad_header;
+       }
     }
 
     skip_integer(s, ch);                       /* skip over major */
@@ -1735,11 +1774,15 @@ import_db(
     }
     ch = *s++;
     skip_integer(s, ch);                       /* skip over minor */
-    if(ch != '.') {
-       goto bad_header;
+    if (vers_patch != -1) {
+       if (ch != '.') {
+           goto bad_header;
+       }
+       ch = *s++;
+       skip_integer(s, ch);                    /* skip over patch */
+    } else {
+       vers_patch = 0;
     }
-    ch = *s++;
-    skip_integer(s, ch);                       /* skip over patch */
 
     hdr = "comment";
     if(ch == '\0') {
@@ -1828,9 +1871,9 @@ import_one(void)
     skip_whitespace(s, ch);
     if(ch == '\0') goto parse_err;
     fp = s-1;
-    skip_non_whitespace(s, ch);
+    skip_quoted_string(s, ch);
     s[-1] = '\0';
-    hostname = stralloc(fp);
+    hostname = unquote_string(fp);
     s[-1] = (char)ch;
 
     skip_whitespace(s, ch);
@@ -1845,9 +1888,9 @@ import_one(void)
     skip_whitespace(s, ch);
     if(ch == '\0') goto parse_err;
     fp = s-1;
-    skip_non_whitespace(s, ch);
+    skip_quoted_string(s, ch);
     s[-1] = '\0';
-    diskname = stralloc(fp);
+    diskname = unquote_string(fp);
     s[-1] = (char)ch;
 
     amfree(line);
@@ -2088,15 +2131,12 @@ disklist_one(
 {
     am_host_t *hp;
     netif_t *ip;
-    sle_t *excl;
-    identlist_t pp_scriptlist;
-    estimatelist_t  estimates;
     dumptype_t *dtype = lookup_dumptype(dp->dtype_name);
 
     hp = dp->host;
     ip = hp->netif;
 
-    g_printf("line %d:\n", dp->line);
+    g_printf("line %d (%s):\n", dp->line, dp->filename);
 
     g_printf("    host %s:\n", hp->hostname);
     g_printf("        interface %s\n",
@@ -2107,213 +2147,10 @@ disklist_one(
     g_printf("        program \"%s\"\n", dp->program);
     if (dp->application)
        g_printf("        application \"%s\"\n", dp->application);
-    g_printf("        data-path %s\n", data_path_to_string(dp->data_path));
-    if (dp->exclude_file != NULL && dp->exclude_file->nb_element > 0) {
-       g_printf("        exclude file");
-       for(excl = dp->exclude_file->first; excl != NULL; excl = excl->next) {
-           g_printf(" \"%s\"", excl->name);
-       }
-       g_printf("\n");
-    }
-    if (dp->exclude_list != NULL && dp->exclude_list->nb_element > 0) {
-       g_printf("        exclude list");
-       if(dp->exclude_optional) g_printf(" optional");
-       for(excl = dp->exclude_list->first; excl != NULL; excl = excl->next) {
-           g_printf(" \"%s\"", excl->name);
-       }
-       g_printf("\n");
-    }
-    if (dp->include_file != NULL && dp->include_file->nb_element > 0) {
-       g_printf("        include file");
-       for(excl = dp->include_file->first; excl != NULL; excl = excl->next) {
-           g_printf(" \"%s\"", excl->name);
-       }
-       g_printf("\n");
-    }
-    if (dp->include_list != NULL && dp->include_list->nb_element > 0) {
-       g_printf("        include list");
-       if (dp->include_optional) g_printf(" optional");
-       for(excl = dp->include_list->first; excl != NULL; excl = excl->next) {
-           g_printf(" \"%s\"", excl->name);
-       }
-       g_printf("\n");
-    }
-    g_printf("        priority %d\n", dp->priority);
-    g_printf("        dumpcycle %d\n", dp->dumpcycle);
-    g_printf("        maxdumps %d\n", dp->maxdumps);
-    g_printf("        maxpromoteday %d\n", dp->maxpromoteday);
-    if (dp->bumppercent > 0) {
-       g_printf("        bumppercent %d\n", dp->bumppercent);
-    }
-    else {
-       g_printf("        bumpsize %lld\n",
-               (long long)dp->bumpsize);
-    }
-    g_printf("        bumpdays %d\n", dp->bumpdays);
-    g_printf("        bumpmult %lf\n", dp->bumpmult);
-
-    g_printf("        strategy ");
-    switch(dp->strategy) {
-    case DS_SKIP:
-       g_printf("SKIP\n");
-       break;
-    case DS_STANDARD:
-       g_printf("STANDARD\n");
-       break;
-    case DS_NOFULL:
-       g_printf("NOFULL\n");
-       break;
-    case DS_NOINC:
-       g_printf("NOINC\n");
-       break;
-    case DS_HANOI:
-       g_printf("HANOI\n");
-       break;
-    case DS_INCRONLY:
-       g_printf("INCRONLY\n");
-       break;
-    }
-    g_printf("        ignore %s\n", (dp->ignore? "YES" : "NO"));
-    g_printf("        estimate ");
-    estimates = dp->estimatelist;
-    while (estimates) {
-       switch((estimate_t)GPOINTER_TO_INT(estimates->data)) {
-       case ES_CLIENT:
-           g_printf("CLIENT");
-           break;
-       case ES_SERVER:
-           g_printf("SERVER");
-           break;
-       case ES_CALCSIZE:
-           g_printf("CALCSIZE");
-           break;
-       case ES_ES:
-           break;
-       }
-       estimates = estimates->next;
-       if (estimates)
-           g_printf(", ");
-    }
-    g_printf("\n");
 
-    g_printf("        compress ");
-    switch(dp->compress) {
-    case COMP_NONE:
-       g_printf("NONE\n");
-       break;
-    case COMP_FAST:
-       g_printf("CLIENT FAST\n");
-       break;
-    case COMP_BEST:
-       g_printf("CLIENT BEST\n");
-       break;
-    case COMP_CUST:
-       g_printf("CLIENT CUSTOM\n");
-       g_printf("        client-custom-compress \"%s\"\n",
-                   dp->clntcompprog? dp->clntcompprog : "");
-       break;
-    case COMP_SERVER_FAST:
-       g_printf("SERVER FAST\n");
-       break;
-    case COMP_SERVER_BEST:
-       g_printf("SERVER BEST\n");
-       break;
-    case COMP_SERVER_CUST:
-       g_printf("SERVER CUSTOM\n");
-       g_printf("        server-custom-compress \"%s\"\n",
-                   dp->srvcompprog? dp->srvcompprog : "");
-       break;
-    }
-    if(dp->compress != COMP_NONE) {
-       g_printf("        comprate %.2lf %.2lf\n",
-              dp->comprate[0], dp->comprate[1]);
-    }
-
-    g_printf("        encrypt ");
-    switch(dp->encrypt) {
-    case ENCRYPT_NONE:
-       g_printf("NONE\n");
-       break;
-    case ENCRYPT_CUST:
-       g_printf("CLIENT\n");
-       g_printf("        client-encrypt \"%s\"\n",
-                   dp->clnt_encrypt? dp->clnt_encrypt : "");
-       g_printf("        client-decrypt-option \"%s\"\n",
-                   dp->clnt_decrypt_opt? dp->clnt_decrypt_opt : "");
-       break;
-    case ENCRYPT_SERV_CUST:
-       g_printf("SERVER\n");
-       g_printf("        server-encrypt \"%s\"\n",
-                   dp->srv_encrypt? dp->srv_encrypt : "");
-       g_printf("        server-decrypt-option \"%s\"\n",
-                   dp->srv_decrypt_opt? dp->srv_decrypt_opt : "");
-       break;
-    }
-
-    g_printf("        auth \"%s\"\n", dp->auth);
-    g_printf("        kencrypt %s\n", (dp->kencrypt? "YES" : "NO"));
-    g_printf("        amandad-path \"%s\"\n", dp->amandad_path);
-    g_printf("        client-username \"%s\"\n", dp->client_username);
-    g_printf("        client-port \"%s\"\n", dp->client_port);
-    g_printf("        ssh-keys \"%s\"\n", dp->ssh_keys);
-
-    g_printf("        holdingdisk ");
-    switch(dp->to_holdingdisk) {
-    case HOLD_NEVER:
-       g_printf("NEVER\n");
-       break;
-    case HOLD_AUTO:
-       g_printf("AUTO\n");
-       break;
-    case HOLD_REQUIRED:
-       g_printf("REQUIRED\n");
-       break;
-    }
-
-    g_printf("        record %s\n", (dp->record? "YES" : "NO"));
-    g_printf("        index %s\n", (dp->index? "YES" : "NO"));
-    g_printf("        starttime %04d\n", (int)dp->starttime);
-    if(dp->tape_splitsize > (off_t)0) {
-       g_printf("        tape-splitsize %lld\n",
-              (long long)dp->tape_splitsize);
-    }
-    if(dp->split_diskbuffer) {
-       g_printf("        split-diskbuffer %s\n", dp->split_diskbuffer);
-    }
-    if(dp->fallback_splitsize > (off_t)0) {
-       g_printf("        fallback-splitsize %lldMb\n",
-              (long long)(dp->fallback_splitsize / (off_t)1024));
-    }
-    g_printf("        skip-incr %s\n", (dp->skip_incr? "YES" : "NO"));
-    g_printf("        skip-full %s\n", (dp->skip_full? "YES" : "NO"));
-    g_printf("        allow-split %s\n", (dp->allow_split ? "YES" : "NO"));
-    if (dumptype_seen(dtype, DUMPTYPE_RECOVERY_LIMIT)) {
-       char **rl, **r1;
-       rl = val_t_display_strs(dumptype_getconf((dtype),
-                               DUMPTYPE_RECOVERY_LIMIT), 1);
-       for(r1 = rl; *r1 != NULL; r1++) {
-           g_printf("        recovery-limit %s\n", *r1);
-       free(*r1);
-       }
-    }
-    g_printf("        spindle %d\n", dp->spindle);
-    pp_scriptlist = dp->pp_scriptlist;
-    while (pp_scriptlist != NULL) {
-       g_printf("        script \"%s\"\n", (char *)pp_scriptlist->data);
-       pp_scriptlist = pp_scriptlist->next;
-    }
-
-    {
-       char **prop, **p1;;
+    dump_dumptype(dtype, "  ", print_default, print_source);
 
-       prop = val_t_display_strs(dumptype_getconf((dtype), DUMPTYPE_PROPERTY),
-                                 0);
-       for(p1 = prop; *p1 != NULL; p1++) {
-           g_printf("        property %s\n", *p1);
-           free(*p1);
-       }
-       amfree(prop);
-    }
+    g_printf("        spindle %d\n", dp->spindle);
 
     g_printf("\n");
 }
@@ -2389,6 +2226,6 @@ void show_config(
     int argc G_GNUC_UNUSED,
     char **argv G_GNUC_UNUSED)
 {
-    dump_configuration();
+    dump_configuration(print_default, print_source);
 }