2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1998 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Author: James da Silva, Systems Design and Analysis Group
24 * Computer Science Department
25 * University of Maryland at College Park
28 * $Id: find.c,v 1.33 2006/07/06 13:13:15 martinea Exp $
30 * controlling process for the Amanda backup system
41 int find_match(char *host, char *disk);
42 void search_holding_disk(find_result_t **output_find);
43 char *find_nicedate(char *datestamp);
44 static int find_compare(const void *, const void *);
45 static int parse_taper_datestamp_log(char *logline, char **datestamp, char **level);
46 static gboolean logfile_has_tape(char * label, char * datestamp,
49 static char *find_sort_order = NULL;
51 find_result_t * find_dump(disklist_t* diskqp) {
52 char *conf_logdir, *logfile = NULL;
53 int tape, maxtape, logs;
56 find_result_t *output_find = NULL;
58 conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR));
59 maxtape = lookup_nb_tape();
61 for(tape = 1; tape <= maxtape; tape++) {
63 tp = lookup_tapepos(tape);
64 if(tp == NULL) continue;
66 /* search log files */
70 /* new-style log.<date>.<seq> */
72 for(seq = 0; 1; seq++) {
73 char seq_str[NUM_STR_SIZE];
75 g_snprintf(seq_str, SIZEOF(seq_str), "%u", seq);
76 logfile = newvstralloc(logfile,
77 conf_logdir, "/log.", tp->datestamp, ".", seq_str, NULL);
78 if(access(logfile, R_OK) != 0) break;
79 if (search_logfile(&output_find, tp->label, tp->datestamp,
85 /* search old-style amflush log, if any */
87 logfile = newvstralloc(logfile, conf_logdir, "/log.",
88 tp->datestamp, ".amflush", NULL);
89 if(access(logfile,R_OK) == 0) {
90 if (search_logfile(&output_find, tp->label, tp->datestamp,
96 /* search old-style main log, if any */
98 logfile = newvstralloc(logfile, conf_logdir, "/log.", tp->datestamp,
100 if(access(logfile,R_OK) == 0) {
101 if (search_logfile(&output_find, tp->label, tp->datestamp,
106 if(logs == 0 && strcmp(tp->datestamp,"0") != 0)
108 _("Warning: no log files found for tape %s written %s\n"),
109 tp->label, find_nicedate(tp->datestamp));
114 search_holding_disk(&output_find);
122 char *conf_logdir, *logfile = NULL;
123 char *pathlogfile = NULL;
124 int tape, maxtape, logs;
127 char **output_find_log = NULL;
130 conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR));
131 maxtape = lookup_nb_tape();
133 output_find_log = alloc((maxtape*5+10) * SIZEOF(char *));
134 current_log = output_find_log;
136 for(tape = 1; tape <= maxtape; tape++) {
138 tp = lookup_tapepos(tape);
139 if(tp == NULL) continue;
141 /* search log files */
145 /* new-style log.<date>.<seq> */
147 for(seq = 0; 1; seq++) {
148 char seq_str[NUM_STR_SIZE];
150 g_snprintf(seq_str, SIZEOF(seq_str), "%u", seq);
151 logfile = newvstralloc(logfile, "log.", tp->datestamp, ".", seq_str, NULL);
152 pathlogfile = newvstralloc(pathlogfile, conf_logdir, "/", logfile, NULL);
153 if (access(pathlogfile, R_OK) != 0) break;
154 if (logfile_has_tape(tp->label, tp->datestamp, pathlogfile)) {
155 if (current_log == output_find_log || strcmp(*(current_log-1), logfile)) {
156 *current_log = stralloc(logfile);
164 /* search old-style amflush log, if any */
166 logfile = newvstralloc(logfile, "log.", tp->datestamp, ".amflush", NULL);
167 pathlogfile = newvstralloc(pathlogfile, conf_logdir, "/", logfile, NULL);
168 if (access(pathlogfile, R_OK) == 0) {
169 if (logfile_has_tape(tp->label, tp->datestamp, pathlogfile)) {
170 if (current_log == output_find_log || strcmp(*(current_log-1), logfile)) {
171 *current_log = stralloc(logfile);
178 /* search old-style main log, if any */
180 logfile = newvstralloc(logfile, "log.", tp->datestamp, NULL);
181 pathlogfile = newvstralloc(pathlogfile, conf_logdir, "/", logfile, NULL);
182 if (access(pathlogfile, R_OK) == 0) {
183 if (logfile_has_tape(tp->label, tp->datestamp, pathlogfile)) {
184 if (current_log == output_find_log || strcmp(*(current_log-1), logfile)) {
185 *current_log = stralloc(logfile);
192 if(logs == 0 && strcmp(tp->datestamp,"0") != 0)
193 g_fprintf(stderr, _("Warning: no log files found for tape %s written %s\n"),
194 tp->label, find_nicedate(tp->datestamp));
200 return(output_find_log);
205 find_result_t **output_find)
207 GSList *holding_file_list;
212 holding_file_list = holding_get_files(NULL, 1);
214 for(e = holding_file_list; e != NULL; e = e->next) {
217 holding_file = (char *)e->data;
219 if (!holding_file_get_dumpfile(holding_file, &file))
222 if (file.dumplevel < 0 || file.dumplevel > 9) {
223 dumpfile_free_data(&file);
230 if((dp = lookup_disk(file.name, file.disk)))
232 if((s = strrchr(file.name,'.')) == NULL)
237 dumpfile_free_data(&file);
241 if(find_match(file.name,file.disk)) {
242 find_result_t *new_output_find = g_new0(find_result_t, 1);
243 new_output_find->next=*output_find;
244 new_output_find->timestamp = stralloc(file.datestamp);
245 new_output_find->hostname = stralloc(file.name);
246 new_output_find->diskname = stralloc(file.disk);
247 new_output_find->level=file.dumplevel;
248 new_output_find->label=stralloc(holding_file);
249 new_output_find->partnum=stralloc("--");
250 new_output_find->filenum=0;
252 new_output_find->status=stralloc("PARTIAL");
254 new_output_find->status=stralloc("OK");
255 *output_find=new_output_find;
257 dumpfile_free_data(&file);
260 g_slist_free_full(holding_file_list);
264 get_write_timestamp(char *tapelabel)
268 if (!tapelabel || !(tp = lookup_tapelabel(tapelabel)))
271 return tp->datestamp;
280 find_result_t *i, *j;
282 size_t nb_compare=strlen(find_sort_order);
285 for(k=0;k<nb_compare;k++) {
286 char sort_key = find_sort_order[k];
287 if (isupper((int)sort_key)) {
289 sort_key = tolower(sort_key);
290 j = *(find_result_t **)i1;
291 i = *(find_result_t **)j1;
293 i = *(find_result_t **)i1;
294 j = *(find_result_t **)j1;
298 case 'h' : compare=strcmp(i->hostname,j->hostname);
300 case 'k' : compare=strcmp(i->diskname,j->diskname);
302 case 'd' : compare=strcmp(i->timestamp,j->timestamp);
304 case 'l' : compare=j->level - i->level;
306 case 'f' : compare=(i->filenum == j->filenum) ? 0 :
307 ((i->filenum < j->filenum) ? -1 : 1);
309 case 'b' : compare=compare_possibly_null_strings(i->label,
312 case 'w': compare=strcmp(get_write_timestamp(i->label),
313 get_write_timestamp(j->label));
316 if(strcmp(i->partnum, "--") != 0 &&
317 strcmp(j->partnum, "--") != 0){
318 compare = atoi(i->partnum) - atoi(j->partnum);
320 else compare=strcmp(i->partnum,j->partnum);
332 find_result_t **output_find)
334 find_result_t *output_find_result;
335 find_result_t **array_find_result = NULL;
339 find_sort_order = sort_order;
340 /* qsort core dump if nothing to sort */
341 if(*output_find==NULL)
344 /* How many result */
345 for(output_find_result=*output_find;
347 output_find_result=output_find_result->next) {
351 /* put the list in an array */
352 array_find_result=alloc(nb_result * SIZEOF(find_result_t *));
353 for(output_find_result=*output_find,no_result=0;
355 output_find_result=output_find_result->next,no_result++) {
356 array_find_result[no_result]=output_find_result;
360 qsort(array_find_result,nb_result,SIZEOF(find_result_t *),
363 /* put the sorted result in the list */
365 no_result<nb_result-1; no_result++) {
366 array_find_result[no_result]->next = array_find_result[no_result+1];
368 array_find_result[nb_result-1]->next=NULL;
369 *output_find=array_find_result[0];
370 amfree(array_find_result);
375 find_result_t *output_find)
377 find_result_t *output_find_result;
378 int max_len_datestamp = 4;
379 int max_len_hostname = 4;
380 int max_len_diskname = 4;
381 int max_len_level = 2;
382 int max_len_label =12;
383 int max_len_filenum = 4;
384 int max_len_part = 4;
385 int max_len_status = 6;
388 for(output_find_result=output_find;
390 output_find_result=output_find_result->next) {
393 len=strlen(find_nicedate(output_find_result->timestamp));
394 if((int)len > max_len_datestamp)
395 max_len_datestamp=(int)len;
397 len=strlen(output_find_result->hostname);
398 if((int)len > max_len_hostname)
399 max_len_hostname = (int)len;
401 qdiskname=quote_string(output_find_result->diskname);
402 len=strlen(qdiskname);
404 if((int)len > max_len_diskname)
405 max_len_diskname = (int)len;
407 if (output_find_result->label != NULL) {
408 len=strlen(output_find_result->label);
409 if((int)len > max_len_label)
410 max_len_label = (int)len;
413 len=strlen(output_find_result->status);
414 if((int)len > max_len_status)
415 max_len_status = (int)len;
417 len=strlen(output_find_result->partnum);
418 if((int)len > max_len_part)
419 max_len_part = (int)len;
423 * Since status is the rightmost field, we zap the maximum length
424 * because it is not needed. The code is left in place in case
425 * another column is added later.
429 if(output_find==NULL) {
430 g_printf(_("\nNo dump to list\n"));
433 g_printf(_("\ndate%*s host%*s disk%*s lv%*s tape or file%*s file%*s part%*s status\n"),
434 max_len_datestamp-4,"",
435 max_len_hostname-4 ,"",
436 max_len_diskname-4 ,"",
438 max_len_label-12 ,"",
439 max_len_filenum-4 ,"",
441 for(output_find_result=output_find;
443 output_find_result=output_find_result->next) {
445 char * formatted_label;
447 qdiskname = quote_string(output_find_result->diskname);
448 formatted_label = output_find_result->label;
449 if (formatted_label == NULL)
450 formatted_label = "";
453 /* sec and kb are omitted here, for compatibility with the existing
454 * output from 'amadmin' */
455 g_printf("%-*s %-*s %-*s %*d %-*s %*lld %*s %-*s\n",
457 find_nicedate(output_find_result->timestamp),
458 max_len_hostname, output_find_result->hostname,
459 max_len_diskname, qdiskname,
460 max_len_level, output_find_result->level,
461 max_len_label, formatted_label,
462 max_len_filenum, (long long)output_find_result->filenum,
463 max_len_part, output_find_result->partnum,
464 max_len_status, output_find_result->status
474 find_result_t **output_find)
476 find_result_t *output_find_result, *prev;
479 for(output_find_result=*output_find;
481 output_find_result=output_find_result->next) {
483 amfree(output_find_result->timestamp);
484 amfree(output_find_result->hostname);
485 amfree(output_find_result->diskname);
486 amfree(output_find_result->label);
487 amfree(output_find_result->partnum);
488 amfree(output_find_result->status);
489 prev = output_find_result;
500 disk_t *dp = lookup_disk(host,disk);
501 return (dp && dp->todo);
508 static char nice[20];
509 int year, month, day;
510 int hours, minutes, seconds;
511 char date[9], atime[7];
512 int numdate, numtime;
514 strncpy(date, datestamp, 8);
516 numdate = atoi(date);
517 year = numdate / 10000;
518 month = (numdate / 100) % 100;
521 if(strlen(datestamp) <= 8) {
522 g_snprintf(nice, SIZEOF(nice), "%4d-%02d-%02d",
526 strncpy(atime, &(datestamp[8]), 6);
528 numtime = atoi(atime);
529 hours = numtime / 10000;
530 minutes = (numtime / 100) % 100;
531 seconds = numtime % 100;
533 g_snprintf(nice, SIZEOF(nice), "%4d-%02d-%02d %02d:%02d:%02d",
534 year, month, day, hours, minutes, seconds);
541 parse_taper_datestamp_log(
552 skip_whitespace(s, ch);
556 if(strncmp_const_skip(s - 1, "datestamp", s, ch) != 0) {
560 skip_whitespace(s, ch);
565 skip_non_whitespace(s, ch);
568 skip_whitespace(s, ch);
572 if(strncmp_const_skip(s - 1, "label", s, ch) != 0) {
576 skip_whitespace(s, ch);
581 skip_non_whitespace(s, ch);
587 /* Returns TRUE if the given logfile mentions the given tape. */
588 static gboolean logfile_has_tape(char * label, char * datestamp,
591 char * ck_datestamp, *ck_label;
592 if((logf = fopen(logfile, "r")) == NULL) {
593 error(_("could not open logfile %s: %s"), logfile, strerror(errno));
597 while(get_logline(logf)) {
598 if(curlog == L_START && curprog == P_TAPER) {
599 if(parse_taper_datestamp_log(curstr,
600 &ck_datestamp, &ck_label) == 0) {
601 g_printf(_("strange log line \"start taper %s\" curstr='%s'\n"),
603 } else if(strcmp(ck_datestamp, datestamp) == 0
604 && strcmp(ck_label, label) == 0) {
615 /* Like (strcmp(label1, label2) == 0), except that NULL values force TRUE. */
616 static gboolean volume_matches(const char * label1, const char * label2) {
617 return (label1 == NULL || label2 == NULL || strcmp(label1, label2) == 0);
620 /* WARNING: Function accesses globals find_diskqp, curlog, curlog, curstr,
621 * dynamic_disklist */
624 find_result_t **output_find,
626 const char *passed_datestamp,
628 disklist_t * dynamic_disklist)
631 char *host, *host_undo;
632 char *disk, *qdisk, *disk_undo;
633 char *date, *date_undo;
634 char *partnum=NULL, *partnum_undo;
637 char *current_label = NULL;
642 char *ck_datestamp, *datestamp;
646 find_result_t *part_find = NULL; /* List for all part of a DLE */
647 find_result_t *a_part_find;
648 gboolean right_label = FALSE;
649 gboolean found_something = FALSE;
652 regmatch_t pmatch[3];
656 g_return_val_if_fail(output_find != NULL, 0);
657 g_return_val_if_fail(logfile != NULL, 0);
659 datestamp = g_strdup(passed_datestamp);
661 if((logf = fopen(logfile, "r")) == NULL) {
662 error(_("could not open logfile %s: %s"), logfile, strerror(errno));
667 while(get_logline(logf)) {
668 if (curlog == L_START && curprog == P_TAPER) {
669 if(parse_taper_datestamp_log(curstr, &ck_datestamp,
671 g_printf(_("strange log line in %s \"start taper %s\"\n"),
675 if (datestamp != NULL) {
676 if (strcmp(datestamp, ck_datestamp) != 0) {
677 g_printf(_("Log file %s stamped %s, expecting %s!\n"),
678 logfile, ck_datestamp, datestamp);
683 right_label = volume_matches(label, ck_label);
684 if (label && datestamp && right_label) {
685 found_something = TRUE;
687 amfree(current_label);
688 current_label = g_strdup(ck_label);
689 if (datestamp == NULL) {
690 datestamp = g_strdup(ck_datestamp);
696 if ((curlog == L_SUCCESS ||
697 curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTPARTIAL) &&
698 curprog == P_TAPER) {
702 if (curlog == L_SUCCESS || curlog == L_CHUNKSUCCESS ||
703 curlog == L_DONE || curlog == L_FAIL ||
704 curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTIAL ||
705 curlog == L_PARTPARTIAL ) {
709 skip_whitespace(s, ch);
711 g_printf(_("strange log line in %s \"%s\"\n"),
716 if (curlog == L_PART || curlog == L_PARTPARTIAL) {
717 char * part_label = s - 1;
718 skip_non_whitespace(s, ch);
721 if (strcmp(current_label, part_label) != 0) {
722 g_printf("PART label %s doesn't match START label %s\n",
723 part_label, current_label);
726 skip_whitespace(s, ch);
728 g_printf("strange log line in %s \"%s\"\n",
734 skip_non_whitespace(s, ch);
736 fileno = atoi(number);
739 skip_whitespace(s, ch);
741 g_printf("strange log line in %s \"%s\"\n",
748 skip_non_whitespace(s, ch);
752 skip_whitespace(s, ch);
754 g_printf(_("strange log line in %s \"%s\"\n"),
759 skip_quoted_string(s, ch);
762 disk = unquote_string(qdisk);
764 skip_whitespace(s, ch);
766 g_printf(_("strange log line in %s \"%s\"\n"),
771 skip_non_whitespace(s, ch);
775 if(strlen(date) < 3) { /* old log didn't have datestamp */
777 date = stralloc(datestamp);
779 if (curlog == L_CHUNK || curlog == L_PART ||
780 curlog == L_PARTPARTIAL || curlog == L_DONE){
781 skip_whitespace(s, ch);
783 skip_non_whitespace(s, ch);
784 partnum_undo = s - 1;
785 *partnum_undo = '\0';
787 skip_whitespace(s, ch);
788 if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
789 g_printf(_("strange log line in %s \"%s\"\n"),
796 skip_whitespace(s, ch);
798 g_printf(_("strange log line in %s \"%s\"\n"),
803 if((s = strchr(s, '\n')) != NULL) {
807 /* extract sec, kb, kps from 'rest', if present. This isn't the stone age
808 * anymore, so we'll just do it the easy way (a regex) */
809 bzero(®ex, sizeof(regex));
810 reg_result = regcomp(®ex,
811 "\\[sec ([0-9.]+) kb ([0-9]+) kps [0-9.]+\\]", REG_EXTENDED);
812 if (reg_result != 0) {
813 error("Error compiling regular expression for parsing log lines");
817 /* an error here just means the line wasn't found -- not fatal. */
818 reg_result = regexec(®ex, rest, sizeof(pmatch)/sizeof(*pmatch), pmatch, 0);
819 if (reg_result == 0) {
822 str = find_regex_substring(rest, pmatch[1]);
826 str = find_regex_substring(rest, pmatch[2]);
827 kb = OFF_T_ATOI(str);
835 dp = lookup_disk(host,disk);
837 if (dynamic_disklist == NULL) {
840 dp = add_disk(dynamic_disklist, host, disk);
841 enqueue_disk(dynamic_disklist, dp);
843 if (find_match(host, disk)) {
844 if(curprog == P_TAPER) {
845 find_result_t *new_output_find = g_new0(find_result_t, 1);
846 new_output_find->timestamp = stralloc(date);
847 new_output_find->hostname=stralloc(host);
848 new_output_find->diskname=stralloc(disk);
849 new_output_find->level=level;
850 new_output_find->partnum = stralloc(partnum);
851 new_output_find->label=stralloc(current_label);
852 new_output_find->status=NULL;
853 new_output_find->filenum=filenum;
854 new_output_find->sec=sec;
855 new_output_find->kb=kb;
856 new_output_find->next=NULL;
857 if (curlog == L_SUCCESS) {
858 new_output_find->status = stralloc("OK");
859 new_output_find->next = *output_find;
860 *output_find = new_output_find;
861 found_something = TRUE;
862 } else if (curlog == L_CHUNKSUCCESS || curlog == L_DONE ||
863 curlog == L_PARTIAL || curlog == L_FAIL) {
865 if (curlog == L_PARTIAL || curlog == L_FAIL) {
866 /* change status of each part */
867 for (a_part_find = part_find; a_part_find;
868 a_part_find = a_part_find->next) {
869 if (curlog == L_PARTIAL)
870 a_part_find->status = stralloc("PARTIAL");
872 a_part_find->status = stralloc(rest);
875 if (part_find) { /* find last element */
876 for (a_part_find = part_find;
877 a_part_find->next != NULL;
878 a_part_find=a_part_find->next) {
880 /* merge part_find to *output_find */
881 a_part_find->next = *output_find;
882 *output_find = part_find;
884 found_something = TRUE;
886 free_find_result(&new_output_find);
887 } else { /* part line */
888 if (curlog == L_PART || curlog == L_CHUNK)
889 new_output_find->status=stralloc("OK");
890 else /* PARTPARTIAL */
891 new_output_find->status=stralloc("PARTIAL");
892 /* Add to part_find list */
893 new_output_find->next = part_find;
894 part_find = new_output_find;
895 found_something = TRUE;
898 else if(curlog == L_FAIL) {
899 /* print other failures too -- this is a hack to ensure that failures which
900 * did not make it to tape are also listed in the output of 'amadmin x find';
901 * users that do not want this information (e.g., Amanda::DB::Catalog) should
902 * filter dumps with a NULL label. */
903 find_result_t *new_output_find = g_new0(find_result_t, 1);
904 new_output_find->next=*output_find;
905 new_output_find->timestamp = stralloc(date);
906 new_output_find->hostname=stralloc(host);
907 new_output_find->diskname=stralloc(disk);
908 new_output_find->level=level;
909 new_output_find->label=NULL;
910 new_output_find->partnum=stralloc(partnum);
911 new_output_find->filenum=0;
912 new_output_find->sec=sec;
913 new_output_find->kb=kb;
914 new_output_find->status=vstralloc(
916 program_str[(int)curprog],
920 *output_find=new_output_find;
921 found_something = TRUE;
928 if (part_find != NULL) {
930 /* parse log file until PARTIAL/DONE/SUCCESS/FAIL from taper */
931 while(get_logline(logf)) {
932 if (curprog == P_TAPER &&
933 (curlog == L_DONE || curlog == L_SUCCESS ||
934 curlog == L_PARTIAL || curlog == L_FAIL)) {
939 for (a_part_find = part_find; a_part_find;
940 a_part_find = a_part_find->next) {
941 if (curlog == L_PARTIAL)
942 a_part_find->status = stralloc("PARTIAL");
943 else if (curlog == L_FAIL)
944 a_part_find->status = stralloc("FAIL");
946 for (a_part_find = part_find;
947 a_part_find->next != NULL;
948 a_part_find=a_part_find->next) {
950 /* merge part_find to *output_find */
951 a_part_find->next = *output_find;
952 *output_find = part_find;
958 amfree(current_label);
960 return found_something;
965 * Return the set of dumps that match *all* of the given patterns (we consider
966 * an empty pattern to match .*, though). If 'ok' is true, will only match
967 * dumps with SUCCESS status.
969 * Returns a newly allocated list of results, where all strings are also newly
970 * allocated. Apparently some part of Amanda leaks under this condition.
974 find_result_t *output_find,
981 find_result_t *cur_result;
982 find_result_t *matches = NULL;
984 for(cur_result=output_find;
986 cur_result=cur_result->next) {
987 char level_str[NUM_STR_SIZE];
988 g_snprintf(level_str, SIZEOF(level_str), "%d", cur_result->level);
989 if((!hostname || *hostname == '\0' || match_host(hostname, cur_result->hostname)) &&
990 (!diskname || *diskname == '\0' || match_disk(diskname, cur_result->diskname)) &&
991 (!datestamp || *datestamp== '\0' || match_datestamp(datestamp, cur_result->timestamp)) &&
992 (!level || *level== '\0' || match_level(level, level_str)) &&
993 (!ok || !strcmp(cur_result->status, "OK"))){
995 find_result_t *curmatch = g_new0(find_result_t, 1);
996 memcpy(curmatch, cur_result, SIZEOF(find_result_t));
998 curmatch->timestamp = stralloc(cur_result->timestamp);
999 curmatch->hostname = stralloc(cur_result->hostname);
1000 curmatch->diskname = stralloc(cur_result->diskname);
1001 curmatch->level = cur_result->level;
1002 curmatch->label = cur_result->label? stralloc(cur_result->label) : NULL;
1003 curmatch->filenum = cur_result->filenum;
1004 curmatch->sec = cur_result->sec;
1005 curmatch->kb = cur_result->kb;
1006 curmatch->status = stralloc(cur_result->status);
1007 curmatch->partnum = stralloc(cur_result->partnum);
1009 curmatch->next = matches;
1018 * Return the set of dumps that match one or more of the given dumpspecs,
1019 * If 'ok' is true, only dumps with a SUCCESS status will be matched.
1021 * Returns a newly allocated list of results, where all strings are also newly
1022 * allocated. Apparently some part of Amanda leaks under this condition.
1025 dumps_match_dumpspecs(
1026 find_result_t *output_find,
1030 find_result_t *cur_result;
1031 find_result_t *matches = NULL;
1035 for(cur_result=output_find;
1037 cur_result=cur_result->next) {
1038 char level_str[NUM_STR_SIZE];
1039 g_snprintf(level_str, SIZEOF(level_str), "%d", cur_result->level);
1040 for (dumpspec = dumpspecs; dumpspec; dumpspec = dumpspec->next) {
1041 ds = (dumpspec_t *)dumpspec->data;
1042 if((!ds->host || *ds->host == '\0' || match_host(ds->host, cur_result->hostname)) &&
1043 (!ds->disk || *ds->disk == '\0' || match_disk(ds->disk, cur_result->diskname)) &&
1044 (!ds->datestamp || *ds->datestamp== '\0' || match_datestamp(ds->datestamp, cur_result->timestamp)) &&
1045 (!ds->level || *ds->level== '\0' || match_level(ds->level, level_str)) &&
1046 (!ok || !strcmp(cur_result->status, "OK"))){
1048 find_result_t *curmatch = alloc(SIZEOF(find_result_t));
1049 memcpy(curmatch, cur_result, SIZEOF(find_result_t));
1051 curmatch->timestamp = stralloc(cur_result->timestamp);
1052 curmatch->hostname = stralloc(cur_result->hostname);
1053 curmatch->diskname = stralloc(cur_result->diskname);
1054 curmatch->level = cur_result->level;
1055 curmatch->label = cur_result->label? stralloc(cur_result->label) : NULL;
1056 curmatch->filenum = cur_result->filenum;
1057 curmatch->status = stralloc(cur_result->status);
1058 curmatch->partnum = stralloc(cur_result->partnum);
1060 curmatch->next = matches;
1072 find_result_t *output_find,
1078 find_result_t *output_find_result;
1080 for(output_find_result=output_find;
1082 output_find_result=output_find_result->next) {
1083 if( !strcmp(output_find_result->hostname, hostname) &&
1084 !strcmp(output_find_result->diskname, diskname) &&
1085 !strcmp(output_find_result->timestamp, datestamp) &&
1086 output_find_result->level == level) {
1088 return output_find_result;