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
42 int find_match(char *host, char *disk);
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, tape1, maxtape, logs;
56 find_result_t *output_find = NULL;
57 gboolean *tape_seen = NULL;
60 conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR));
61 maxtape = lookup_nb_tape();
62 tape_seen = g_new0(gboolean, maxtape+1);
64 for(tape = 1; tape <= maxtape; tape++) {
66 if (tape_seen[tape] == 1)
68 tp = lookup_tapepos(tape);
69 if(tp == NULL) continue;
71 /* find all tape with the same datestamp
72 add them to label_list */
74 for (tape1 = tape; tape1 <= maxtape; tape1++) {
75 tp1 = lookup_tapepos(tape1);
76 if (tp1 == NULL) continue;
77 if (strcmp(tp->datestamp, tp1->datestamp) != 0)
81 label_list = g_slist_append(label_list, tp1->label);
84 /* search log files */
88 /* new-style log.<date>.<seq> */
90 for(seq = 0; 1; seq++) {
91 char seq_str[NUM_STR_SIZE];
93 g_snprintf(seq_str, SIZEOF(seq_str), "%u", seq);
94 logfile = newvstralloc(logfile,
95 conf_logdir, "/log.", tp->datestamp, ".", seq_str, NULL);
96 if(access(logfile, R_OK) != 0) break;
97 if (search_logfile(&output_find, NULL, tp->datestamp,
103 /* search old-style amflush log, if any */
105 logfile = newvstralloc(logfile, conf_logdir, "/log.",
106 tp->datestamp, ".amflush", NULL);
107 if(access(logfile,R_OK) == 0) {
108 if (search_logfile(&output_find, NULL, tp->datestamp,
114 /* search old-style main log, if any */
116 logfile = newvstralloc(logfile, conf_logdir, "/log.", tp->datestamp,
118 if(access(logfile,R_OK) == 0) {
119 if (search_logfile(&output_find, NULL, tp->datestamp,
124 if (logs == 0 && strcmp(tp->datestamp,"0") != 0) {
126 for (l_label = label_list; l_label != NULL ; l_label = l_label->next) {
128 _("Warning: no log files found for tape %s written %s\n"),
129 (char *)l_label->data, find_nicedate(tp->datestamp));
132 g_slist_free(label_list);
138 search_holding_disk(&output_find, diskqp);
146 char *conf_logdir, *logfile = NULL;
147 char *pathlogfile = NULL;
148 int tape, maxtape, logs;
151 char **output_find_log = NULL;
154 conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR));
155 maxtape = lookup_nb_tape();
157 output_find_log = alloc((maxtape*5+10) * SIZEOF(char *));
158 current_log = output_find_log;
160 for(tape = 1; tape <= maxtape; tape++) {
162 tp = lookup_tapepos(tape);
163 if(tp == NULL) continue;
165 /* search log files */
169 /* new-style log.<date>.<seq> */
171 for(seq = 0; 1; seq++) {
172 char seq_str[NUM_STR_SIZE];
174 g_snprintf(seq_str, SIZEOF(seq_str), "%u", seq);
175 logfile = newvstralloc(logfile, "log.", tp->datestamp, ".", seq_str, NULL);
176 pathlogfile = newvstralloc(pathlogfile, conf_logdir, "/", logfile, NULL);
177 if (access(pathlogfile, R_OK) != 0) break;
178 if (logfile_has_tape(tp->label, tp->datestamp, pathlogfile)) {
179 if (current_log == output_find_log || strcmp(*(current_log-1), logfile)) {
180 *current_log = stralloc(logfile);
188 /* search old-style amflush log, if any */
190 logfile = newvstralloc(logfile, "log.", tp->datestamp, ".amflush", NULL);
191 pathlogfile = newvstralloc(pathlogfile, conf_logdir, "/", logfile, NULL);
192 if (access(pathlogfile, R_OK) == 0) {
193 if (logfile_has_tape(tp->label, tp->datestamp, pathlogfile)) {
194 if (current_log == output_find_log || strcmp(*(current_log-1), logfile)) {
195 *current_log = stralloc(logfile);
202 /* search old-style main log, if any */
204 logfile = newvstralloc(logfile, "log.", tp->datestamp, NULL);
205 pathlogfile = newvstralloc(pathlogfile, conf_logdir, "/", logfile, NULL);
206 if (access(pathlogfile, R_OK) == 0) {
207 if (logfile_has_tape(tp->label, tp->datestamp, pathlogfile)) {
208 if (current_log == output_find_log || strcmp(*(current_log-1), logfile)) {
209 *current_log = stralloc(logfile);
216 if(logs == 0 && strcmp(tp->datestamp,"0") != 0)
217 g_fprintf(stderr, _("Warning: no log files found for tape %s written %s\n"),
218 tp->label, find_nicedate(tp->datestamp));
224 return(output_find_log);
229 find_result_t **output_find,
230 disklist_t * dynamic_disklist)
232 GSList *holding_file_list;
238 holding_file_list = holding_get_files(NULL, 1);
240 for(e = holding_file_list; e != NULL; e = e->next) {
243 holding_file = (char *)e->data;
245 if (!holding_file_get_dumpfile(holding_file, &file))
248 if (file.dumplevel < 0 || file.dumplevel >= DUMP_LEVELS) {
249 dumpfile_free_data(&file);
254 orig_name = g_strdup(file.name);
257 if((dp = lookup_disk(file.name, file.disk)))
259 if((s = strrchr(file.name,'.')) == NULL)
263 strcpy(file.name, orig_name); /* restore munged string */
267 if (dynamic_disklist == NULL) {
268 dumpfile_free_data(&file);
271 dp = add_disk(dynamic_disklist, file.name, file.disk);
272 enqueue_disk(dynamic_disklist, dp);
275 if(find_match(file.name,file.disk)) {
276 find_result_t *new_output_find = g_new0(find_result_t, 1);
277 new_output_find->next=*output_find;
278 new_output_find->timestamp = stralloc(file.datestamp);
279 new_output_find->hostname = stralloc(file.name);
280 new_output_find->diskname = stralloc(file.disk);
281 new_output_find->level=file.dumplevel;
282 new_output_find->label=stralloc(holding_file);
283 new_output_find->partnum = -1;
284 new_output_find->totalparts = -1;
285 new_output_find->filenum=0;
286 if (file.is_partial) {
287 new_output_find->status=stralloc("PARTIAL");
288 new_output_find->dump_status=stralloc("PARTIAL");
290 new_output_find->status=stralloc("OK");
291 new_output_find->dump_status=stralloc("OK");
293 new_output_find->message=stralloc("");
294 new_output_find->kb = holding_file_size(holding_file, 1);
295 new_output_find->orig_kb = file.orig_size;
297 *output_find=new_output_find;
299 dumpfile_free_data(&file);
302 g_slist_free_full(holding_file_list);
306 get_write_timestamp(char *tapelabel)
310 if (!tapelabel || !(tp = lookup_tapelabel(tapelabel)))
313 return tp->datestamp;
322 find_result_t *i, *j;
324 size_t nb_compare=strlen(find_sort_order);
327 for(k=0;k<nb_compare;k++) {
328 char sort_key = find_sort_order[k];
329 if (isupper((int)sort_key)) {
331 sort_key = tolower(sort_key);
332 j = *(find_result_t **)i1;
333 i = *(find_result_t **)j1;
335 i = *(find_result_t **)i1;
336 j = *(find_result_t **)j1;
340 case 'h' : compare=strcmp(i->hostname,j->hostname);
342 case 'k' : compare=strcmp(i->diskname,j->diskname);
344 case 'd' : compare=strcmp(i->timestamp,j->timestamp);
346 case 'l' : compare=j->level - i->level;
348 case 'f' : compare=(i->filenum == j->filenum) ? 0 :
349 ((i->filenum < j->filenum) ? -1 : 1);
351 case 'b' : compare=compare_possibly_null_strings(i->label,
354 case 'w': compare=strcmp(get_write_timestamp(i->label),
355 get_write_timestamp(j->label));
358 compare=i->partnum - j->partnum;
370 find_result_t **output_find)
372 find_result_t *output_find_result;
373 find_result_t **array_find_result = NULL;
377 find_sort_order = sort_order;
378 /* qsort core dump if nothing to sort */
379 if(*output_find==NULL)
382 /* How many result */
383 for(output_find_result=*output_find;
385 output_find_result=output_find_result->next) {
389 /* put the list in an array */
390 array_find_result=alloc(nb_result * SIZEOF(find_result_t *));
391 for(output_find_result=*output_find,no_result=0;
393 output_find_result=output_find_result->next,no_result++) {
394 array_find_result[no_result]=output_find_result;
398 qsort(array_find_result,nb_result,SIZEOF(find_result_t *),
401 /* put the sorted result in the list */
403 no_result<nb_result-1; no_result++) {
404 array_find_result[no_result]->next = array_find_result[no_result+1];
406 array_find_result[nb_result-1]->next=NULL;
407 *output_find=array_find_result[0];
408 amfree(array_find_result);
413 find_result_t *output_find)
415 find_result_t *output_find_result;
416 int max_len_datestamp = 4;
417 int max_len_hostname = 4;
418 int max_len_diskname = 4;
419 int max_len_level = 2;
420 int max_len_label =12;
421 int max_len_filenum = 4;
422 int max_len_part = 4;
423 int max_len_status = 6;
426 for(output_find_result=output_find;
428 output_find_result=output_find_result->next) {
432 len=strlen(find_nicedate(output_find_result->timestamp));
433 if((int)len > max_len_datestamp)
434 max_len_datestamp=(int)len;
436 len=strlen(output_find_result->hostname);
437 if((int)len > max_len_hostname)
438 max_len_hostname = (int)len;
440 qdiskname=quote_string(output_find_result->diskname);
441 len=strlen(qdiskname);
443 if((int)len > max_len_diskname)
444 max_len_diskname = (int)len;
446 if (output_find_result->label != NULL) {
447 len=strlen(output_find_result->label);
448 if((int)len > max_len_label)
449 max_len_label = (int)len;
452 len=strlen(output_find_result->status) + 1 + strlen(output_find_result->dump_status);
453 if((int)len > max_len_status)
454 max_len_status = (int)len;
456 s = g_strdup_printf("%d/%d", output_find_result->partnum,
457 output_find_result->totalparts);
459 if((int)len > max_len_part)
460 max_len_part = (int)len;
464 * Since status is the rightmost field, we zap the maximum length
465 * because it is not needed. The code is left in place in case
466 * another column is added later.
470 if(output_find==NULL) {
471 g_printf(_("\nNo dump to list\n"));
474 g_printf(_("\ndate%*s host%*s disk%*s lv%*s tape or file%*s file%*s part%*s status\n"),
475 max_len_datestamp-4,"",
476 max_len_hostname-4 ,"",
477 max_len_diskname-4 ,"",
479 max_len_label-12 ,"",
480 max_len_filenum-4 ,"",
482 for(output_find_result=output_find;
484 output_find_result=output_find_result->next) {
486 char * formatted_label;
490 qdiskname = quote_string(output_find_result->diskname);
491 formatted_label = output_find_result->label;
492 if (formatted_label == NULL)
493 formatted_label = "";
495 if (strcmp(output_find_result->status, "OK") != 0 ||
496 strcmp(output_find_result->dump_status, "OK") != 0) {
497 status = vstralloc(output_find_result->status, " ",
498 output_find_result->dump_status, NULL);
500 status = stralloc(output_find_result->status);
504 /* sec and kb are omitted here, for compatibility with the existing
505 * output from 'amadmin' */
506 s = g_strdup_printf("%d/%d", output_find_result->partnum,
507 output_find_result->totalparts);
508 g_printf("%-*s %-*s %-*s %*d %-*s %*lld %*s %s %s\n",
510 find_nicedate(output_find_result->timestamp),
511 max_len_hostname, output_find_result->hostname,
512 max_len_diskname, qdiskname,
513 max_len_level, output_find_result->level,
514 max_len_label, formatted_label,
515 max_len_filenum, (long long)output_find_result->filenum,
518 output_find_result->message
530 find_result_t **output_find)
532 find_result_t *output_find_result, *prev;
535 for(output_find_result=*output_find;
537 output_find_result=output_find_result->next) {
539 amfree(output_find_result->timestamp);
540 amfree(output_find_result->hostname);
541 amfree(output_find_result->diskname);
542 amfree(output_find_result->label);
543 amfree(output_find_result->status);
544 amfree(output_find_result->dump_status);
545 amfree(output_find_result->message);
546 prev = output_find_result;
557 disk_t *dp = lookup_disk(host,disk);
558 return (dp && dp->todo);
565 static char nice[20];
566 int year, month, day;
567 int hours, minutes, seconds;
568 char date[9], atime[7];
569 int numdate, numtime;
571 strncpy(date, datestamp, 8);
573 numdate = atoi(date);
574 year = numdate / 10000;
575 month = (numdate / 100) % 100;
578 if(strlen(datestamp) <= 8) {
579 g_snprintf(nice, SIZEOF(nice), "%4d-%02d-%02d",
583 strncpy(atime, &(datestamp[8]), 6);
585 numtime = atoi(atime);
586 hours = numtime / 10000;
587 minutes = (numtime / 100) % 100;
588 seconds = numtime % 100;
590 g_snprintf(nice, SIZEOF(nice), "%4d-%02d-%02d %02d:%02d:%02d",
591 year, month, day, hours, minutes, seconds);
598 parse_taper_datestamp_log(
609 skip_whitespace(s, ch);
613 if(strncmp_const_skip(s - 1, "datestamp", s, ch) != 0) {
617 skip_whitespace(s, ch);
622 skip_non_whitespace(s, ch);
625 skip_whitespace(s, ch);
629 if(strncmp_const_skip(s - 1, "label", s, ch) != 0) {
633 skip_whitespace(s, ch);
638 skip_non_whitespace(s, ch);
644 /* Returns TRUE if the given logfile mentions the given tape. */
645 static gboolean logfile_has_tape(char * label, char * datestamp,
648 char * ck_datestamp, *ck_label;
649 if((logf = fopen(logfile, "r")) == NULL) {
650 error(_("could not open logfile %s: %s"), logfile, strerror(errno));
654 while(get_logline(logf)) {
655 if(curlog == L_START && curprog == P_TAPER) {
656 if(parse_taper_datestamp_log(curstr,
657 &ck_datestamp, &ck_label) == 0) {
658 g_printf(_("strange log line \"start taper %s\" curstr='%s'\n"),
660 } else if(strcmp(ck_datestamp, datestamp) == 0
661 && strcmp(ck_label, label) == 0) {
676 const char *datestamp)
684 return (strcmp(label1, label2) == 0);
686 /* check in tapelist */
687 if (!(tp = lookup_tapelabel(label2)))
690 if (strcmp(tp->datestamp, datestamp) != 0)
697 /* WARNING: Function accesses globals find_diskqp, curlog, curlog, curstr,
698 * dynamic_disklist */
701 find_result_t **output_find,
703 const char *passed_datestamp,
705 disklist_t * dynamic_disklist)
708 char *host, *host_undo;
709 char *disk, *qdisk, *disk_undo;
710 char *date, *date_undo;
716 char *current_label = stralloc("");
721 char *ck_datestamp, *datestamp;
725 find_result_t *part_find = NULL; /* List for all part of a DLE */
726 find_result_t *a_part_find;
727 gboolean right_label = FALSE;
728 gboolean found_something = FALSE;
731 regmatch_t pmatch[4];
736 g_return_val_if_fail(output_find != NULL, 0);
737 g_return_val_if_fail(logfile != NULL, 0);
739 datestamp = g_strdup(passed_datestamp);
741 if((logf = fopen(logfile, "r")) == NULL) {
742 error(_("could not open logfile %s: %s"), logfile, strerror(errno));
747 while(get_logline(logf)) {
748 if (curlog == L_START && curprog == P_TAPER) {
749 if(parse_taper_datestamp_log(curstr, &ck_datestamp,
751 g_printf(_("strange log line in %s \"start taper %s\"\n"),
755 if (datestamp != NULL) {
756 if (strcmp(datestamp, ck_datestamp) != 0) {
757 g_printf(_("Log file %s stamped %s, expecting %s!\n"),
758 logfile, ck_datestamp, datestamp);
763 right_label = volume_matches(label, ck_label, ck_datestamp);
764 if (label && datestamp && right_label) {
765 found_something = TRUE;
767 amfree(current_label);
768 current_label = g_strdup(ck_label);
769 if (datestamp == NULL) {
770 datestamp = g_strdup(ck_datestamp);
774 (curlog == L_SUCCESS ||
775 curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTPARTIAL) &&
776 curprog == P_TAPER) {
781 if (curlog == L_SUCCESS || curlog == L_CHUNKSUCCESS ||
782 curlog == L_DONE || curlog == L_FAIL ||
783 curlog == L_CHUNK || curlog == L_PART || curlog == L_PARTIAL ||
784 curlog == L_PARTPARTIAL ) {
788 skip_whitespace(s, ch);
790 g_printf(_("strange log line in %s \"%s\"\n"),
795 if (curlog == L_PART || curlog == L_PARTPARTIAL) {
796 char * part_label = s - 1;
797 skip_non_whitespace(s, ch);
803 if (strcmp(current_label, part_label) != 0) {
804 g_printf("PART label %s doesn't match START label %s\n",
805 part_label, current_label);
808 skip_whitespace(s, ch);
810 g_printf("strange log line in %s \"%s\"\n",
816 skip_non_whitespace(s, ch);
818 fileno = atoi(number);
823 skip_whitespace(s, ch);
825 g_printf("strange log line in %s \"%s\"\n",
832 skip_non_whitespace(s, ch);
836 skip_whitespace(s, ch);
838 g_printf(_("strange log line in %s \"%s\"\n"),
843 skip_quoted_string(s, ch);
846 disk = unquote_string(qdisk);
848 skip_whitespace(s, ch);
850 g_printf(_("strange log line in %s \"%s\"\n"),
855 skip_non_whitespace(s, ch);
859 if(strlen(date) < 3) { /* old log didn't have datestamp */
861 date = stralloc(datestamp);
865 if (curlog == L_CHUNK || curlog == L_PART ||
866 curlog == L_PARTPARTIAL || curlog == L_DONE){
867 skip_whitespace(s, ch);
869 skip_non_whitespace(s, ch);
871 sscanf(number, "%d/%d", &partnum, &totalparts);
872 if (partnum > maxparts)
874 if (totalparts > maxparts)
875 maxparts = totalparts;
877 skip_whitespace(s, ch);
878 if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
879 g_printf(_("strange log line in %s \"%s\"\n"),
886 skip_whitespace(s, ch);
888 g_printf(_("strange log line in %s \"%s\"\n"),
893 if((s = strchr(s, '\n')) != NULL) {
897 /* extract sec, kb, kps, orig-kb from 'rest', if present. This isn't the stone age
898 * anymore, so we'll just do it the easy way (a regex) */
899 bzero(®ex, sizeof(regex));
900 reg_result = regcomp(®ex,
901 "\\[sec ([0-9.]+) kb ([0-9]+) kps [0-9.]+ orig-kb ([0-9]+)\\]", REG_EXTENDED);
902 if (reg_result != 0) {
903 error("Error compiling regular expression for parsing log lines");
907 /* an error here just means the line wasn't found -- not fatal. */
908 reg_result = regexec(®ex, rest, sizeof(pmatch)/sizeof(*pmatch), pmatch, 0);
909 if (reg_result == 0) {
912 str = find_regex_substring(rest, pmatch[1]);
916 str = find_regex_substring(rest, pmatch[2]);
917 kb = OFF_T_ATOI(str);
920 str = find_regex_substring(rest, pmatch[3]);
921 orig_kb = OFF_T_ATOI(str);
924 bzero(®ex, sizeof(regex));
925 reg_result = regcomp(®ex,
926 "\\[sec ([0-9.]+) kb ([0-9]+) kps [0-9.]+\\]", REG_EXTENDED);
927 if (reg_result != 0) {
928 error("Error compiling regular expression for parsing log lines");
932 /* an error here just means the line wasn't found -- not fatal. */
933 reg_result = regexec(®ex, rest, sizeof(pmatch)/sizeof(*pmatch), pmatch, 0);
934 if (reg_result == 0) {
937 str = find_regex_substring(rest, pmatch[1]);
941 str = find_regex_substring(rest, pmatch[2]);
942 kb = OFF_T_ATOI(str);
953 dp = lookup_disk(host,disk);
955 if (dynamic_disklist == NULL) {
958 dp = add_disk(dynamic_disklist, host, disk);
959 enqueue_disk(dynamic_disklist, dp);
961 if (find_match(host, disk)) {
962 if(curprog == P_TAPER) {
963 find_result_t *new_output_find = g_new0(find_result_t, 1);
964 new_output_find->timestamp = stralloc(date);
965 new_output_find->hostname=stralloc(host);
966 new_output_find->diskname=stralloc(disk);
967 new_output_find->level=level;
968 new_output_find->partnum = partnum;
969 new_output_find->totalparts = totalparts;
970 new_output_find->label=stralloc(current_label);
971 new_output_find->status=NULL;
972 new_output_find->dump_status=NULL;
973 new_output_find->message=stralloc("");
974 new_output_find->filenum=filenum;
975 new_output_find->sec=sec;
976 new_output_find->kb=kb;
977 new_output_find->orig_kb=orig_kb;
978 new_output_find->next=NULL;
979 if (curlog == L_SUCCESS) {
980 new_output_find->status = stralloc("OK");
981 new_output_find->dump_status = stralloc("OK");
982 new_output_find->next = *output_find;
983 *output_find = new_output_find;
984 found_something = TRUE;
985 } else if (curlog == L_CHUNKSUCCESS || curlog == L_DONE ||
986 curlog == L_PARTIAL || curlog == L_FAIL) {
988 if (curlog == L_PARTIAL || curlog == L_FAIL) {
989 /* set dump_status of each part */
990 for (a_part_find = part_find; a_part_find;
991 a_part_find = a_part_find->next) {
992 amfree(a_part_find->dump_status);
993 if (curlog == L_PARTIAL)
994 a_part_find->dump_status = stralloc("PARTIAL");
996 a_part_find->dump_status = stralloc("FAIL");
997 amfree(a_part_find->message);
998 a_part_find->message = stralloc(rest);
1002 if (maxparts > -1) { /* format with part */
1003 /* must check if all part are there */
1004 int num_part = maxparts;
1005 for (a_part_find = part_find; a_part_find;
1006 a_part_find = a_part_find->next) {
1007 if (a_part_find->partnum == num_part &&
1008 strcmp(a_part_find->status, "OK") == 0)
1011 /* set dump_status of each part */
1012 for (a_part_find = part_find; a_part_find;
1013 a_part_find = a_part_find->next) {
1014 amfree(a_part_find->dump_status);
1015 if (num_part == 0) {
1016 a_part_find->dump_status =
1019 a_part_find->dump_status =
1021 amfree(a_part_find->message);
1022 a_part_find->message =
1023 stralloc("Missing part");
1028 if (curlog == L_DONE) {
1029 for (a_part_find = part_find; a_part_find;
1030 a_part_find = a_part_find->next) {
1031 if (a_part_find->totalparts == -1) {
1032 a_part_find->totalparts = maxparts;
1034 if (a_part_find->orig_kb == 0) {
1035 a_part_find->orig_kb = orig_kb;
1039 if (part_find) { /* find last element */
1040 for (a_part_find = part_find;
1041 a_part_find->next != NULL;
1042 a_part_find=a_part_find->next) {
1044 /* merge part_find to *output_find */
1045 a_part_find->next = *output_find;
1046 *output_find = part_find;
1049 found_something = TRUE;
1051 free_find_result(&new_output_find);
1052 } else { /* part line */
1053 if (curlog == L_PART || curlog == L_CHUNK) {
1054 new_output_find->status=stralloc("OK");
1055 new_output_find->dump_status=stralloc("OK");
1056 } else { /* PARTPARTIAL */
1057 new_output_find->status=stralloc("PARTIAL");
1058 new_output_find->dump_status=stralloc("PARTIAL");
1060 /* Add to part_find list */
1061 new_output_find->next = part_find;
1062 part_find = new_output_find;
1063 found_something = TRUE;
1066 else if(curlog == L_FAIL) {
1067 /* print other failures too -- this is a hack to ensure that failures which
1068 * did not make it to tape are also listed in the output of 'amadmin x find';
1069 * users that do not want this information (e.g., Amanda::DB::Catalog) should
1070 * filter dumps with a NULL label. */
1071 find_result_t *new_output_find = g_new0(find_result_t, 1);
1072 new_output_find->next=*output_find;
1073 new_output_find->timestamp = stralloc(date);
1074 new_output_find->hostname=stralloc(host);
1075 new_output_find->diskname=stralloc(disk);
1076 new_output_find->level=level;
1077 new_output_find->label=NULL;
1078 new_output_find->partnum=partnum;
1079 new_output_find->totalparts=totalparts;
1080 new_output_find->filenum=0;
1081 new_output_find->sec=sec;
1082 new_output_find->kb=kb;
1083 new_output_find->kb=orig_kb;
1084 new_output_find->status=vstralloc(
1086 program_str[(int)curprog],
1090 new_output_find->dump_status=stralloc("");
1091 new_output_find->message=stralloc("");
1092 *output_find=new_output_find;
1093 found_something = TRUE;
1101 /* This could propably be completely removed */
1102 if (part_find != NULL) {
1104 /* parse log file until PARTIAL/DONE/SUCCESS/FAIL from taper */
1105 while(get_logline(logf)) {
1106 if (curprog == P_TAPER &&
1107 (curlog == L_DONE || curlog == L_SUCCESS ||
1108 curlog == L_PARTIAL || curlog == L_FAIL)) {
1113 for (a_part_find = part_find; a_part_find;
1114 a_part_find = a_part_find->next) {
1115 if (curlog == L_PARTIAL)
1116 a_part_find->status = stralloc("PARTIAL");
1117 else if (curlog == L_FAIL)
1118 a_part_find->status = stralloc("FAIL");
1119 else if (curlog == L_DONE || curlog == L_SUCCESS) {
1120 if (a_part_find->totalparts == -1) {
1121 a_part_find->totalparts = maxparts;
1125 for (a_part_find = part_find;
1126 a_part_find->next != NULL;
1127 a_part_find=a_part_find->next) {
1129 /* merge part_find to *output_find */
1130 a_part_find->next = *output_find;
1131 *output_find = part_find;
1138 amfree(current_label);
1140 return found_something;
1145 * Return the set of dumps that match *all* of the given patterns (we consider
1146 * an empty pattern to match .*, though). If 'ok' is true, will only match
1147 * dumps with SUCCESS status.
1149 * Returns a newly allocated list of results, where all strings are also newly
1150 * allocated. Apparently some part of Amanda leaks under this condition.
1154 find_result_t *output_find,
1161 find_result_t *cur_result;
1162 find_result_t *matches = NULL;
1164 for(cur_result=output_find;
1166 cur_result=cur_result->next) {
1167 char level_str[NUM_STR_SIZE];
1168 g_snprintf(level_str, SIZEOF(level_str), "%d", cur_result->level);
1169 if((!hostname || *hostname == '\0' || match_host(hostname, cur_result->hostname)) &&
1170 (!diskname || *diskname == '\0' || match_disk(diskname, cur_result->diskname)) &&
1171 (!datestamp || *datestamp== '\0' || match_datestamp(datestamp, cur_result->timestamp)) &&
1172 (!level || *level== '\0' || match_level(level, level_str)) &&
1173 (!ok || !strcmp(cur_result->status, "OK")) &&
1174 (!ok || !strcmp(cur_result->dump_status, "OK"))){
1176 find_result_t *curmatch = g_new0(find_result_t, 1);
1177 memcpy(curmatch, cur_result, SIZEOF(find_result_t));
1179 curmatch->timestamp = stralloc(cur_result->timestamp);
1180 curmatch->hostname = stralloc(cur_result->hostname);
1181 curmatch->diskname = stralloc(cur_result->diskname);
1182 curmatch->level = cur_result->level;
1183 curmatch->label = cur_result->label? stralloc(cur_result->label) : NULL;
1184 curmatch->filenum = cur_result->filenum;
1185 curmatch->sec = cur_result->sec;
1186 curmatch->kb = cur_result->kb;
1187 curmatch->orig_kb = cur_result->orig_kb;
1188 curmatch->status = stralloc(cur_result->status);
1189 curmatch->dump_status = stralloc(cur_result->dump_status);
1190 curmatch->message = stralloc(cur_result->message);
1191 curmatch->partnum = cur_result->partnum;
1192 curmatch->totalparts = cur_result->totalparts;
1193 curmatch->next = matches;
1202 * Return the set of dumps that match one or more of the given dumpspecs,
1203 * If 'ok' is true, only dumps with a SUCCESS status will be matched.
1205 * Returns a newly allocated list of results, where all strings are also newly
1206 * allocated. Apparently some part of Amanda leaks under this condition.
1209 dumps_match_dumpspecs(
1210 find_result_t *output_find,
1214 find_result_t *cur_result;
1215 find_result_t *matches = NULL;
1219 for(cur_result=output_find;
1221 cur_result=cur_result->next) {
1222 char level_str[NUM_STR_SIZE];
1223 g_snprintf(level_str, SIZEOF(level_str), "%d", cur_result->level);
1224 for (dumpspec = dumpspecs; dumpspec; dumpspec = dumpspec->next) {
1225 ds = (dumpspec_t *)dumpspec->data;
1226 if((!ds->host || *ds->host == '\0' || match_host(ds->host, cur_result->hostname)) &&
1227 (!ds->disk || *ds->disk == '\0' || match_disk(ds->disk, cur_result->diskname)) &&
1228 (!ds->datestamp || *ds->datestamp== '\0' || match_datestamp(ds->datestamp, cur_result->timestamp)) &&
1229 (!ds->level || *ds->level== '\0' || match_level(ds->level, level_str)) &&
1230 (!ok || !strcmp(cur_result->status, "OK")) &&
1231 (!ok || !strcmp(cur_result->dump_status, "OK"))) {
1233 find_result_t *curmatch = alloc(SIZEOF(find_result_t));
1234 memcpy(curmatch, cur_result, SIZEOF(find_result_t));
1236 curmatch->timestamp = stralloc(cur_result->timestamp);
1237 curmatch->hostname = stralloc(cur_result->hostname);
1238 curmatch->diskname = stralloc(cur_result->diskname);
1239 curmatch->level = cur_result->level;
1240 curmatch->label = cur_result->label? stralloc(cur_result->label) : NULL;
1241 curmatch->filenum = cur_result->filenum;
1242 curmatch->status = stralloc(cur_result->status);
1243 curmatch->dump_status = stralloc(cur_result->dump_status);
1244 curmatch->message = stralloc(cur_result->message);
1245 curmatch->partnum = cur_result->partnum;
1246 curmatch->totalparts = cur_result->totalparts;
1248 curmatch->next = matches;
1260 find_result_t *output_find,
1266 find_result_t *output_find_result;
1268 for(output_find_result=output_find;
1270 output_find_result=output_find_result->next) {
1271 if( !strcmp(output_find_result->hostname, hostname) &&
1272 !strcmp(output_find_result->diskname, diskname) &&
1273 !strcmp(output_find_result->timestamp, datestamp) &&
1274 output_find_result->level == level) {
1276 return output_find_result;