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
40 int find_match(char *host, char *disk);
41 void search_holding_disk(find_result_t **output_find);
42 char *find_nicedate(char *datestamp);
43 static int find_compare(const void *, const void *);
44 static int parse_taper_datestamp_log(char *logline, char **datestamp, char **level);
45 static gboolean logfile_has_tape(char * label, char * datestamp,
48 static char *find_sort_order = NULL;
50 find_result_t * find_dump(disklist_t* diskqp) {
51 char *conf_logdir, *logfile = NULL;
52 int tape, maxtape, logs;
55 find_result_t *output_find = NULL;
57 conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR));
58 maxtape = lookup_nb_tape();
60 for(tape = 1; tape <= maxtape; tape++) {
62 tp = lookup_tapepos(tape);
63 if(tp == NULL) continue;
65 /* search log files */
69 /* new-style log.<date>.<seq> */
71 for(seq = 0; 1; seq++) {
72 char seq_str[NUM_STR_SIZE];
74 g_snprintf(seq_str, SIZEOF(seq_str), "%u", seq);
75 logfile = newvstralloc(logfile,
76 conf_logdir, "/log.", tp->datestamp, ".", seq_str, NULL);
77 if(access(logfile, R_OK) != 0) break;
78 if (search_logfile(&output_find, tp->label, tp->datestamp,
84 /* search old-style amflush log, if any */
86 logfile = newvstralloc(logfile, conf_logdir, "/log.",
87 tp->datestamp, ".amflush", NULL);
88 if(access(logfile,R_OK) == 0) {
89 if (search_logfile(&output_find, tp->label, tp->datestamp,
95 /* search old-style main log, if any */
97 logfile = newvstralloc(logfile, conf_logdir, "/log.", tp->datestamp,
99 if(access(logfile,R_OK) == 0) {
100 if (search_logfile(&output_find, tp->label, tp->datestamp,
105 if(logs == 0 && strcmp(tp->datestamp,"0") != 0)
107 _("Warning: no log files found for tape %s written %s\n"),
108 tp->label, find_nicedate(tp->datestamp));
113 search_holding_disk(&output_find);
121 char *conf_logdir, *logfile = NULL;
122 char *pathlogfile = NULL;
123 int tape, maxtape, logs;
126 char **output_find_log = NULL;
129 conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR));
130 maxtape = lookup_nb_tape();
132 output_find_log = alloc((maxtape*5+10) * SIZEOF(char *));
133 current_log = output_find_log;
135 for(tape = 1; tape <= maxtape; tape++) {
137 tp = lookup_tapepos(tape);
138 if(tp == NULL) continue;
140 /* search log files */
144 /* new-style log.<date>.<seq> */
146 for(seq = 0; 1; seq++) {
147 char seq_str[NUM_STR_SIZE];
149 g_snprintf(seq_str, SIZEOF(seq_str), "%u", seq);
150 logfile = newvstralloc(logfile, "log.", tp->datestamp, ".", seq_str, NULL);
151 pathlogfile = newvstralloc(pathlogfile, conf_logdir, "/", logfile, NULL);
152 if (access(pathlogfile, R_OK) != 0) break;
153 if (logfile_has_tape(tp->label, tp->datestamp, pathlogfile)) {
154 if (current_log == output_find_log || strcmp(*(current_log-1), logfile)) {
155 *current_log = stralloc(logfile);
163 /* search old-style amflush log, if any */
165 logfile = newvstralloc(logfile, "log.", tp->datestamp, ".amflush", NULL);
166 pathlogfile = newvstralloc(pathlogfile, conf_logdir, "/", logfile, NULL);
167 if (access(pathlogfile, R_OK) == 0) {
168 if (logfile_has_tape(tp->label, tp->datestamp, pathlogfile)) {
169 if (current_log == output_find_log || strcmp(*(current_log-1), logfile)) {
170 *current_log = stralloc(logfile);
177 /* search old-style main log, if any */
179 logfile = newvstralloc(logfile, "log.", tp->datestamp, NULL);
180 pathlogfile = newvstralloc(pathlogfile, conf_logdir, "/", logfile, NULL);
181 if (access(pathlogfile, R_OK) == 0) {
182 if (logfile_has_tape(tp->label, tp->datestamp, pathlogfile)) {
183 if (current_log == output_find_log || strcmp(*(current_log-1), logfile)) {
184 *current_log = stralloc(logfile);
191 if(logs == 0 && strcmp(tp->datestamp,"0") != 0)
192 g_fprintf(stderr, _("Warning: no log files found for tape %s written %s\n"),
193 tp->label, find_nicedate(tp->datestamp));
199 return(output_find_log);
204 find_result_t **output_find)
206 GSList *holding_file_list;
212 holding_file_list = holding_get_files(NULL, 1);
214 for(e = holding_file_list; e != NULL; e = e->next) {
215 holding_file = (char *)e->data;
217 if (!holding_file_get_dumpfile(holding_file, &file))
220 if (file.dumplevel < 0 || file.dumplevel > 9)
226 if((dp = lookup_disk(file.name, file.disk)))
228 if((s = strrchr(file.name,'.')) == NULL)
236 if(find_match(file.name,file.disk)) {
237 find_result_t *new_output_find =
238 alloc(SIZEOF(find_result_t));
239 new_output_find->next=*output_find;
240 new_output_find->timestamp = stralloc(file.datestamp);
241 new_output_find->hostname = stralloc(file.name);
242 new_output_find->diskname = stralloc(file.disk);
243 new_output_find->level=file.dumplevel;
244 new_output_find->label=stralloc(holding_file);
245 new_output_find->partnum=stralloc("--");
246 new_output_find->filenum=0;
247 new_output_find->status=stralloc("OK");
248 *output_find=new_output_find;
252 g_slist_free_full(holding_file_list);
261 find_result_t *i, *j;
263 size_t nb_compare=strlen(find_sort_order);
266 for(k=0;k<nb_compare;k++) {
267 char sort_key = find_sort_order[k];
268 if (isupper((int)sort_key)) {
270 sort_key = tolower(sort_key);
271 j = *(find_result_t **)i1;
272 i = *(find_result_t **)j1;
274 i = *(find_result_t **)i1;
275 j = *(find_result_t **)j1;
279 case 'h' : compare=strcmp(i->hostname,j->hostname);
281 case 'k' : compare=strcmp(i->diskname,j->diskname);
283 case 'd' : compare=strcmp(i->timestamp,j->timestamp);
285 case 'l' : compare=j->level - i->level;
287 case 'f' : compare=(i->filenum == j->filenum) ? 0 :
288 ((i->filenum < j->filenum) ? -1 : 1);
290 case 'b' : compare=compare_possibly_null_strings(i->label,
294 if(strcmp(i->partnum, "--") != 0 &&
295 strcmp(j->partnum, "--") != 0){
296 compare = atoi(i->partnum) - atoi(j->partnum);
298 else compare=strcmp(i->partnum,j->partnum);
310 find_result_t **output_find)
312 find_result_t *output_find_result;
313 find_result_t **array_find_result = NULL;
317 find_sort_order = sort_order;
318 /* qsort core dump if nothing to sort */
319 if(*output_find==NULL)
322 /* How many result */
323 for(output_find_result=*output_find;
325 output_find_result=output_find_result->next) {
329 /* put the list in an array */
330 array_find_result=alloc(nb_result * SIZEOF(find_result_t *));
331 for(output_find_result=*output_find,no_result=0;
333 output_find_result=output_find_result->next,no_result++) {
334 array_find_result[no_result]=output_find_result;
338 qsort(array_find_result,nb_result,SIZEOF(find_result_t *),
341 /* put the sorted result in the list */
343 no_result<nb_result-1; no_result++) {
344 array_find_result[no_result]->next = array_find_result[no_result+1];
346 array_find_result[nb_result-1]->next=NULL;
347 *output_find=array_find_result[0];
348 amfree(array_find_result);
353 find_result_t *output_find)
355 find_result_t *output_find_result;
356 int max_len_datestamp = 4;
357 int max_len_hostname = 4;
358 int max_len_diskname = 4;
359 int max_len_level = 2;
360 int max_len_label =12;
361 int max_len_filenum = 4;
362 int max_len_part = 4;
363 int max_len_status = 6;
366 for(output_find_result=output_find;
368 output_find_result=output_find_result->next) {
371 len=strlen(find_nicedate(output_find_result->timestamp));
372 if((int)len > max_len_datestamp)
373 max_len_datestamp=(int)len;
375 len=strlen(output_find_result->hostname);
376 if((int)len > max_len_hostname)
377 max_len_hostname = (int)len;
379 qdiskname=quote_string(output_find_result->diskname);
380 len=strlen(qdiskname);
382 if((int)len > max_len_diskname)
383 max_len_diskname = (int)len;
385 if (output_find_result->label != NULL) {
386 len=strlen(output_find_result->label);
387 if((int)len > max_len_label)
388 max_len_label = (int)len;
391 len=strlen(output_find_result->status);
392 if((int)len > max_len_status)
393 max_len_status = (int)len;
395 len=strlen(output_find_result->partnum);
396 if((int)len > max_len_part)
397 max_len_part = (int)len;
401 * Since status is the rightmost field, we zap the maximum length
402 * because it is not needed. The code is left in place in case
403 * another column is added later.
407 if(output_find==NULL) {
408 g_printf(_("\nNo dump to list\n"));
411 g_printf(_("\ndate%*s host%*s disk%*s lv%*s tape or file%*s file%*s part%*s status\n"),
412 max_len_datestamp-4,"",
413 max_len_hostname-4 ,"",
414 max_len_diskname-4 ,"",
416 max_len_label-12 ,"",
417 max_len_filenum-4 ,"",
419 for(output_find_result=output_find;
421 output_find_result=output_find_result->next) {
423 char * formatted_label;
425 qdiskname = quote_string(output_find_result->diskname);
426 formatted_label = output_find_result->label;
427 if (formatted_label == NULL)
428 formatted_label = "";
430 g_printf("%-*s %-*s %-*s %*d %-*s %*lld %*s %-*s\n",
432 find_nicedate(output_find_result->timestamp),
433 max_len_hostname, output_find_result->hostname,
434 max_len_diskname, qdiskname,
435 max_len_level, output_find_result->level,
436 max_len_label, formatted_label,
437 max_len_filenum, (long long)output_find_result->filenum,
438 max_len_part, output_find_result->partnum,
439 max_len_status, output_find_result->status
449 find_result_t **output_find)
451 find_result_t *output_find_result, *prev;
454 for(output_find_result=*output_find;
456 output_find_result=output_find_result->next) {
458 amfree(output_find_result->timestamp);
459 amfree(output_find_result->hostname);
460 amfree(output_find_result->diskname);
461 amfree(output_find_result->label);
462 amfree(output_find_result->partnum);
463 amfree(output_find_result->status);
464 amfree(output_find_result->timestamp);
465 prev = output_find_result;
476 disk_t *dp = lookup_disk(host,disk);
477 return (dp && dp->todo);
484 static char nice[20];
485 int year, month, day;
486 int hours, minutes, seconds;
487 char date[9], atime[7];
488 int numdate, numtime;
490 strncpy(date, datestamp, 8);
492 numdate = atoi(date);
493 year = numdate / 10000;
494 month = (numdate / 100) % 100;
497 if(strlen(datestamp) <= 8) {
498 g_snprintf(nice, SIZEOF(nice), "%4d-%02d-%02d",
502 strncpy(atime, &(datestamp[8]), 6);
504 numtime = atoi(atime);
505 hours = numtime / 10000;
506 minutes = (numtime / 100) % 100;
507 seconds = numtime % 100;
509 g_snprintf(nice, SIZEOF(nice), "%4d-%02d-%02d %02d:%02d:%02d",
510 year, month, day, hours, minutes, seconds);
517 parse_taper_datestamp_log(
528 skip_whitespace(s, ch);
532 if(strncmp_const_skip(s - 1, "datestamp", s, ch) != 0) {
536 skip_whitespace(s, ch);
541 skip_non_whitespace(s, ch);
544 skip_whitespace(s, ch);
548 if(strncmp_const_skip(s - 1, "label", s, ch) != 0) {
552 skip_whitespace(s, ch);
557 skip_non_whitespace(s, ch);
563 /* Returns TRUE if the given logfile mentions the given tape. */
564 static gboolean logfile_has_tape(char * label, char * datestamp,
567 char * ck_datestamp, *ck_label;
568 if((logf = fopen(logfile, "r")) == NULL) {
569 error(_("could not open logfile %s: %s"), logfile, strerror(errno));
573 while(get_logline(logf)) {
574 if(curlog == L_START && curprog == P_TAPER) {
575 if(parse_taper_datestamp_log(curstr,
576 &ck_datestamp, &ck_label) == 0) {
577 g_printf(_("strange log line \"start taper %s\" curstr='%s'\n"),
579 } else if(strcmp(ck_datestamp, datestamp) == 0
580 && strcmp(ck_label, label) == 0) {
591 /* Like (strcmp(label1, label2) == 0), except that NULL values force TRUE. */
592 static gboolean volume_matches(const char * label1, const char * label2) {
593 return (label1 == NULL || label2 == NULL || strcmp(label1, label2) == 0);
596 /* WARNING: Function accesses globals find_diskqp, curlog, curlog, curstr,
597 * dynamic_disklist */
600 find_result_t **output_find,
602 const char *passed_datestamp,
604 disklist_t * dynamic_disklist)
607 char *host, *host_undo;
608 char *disk, *qdisk, *disk_undo;
609 char *date, *date_undo;
610 char *partnum=NULL, *partnum_undo;
613 char *current_label = NULL;
618 char *ck_datestamp, *datestamp;
622 find_result_t *part_find = NULL; /* List for all part of a DLE */
623 find_result_t *a_part_find;
624 gboolean right_label = FALSE;
625 gboolean found_something = FALSE;
627 g_return_val_if_fail(output_find != NULL, 0);
628 g_return_val_if_fail(logfile != NULL, 0);
630 datestamp = g_strdup(passed_datestamp);
632 if((logf = fopen(logfile, "r")) == NULL) {
633 error(_("could not open logfile %s: %s"), logfile, strerror(errno));
638 while(get_logline(logf)) {
639 if (curlog == L_START && curprog == P_TAPER) {
640 if(parse_taper_datestamp_log(curstr, &ck_datestamp,
642 g_printf(_("strange log line in %s \"start taper %s\"\n"),
646 if (datestamp != NULL) {
647 if (strcmp(datestamp, ck_datestamp) != 0) {
648 g_printf(_("Log file %s stamped %s, expecting %s!\n"),
649 logfile, ck_datestamp, datestamp);
654 right_label = volume_matches(label, ck_label);
655 if (label && datestamp && right_label) {
656 found_something = TRUE;
658 amfree(current_label);
659 current_label = g_strdup(ck_label);
660 if (datestamp == NULL) {
661 datestamp = g_strdup(ck_datestamp);
667 if ((curlog == L_SUCCESS ||
668 curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTPARTIAL) &&
669 curprog == P_TAPER) {
673 if (curlog == L_SUCCESS || curlog == L_CHUNKSUCCESS ||
674 curlog == L_DONE || curlog == L_FAIL ||
675 curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTIAL ||
676 curlog == L_PARTPARTIAL ) {
680 skip_whitespace(s, ch);
682 g_printf(_("strange log line in %s \"%s\"\n"),
687 if (curlog == L_PART || curlog == L_PARTPARTIAL) {
688 char * part_label = s - 1;
689 skip_non_whitespace(s, ch);
692 if (strcmp(current_label, part_label) != 0) {
693 g_printf("PART label %s doesn't match START label %s\n",
694 part_label, current_label);
697 skip_whitespace(s, ch);
699 g_printf("strange log line in %s \"%s\"\n",
705 skip_non_whitespace(s, ch);
707 fileno = atoi(number);
710 skip_whitespace(s, ch);
712 g_printf("strange log line in %s \"%s\"\n",
719 skip_non_whitespace(s, ch);
723 skip_whitespace(s, ch);
725 g_printf(_("strange log line in %s \"%s\"\n"),
730 skip_quoted_string(s, ch);
733 disk = unquote_string(qdisk);
735 skip_whitespace(s, ch);
737 g_printf(_("strange log line in %s \"%s\"\n"),
742 skip_non_whitespace(s, ch);
746 if(strlen(date) < 3) { /* old log didn't have datestamp */
748 date = stralloc(datestamp);
750 if (curlog == L_CHUNK || curlog == L_PART ||
751 curlog == L_PARTPARTIAL || curlog == L_DONE){
752 skip_whitespace(s, ch);
754 skip_non_whitespace(s, ch);
755 partnum_undo = s - 1;
756 *partnum_undo = '\0';
758 skip_whitespace(s, ch);
759 if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
760 g_printf(_("strange log line in %s \"%s\"\n"),
767 skip_whitespace(s, ch);
769 g_printf(_("strange log line in %s \"%s\"\n"),
774 if((s = strchr(s, '\n')) != NULL) {
778 dp = lookup_disk(host,disk);
780 if (dynamic_disklist == NULL) {
783 dp = add_disk(dynamic_disklist, host, disk);
784 enqueue_disk(dynamic_disklist, dp);
786 if (find_match(host, disk)) {
787 if(curprog == P_TAPER) {
788 find_result_t *new_output_find =
789 (find_result_t *)alloc(SIZEOF(find_result_t));
790 new_output_find->timestamp = stralloc(date);
791 new_output_find->hostname=stralloc(host);
792 new_output_find->diskname=stralloc(disk);
793 new_output_find->level=level;
794 new_output_find->partnum = stralloc(partnum);
795 new_output_find->label=stralloc(current_label);
796 new_output_find->status=NULL;
797 new_output_find->filenum=filenum;
798 new_output_find->next=NULL;
799 if (curlog == L_SUCCESS) {
800 new_output_find->status = stralloc("OK");
801 new_output_find->next = *output_find;
802 *output_find = new_output_find;
803 found_something = TRUE;
804 } else if (curlog == L_CHUNKSUCCESS || curlog == L_DONE ||
805 curlog == L_PARTIAL || curlog == L_FAIL) {
807 if (curlog == L_PARTIAL || curlog == L_FAIL) {
808 /* change status of each part */
809 for (a_part_find = part_find; a_part_find;
810 a_part_find = a_part_find->next) {
811 if (curlog == L_PARTIAL)
812 a_part_find->status = stralloc("PARTIAL");
814 a_part_find->status = stralloc(rest);
817 if (part_find) { /* find last element */
818 for (a_part_find = part_find;
819 a_part_find->next != NULL;
820 a_part_find=a_part_find->next) {
822 /* merge part_find to *output_find */
823 a_part_find->next = *output_find;
824 *output_find = part_find;
826 found_something = TRUE;
828 free_find_result(&new_output_find);
829 } else { /* part line */
830 if (curlog == L_PART || curlog == L_CHUNK)
831 new_output_find->status=stralloc("OK");
832 else /* PARTPARTIAL */
833 new_output_find->status=stralloc("PARTIAL");
834 /* Add to part_find list */
835 new_output_find->next = part_find;
836 part_find = new_output_find;
837 found_something = TRUE;
840 else if(curlog == L_FAIL) { /* print other failures too */
841 find_result_t *new_output_find =
842 (find_result_t *)alloc(SIZEOF(find_result_t));
843 new_output_find->next=*output_find;
844 new_output_find->timestamp = stralloc(date);
845 new_output_find->hostname=stralloc(host);
846 new_output_find->diskname=stralloc(disk);
847 new_output_find->level=level;
848 new_output_find->label=NULL;
849 new_output_find->partnum=stralloc(partnum);
850 new_output_find->filenum=0;
851 new_output_find->status=vstralloc(
853 program_str[(int)curprog],
857 *output_find=new_output_find;
858 found_something = TRUE;
865 if (part_find != NULL) {
867 /* parse log file until PARTIAL/DONE/SUCCESS/FAIL from taper */
868 while(get_logline(logf)) {
869 if (curprog == P_TAPER &&
870 (curlog == L_DONE || curlog == L_SUCCESS ||
871 curlog == L_PARTIAL || curlog == L_FAIL)) {
876 for (a_part_find = part_find; a_part_find;
877 a_part_find = a_part_find->next) {
878 if (curlog == L_PARTIAL)
879 a_part_find->status = stralloc("PARTIAL");
880 else if (curlog == L_FAIL)
881 a_part_find->status = stralloc("FAIL");
883 for (a_part_find = part_find;
884 a_part_find->next != NULL;
885 a_part_find=a_part_find->next) {
887 /* merge part_find to *output_find */
888 a_part_find->next = *output_find;
889 *output_find = part_find;
895 amfree(current_label);
897 return found_something;
902 * Return the set of dumps that match *all* of the given patterns (we consider
903 * an empty pattern to match .*, though). If 'ok' is true, will only match
904 * dumps with SUCCESS status.
906 * Returns a newly allocated list of results, where all strings are also newly
907 * allocated. Apparently some part of Amanda leaks under this condition.
911 find_result_t *output_find,
918 find_result_t *cur_result;
919 find_result_t *matches = NULL;
921 for(cur_result=output_find;
923 cur_result=cur_result->next) {
924 char level_str[NUM_STR_SIZE];
925 g_snprintf(level_str, SIZEOF(level_str), "%d", cur_result->level);
926 if((!hostname || *hostname == '\0' || match_host(hostname, cur_result->hostname)) &&
927 (!diskname || *diskname == '\0' || match_disk(diskname, cur_result->diskname)) &&
928 (!datestamp || *datestamp== '\0' || match_datestamp(datestamp, cur_result->timestamp)) &&
929 (!level || *level== '\0' || match_level(level, level_str)) &&
930 (!ok || !strcmp(cur_result->status, "OK"))){
932 find_result_t *curmatch = alloc(SIZEOF(find_result_t));
933 memcpy(curmatch, cur_result, SIZEOF(find_result_t));
935 curmatch->timestamp = stralloc(cur_result->timestamp);
936 curmatch->hostname = stralloc(cur_result->hostname);
937 curmatch->diskname = stralloc(cur_result->diskname);
938 curmatch->level = cur_result->level;
939 curmatch->label = stralloc(cur_result->label);
940 curmatch->filenum = cur_result->filenum;
941 curmatch->status = stralloc(cur_result->status);
942 curmatch->partnum = stralloc(cur_result->partnum);
944 curmatch->next = matches;
953 * Return the set of dumps that match one or more of the given dumpspecs,
954 * If 'ok' is true, only dumps with a SUCCESS status will be matched.
956 * Returns a newly allocated list of results, where all strings are also newly
957 * allocated. Apparently some part of Amanda leaks under this condition.
960 dumps_match_dumpspecs(
961 find_result_t *output_find,
965 find_result_t *cur_result;
966 find_result_t *matches = NULL;
970 for(cur_result=output_find;
972 cur_result=cur_result->next) {
973 char level_str[NUM_STR_SIZE];
974 g_snprintf(level_str, SIZEOF(level_str), "%d", cur_result->level);
975 for (dumpspec = dumpspecs; dumpspec; dumpspec = dumpspec->next) {
976 ds = (dumpspec_t *)dumpspec->data;
977 if((!ds->host || *ds->host == '\0' || match_host(ds->host, cur_result->hostname)) &&
978 (!ds->disk || *ds->disk == '\0' || match_disk(ds->disk, cur_result->diskname)) &&
979 (!ds->datestamp || *ds->datestamp== '\0' || match_datestamp(ds->datestamp, cur_result->timestamp)) &&
980 (!ds->level || *ds->level== '\0' || match_level(ds->level, level_str)) &&
981 (!ok || !strcmp(cur_result->status, "OK"))){
983 find_result_t *curmatch = alloc(SIZEOF(find_result_t));
984 memcpy(curmatch, cur_result, SIZEOF(find_result_t));
986 curmatch->timestamp = stralloc(cur_result->timestamp);
987 curmatch->hostname = stralloc(cur_result->hostname);
988 curmatch->diskname = stralloc(cur_result->diskname);
989 curmatch->level = cur_result->level;
990 curmatch->label = stralloc(cur_result->label);
991 curmatch->filenum = cur_result->filenum;
992 curmatch->status = stralloc(cur_result->status);
993 curmatch->partnum = stralloc(cur_result->partnum);
995 curmatch->next = matches;
1007 find_result_t *output_find,
1013 find_result_t *output_find_result;
1015 for(output_find_result=output_find;
1017 output_find_result=output_find_result->next) {
1018 if( !strcmp(output_find_result->hostname, hostname) &&
1019 !strcmp(output_find_result->diskname, diskname) &&
1020 !strcmp(output_find_result->timestamp, datestamp) &&
1021 output_find_result->level == level) {
1023 return output_find_result;