X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Ffind.c;h=6891d00539a5e1c84a4a6b4028ffc94483f0a138;hb=HEAD;hp=cc07fb1b804e47d277adc8cea48d7eb5ee7a2371;hpb=0de2ad0a86685398621fb8ffa6990c029681bb3a;p=debian%2Famanda diff --git a/server-src/find.c b/server-src/find.c index cc07fb1..6891d00 100644 --- a/server-src/find.c +++ b/server-src/find.c @@ -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 @@ -25,52 +26,62 @@ * University of Maryland at College Park */ /* - * $Id: find.c,v 1.6.2.4.4.2.2.5.2.1 2004/02/02 20:29:12 martinea Exp $ + * $Id: find.c,v 1.33 2006/07/06 13:13:15 martinea Exp $ * * controlling process for the Amanda backup system */ #include "amanda.h" +#include "match.h" #include "conffile.h" #include "tapefile.h" #include "logfile.h" #include "holding.h" #include "find.h" +#include +#include "cmdline.h" -void find P((int argc, char **argv)); -int find_match P((char *host, char *disk)); -int search_logfile P((find_result_t **output_find, char *label, int datestamp, int datestamp_aux, char *logfile)); -void search_holding_disk P((find_result_t **output_find)); -char *find_nicedate P((int datestamp)); +int find_match(char *host, char *disk); +static char *find_nicedate(char *datestamp); +static int len_find_nicedate(char *datestamp); +static int find_compare(const void *, const void *); +static int parse_taper_datestamp_log(char *logline, char **datestamp, char **level); +static gboolean logfile_has_tape(char * label, char * datestamp, + char * logfile); static char *find_sort_order = NULL; -int dynamic_disklist = 0; -disklist_t* find_diskqp = NULL; +static GStringChunk *string_chunk = NULL; -find_result_t *find_dump(dyna_disklist, diskqp) -int dyna_disklist; -disklist_t* diskqp; -{ +find_result_t * find_dump(disklist_t* diskqp) { char *conf_logdir, *logfile = NULL; - int tape, maxtape, seq, logs; - tape_t *tp; + int tape, tape1, maxtape, logs; + unsigned seq; + tape_t *tp, *tp1; find_result_t *output_find = NULL; + gboolean *tape_seen = NULL; - dynamic_disklist = dyna_disklist; - find_diskqp = diskqp; - conf_logdir = getconf_str(CNF_LOGDIR); - if (*conf_logdir == '/') { - conf_logdir = stralloc(conf_logdir); - } else { - conf_logdir = stralloc2(config_dir, conf_logdir); + if (string_chunk == NULL) { + string_chunk = g_string_chunk_new(32768); } + conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR)); maxtape = lookup_nb_tape(); + tape_seen = g_new0(gboolean, maxtape+1); for(tape = 1; tape <= maxtape; tape++) { - char ds_str[NUM_STR_SIZE]; + if (tape_seen[tape] == 1) + continue; tp = lookup_tapepos(tape); if(tp == NULL) continue; - ap_snprintf(ds_str, sizeof(ds_str), "%d", tp->datestamp); + + /* find all tape with the same datestamp */ + for (tape1 = tape; tape1 <= maxtape; tape1++) { + tp1 = lookup_tapepos(tape1); + if (tp1 == NULL) continue; + if (strcmp(tp->datestamp, tp1->datestamp) != 0) + continue; + + tape_seen[tape1] = 1; + } /* search log files */ @@ -81,63 +92,68 @@ disklist_t* diskqp; for(seq = 0; 1; seq++) { char seq_str[NUM_STR_SIZE]; - ap_snprintf(seq_str, sizeof(seq_str), "%d", seq); + g_snprintf(seq_str, SIZEOF(seq_str), "%u", seq); logfile = newvstralloc(logfile, - conf_logdir, "/log.", ds_str, ".", seq_str, NULL); + conf_logdir, "/log.", tp->datestamp, ".", seq_str, NULL); if(access(logfile, R_OK) != 0) break; - logs += search_logfile(&output_find, tp->label, tp->datestamp, seq, logfile); + if (search_logfile(&output_find, NULL, tp->datestamp, + logfile, diskqp)) { + logs ++; + } } /* search old-style amflush log, if any */ - logfile = newvstralloc(logfile, - conf_logdir, "/log.", ds_str, ".amflush", NULL); + logfile = newvstralloc(logfile, conf_logdir, "/log.", + tp->datestamp, ".amflush", NULL); if(access(logfile,R_OK) == 0) { - logs += search_logfile(&output_find, tp->label, tp->datestamp, 1000, logfile); - } - + if (search_logfile(&output_find, NULL, tp->datestamp, + logfile, diskqp)) { + logs ++; + } + } + /* search old-style main log, if any */ - logfile = newvstralloc(logfile, conf_logdir, "/log.", ds_str, NULL); + logfile = newvstralloc(logfile, conf_logdir, "/log.", tp->datestamp, + NULL); if(access(logfile,R_OK) == 0) { - logs += search_logfile(&output_find, tp->label, tp->datestamp, -1, logfile); + if (search_logfile(&output_find, NULL, tp->datestamp, + logfile, diskqp)) { + logs ++; + } } - if(logs == 0 && tp->datestamp != 0) - printf("Warning: no log files found for tape %s written %s\n", - tp->label, find_nicedate(tp->datestamp)); } + g_free(tape_seen); amfree(logfile); amfree(conf_logdir); - search_holding_disk(&output_find); + search_holding_disk(&output_find, diskqp); + return(output_find); } -char **find_log() +char ** +find_log(void) { char *conf_logdir, *logfile = NULL; - int tape, maxtape, seq, logs; + char *pathlogfile = NULL; + int tape, maxtape, logs; + unsigned seq; tape_t *tp; char **output_find_log = NULL; char **current_log; - conf_logdir = getconf_str(CNF_LOGDIR); - if (*conf_logdir == '/') { - conf_logdir = stralloc(conf_logdir); - } else { - conf_logdir = stralloc2(config_dir, conf_logdir); - } + conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR)); maxtape = lookup_nb_tape(); - output_find_log = alloc((maxtape*5+10) * sizeof(char *)); + output_find_log = alloc((maxtape*5+10) * SIZEOF(char *)); current_log = output_find_log; for(tape = 1; tape <= maxtape; tape++) { - char ds_str[NUM_STR_SIZE]; tp = lookup_tapepos(tape); if(tp == NULL) continue; - ap_snprintf(ds_str, sizeof(ds_str), "%d", tp->datestamp); /* search log files */ @@ -148,13 +164,15 @@ char **find_log() for(seq = 0; 1; seq++) { char seq_str[NUM_STR_SIZE]; - ap_snprintf(seq_str, sizeof(seq_str), "%d", seq); - logfile = newvstralloc(logfile, - conf_logdir, "/log.", ds_str, ".", seq_str, NULL); - if(access(logfile, R_OK) != 0) break; - if( search_logfile(NULL, tp->label, tp->datestamp, seq, logfile)) { - *current_log = vstralloc("log.", ds_str, ".", seq_str, NULL); - current_log++; + g_snprintf(seq_str, SIZEOF(seq_str), "%u", seq); + logfile = newvstralloc(logfile, "log.", tp->datestamp, ".", seq_str, NULL); + pathlogfile = newvstralloc(pathlogfile, conf_logdir, "/", logfile, NULL); + if (access(pathlogfile, R_OK) != 0) break; + if (logfile_has_tape(tp->label, tp->datestamp, pathlogfile)) { + if (current_log == output_find_log || strcmp(*(current_log-1), logfile)) { + *current_log = stralloc(logfile); + current_log++; + } logs++; break; } @@ -162,170 +180,170 @@ char **find_log() /* search old-style amflush log, if any */ - logfile = newvstralloc(logfile, - conf_logdir, "/log.", ds_str, ".amflush", NULL); - if(access(logfile,R_OK) == 0) { - if( search_logfile(NULL, tp->label, tp->datestamp, 1000, logfile)) { - *current_log = vstralloc("log.", ds_str, ".amflush", NULL); - current_log++; + logfile = newvstralloc(logfile, "log.", tp->datestamp, ".amflush", NULL); + pathlogfile = newvstralloc(pathlogfile, conf_logdir, "/", logfile, NULL); + if (access(pathlogfile, R_OK) == 0) { + if (logfile_has_tape(tp->label, tp->datestamp, pathlogfile)) { + if (current_log == output_find_log || strcmp(*(current_log-1), logfile)) { + *current_log = stralloc(logfile); + current_log++; + } logs++; } } /* search old-style main log, if any */ - logfile = newvstralloc(logfile, conf_logdir, "/log.", ds_str, NULL); - if(access(logfile,R_OK) == 0) { - if(search_logfile(NULL, tp->label, tp->datestamp, -1, logfile)) { - *current_log = vstralloc("log.", ds_str, NULL); - current_log++; + logfile = newvstralloc(logfile, "log.", tp->datestamp, NULL); + pathlogfile = newvstralloc(pathlogfile, conf_logdir, "/", logfile, NULL); + if (access(pathlogfile, R_OK) == 0) { + if (logfile_has_tape(tp->label, tp->datestamp, pathlogfile)) { + if (current_log == output_find_log || strcmp(*(current_log-1), logfile)) { + *current_log = stralloc(logfile); + current_log++; + } logs++; } } - if(logs == 0 && tp->datestamp != 0) - printf("Warning: no log files found for tape %s written %s\n", + + if(logs == 0 && strcmp(tp->datestamp,"0") != 0) + g_fprintf(stderr, _("Warning: no log files found for tape %s written %s\n"), tp->label, find_nicedate(tp->datestamp)); } amfree(logfile); + amfree(pathlogfile); amfree(conf_logdir); *current_log = NULL; return(output_find_log); } -void search_holding_disk(output_find) -find_result_t **output_find; +void +search_holding_disk( + find_result_t **output_find, + disklist_t * dynamic_disklist) { - holdingdisk_t *hdisk; - sl_t *holding_list; - sle_t *dir; - char *sdirname = NULL; - char *destname = NULL; - char *hostname = NULL; - char *diskname = NULL; - DIR *workdir; - struct dirent *entry; - int level; + GSList *holding_file_list; + GSList *e; + char *holding_file; disk_t *dp; + char *orig_name; - holding_list = pick_all_datestamp(1); + holding_file_list = holding_get_files(NULL, 1); - for(hdisk = getconf_holdingdisks(); hdisk != NULL; hdisk = hdisk->next) { - for(dir = holding_list->first; dir != NULL; dir = dir->next) { - sdirname = newvstralloc(sdirname, - hdisk->diskdir, "/", dir->name, - NULL); - if((workdir = opendir(sdirname)) == NULL) { - continue; - } + if (string_chunk == NULL) { + string_chunk = g_string_chunk_new(32768); + } - while((entry = readdir(workdir)) != NULL) { - if(is_dot_or_dotdot(entry->d_name)) { - continue; - } - destname = newvstralloc(destname, - sdirname, "/", entry->d_name, - NULL); - if(is_emptyfile(destname)) { - continue; - } - amfree(hostname); - amfree(diskname); - if(get_amanda_names(destname, &hostname, &diskname, &level) != F_DUMPFILE) { - continue; - } - if(level < 0 || level > 9) - continue; + for(e = holding_file_list; e != NULL; e = e->next) { + dumpfile_t file; - dp = NULL; - for(;;) { - char *s; - if((dp = lookup_disk(hostname, diskname))) - break; - if((s = strrchr(hostname,'.')) == NULL) - break; - *s = '\0'; - } - if ( dp == NULL ) { - continue; - } + holding_file = (char *)e->data; - if(find_match(hostname,diskname)) { - find_result_t *new_output_find = - alloc(sizeof(find_result_t)); - new_output_find->next=*output_find; - if(strlen(dir->name) == 8) { - new_output_find->datestamp=atoi(dir->name); - new_output_find->timestamp=stralloc2(dir->name, "000000"); - } - else if(strlen(dir->name) == 14) { - char *name = stralloc(dir->name); - name[8] = '\0'; - new_output_find->datestamp=atoi(name); - new_output_find->timestamp=stralloc(dir->name); - amfree(name); - } - else { - error("Bad date\n"); - } - new_output_find->datestamp_aux=1001; - new_output_find->hostname=hostname; - hostname = NULL; - new_output_find->diskname=diskname; - diskname = NULL; - new_output_find->level=level; - new_output_find->label=stralloc(destname); - new_output_find->filenum=0; - new_output_find->status=stralloc("OK"); - *output_find=new_output_find; - } + if (!holding_file_get_dumpfile(holding_file, &file)) + continue; + + if (file.dumplevel < 0 || file.dumplevel >= DUMP_LEVELS) { + dumpfile_free_data(&file); + continue; + } + + dp = NULL; + orig_name = g_strdup(file.name); + for(;;) { + char *s; + if((dp = lookup_disk(file.name, file.disk))) + break; + if((s = strrchr(file.name,'.')) == NULL) + break; + *s = '\0'; + } + strcpy(file.name, orig_name); /* restore munged string */ + g_free(orig_name); + + if ( dp == NULL ) { + if (dynamic_disklist == NULL) { + dumpfile_free_data(&file); + continue; + } + dp = add_disk(dynamic_disklist, file.name, file.disk); + enqueue_disk(dynamic_disklist, dp); + } + + if(find_match(file.name,file.disk)) { + find_result_t *new_output_find = g_new0(find_result_t, 1); + new_output_find->next=*output_find; + new_output_find->timestamp = g_string_chunk_insert_const(string_chunk, file.datestamp); + new_output_find->write_timestamp = g_string_chunk_insert_const(string_chunk, "00000000000000"); + new_output_find->hostname = g_string_chunk_insert_const(string_chunk, file.name); + new_output_find->diskname = g_string_chunk_insert_const(string_chunk, file.disk); + new_output_find->level=file.dumplevel; + new_output_find->label=g_string_chunk_insert_const(string_chunk, holding_file); + new_output_find->partnum = -1; + new_output_find->totalparts = -1; + new_output_find->filenum=0; + if (file.is_partial) { + new_output_find->status="PARTIAL"; + new_output_find->dump_status="PARTIAL"; + } else { + new_output_find->status="OK"; + new_output_find->dump_status="OK"; } - closedir(workdir); - } + new_output_find->message=""; + new_output_find->kb = holding_file_size(holding_file, 1); + new_output_find->bytes = 0; + + new_output_find->orig_kb = file.orig_size; + + *output_find=new_output_find; + } + dumpfile_free_data(&file); } - free_sl(holding_list); - holding_list = NULL; - amfree(destname); - amfree(sdirname); - amfree(hostname); - amfree(diskname); + + slist_free_full(holding_file_list, g_free); } -static int find_compare(i1, j1) -const void *i1; -const void *j1; +static int +find_compare( + const void *i1, + const void *j1) { int compare=0; - find_result_t **i = (find_result_t **)i1; - find_result_t **j = (find_result_t **)j1; + find_result_t *i, *j; - int nb_compare=strlen(find_sort_order); - int k; + size_t nb_compare=strlen(find_sort_order); + size_t k; for(k=0;khostname,(*j)->hostname); - break; - case 'H' : compare=strcmp((*j)->hostname,(*i)->hostname); - break; - case 'k' : compare=strcmp((*i)->diskname,(*j)->diskname); - break; - case 'K' : compare=strcmp((*j)->diskname,(*i)->diskname); + char sort_key = find_sort_order[k]; + if (isupper((int)sort_key)) { + /* swap */ + sort_key = tolower(sort_key); + j = *(find_result_t **)i1; + i = *(find_result_t **)j1; + } else { + i = *(find_result_t **)i1; + j = *(find_result_t **)j1; + } + + switch (sort_key) { + case 'h' : compare=strcmp(i->hostname,j->hostname); break; - case 'd' : compare=(*i)->datestamp - (*j)->datestamp; - if (compare == 0) - compare = (*i)->datestamp_aux - (*j)->datestamp_aux; + case 'k' : compare=strcmp(i->diskname,j->diskname); break; - case 'D' : compare=(*j)->datestamp - (*i)->datestamp; - if (compare == 0) - compare = (*j)->datestamp_aux - (*i)->datestamp_aux; + case 'd' : compare=strcmp(i->timestamp,j->timestamp); break; - case 'l' : compare=(*j)->level - (*i)->level; + case 'l' : compare=j->level - i->level; break; - case 'L' : compare=(*i)->level - (*j)->level; + case 'f' : compare=(i->filenum == j->filenum) ? 0 : + ((i->filenum < j->filenum) ? -1 : 1); break; - case 'b' : compare=strcmp((*i)->label,(*j)->label); + case 'b' : compare=compare_possibly_null_strings(i->label, + j->label); + break; + case 'w': compare=strcmp(i->write_timestamp, j->write_timestamp); break; - case 'B' : compare=strcmp((*j)->label,(*i)->label); + case 'p' : + compare=i->partnum - j->partnum; break; } if(compare != 0) @@ -334,14 +352,15 @@ const void *j1; return 0; } -void sort_find_result(sort_order, output_find) -char *sort_order; -find_result_t **output_find; +void +sort_find_result( + char *sort_order, + find_result_t **output_find) { find_result_t *output_find_result; find_result_t **array_find_result = NULL; - int nb_result=0; - int no_result; + size_t nb_result=0; + size_t no_result; find_sort_order = sort_order; /* qsort core dump if nothing to sort */ @@ -356,7 +375,7 @@ find_result_t **output_find; } /* put the list in an array */ - array_find_result=alloc(nb_result * sizeof(find_result_t *)); + array_find_result=alloc(nb_result * SIZEOF(find_result_t *)); for(output_find_result=*output_find,no_result=0; output_find_result; output_find_result=output_find_result->next,no_result++) { @@ -364,7 +383,7 @@ find_result_t **output_find; } /* sort the array */ - qsort(array_find_result,nb_result,sizeof(find_result_t *), + qsort(array_find_result,nb_result,SIZEOF(find_result_t *), find_compare); /* put the sorted result in the list */ @@ -377,8 +396,9 @@ find_result_t **output_find; amfree(array_find_result); } -void print_find_result(output_find) -find_result_t *output_find; +void +print_find_result( + find_result_t *output_find) { find_result_t *output_find_result; int max_len_datestamp = 4; @@ -387,27 +407,43 @@ find_result_t *output_find; int max_len_level = 2; int max_len_label =12; int max_len_filenum = 4; + int max_len_part = 4; int max_len_status = 6; - int len; + size_t len; for(output_find_result=output_find; output_find_result; output_find_result=output_find_result->next) { + char *s; - len=strlen(find_nicedate(output_find_result->datestamp)); - if(len>max_len_datestamp) max_len_datestamp=len; + len=len_find_nicedate(output_find_result->timestamp); + if((int)len > max_len_datestamp) + max_len_datestamp=(int)len; len=strlen(output_find_result->hostname); - if(len>max_len_hostname) max_len_hostname=len; - - len=strlen(output_find_result->diskname); - if(len>max_len_diskname) max_len_diskname=len; - - len=strlen(output_find_result->label); - if(len>max_len_label) max_len_label=len; - - len=strlen(output_find_result->status); - if(len>max_len_status) max_len_status=len; + if((int)len > max_len_hostname) + max_len_hostname = (int)len; + + len = len_quote_string(output_find_result->diskname); + if((int)len > max_len_diskname) + max_len_diskname = (int)len; + + if (output_find_result->label != NULL) { + len = len_quote_string(output_find_result->label); + if((int)len > max_len_label) + max_len_label = (int)len; + } + + len=strlen(output_find_result->status) + 1 + strlen(output_find_result->dump_status); + if((int)len > max_len_status) + max_len_status = (int)len; + + s = g_strdup_printf("%d/%d", output_find_result->partnum, + output_find_result->totalparts); + len=strlen(s); + if((int)len > max_len_part) + max_len_part = (int)len; + amfree(s); } /* @@ -418,35 +454,68 @@ find_result_t *output_find; max_len_status = 1; if(output_find==NULL) { - printf("\nNo dump to list\n"); + g_printf(_("\nNo dump to list\n")); } else { - printf("\ndate%*s host%*s disk%*s lv%*s tape or file%*s file%*s status\n", + g_printf(_("\ndate%*s host%*s disk%*s lv%*s tape or file%*s file%*s part%*s status\n"), max_len_datestamp-4,"", max_len_hostname-4 ,"", max_len_diskname-4 ,"", max_len_level-2 ,"", max_len_label-12 ,"", - max_len_filenum-4 ,""); + max_len_filenum-4 ,"", + max_len_part-4 ,""); for(output_find_result=output_find; output_find_result; output_find_result=output_find_result->next) { + char *qdiskname; + char * formatted_label; + char *s; + char *status; + + qdiskname = quote_string(output_find_result->diskname); + if (output_find_result->label == NULL) + formatted_label = stralloc(""); + else + formatted_label = quote_string(output_find_result->label); + + if (strcmp(output_find_result->status, "OK") != 0 || + strcmp(output_find_result->dump_status, "OK") != 0) { + status = vstralloc(output_find_result->status, " ", + output_find_result->dump_status, NULL); + } else { + status = stralloc(output_find_result->status); + } - printf("%-*s %-*s %-*s %*d %-*s %*d %-*s\n", - max_len_datestamp, - find_nicedate(output_find_result->datestamp), - max_len_hostname, output_find_result->hostname, - max_len_diskname, output_find_result->diskname, - max_len_level, output_find_result->level, - max_len_label, output_find_result->label, - max_len_filenum, output_find_result->filenum, - max_len_status, output_find_result->status); + /*@ignore@*/ + /* sec and kb are omitted here, for compatibility with the existing + * output from 'amadmin' */ + s = g_strdup_printf("%d/%d", output_find_result->partnum, + output_find_result->totalparts); + g_printf("%-*s %-*s %-*s %*d %-*s %*lld %*s %s %s\n", + max_len_datestamp, + find_nicedate(output_find_result->timestamp), + max_len_hostname, output_find_result->hostname, + max_len_diskname, qdiskname, + max_len_level, output_find_result->level, + max_len_label, formatted_label, + max_len_filenum, (long long)output_find_result->filenum, + max_len_part, s, + status, + output_find_result->message + ); + amfree(status); + amfree(s); + /*@end@*/ + amfree(qdiskname); + amfree(formatted_label); } } } -void free_find_result(output_find) -find_result_t **output_find; +void +free_find_result( + find_result_t **output_find) { find_result_t *output_find_result, *prev; @@ -454,43 +523,74 @@ find_result_t **output_find; for(output_find_result=*output_find; output_find_result; output_find_result=output_find_result->next) { - if(prev != NULL) amfree(prev); - amfree(output_find_result->hostname); - amfree(output_find_result->diskname); - amfree(output_find_result->label); - amfree(output_find_result->status); + amfree(prev); prev = output_find_result; } - if(prev != NULL) amfree(prev); - output_find = NULL; + amfree(prev); + *output_find = NULL; } -int find_match(host, disk) -char *host, *disk; +int +find_match( + char *host, + char *disk) { disk_t *dp = lookup_disk(host,disk); return (dp && dp->todo); } -char *find_nicedate(datestamp) -int datestamp; +static char * +find_nicedate( + char *datestamp) { static char nice[20]; int year, month, day; - - year = datestamp / 10000; - month = (datestamp / 100) % 100; - day = datestamp % 100; - - ap_snprintf(nice, sizeof(nice), "%4d-%02d-%02d", year, month, day); + int hours, minutes, seconds; + char date[9], atime[7]; + int numdate, numtime; + + strncpy(date, datestamp, 8); + date[8] = '\0'; + numdate = atoi(date); + year = numdate / 10000; + month = (numdate / 100) % 100; + day = numdate % 100; + + if(strlen(datestamp) <= 8) { + g_snprintf(nice, SIZEOF(nice), "%4d-%02d-%02d", + year, month, day); + } + else { + strncpy(atime, &(datestamp[8]), 6); + atime[6] = '\0'; + numtime = atoi(atime); + hours = numtime / 10000; + minutes = (numtime / 100) % 100; + seconds = numtime % 100; + + g_snprintf(nice, SIZEOF(nice), "%4d-%02d-%02d %02d:%02d:%02d", + year, month, day, hours, minutes, seconds); + } return nice; } -static int parse_taper_datestamp_log(logline, datestamp, label) -char *logline; -int *datestamp; -char **label; +static int +len_find_nicedate( + char *datestamp) +{ + if(strlen(datestamp) <= 8) { + return 10; + } else { + return 19; + } +} + +static int +parse_taper_datestamp_log( + char *logline, + char **datestamp, + char **label) { char *s; int ch; @@ -502,117 +602,251 @@ char **label; if(ch == '\0') { return 0; } -#define sc "datestamp" - if(strncmp(s - 1, sc, sizeof(sc)-1) != 0) { + if(strncmp_const_skip(s - 1, "datestamp", s, ch) != 0) { return 0; } - s += sizeof(sc)-1; - ch = s[-1]; -#undef sc skip_whitespace(s, ch); - if(ch == '\0' || sscanf(s - 1, "%d", datestamp) != 1) { + if(ch == '\0') { return 0; } - skip_integer(s, ch); + *datestamp = s - 1; + skip_non_whitespace(s, ch); + s[-1] = '\0'; skip_whitespace(s, ch); if(ch == '\0') { return 0; } -#define sc "label" - if(strncmp(s - 1, sc, sizeof(sc)-1) != 0) { + if(strncmp_const_skip(s - 1, "label", s, ch) != 0) { return 0; } - s += sizeof(sc)-1; - ch = s[-1]; -#undef sc skip_whitespace(s, ch); if(ch == '\0') { return 0; } *label = s - 1; - skip_non_whitespace(s, ch); + skip_quoted_string(s, ch); s[-1] = '\0'; + *label = unquote_string(*label); return 1; } -/* if output_find is NULL */ -/* return 1 if this is the logfile for this label */ -/* return 0 if this is not the logfile for this label */ -/* else */ -/* add to output_find all the dump for this label */ -/* return the number of dump added. */ -int search_logfile(output_find, label, datestamp, datestamp_aux, logfile) -find_result_t **output_find; -char *label, *logfile; -int datestamp, datestamp_aux; -{ - FILE *logf; - char *host, *host_undo; - char *disk, *disk_undo; - int datestampI; - char *rest; - char *ck_label; - int level, filenum, ck_datestamp, tapematch; - int passlabel, ck_datestamp2; - char *s; - int ch; - disk_t *dp; - - if((logf = fopen(logfile, "r")) == NULL) - error("could not open logfile %s: %s", logfile, strerror(errno)); +/* Returns TRUE if the given logfile mentions the given tape. */ +static gboolean logfile_has_tape(char * label, char * datestamp, + char * logfile) { + FILE * logf; + char * ck_datestamp, *ck_label = NULL; + if((logf = fopen(logfile, "r")) == NULL) { + error(_("could not open logfile %s: %s"), logfile, strerror(errno)); + /*NOTREACHED*/ + } - /* check that this log file corresponds to the right tape */ - tapematch = 0; - while(!tapematch && get_logline(logf)) { + while(get_logline(logf)) { if(curlog == L_START && curprog == P_TAPER) { if(parse_taper_datestamp_log(curstr, &ck_datestamp, &ck_label) == 0) { - printf("strange log line \"start taper %s\"\n", curstr); - } else if(ck_datestamp == datestamp + g_printf(_("strange log line \"start taper %s\" curstr='%s'\n"), + logfile, curstr); + } else if(strcmp(ck_datestamp, datestamp) == 0 && strcmp(ck_label, label) == 0) { - tapematch = 1; + amfree(ck_label); + afclose(logf); + return TRUE; } + amfree(ck_label); } } - if(output_find == NULL) { - afclose(logf); - if(tapematch == 0) - return 0; - else - return 1; + afclose(logf); + return FALSE; +} + +static gboolean +volume_matches( + const char *label1, + const char *label2, + const char *datestamp) +{ + tape_t *tp; + + if (!label2) + return TRUE; + + if (label1) + return (strcmp(label1, label2) == 0); + + /* check in tapelist */ + if (!(tp = lookup_tapelabel(label2))) + return FALSE; + + if (strcmp(tp->datestamp, datestamp) != 0) + return FALSE; + + return TRUE; +} + +/* WARNING: Function accesses globals find_diskqp, curlog, curlog, curstr, + * dynamic_disklist */ +gboolean +search_logfile( + find_result_t **output_find, + const char *label, + const char *passed_datestamp, + const char *logfile, + disklist_t * dynamic_disklist) +{ + FILE *logf; + char *host, *host_undo; + char *disk, *qdisk, *disk_undo; + char *date, *date_undo; + int partnum; + int totalparts; + int maxparts = -1; + char *number; + int fileno; + char *current_label = stralloc(""); + char *rest, *rest_undo; + char *ck_label=NULL; + int level = 0; + off_t filenum; + char *ck_datestamp=NULL; + char *datestamp; + char *s; + int ch; + disk_t *dp; + GHashTable* valid_label; + GHashTable* part_by_dle; + find_result_t *part_find; + find_result_t *a_part_find; + gboolean right_label = FALSE; + gboolean found_something = FALSE; + double sec; + off_t kb; + off_t bytes; + off_t orig_kb; + int taper_part = 0; + + g_return_val_if_fail(output_find != NULL, 0); + g_return_val_if_fail(logfile != NULL, 0); + + if (string_chunk == NULL) { + string_chunk = g_string_chunk_new(32768); } + valid_label = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + part_by_dle = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + datestamp = g_strdup(passed_datestamp); - if(tapematch == 0) { - afclose(logf); - return 0; + if((logf = fopen(logfile, "r")) == NULL) { + error(_("could not open logfile %s: %s"), logfile, strerror(errno)); + /*NOTREACHED*/ } - filenum = 0; - passlabel = 1; - while(get_logline(logf) && passlabel) { - if(curlog == L_SUCCESS && curprog == P_TAPER && passlabel) filenum++; - if(curlog == L_START && curprog == P_TAPER) { - if(parse_taper_datestamp_log(curstr, - &ck_datestamp2, &ck_label) == 0) { - printf("strange log line \"start taper %s\"\n", curstr); - } else if (strcmp(ck_label, label)) { - passlabel = !passlabel; + filenum = (off_t)0; + while(get_logline(logf)) { + if (curlog == L_START && curprog == P_TAPER) { + amfree(ck_label); + ck_datestamp = NULL; + if(parse_taper_datestamp_log(curstr, &ck_datestamp, + &ck_label) == 0) { + g_printf(_("strange log line in %s \"start taper %s\"\n"), + logfile, curstr); + continue; + } + if (datestamp != NULL) { + if (strcmp(datestamp, ck_datestamp) != 0) { + g_printf(_("Log file %s stamped %s, expecting %s!\n"), + logfile, ck_datestamp, datestamp); + amfree(ck_label); + break; + } + } + + right_label = volume_matches(label, ck_label, ck_datestamp); + if (right_label && ck_label) { + g_hash_table_insert(valid_label, g_strdup(ck_label), + GINT_TO_POINTER(1)); + } + if (label && datestamp && right_label) { + found_something = TRUE; } + amfree(current_label); + current_label = ck_label; + ck_label = NULL; + if (datestamp == NULL) { + datestamp = g_strdup(ck_datestamp); + } + filenum = (off_t)0; } - if(curlog == L_SUCCESS || curlog == L_FAIL) { + if (!datestamp) + continue; + if (right_label && + (curlog == L_SUCCESS || + curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTPARTIAL) && + curprog == P_TAPER) { + filenum++; + } else if (right_label && curlog == L_PARTIAL && curprog == P_TAPER && + taper_part == 0) { + filenum++; + } + partnum = -1; + totalparts = -1; + if (curlog == L_SUCCESS || curlog == L_CHUNKSUCCESS || + curlog == L_DONE || curlog == L_FAIL || + curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTIAL || + curlog == L_PARTPARTIAL ) { s = curstr; ch = *s++; skip_whitespace(s, ch); if(ch == '\0') { - printf("strange log line \"%s\"\n", curstr); + g_printf(_("strange log line in %s \"%s\"\n"), + logfile, curstr); continue; } + + if (curlog == L_PART || curlog == L_PARTPARTIAL) { + char *part_label; + char *qpart_label = s - 1; + taper_part++; + skip_quoted_string(s, ch); + s[-1] = '\0'; + + part_label = unquote_string(qpart_label); + if (!g_hash_table_lookup(valid_label, part_label)) { + amfree(part_label); + continue; + } + amfree(current_label); + current_label = part_label; + + skip_whitespace(s, ch); + if(ch == '\0') { + g_printf("strange log line in %s \"%s\"\n", + logfile, curstr); + continue; + } + + number = s - 1; + skip_non_whitespace(s, ch); + s[-1] = '\0'; + fileno = atoi(number); + filenum = fileno; + if (filenum == 0) + continue; + + skip_whitespace(s, ch); + if(ch == '\0') { + g_printf("strange log line in %s \"%s\"\n", + logfile, curstr); + continue; + } + } else { + taper_part = 0; + } + host = s - 1; skip_non_whitespace(s, ch); host_undo = s - 1; @@ -620,29 +854,62 @@ int datestamp, datestamp_aux; skip_whitespace(s, ch); if(ch == '\0') { - printf("strange log line \"%s\"\n", curstr); + g_printf(_("strange log line in %s \"%s\"\n"), + logfile, curstr); continue; } - disk = s - 1; - skip_non_whitespace(s, ch); + qdisk = s - 1; + skip_quoted_string(s, ch); disk_undo = s - 1; *disk_undo = '\0'; + disk = unquote_string(qdisk); skip_whitespace(s, ch); - if(ch == '\0' || sscanf(s - 1, "%d", &datestampI) != 1) { - printf("strange log line \"%s\"\n", curstr); + if(ch == '\0') { + g_printf(_("strange log line in %s \"%s\"\n"), + logfile, curstr); continue; } - skip_integer(s, ch); - - if(datestampI < 100) { /* old log didn't have datestamp */ - level = datestampI; - datestampI = datestamp; - } - else { - skip_whitespace(s, ch); + date = s - 1; + skip_non_whitespace(s, ch); + date_undo = s - 1; + *date_undo = '\0'; + + if(strlen(date) < 3) { /* old log didn't have datestamp */ + level = atoi(date); + date = stralloc(datestamp); + partnum = 1; + totalparts = 1; + } else { + if (curprog == P_TAPER && + (curlog == L_CHUNK || curlog == L_PART || + curlog == L_PARTPARTIAL || curlog == L_PARTIAL || + curlog == L_DONE)) { + char *s1, ch1; + skip_whitespace(s, ch); + number = s - 1; + skip_non_whitespace(s, ch); + s1 = &s[-1]; + ch1 = *s1; + skip_whitespace(s, ch); + if (*(s-1) != '[') { + *s1 = ch1; + sscanf(number, "%d/%d", &partnum, &totalparts); + if (partnum > maxparts) + maxparts = partnum; + if (totalparts > maxparts) + maxparts = totalparts; + } else { /* nparts is not in all PARTIAL lines */ + partnum = 1; + totalparts = 1; + s = number + 1; + } + } else { + skip_whitespace(s, ch); + } if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) { - printf("strange log line \"%s\"\n", curstr); + g_printf(_("Fstrange log line in %s \"%s\"\n"), + logfile, s-1); continue; } skip_integer(s, ch); @@ -650,76 +917,429 @@ int datestamp, datestamp_aux; skip_whitespace(s, ch); if(ch == '\0') { - printf("strange log line \"%s\"\n", curstr); + g_printf(_("strange log line in %s \"%s\"\n"), + logfile, curstr); continue; } rest = s - 1; - if((s = strchr(s, '\n')) != NULL) { - *s = '\0'; + skip_non_whitespace(s, ch); + rest_undo = s - 1; + *rest_undo = '\0'; + if (strcmp(rest, "[sec") == 0) { + skip_whitespace(s, ch); + if(ch == '\0') { + g_printf(_("strange log line in %s \"%s\"\n"), + logfile, curstr); + continue; + } + sec = atof(s - 1); + skip_non_whitespace(s, ch); + skip_whitespace(s, ch); + rest = s - 1; + skip_non_whitespace(s, ch); + rest_undo = s - 1; + *rest_undo = '\0'; + if (strcmp(rest, "kb") != 0 && + strcmp(rest, "bytes") != 0) { + g_printf(_("Bstrange log line in %s \"%s\"\n"), + logfile, curstr); + continue; + } + + skip_whitespace(s, ch); + if (ch == '\0') { + g_printf(_("strange log line in %s \"%s\"\n"), + logfile, curstr); + continue; + } + if (strcmp(rest, "kb") == 0) { + kb = atof(s - 1); + bytes = 0; + } else { + bytes = atof(s - 1); + kb = bytes / 1024; + } + skip_non_whitespace(s, ch); + skip_whitespace(s, ch); + rest = s - 1; + skip_non_whitespace(s, ch); + rest_undo = s - 1; + *rest_undo = '\0'; + if (strcmp(rest, "kps") != 0) { + g_printf(_("Cstrange log line in %s \"%s\"\n"), + logfile, curstr); + continue; + } + + skip_whitespace(s, ch); + if (ch == '\0') { + g_printf(_("strange log line in %s \"%s\"\n"), + logfile, curstr); + continue; + } + /* kps = atof(s - 1); */ + skip_non_whitespace(s, ch); + skip_whitespace(s, ch); + rest = s - 1; + skip_non_whitespace(s, ch); + rest_undo = s - 1; + *rest_undo = '\0'; + if (strcmp(rest, "orig-kb") != 0) { + orig_kb = 0; + } else { + + skip_whitespace(s, ch); + if(ch == '\0') { + g_printf(_("strange log line in %s \"%s\"\n"), + logfile, curstr); + continue; + } + orig_kb = atof(s - 1); + } + } else { + sec = 0; + kb = 0; + bytes = 0; + orig_kb = 0; + *rest_undo = ' '; } + if (strncmp(rest, "error", 5) == 0) rest += 6; + if (strncmp(rest, "config", 6) == 0) rest += 7; + dp = lookup_disk(host,disk); if ( dp == NULL ) { - if (dynamic_disklist == 0) { + if (dynamic_disklist == NULL) { continue; } - dp = add_disk(host, disk); - enqueue_disk(find_diskqp , dp); + dp = add_disk(dynamic_disklist, host, disk); + enqueue_disk(dynamic_disklist, dp); } - if(find_match(host, disk)) { + if (find_match(host, disk)) { if(curprog == P_TAPER) { - find_result_t *new_output_find = - (find_result_t *)alloc(sizeof(find_result_t)); - new_output_find->next=*output_find; - new_output_find->datestamp=datestampI; - new_output_find->timestamp = alloc(15); - ap_snprintf(new_output_find->timestamp, 15, "%d000000", datestampI); - new_output_find->datestamp_aux=datestamp_aux; - new_output_find->hostname=stralloc(host); - new_output_find->diskname=stralloc(disk); + char *key = g_strdup_printf( + "HOST:%s DISK:%s: DATE:%s LEVEL:%d", + host, disk, date, level); + find_result_t *new_output_find = g_new0(find_result_t, 1); + part_find = g_hash_table_lookup(part_by_dle, key); + maxparts = partnum; + if (maxparts < totalparts) + maxparts = totalparts; + for (a_part_find = part_find; + a_part_find; + a_part_find = a_part_find->next) { + if (maxparts < a_part_find->partnum) + maxparts = a_part_find->partnum; + if (maxparts < a_part_find->totalparts) + maxparts = a_part_find->totalparts; + } + new_output_find->timestamp = g_string_chunk_insert_const(string_chunk, date); + new_output_find->write_timestamp = g_string_chunk_insert_const(string_chunk, datestamp); + new_output_find->hostname=g_string_chunk_insert_const(string_chunk, host); + new_output_find->diskname=g_string_chunk_insert_const(string_chunk, disk); new_output_find->level=level; - new_output_find->label=stralloc(label); + new_output_find->partnum = partnum; + new_output_find->totalparts = totalparts; + new_output_find->label=g_string_chunk_insert_const(string_chunk, current_label); + new_output_find->status=NULL; + new_output_find->dump_status=NULL; + new_output_find->message=""; new_output_find->filenum=filenum; - if(curlog == L_SUCCESS) - new_output_find->status=stralloc("OK"); - else - new_output_find->status=stralloc(rest); - *output_find=new_output_find; + new_output_find->sec=sec; + new_output_find->kb=kb; + new_output_find->bytes=bytes; + new_output_find->orig_kb=orig_kb; + new_output_find->next=NULL; + if (curlog == L_SUCCESS) { + new_output_find->status = "OK"; + new_output_find->dump_status = "OK"; + new_output_find->next = *output_find; + new_output_find->partnum = 1; /* L_SUCCESS is pre-splitting */ + *output_find = new_output_find; + found_something = TRUE; + } else if (curlog == L_CHUNKSUCCESS || curlog == L_DONE || + curlog == L_PARTIAL || curlog == L_FAIL) { + /* result line */ + if (curlog == L_PARTIAL || curlog == L_FAIL) { + /* set dump_status of each part */ + for (a_part_find = part_find; + a_part_find; + a_part_find = a_part_find->next) { + if (curlog == L_PARTIAL) + a_part_find->dump_status = "PARTIAL"; + else { + a_part_find->dump_status = "FAIL"; + a_part_find->message = g_string_chunk_insert_const(string_chunk, rest); + } + } + } else { + if (maxparts > -1) { /* format with part */ + /* must check if all part are there */ + int num_part = maxparts; + for (a_part_find = part_find; + a_part_find; + a_part_find = a_part_find->next) { + if (a_part_find->partnum == num_part && + strcmp(a_part_find->status, "OK") == 0) + num_part--; + } + /* set dump_status of each part */ + for (a_part_find = part_find; + a_part_find; + a_part_find = a_part_find->next) { + if (num_part == 0) { + a_part_find->dump_status = "OK"; + } else { + a_part_find->dump_status = "FAIL"; + a_part_find->message = + g_string_chunk_insert_const(string_chunk, "Missing part"); + } + } + } + } + if (curlog == L_DONE) { + for (a_part_find = part_find; + a_part_find; + a_part_find = a_part_find->next) { + if (a_part_find->totalparts == -1) { + a_part_find->totalparts = maxparts; + } + if (a_part_find->orig_kb == 0) { + a_part_find->orig_kb = orig_kb; + } + } + } + if (part_find) { /* find last element */ + for (a_part_find = part_find; + a_part_find->next != NULL; + a_part_find=a_part_find->next) { + } + /* merge part_find to *output_find */ + a_part_find->next = *output_find; + *output_find = part_find; + part_find = NULL; + maxparts = -1; + found_something = TRUE; + g_hash_table_remove(part_by_dle, key); + } + free_find_result(&new_output_find); + } else { /* part line */ + if (curlog == L_PART || curlog == L_CHUNK) { + new_output_find->status = "OK"; + new_output_find->dump_status = "OK"; + } else { /* PARTPARTIAL */ + new_output_find->status = "PARTIAL"; + new_output_find->dump_status = "PARTIAL"; + } + /* Add to part_find list */ + if (part_find) { + new_output_find->next = part_find; + part_find = new_output_find; + } else { + new_output_find->next = NULL; + part_find = new_output_find; + } + g_hash_table_insert(part_by_dle, g_strdup(key), + part_find); + found_something = TRUE; + } + amfree(key); } - else if(curlog == L_FAIL) { /* print other failures too */ - find_result_t *new_output_find = - (find_result_t *)alloc(sizeof(find_result_t)); - new_output_find->next=*output_find; - new_output_find->datestamp=datestamp; - new_output_find->datestamp_aux=datestamp_aux; - new_output_find->timestamp = alloc(15); - ap_snprintf(new_output_find->timestamp, 15, "%d000000", datestamp); - new_output_find->hostname=stralloc(host); - new_output_find->diskname=stralloc(disk); + else if(curlog == L_FAIL) { + char *status_failed; + /* 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 = g_string_chunk_insert_const(string_chunk, date); + new_output_find->write_timestamp = g_strdup("00000000000000"); /* dump was not written.. */ + new_output_find->hostname=g_string_chunk_insert_const(string_chunk, host); + new_output_find->diskname=g_string_chunk_insert_const(string_chunk, disk); new_output_find->level=level; - new_output_find->label=stralloc("---"); + new_output_find->label=NULL; + new_output_find->partnum=partnum; + new_output_find->totalparts=totalparts; new_output_find->filenum=0; - new_output_find->status=vstralloc( + new_output_find->sec=sec; + new_output_find->kb=kb; + new_output_find->bytes=bytes; + new_output_find->orig_kb=orig_kb; + status_failed = vstralloc( "FAILED (", program_str[(int)curprog], ") ", rest, NULL); + new_output_find->status = g_string_chunk_insert_const(string_chunk, status_failed); + amfree(status_failed); + new_output_find->dump_status=""; + new_output_find->message=""; *output_find=new_output_find; + found_something = TRUE; + maxparts = -1; } } + amfree(disk); } } + + g_hash_table_destroy(valid_label); afclose(logf); - return 1; + amfree(datestamp); + amfree(current_label); + + return found_something; +} + + +/* + * Return the set of dumps that match *all* of the given patterns (we consider + * an empty pattern to match .*, though). If 'ok' is true, will only match + * dumps with SUCCESS status. + * + * 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( + find_result_t *output_find, + char *hostname, + char *diskname, + char *datestamp, + char *level, + int ok) +{ + find_result_t *cur_result; + find_result_t *matches = NULL; + + 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); + if((!hostname || *hostname == '\0' || match_host(hostname, cur_result->hostname)) && + (!diskname || *diskname == '\0' || match_disk(diskname, cur_result->diskname)) && + (!datestamp || *datestamp== '\0' || match_datestamp(datestamp, cur_result->timestamp)) && + (!level || *level== '\0' || match_level(level, level_str)) && + (!ok || !strcmp(cur_result->status, "OK")) && + (!ok || !strcmp(cur_result->dump_status, "OK"))){ + + find_result_t *curmatch = g_new0(find_result_t, 1); + memcpy(curmatch, cur_result, SIZEOF(find_result_t)); + + curmatch->timestamp = cur_result->timestamp; + curmatch->write_timestamp = cur_result->write_timestamp; + curmatch->hostname = cur_result->hostname; + curmatch->diskname = cur_result->diskname; + curmatch->level = cur_result->level; + curmatch->label = cur_result->label? cur_result->label : NULL; + curmatch->filenum = cur_result->filenum; + curmatch->sec = cur_result->sec; + curmatch->kb = cur_result->kb; + curmatch->bytes = cur_result->bytes; + curmatch->orig_kb = cur_result->orig_kb; + curmatch->status = cur_result->status; + curmatch->dump_status = cur_result->dump_status; + curmatch->message = cur_result->message; + curmatch->partnum = cur_result->partnum; + curmatch->totalparts = cur_result->totalparts; + curmatch->next = matches; + matches = curmatch; + } + } + + 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]; + char *zeropad_ts = NULL; + char *zeropad_w_ts = NULL; + g_snprintf(level_str, SIZEOF(level_str), "%d", cur_result->level); + + /* get the timestamp padded to full width */ + if (strlen(cur_result->timestamp) < 14) { + zeropad_ts = g_new0(char, 15); + memset(zeropad_ts, '0', 14); + memcpy(zeropad_ts, cur_result->timestamp, strlen(cur_result->timestamp)); + } + if (strlen(cur_result->write_timestamp) < 14) { + zeropad_w_ts = g_new0(char, 15); + memset(zeropad_w_ts, '0', 14); + memcpy(zeropad_w_ts, cur_result->write_timestamp, strlen(cur_result->write_timestamp)); + } + + 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) + || (zeropad_ts && match_datestamp(ds->datestamp, zeropad_ts))) && + (!ds->write_timestamp || *ds->write_timestamp== '\0' + || match_datestamp(ds->write_timestamp, cur_result->write_timestamp) + || (zeropad_w_ts && match_datestamp(ds->write_timestamp, zeropad_w_ts))) && + (!ds->level || *ds->level== '\0' || match_level(ds->level, level_str)) && + (!ok || !strcmp(cur_result->status, "OK")) && + (!ok || !strcmp(cur_result->dump_status, "OK"))) { + + find_result_t *curmatch = alloc(SIZEOF(find_result_t)); + memcpy(curmatch, cur_result, SIZEOF(find_result_t)); + + curmatch->timestamp = cur_result->timestamp; + curmatch->write_timestamp = cur_result->write_timestamp; + curmatch->hostname = cur_result->hostname; + curmatch->diskname = cur_result->diskname; + curmatch->level = cur_result->level; + curmatch->label = cur_result->label? cur_result->label : NULL; + curmatch->filenum = cur_result->filenum; + curmatch->status = cur_result->status; + curmatch->dump_status = cur_result->dump_status; + curmatch->message = cur_result->message; + curmatch->partnum = cur_result->partnum; + curmatch->totalparts = cur_result->totalparts; + + curmatch->next = matches; + matches = curmatch; + break; + } + } + + amfree(zeropad_ts); + } + + return(matches); } -find_result_t *dump_exist(output_find, hostname, diskname, datestamp, level) -find_result_t *output_find; -char *hostname; -char *diskname; -int datestamp; -int level; +find_result_t * +dump_exist( + find_result_t *output_find, + char *hostname, + char *diskname, + char *datestamp, + int level) { find_result_t *output_find_result; @@ -728,7 +1348,7 @@ int level; output_find_result=output_find_result->next) { if( !strcmp(output_find_result->hostname, hostname) && !strcmp(output_find_result->diskname, diskname) && - output_find_result->datestamp == datestamp && + !strcmp(output_find_result->timestamp, datestamp) && output_find_result->level == level) { return output_find_result;