Imported Upstream version 2.6.1p1
[debian/amanda] / server-src / find.c
index e430bf3abaf7f1a2922de2018bf1aa9069c835ad..631c4b84ca1de89f703a5191d0e3db2b46b909b2 100644 (file)
@@ -35,6 +35,8 @@
 #include "logfile.h"
 #include "holding.h"
 #include "find.h"
+#include <regex.h>
+#include "cmdline.h"
 
 int find_match(char *host, char *disk);
 void search_holding_disk(find_result_t **output_find);
@@ -206,18 +208,21 @@ search_holding_disk(
     GSList *e;
     char *holding_file;
     disk_t *dp;
-    dumpfile_t file;
 
     holding_file_list = holding_get_files(NULL, 1);
 
     for(e = holding_file_list; e != NULL; e = e->next) {
+       dumpfile_t file;
+
        holding_file = (char *)e->data;
 
        if (!holding_file_get_dumpfile(holding_file, &file))
            continue;
 
-       if (file.dumplevel < 0 || file.dumplevel > 9)
+       if (file.dumplevel < 0 || file.dumplevel > 9) {
+           dumpfile_free_data(&file);
            continue;
+       }
 
        dp = NULL;
        for(;;) {
@@ -229,12 +234,12 @@ search_holding_disk(
            *s = '\0';
        }
        if ( dp == NULL ) {
+           dumpfile_free_data(&file);
            continue;
        }
 
        if(find_match(file.name,file.disk)) {
-           find_result_t *new_output_find =
-               alloc(SIZEOF(find_result_t));
+           find_result_t *new_output_find = g_new0(find_result_t, 1);
            new_output_find->next=*output_find;
            new_output_find->timestamp = stralloc(file.datestamp);
            new_output_find->hostname = stralloc(file.name);
@@ -243,14 +248,29 @@ search_holding_disk(
            new_output_find->label=stralloc(holding_file);
            new_output_find->partnum=stralloc("--");
            new_output_find->filenum=0;
-           new_output_find->status=stralloc("OK");
+           if (file.is_partial)
+               new_output_find->status=stralloc("PARTIAL");
+           else
+               new_output_find->status=stralloc("OK");
            *output_find=new_output_find;
        }
+       dumpfile_free_data(&file);
     }
 
     g_slist_free_full(holding_file_list);
 }
 
+static char *
+get_write_timestamp(char *tapelabel)
+{
+    tape_t *tp;
+
+    if (!tapelabel || !(tp = lookup_tapelabel(tapelabel)))
+       return "0";
+
+    return tp->datestamp;
+}
+
 static int
 find_compare(
     const void *i1,
@@ -289,6 +309,9 @@ find_compare(
        case 'b' : compare=compare_possibly_null_strings(i->label,
                                                          j->label);
                    break;
+       case 'w': compare=strcmp(get_write_timestamp(i->label),
+                                get_write_timestamp(j->label));
+                  break;
        case 'p' :
                   if(strcmp(i->partnum, "--") != 0 &&
                      strcmp(j->partnum, "--") != 0){
@@ -425,7 +448,10 @@ print_find_result(
             formatted_label = output_find_result->label;
             if (formatted_label == NULL)
                 formatted_label = "";
+
            /*@ignore@*/
+           /* sec and kb are omitted here, for compatibility with the existing
+            * output from 'amadmin' */
            g_printf("%-*s %-*s %-*s %*d %-*s %*lld %*s %-*s\n",
                      max_len_datestamp, 
                      find_nicedate(output_find_result->timestamp),
@@ -621,6 +647,11 @@ search_logfile(
     find_result_t *a_part_find;
     gboolean right_label = FALSE;
     gboolean found_something = FALSE;
+    regex_t regex;
+    int reg_result;
+    regmatch_t pmatch[3];
+    double sec;
+    size_t kb;
 
     g_return_val_if_fail(output_find != NULL, 0);
     g_return_val_if_fail(logfile != NULL, 0);
@@ -773,6 +804,34 @@ search_logfile(
                *s = '\0';
            }
 
+           /* extract sec, kb, kps from 'rest', if present.  This isn't the stone age
+            * anymore, so we'll just do it the easy way (a regex) */
+           bzero(&regex, sizeof(regex));
+           reg_result = regcomp(&regex,
+                   "\\[sec ([0-9.]+) kb ([0-9]+) kps [0-9.]+\\]", REG_EXTENDED);
+           if (reg_result != 0) {
+               error("Error compiling regular expression for parsing log lines");
+               /* NOTREACHED */
+           }
+
+           /* an error here just means the line wasn't found -- not fatal. */
+           reg_result = regexec(&regex, rest, sizeof(pmatch)/sizeof(*pmatch), pmatch, 0);
+           if (reg_result == 0) {
+               char *str;
+
+               str = find_regex_substring(rest, pmatch[1]);
+               sec = atof(str);
+               amfree(str);
+
+               str = find_regex_substring(rest, pmatch[2]);
+               kb = OFF_T_ATOI(str);
+               amfree(str);
+           } else {
+               sec = 0;
+               kb = 0;
+           }
+           regfree(&regex);
+
            dp = lookup_disk(host,disk);
            if ( dp == NULL ) {
                if (dynamic_disklist == NULL) {
@@ -783,8 +842,7 @@ search_logfile(
            }
             if (find_match(host, disk)) {
                if(curprog == P_TAPER) {
-                   find_result_t *new_output_find =
-                       (find_result_t *)alloc(SIZEOF(find_result_t));
+                   find_result_t *new_output_find = g_new0(find_result_t, 1);
                    new_output_find->timestamp = stralloc(date);
                    new_output_find->hostname=stralloc(host);
                    new_output_find->diskname=stralloc(disk);
@@ -793,6 +851,8 @@ search_logfile(
                     new_output_find->label=stralloc(current_label);
                    new_output_find->status=NULL;
                    new_output_find->filenum=filenum;
+                   new_output_find->sec=sec;
+                   new_output_find->kb=kb;
                    new_output_find->next=NULL;
                    if (curlog == L_SUCCESS) {
                        new_output_find->status = stralloc("OK");
@@ -835,9 +895,12 @@ search_logfile(
                        found_something = TRUE;
                    }
                }
-               else if(curlog == L_FAIL) {     /* print other failures too */
-                   find_result_t *new_output_find =
-                       (find_result_t *)alloc(SIZEOF(find_result_t));
+               else if(curlog == L_FAIL) {
+                   /* print other failures too -- this is a hack to ensure that failures which
+                    * did not make it to tape are also listed in the output of 'amadmin x find';
+                    * users that do not want this information (e.g., Amanda::DB::Catalog) should
+                    * filter dumps with a NULL label. */
+                   find_result_t *new_output_find = g_new0(find_result_t, 1);
                    new_output_find->next=*output_find;
                    new_output_find->timestamp = stralloc(date);
                    new_output_find->hostname=stralloc(host);
@@ -846,6 +909,8 @@ search_logfile(
                    new_output_find->label=NULL;
                    new_output_find->partnum=stralloc(partnum);
                    new_output_find->filenum=0;
+                   new_output_find->sec=sec;
+                   new_output_find->kb=kb;
                    new_output_find->status=vstralloc(
                         "FAILED (",
                         program_str[(int)curprog],
@@ -927,15 +992,17 @@ dumps_match(
           (!level || *level== '\0' || match_level(level, level_str)) &&
           (!ok || !strcmp(cur_result->status, "OK"))){
 
-           find_result_t *curmatch = alloc(SIZEOF(find_result_t));
+           find_result_t *curmatch = g_new0(find_result_t, 1);
            memcpy(curmatch, cur_result, SIZEOF(find_result_t));
 
            curmatch->timestamp = stralloc(cur_result->timestamp);
            curmatch->hostname = stralloc(cur_result->hostname);
            curmatch->diskname = stralloc(cur_result->diskname);
            curmatch->level = cur_result->level;
-           curmatch->label = stralloc(cur_result->label);
+           curmatch->label = cur_result->label? stralloc(cur_result->label) : NULL;
            curmatch->filenum = cur_result->filenum;
+           curmatch->sec = cur_result->sec;
+           curmatch->kb = cur_result->kb;
            curmatch->status = stralloc(cur_result->status);
            curmatch->partnum = stralloc(cur_result->partnum);
 
@@ -947,6 +1014,59 @@ dumps_match(
     return(matches);
 }
 
+/*
+ * Return the set of dumps that match one or more of the given dumpspecs,
+ * If 'ok' is true, only dumps with a SUCCESS status will be matched.
+ * 
+ * Returns a newly allocated list of results, where all strings are also newly
+ * allocated.  Apparently some part of Amanda leaks under this condition.
+ */
+find_result_t *
+dumps_match_dumpspecs(
+    find_result_t *output_find,
+    GSList        *dumpspecs,
+    int ok)
+{
+    find_result_t *cur_result;
+    find_result_t *matches = NULL;
+    GSList        *dumpspec;
+    dumpspec_t    *ds;
+
+    for(cur_result=output_find;
+       cur_result;
+       cur_result=cur_result->next) {
+       char level_str[NUM_STR_SIZE];
+       g_snprintf(level_str, SIZEOF(level_str), "%d", cur_result->level);
+       for (dumpspec = dumpspecs; dumpspec; dumpspec = dumpspec->next) {
+           ds = (dumpspec_t *)dumpspec->data;
+           if((!ds->host || *ds->host == '\0' || match_host(ds->host, cur_result->hostname)) &&
+              (!ds->disk || *ds->disk == '\0' || match_disk(ds->disk, cur_result->diskname)) &&
+              (!ds->datestamp || *ds->datestamp== '\0' || match_datestamp(ds->datestamp, cur_result->timestamp)) &&
+              (!ds->level || *ds->level== '\0' || match_level(ds->level, level_str)) &&
+              (!ok || !strcmp(cur_result->status, "OK"))){
+
+               find_result_t *curmatch = alloc(SIZEOF(find_result_t));
+               memcpy(curmatch, cur_result, SIZEOF(find_result_t));
+
+               curmatch->timestamp = stralloc(cur_result->timestamp);
+               curmatch->hostname = stralloc(cur_result->hostname);
+               curmatch->diskname = stralloc(cur_result->diskname);
+               curmatch->level = cur_result->level;
+               curmatch->label = cur_result->label? stralloc(cur_result->label) : NULL;
+               curmatch->filenum = cur_result->filenum;
+               curmatch->status = stralloc(cur_result->status);
+               curmatch->partnum = stralloc(cur_result->partnum);
+
+               curmatch->next = matches;
+               matches = curmatch;
+               break;
+           }
+       }
+    }
+
+    return(matches);
+}
+
 find_result_t *
 dump_exist(
     find_result_t *output_find,