/* 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*/ } while(get_logline(logf)) { if(curlog == L_START && curprog == P_TAPER) { if(parse_taper_datestamp_log(curstr, &ck_datestamp, &ck_label) == 0) { g_printf(_("strange log line \"start taper %s\" curstr='%s'\n"), logfile, curstr); } else if(g_str_equal(ck_datestamp, datestamp) && g_str_equal(ck_label, label)) { amfree(ck_label); afclose(logf); return TRUE; } amfree(ck_label); } } afclose(logf); return FALSE; }
int main( int argc, char ** argv) { char *logfname; char *conf_logdir; FILE *logfile; config_overrides_t *cfg_ovr = NULL; char *cfg_opt = NULL; /* * Configure program for internationalization: * 1) Only set the message locale for now. * 2) Set textdomain for all amanda related programs to "amanda" * We don't want to be forced to support dozens of message catalogs. */ setlocale(LC_MESSAGES, "C"); textdomain("amanda"); safe_fd(-1, 0); set_pname("amlogroll"); dbopen(DBG_SUBDIR_SERVER); add_amanda_log_handler(amanda_log_stderr); /* Process options */ cfg_ovr = extract_commandline_config_overrides(&argc, &argv); if (argc >= 2) { cfg_opt = argv[1]; } /* read configuration files */ set_config_overrides(cfg_ovr); config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD, cfg_opt); if (config_errors(NULL) >= CFGERR_WARNINGS) { config_print_errors(); if (config_errors(NULL) >= CFGERR_ERRORS) { g_critical(_("errors processing config file")); } } safe_cd(); /* must happen after config_init */ check_running_as(RUNNING_AS_DUMPUSER); dbrename(get_config_name(), DBG_SUBDIR_SERVER); conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR)); logfname = vstralloc(conf_logdir, "/", "log", NULL); amfree(conf_logdir); if((logfile = fopen(logfname, "r")) == NULL) { error(_("could not open log %s: %s"), logfname, strerror(errno)); /*NOTREACHED*/ } amfree(logfname); add_amanda_log_handler(amanda_log_trace_log); while(get_logline(logfile)) { if(curlog == L_START) { handle_start(); if(datestamp != NULL) { break; } } } afclose(logfile); log_rename(datestamp); amfree(datestamp); dbclose(); return 0; }
/* 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 = NULL, *qdisk, *disk_undo; char *date, *date_undo; int partnum; int totalparts; int maxparts = -1; char *number; int fileno; char *current_label; 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); current_label = g_strdup(""); 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((logf = fopen(logfile, "r")) == NULL) { error(_("could not open logfile %s: %s"), logfile, strerror(errno)); /*NOTREACHED*/ } 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 (!g_str_equal(datestamp, ck_datestamp)) { 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 (!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') { 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; *host_undo = '\0'; skip_whitespace(s, ch); if(ch == '\0') { g_printf(_("strange log line in %s \"%s\"\n"), logfile, curstr); continue; } 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') { g_printf(_("strange log line in %s \"%s\"\n"), logfile, curstr); amfree(disk); continue; } 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 = 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) { g_printf(_("Fstrange log line in %s \"%s\"\n"), logfile, s-1); amfree(disk); continue; } skip_integer(s, ch); } skip_whitespace(s, ch); if(ch == '\0') { g_printf(_("strange log line in %s \"%s\"\n"), logfile, curstr); amfree(disk); continue; } rest = s - 1; skip_non_whitespace(s, ch); rest_undo = s - 1; *rest_undo = '\0'; if (g_str_equal(rest, "[sec")) { skip_whitespace(s, ch); if(ch == '\0') { g_printf(_("strange log line in %s \"%s\"\n"), logfile, curstr); amfree(disk); 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 (!g_str_equal(rest, "kb") && !g_str_equal(rest, "bytes")) { g_printf(_("Bstrange log line in %s \"%s\"\n"), logfile, curstr); amfree(disk); continue; } skip_whitespace(s, ch); if (ch == '\0') { g_printf(_("strange log line in %s \"%s\"\n"), logfile, curstr); amfree(disk); continue; } if (g_str_equal(rest, "kb")) { 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 (!g_str_equal(rest, "kps")) { g_printf(_("Cstrange log line in %s \"%s\"\n"), logfile, curstr); amfree(disk); continue; } skip_whitespace(s, ch); if (ch == '\0') { g_printf(_("strange log line in %s \"%s\"\n"), logfile, curstr); amfree(disk); 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 (!g_str_equal(rest, "orig-kb")) { orig_kb = 0; } else { skip_whitespace(s, ch); if(ch == '\0') { g_printf(_("strange log line in %s \"%s\"\n"), logfile, curstr); amfree(disk); continue; } orig_kb = atof(s - 1); } } else { sec = 0; kb = 0; bytes = 0; orig_kb = 0; *rest_undo = ' '; } if (g_str_has_prefix(rest, "error")) rest += 6; if (g_str_has_prefix(rest, "config")) rest += 7; dp = lookup_disk(host,disk); if ( dp == NULL ) { if (dynamic_disklist == NULL) { amfree(disk); continue; } dp = add_disk(dynamic_disklist, host, disk); enqueue_disk(dynamic_disklist, dp); } if (find_match(host, disk)) { if(curprog == P_TAPER) { 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->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; 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 && g_str_equal(a_part_find->status, "OK")) 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) { 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=NULL; new_output_find->partnum=partnum; new_output_find->totalparts=totalparts; new_output_find->filenum=0; new_output_find->sec=sec; new_output_find->kb=kb; new_output_find->bytes=bytes; new_output_find->orig_kb=orig_kb; status_failed = g_strjoin(NULL, "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); amfree(datestamp); amfree(current_label); amfree(disk); return found_something; }