lintian doesn't like orphan packages with uploaders...
[debian/amanda] / server-src / amflush.c
index d8e11786b29842896e08c0fae4e6d7809fd7294c..481ff289966e4fe495da10b5d423bea40290b9de 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
 #include "amanda.h"
 
 #include "match.h"
+#include "find.h"
 #include "conffile.h"
 #include "diskfile.h"
 #include "tapefile.h"
 #include "logfile.h"
 #include "clock.h"
 #include "holding.h"
-#include "driverio.h"
 #include "server_util.h"
 #include "timestamp.h"
+#include "getopt.h"
+
+static struct option long_options[] = {
+    {"version"         , 0, NULL,  1},
+    {"exact-match"     , 0, NULL,  2},
+    {NULL, 0, NULL, 0}
+};
 
 static char *conf_logdir;
 FILE *driver_stream;
@@ -92,6 +100,9 @@ main(
     GSList *datestamp_list = NULL;
     config_overrides_t *cfg_ovr;
     char **config_options;
+    find_result_t *holding_files;
+    disklist_t holding_disklist = { NULL, NULL };
+    gboolean exact_match = FALSE;
 
     /*
      * Configure program for internationalization:
@@ -120,8 +131,13 @@ main(
     /* process arguments */
 
     cfg_ovr = new_config_overrides(argc/2);
-    while((opt = getopt(argc, argv, "bfso:D:")) != EOF) {
+    while((opt = getopt_long(argc, argv, "bfso:D:", long_options, NULL)) != EOF) {
        switch(opt) {
+       case 1  : printf("amflush-%s\n", VERSION);
+                 return(0);
+                 break;
+       case 2  : exact_match = TRUE;
+                 break;
        case 'b': batch = 1;
                  break;
        case 'f': foreground = 1;
@@ -149,7 +165,7 @@ main(
     }
 
     if(argc < 1) {
-       error(_("Usage: amflush [-b] [-f] [-s] [-D date]* [-o configoption]* <confdir> [host [disk]* ]*"));
+       error(_("Usage: amflush [-b] [-f] [-s] [-D date]* [--exact-match] [-o configoption]* <confdir> [host [disk]* ]*"));
        /*NOTREACHED*/
     }
 
@@ -172,7 +188,14 @@ main(
 
     dbrename(get_config_name(), DBG_SUBDIR_SERVER);
 
-    errstr = match_disklist(&diskq, argc-1, argv+1);
+    /* load DLEs from the holding disk, in case there's anything to flush there */
+    search_holding_disk(&holding_files, &holding_disklist);
+    /* note that the dumps are added to the global disklist, so we need not
+     * consult holding_files or holding_disklist after this.  The holding-only
+     * dumps will be filtered properly by match_disklist, setting the dp->todo
+     * flag appropriately. */
+
+    errstr = match_disklist(&diskq, exact_match, argc-1, argv+1);
     if (errstr) {
        g_printf(_("%s"),errstr);
        amfree(errstr);
@@ -236,7 +259,7 @@ main(
                    stralloc((char *)datestamp->data),
                    g_compare_strings);
        }
-       g_slist_free_full(all_datestamps);
+       slist_free_full(all_datestamps, g_free);
     }
     else {
        /* otherwise, in batch mode, use all datestamps */
@@ -271,10 +294,19 @@ main(
 
     for(dp = diskq.head; dp != NULL; dp = dp->next) {
        if(dp->todo) {
-           char *qname;
-           qname = quote_string(dp->name);
-           log_add(L_DISK, "%s %s", dp->host->hostname, qname);
-           amfree(qname);
+           /* is it holding_list */
+           for (holding_file=holding_list; holding_file != NULL;
+                                           holding_file = holding_file->next) {
+               dumpfile_t file;
+               holding_file_get_dumpfile((char *)holding_file->data, &file);
+               if (g_str_equal(dp->host->hostname, file.name) &&
+                   g_str_equal(dp->name, file.disk)) {
+                   char *qname;
+                   qname = quote_string(dp->name);
+                   log_add(L_DISK, "%s %s", dp->host->hostname, qname);
+                   amfree(qname);
+               }
+           }
        }
     }
 
@@ -340,6 +372,7 @@ main(
        holding_file_get_dumpfile((char *)holding_file->data, &file);
 
        if (holding_file_size((char *)holding_file->data, 1) <= 0) {
+           g_debug("%s is empty - ignoring", (char *)holding_file->data);
            log_add(L_INFO, "%s: removing file with no data.",
                    (char *)holding_file->data);
            holding_file_unlink((char *)holding_file->data);
@@ -347,11 +380,12 @@ main(
            continue;
        }
 
+       /* search_holding_disk should have already ensured that every
+        * holding dumpfile has an entry in the dynamic disklist */
        dp = lookup_disk(file.name, file.disk);
-       if (!dp) {
-           error("dp == NULL");
-           /*NOTREACHED*/
-       }
+       assert(dp != NULL);
+
+       /* but match_disklist may have indicated we should not flush it */
        if (dp->todo == 0) continue;
 
        qdisk = quote_string(file.disk);
@@ -363,6 +397,8 @@ main(
                file.datestamp,
                file.dumplevel,
                qhname);
+
+       g_debug("flushing '%s'", (char *)holding_file->data);
        g_fprintf(driver_stream,
                "FLUSH %s %s %s %d %s\n",
                file.name,
@@ -392,9 +428,9 @@ main(
        }
     }
 
-    g_slist_free_full(datestamp_list);
+    slist_free_full(datestamp_list, g_free);
     datestamp_list = NULL;
-    g_slist_free_full(holding_list);
+    slist_free_full(holding_list, g_free);
     holding_list = NULL;
 
     if(redirect) { /* rename errfile */
@@ -586,7 +622,7 @@ pick_datestamp(void)
                }
                chupper = (char)toupper(ch);
                if (chupper < 'A' || chupper > max_char) {
-                   g_slist_free_full(r_datestamp_list);
+                   slist_free_full(r_datestamp_list, g_free);
                    r_datestamp_list = NULL;
                    break;
                }
@@ -594,7 +630,7 @@ pick_datestamp(void)
                                           stralloc(datestamps[chupper - 'A']));
            } while ((ch = *a++) != '\0');
            if (r_datestamp_list && ch == '\0') {
-               g_slist_free_full(datestamp_list);
+               slist_free_full(datestamp_list, g_free);
                datestamp_list = r_datestamp_list;
                break;
            }
@@ -656,6 +692,7 @@ confirm(GSList *datestamp_list)
     }
 
     g_printf(_("Ok, quitting.  Run amflush again when you are ready.\n"));
+    log_add(L_INFO, "pid-done %ld", (long)getpid());
     exit(1);
 }
 
@@ -667,7 +704,7 @@ redirect_stderr(void)
 
     fflush(stdout); fflush(stderr);
     errfile = vstralloc(conf_logdir, "/amflush", NULL);
-    if((fderr = open(errfile, O_WRONLY| O_CREAT | O_TRUNC, 0600)) == -1) {
+    if((fderr = open(errfile, O_WRONLY| O_APPEND | O_CREAT | O_TRUNC, 0600)) == -1) {
        error(_("could not open %s: %s"), errfile, strerror(errno));
        /*NOTREACHED*/
     }