X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Freporter.c;h=f9fabea9535f5ed26d7096d5e198bd1219454e6d;hb=2627875b7d18858bc1f9f7652811e4d8c15a23eb;hp=96bf404faf2d8a9bc15c05fd13831e3f8e4efdc7;hpb=3ab887b9bc819a846c75dd7f2ee5d41fac22b19f;p=debian%2Famanda diff --git a/server-src/reporter.c b/server-src/reporter.c index 96bf404..f9fabea 100644 --- a/server-src/reporter.c +++ b/server-src/reporter.c @@ -25,144 +25,190 @@ * University of Maryland at College Park */ /* - * $Id: reporter.c,v 1.44.2.17.4.6.2.16 2003/11/26 16:10:23 martinea Exp $ + * $Id: reporter.c,v 1.132 2006/08/28 17:02:48 martinea Exp $ * * nightly Amanda Report generator */ /* -report format - tape label message - error messages - summary stats - details for errors - notes - success summary -*/ + * report format + * tape label message + * error messages + * strange messages + * summary stats + * details for errors + * details for strange + * notes + * success summary + */ #include "amanda.h" #include "conffile.h" +#include "columnar.h" #include "tapefile.h" #include "diskfile.h" #include "infofile.h" #include "logfile.h" #include "version.h" #include "util.h" +#include "timestamp.h" +#include "holding.h" /* don't have (or need) a skipped type except internally to reporter */ #define L_SKIPPED L_MARKER + +#define STATUS_STRANGE 2 +#define STATUS_FAILED 4 +#define STATUS_MISSING 8 +#define STATUS_TAPE 16 + typedef struct line_s { - struct line_s *next; + struct line_s *next, *last; char *str; } line_t; typedef struct timedata_s { logtype_t result; - float origsize, outsize; + double origsize, outsize; char *datestamp; - float sec, kps; + double sec, kps; int filenum; char *tapelabel; + int totpart; } timedata_t; typedef struct repdata_s { disk_t *disk; char *datestamp; + double est_nsize, est_csize; timedata_t taper; timedata_t dumper; + timedata_t chunker; + timedata_t planner; int level; struct repdata_s *next; } repdata_t; #define data(dp) ((repdata_t *)(dp)->up) -struct cumulative_stats { - int dumpdisks, tapedisks; +static struct cumulative_stats { + int dumpdisks, tapedisks, tapechunks; double taper_time, dumper_time; double outsize, origsize, tapesize; double coutsize, corigsize; /* compressed dump only */ } stats[3]; -int dumpdisks[10], tapedisks[10]; /* by-level breakdown of disk count */ +static int dumpdisks[10], tapedisks[10], tapechunks[10]; /* by-level breakdown of disk count */ typedef struct taper_s { char *label; double taper_time; double coutsize, corigsize; - int tapedisks; + int tapedisks, tapechunks; struct taper_s *next; } taper_t; -taper_t *stats_by_tape = NULL; -taper_t *current_tape = NULL; +static taper_t *stats_by_tape = NULL; +static taper_t *current_tape = NULL; + +typedef struct X_summary_s { + char *hostname; + char *diskname; + int level; + char *str; + struct X_summary_s *next; +} X_summary_t; + +static X_summary_t *first_strange=NULL, *last_strange=NULL; +static X_summary_t *first_failed=NULL, *last_failed=NULL; -float total_time, startup_time; +static double total_time, startup_time, planner_time; /* count files to tape */ -int tapefcount = 0; +static int tapefcount = 0; -char *run_datestamp; -char *today_datestamp; -char *tape_labels = NULL; -int last_run_tapes = 0; +static int exit_status = 0; +static char *run_datestamp; +static char *tape_labels = NULL; +static int last_run_tapes = 0; static int degraded_mode = 0; /* defined in driverio too */ -int normal_run = 0; -int amflush_run = 0; -int got_finish = 0; +static int normal_run = 0; +static int amflush_run = 0; +static int got_finish = 0; +static int cmdlogfname = 0; +static char *ghostname = NULL; -char *tapestart_error = NULL; +static char *tapestart_error = NULL; -FILE *logfile, *mailf; +static FILE *logfile, *mailf; -FILE *postscript; -char *printer; +static FILE *postscript; +static char *printer; -disklist_t *diskq; -disklist_t sortq; +static disklist_t diskq; +static disklist_t sortq; -line_t *errsum = NULL; -line_t *errdet = NULL; -line_t *notes = NULL; +static line_t *errsum = NULL; +static line_t *errdet = NULL; +static line_t *strangedet = NULL; +static line_t *notes = NULL; static char MaxWidthsRequested = 0; /* determined via config data */ -/* -char *hostname = NULL, *diskname = NULL; -*/ +static char *displayunit; +static long int unitdivisor; /* local functions */ -int contline_next P((void)); -void addline P((line_t **lp, char *str)); -void usage P((void)); -int main P((int argc, char **argv)); - -void copy_template_file P((char *lbl_templ)); -void do_postscript_output P((void)); -void handle_start P((void)); -void handle_finish P((void)); -void handle_note P((void)); -void handle_summary P((void)); -void handle_stats P((void)); -void handle_error P((void)); -void handle_disk P((void)); -repdata_t *handle_success P((void)); -void handle_strange P((void)); -void handle_failed P((void)); -void generate_missing P((void)); -void output_tapeinfo P((void)); -void output_lines P((line_t *lp, FILE *f)); -void output_stats P((void)); -void output_summary P((void)); -void sort_disks P((void)); -int sort_by_time P((disk_t *a, disk_t *b)); -int sort_by_name P((disk_t *a, disk_t *b)); -void bogus_line P((void)); -char *nicedate P((int datestamp)); -static char *prefix P((char *host, char *disk, int level)); -repdata_t *find_repdata P((disk_t *dp, char *datestamp, int level)); - - -static int ColWidth(int From, int To) { +int main(int argc, char **argv); + +static char * nicedate(const char * datestamp); +static char * prefix(char *host, char *disk, int level); +static char * prefixstrange(char *host, char *disk, int level, + size_t len_host, size_t len_disk); +static char * Rule(int From, int To); +static char * sDivZero(double a, double b, int cn); +static char * TextRule(int From, int To, char *s); +static int ColWidth(int From, int To); +static int contline_next(void); +static int sort_by_name(disk_t *a, disk_t *b); +static repdata_t *find_repdata(disk_t *dp, char *datestamp, int level); +static repdata_t *handle_chunk(logtype_t logtype); +static repdata_t *handle_success(logtype_t logtype); +static void addline(line_t **lp, char *str); +static void addtoX_summary(X_summary_t **first, X_summary_t **last, + char *host, char *disk, int level, char *str); +static void bogus_line(const char *); +static void CalcMaxWidth(void); +static void CheckFloatMax(ColumnInfo *cd, double d); +static void CheckIntMax(ColumnInfo *cd, int n); +static void CheckStringMax(ColumnInfo *cd, char *s); +static void copy_template_file(char *lbl_templ); +static void do_postscript_output(void); +static void generate_missing(void); +static void generate_bad_estimate(void); +static void handle_disk(void); +static void handle_error(void); +static void handle_failed(void); +static void handle_finish(void); +static void handle_note(void); +static void handle_partial(void); +static void handle_start(void); +static void handle_stats(void); +static void handle_strange(void); +static void handle_summary(void); +static void output_lines(line_t *lp, FILE *f); +static void output_stats(void); +static void output_X_summary(X_summary_t *first); +static void output_summary(void); +static void output_tapeinfo(void); +static void sort_disks(void); +static void usage(void); + +static int +ColWidth( + int From, + int To) +{ int i, Width= 0; for (i=From; i<=To && ColumnData[i].Name != NULL; i++) { Width+= ColumnData[i].PrefixSpace + ColumnData[i].Width; @@ -170,10 +216,14 @@ static int ColWidth(int From, int To) { return Width; } -static char *Rule(int From, int To) { +static char * +Rule( + int From, + int To) +{ int i, ThisLeng; int Leng= ColWidth(0, ColumnDataCount()); - char *RuleSpace= alloc(Leng+1); + char *RuleSpace= alloc((size_t)(Leng+1)); ThisLeng= ColWidth(From, To); for (i=0;i= (RuleSpaceSize - cd->PrefixSpace)) leng = RuleSpaceSize - cd->PrefixSpace - 1; - ap_snprintf(RuleSpace, RuleSpaceSize, "%*s%*.*s ", cd->PrefixSpace, "", - leng, leng, s); + g_snprintf(RuleSpace, (size_t)RuleSpaceSize, "%*s%*.*s ", cd->PrefixSpace, "", + leng, leng, s); txtlength = cd->PrefixSpace + leng + 1; nbrules = ColWidth(From,To) - txtlength; for(tmp=RuleSpace + txtlength, i=nbrules ; i>0; tmp++,i--) @@ -202,85 +258,116 @@ static char *TextRule(int From, int To, char *s) { return RuleSpace; } -char *sDivZero(float a, float b, int cn) { +static char * +sDivZero( + double a, + double b, + int cn) +{ ColumnInfo *cd= &ColumnData[cn]; static char PrtBuf[256]; - if (b == 0.0) - ap_snprintf(PrtBuf, sizeof(PrtBuf), + if (!isnormal(b)) + g_snprintf(PrtBuf, SIZEOF(PrtBuf), "%*s", cd->Width, "-- "); else - ap_snprintf(PrtBuf, sizeof(PrtBuf), + g_snprintf(PrtBuf, SIZEOF(PrtBuf), cd->Format, cd->Width, cd->Precision, a/b); return PrtBuf; } - - -int contline_next() +static int +contline_next(void) { int ch; - ch = getc(logfile); - ungetc(ch, logfile); - + if ((ch = getc(logfile)) != EOF) { + if (ungetc(ch, logfile) == EOF) { + if (ferror(logfile)) { + error(_("ungetc failed: %s\n"), strerror(errno)); + /*NOTREACHED*/ + } + error(_("ungetc failed: EOF\n")); + /*NOTREACHED*/ + } + } return ch == ' '; } -void addline(lp, str) -line_t **lp; -char *str; +static void +addline( + line_t ** lp, + char * str) { - line_t *new, *p, *q; + line_t *new, *p; /* allocate new line node */ - new = (line_t *) alloc(sizeof(line_t)); + new = (line_t *) alloc(SIZEOF(line_t)); new->next = NULL; + new->last = NULL; new->str = stralloc(str); /* add to end of list */ - for(p = *lp, q = NULL; p != NULL; q = p, p = p->next); - if(q == NULL) *lp = new; - else q->next = new; + p = *lp; + if (p == NULL) { + *lp = new; + } else { + if (p->last) { + p->last->next = new; + } else { + p->next = new; + } + p->last = new; + } } -void usage() +static void +usage(void) { - error("Usage: amreport conf [-f output-file] [-l logfile] [-p postscript-file]"); + error(_("Usage: amreport conf [-i] [-M address] [-f output-file] [-l logfile] [-p postscript-file] [-o configoption]*")); + /*NOTREACHED*/ } -int main(argc, argv) -int argc; -char **argv; +int +main( + int argc, + char ** argv) { - char *conffile; char *conf_diskfile; char *conf_tapelist; char *conf_infofile; char *logfname, *psfname, *outfname, *subj_str = NULL; tapetype_t *tp; - int fd, opt; - unsigned long malloc_hist_1, malloc_size_1; - unsigned long malloc_hist_2, malloc_size_2; + int opt; char *mail_cmd = NULL, *printer_cmd = NULL; extern int optind; - char my_cwd[STR_SIZE]; + char * cwd = NULL; char *ColumnSpec = ""; char *errstr = NULL; int cn; - - for(fd = 3; fd < FD_SETSIZE; fd++) { - /* - * Make sure nobody spoofs us with a lot of extra open files - * that would cause an open we do to get a very high file - * descriptor, which in turn might be used as an index into - * an array (e.g. an fd_set). - */ - close(fd); - } + int mailout = 1; + char *mailto = NULL; + char *lbl_templ = NULL; + config_overwrites_t *cfg_ovr = NULL; + char *cfg_opt = NULL; + char *mailer; + + /* + * 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("amreport"); - malloc_size_1 = malloc_inuse(&malloc_hist_1); + dbopen(DBG_SUBDIR_SERVER); + + /* Don't die when child closes pipe */ + signal(SIGPIPE, SIG_IGN); /* Process options */ @@ -288,124 +375,149 @@ char **argv; outfname = NULL; psfname = NULL; logfname = NULL; + cmdlogfname = 0; - if (getcwd(my_cwd, sizeof(my_cwd)) == NULL) { - error("cannot determine current working directory"); + cwd = g_get_current_dir(); + if (cwd == NULL) { + error(_("Cannot determine current working directory: %s"), + strerror(errno)); + /*NOTREACHED*/ } - if (argc < 2) { - config_dir = stralloc2(my_cwd, "/"); - if ((config_name = strrchr(my_cwd, '/')) != NULL) { - config_name = stralloc(config_name + 1); - } - } else { + if (argc >= 2) { if (argv[1][0] == '-') { usage(); return 1; } - config_name = stralloc(argv[1]); - config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL); + + /* get the config name and move past it */ + cfg_opt = argv[1]; --argc; ++argv; - while((opt = getopt(argc, argv, "f:l:p:")) != EOF) { + + cfg_ovr = new_config_overwrites(argc/2); + while((opt = getopt(argc, argv, "o:M:f:l:p:i")) != EOF) { switch(opt) { + case 'i': + mailout = 0; + break; + case 'M': + if (mailto != NULL) { + error(_("you may specify at most one -M")); + /*NOTREACHED*/ + } + mailto = stralloc(optarg); + if(!validate_mailto(mailto)) { + error(_("mail address has invalid characters")); + /*NOTREACHED*/ + } + break; case 'f': if (outfname != NULL) { - error("you may specify at most one -f"); + error(_("you may specify at most one -f")); + /*NOTREACHED*/ } if (*optarg == '/') { outfname = stralloc(optarg); } else { - outfname = vstralloc(my_cwd, "/", optarg, NULL); + outfname = vstralloc(cwd, "/", optarg, NULL); } break; case 'l': + cmdlogfname = 1; if (logfname != NULL) { - error("you may specify at most one -l"); + error(_("you may specify at most one -l")); + /*NOTREACHED*/ } if (*optarg == '/') { logfname = stralloc(optarg); } else { - logfname = vstralloc(my_cwd, "/", optarg, NULL); + logfname = vstralloc(cwd, "/", optarg, NULL); } break; case 'p': if (psfname != NULL) { - error("you may specify at most one -p"); + error(_("you may specify at most one -p")); + /*NOTREACHED*/ } if (*optarg == '/') { psfname = stralloc(optarg); } else { - psfname = vstralloc(my_cwd, "/", optarg, NULL); + psfname = vstralloc(cwd, "/", optarg, NULL); } break; + case 'o': + add_config_overwrite_opt(cfg_ovr, optarg); + break; case '?': - default: usage(); return 1; + default: + break; } } argc -= optind; argv += optind; - - if (argc > 1) { - usage(); - return 1; - } } - -#if !defined MAILER - if(!outfname) { - printf("You must run amreport with '-f ' because configure\n"); - printf("didn't find a mailer.\n"); - exit (1); + if( !mailout && mailto ){ + g_printf(_("You cannot specify both -i & -M at the same time\n")); + exit(1); } -#endif - safe_cd(); + amfree(cwd); /* read configuration files */ - conffile = stralloc2(config_dir, CONFFILE_NAME); - if(read_conffile(conffile)) { - error("errors processing config file \"%s\"", conffile); - } - amfree(conffile); - conf_diskfile = getconf_str(CNF_DISKFILE); - if (*conf_diskfile == '/') { - conf_diskfile = stralloc(conf_diskfile); - } else { - conf_diskfile = stralloc2(config_dir, conf_diskfile); + /* ignore any errors reading the config file (amreport can run without a config) */ + config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD, cfg_opt); + apply_config_overwrites(cfg_ovr); + + if (config_errors(NULL) >= CFGERR_WARNINGS) { + config_print_errors(); } - if((diskq = read_diskfile(conf_diskfile)) == NULL) { - error("could not load disklist \"%s\"", conf_diskfile); + + check_running_as(RUNNING_AS_DUMPUSER); + + dbrename(get_config_name(), DBG_SUBDIR_SERVER); + + safe_cd(); /* must be called *after* config_init() */ + + mailer = getconf_str(CNF_MAILER); + if (mailer && *mailer == '\0') + mailer = NULL; + if (!mailer && !outfname) { + g_printf(_("You must run amreport with '-f ' because a mailer is not defined\n")); + exit (1); } + + conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE)); + /* Ignore error from read_diskfile */ + read_diskfile(conf_diskfile, &diskq); amfree(conf_diskfile); - conf_tapelist = getconf_str(CNF_TAPELIST); - if (*conf_tapelist == '/') { - conf_tapelist = stralloc(conf_tapelist); - } else { - conf_tapelist = stralloc2(config_dir, conf_tapelist); - } - if(read_tapelist(conf_tapelist)) { - error("could not read tapelist \"%s\"", conf_tapelist); + if(mailout && !mailto && + getconf_seen(CNF_MAILTO) && strlen(getconf_str(CNF_MAILTO)) > 0) { + mailto = getconf_str(CNF_MAILTO); + if(!validate_mailto(mailto)){ + mailto = NULL; + } } + + conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST)); + /* Ignore error from read_tapelist */ + read_tapelist(conf_tapelist); amfree(conf_tapelist); - conf_infofile = getconf_str(CNF_INFOFILE); - if (*conf_infofile == '/') { - conf_infofile = stralloc(conf_infofile); - } else { - conf_infofile = stralloc2(config_dir, conf_infofile); - } + conf_infofile = config_dir_relative(getconf_str(CNF_INFOFILE)); if(open_infofile(conf_infofile)) { - error("could not open info db \"%s\"", conf_infofile); + error(_("could not open info db \"%s\""), conf_infofile); + /*NOTREACHED*/ } amfree(conf_infofile); - today_datestamp = construct_datestamp(NULL); + displayunit = getconf_str(CNF_DISPLAYUNIT); + unitdivisor = getconf_unit_divisor(); ColumnSpec = getconf_str(CNF_COLUMNSPEC); - if(SetColumDataFromString(ColumnData, ColumnSpec, &errstr) < 0) { + if(SetColumnDataFromString(ColumnData, ColumnSpec, &errstr) < 0) { curlog = L_ERROR; curprog = P_REPORTER; curstr = errstr; @@ -413,7 +525,7 @@ char **argv; amfree(errstr); curstr = NULL; ColumnSpec = ""; /* use the default */ - if(SetColumDataFromString(ColumnData, ColumnSpec, &errstr) < 0) { + if(SetColumnDataFromString(ColumnData, ColumnSpec, &errstr) < 0) { curlog = L_ERROR; curprog = P_REPORTER; curstr = errstr; @@ -432,12 +544,7 @@ char **argv; if(!logfname) { char *conf_logdir; - 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)); logfname = vstralloc(conf_logdir, "/", "log", NULL); amfree(conf_logdir); } @@ -445,7 +552,7 @@ char **argv; if((logfile = fopen(logfname, "r")) == NULL) { curlog = L_ERROR; curprog = P_REPORTER; - curstr = vstralloc("could not open log ", + curstr = vstralloc(_("could not open log "), logfname, ": ", strerror(errno), @@ -456,41 +563,49 @@ char **argv; while(logfile && get_logline(logfile)) { switch(curlog) { - case L_START: handle_start(); break; - case L_FINISH: handle_finish(); break; + case L_START: handle_start(); break; + case L_FINISH: handle_finish(); break; - case L_INFO: handle_note(); break; - case L_WARNING: handle_note(); break; + case L_INFO: handle_note(); break; + case L_WARNING: handle_note(); break; - case L_SUMMARY: handle_summary(); break; - case L_STATS: handle_stats(); break; + case L_SUMMARY: handle_summary(); break; + case L_STATS: handle_stats(); break; - case L_ERROR: handle_error(); break; - case L_FATAL: handle_error(); break; + case L_ERROR: handle_error(); break; + case L_FATAL: handle_error(); break; - case L_DISK: handle_disk(); break; + case L_DISK: handle_disk(); break; - case L_SUCCESS: handle_success(); break; - case L_STRANGE: handle_strange(); break; - case L_FAIL: handle_failed(); break; + case L_DONE: handle_success(curlog); break; + case L_SUCCESS: handle_success(curlog); break; + case L_CHUNKSUCCESS: handle_success(curlog); break; + case L_PART: handle_chunk(curlog); break; + case L_PARTPARTIAL: handle_chunk(curlog); break; + case L_CHUNK: handle_chunk(curlog); break; + case L_PARTIAL: handle_partial(); break; + case L_STRANGE: handle_strange(); break; + case L_FAIL: handle_failed(); break; default: curlog = L_ERROR; curprog = P_REPORTER; - curstr = stralloc2("unexpected log line: ", curstr); + curstr = vstrallocf(_("unexpected log line: %s"), curstr); handle_error(); amfree(curstr); } } afclose(logfile); close_infofile(); - if(!amflush_run) + if(!amflush_run) { generate_missing(); + generate_bad_estimate(); + } subj_str = vstralloc(getconf_str(CNF_ORG), " ", amflush_run ? "AMFLUSH" : "AMANDA", " ", "MAIL REPORT FOR", - " ", nicedate(run_datestamp ? atoi(run_datestamp) : 0), + " ", nicedate(run_datestamp ? run_datestamp : "0"), NULL); /* lookup the tapetype and printer type from the amanda.conf file. */ @@ -500,43 +615,21 @@ char **argv; /* ignore SIGPIPE so if a child process dies we do not also go away */ signal(SIGPIPE, SIG_IGN); - /* open pipe to mailer */ - - if(outfname) { - /* output to a file */ - if((mailf = fopen(outfname,"w")) == NULL) { - error("could not open output file: %s %s", outfname, strerror(errno)); - } - fprintf(mailf, "To: %s\n", getconf_str(CNF_MAILTO)); - fprintf(mailf, "Subject: %s\n\n", subj_str); - - } else { -#ifdef MAILER - mail_cmd = vstralloc(MAILER, - " -s", " \"", subj_str, "\"", - " ", getconf_str(CNF_MAILTO), - NULL); - if((mailf = popen(mail_cmd, "w")) == NULL) - error("could not open pipe to \"%s\": %s", - mail_cmd, strerror(errno)); -#endif - } - /* open pipe to print spooler if necessary) */ if(psfname) { /* if the postscript_label_template (tp->lbl_templ) field is not */ /* the empty string (i.e. it is set to something), open the */ /* postscript debugging file for writing. */ - if ((strcmp(tp->lbl_templ, "")) != 0) { + if (tp) + lbl_templ = tapetype_get_lbl_templ(tp); + if (tp && lbl_templ && strcmp(lbl_templ, "") != 0) { if ((postscript = fopen(psfname, "w")) == NULL) { curlog = L_ERROR; curprog = P_REPORTER; - curstr = vstralloc("could not open ", + curstr = vstrallocf(_("could not open %s: %s"), psfname, - ": ", - strerror(errno), - NULL); + strerror(errno)); handle_error(); amfree(curstr); } @@ -554,60 +647,128 @@ char **argv; /* print to the default printer */ printer_cmd = vstralloc(LPRCMD, NULL); #endif - - if ((strcmp(tp->lbl_templ, "")) != 0) { + if (tp) + lbl_templ = tapetype_get_lbl_templ(tp); + if (tp && lbl_templ && strcmp(lbl_templ, "") != 0) { #ifdef LPRCMD if ((postscript = popen(printer_cmd, "w")) == NULL) { curlog = L_ERROR; curprog = P_REPORTER; - curstr = vstralloc("could not open pipe to ", - printer_cmd, - ": ", - strerror(errno), - NULL); + curstr = vstrallocf(_("could not open pipe to %s: %s"), + printer_cmd, strerror(errno)); handle_error(); amfree(curstr); } #else curlog = L_ERROR; curprog = P_REPORTER; - curstr = stralloc("no printer command defined"); + curstr = vstrallocf(_("no printer command defined")); handle_error(); amfree(curstr); #endif } } - amfree(subj_str); - + sort_disks(); - if(!got_finish) fputs("*** THE DUMPS DID NOT FINISH PROPERLY!\n\n", mailf); + /* open pipe to mailer */ - output_tapeinfo(); + if(outfname) { + /* output to a file */ + if((mailf = fopen(outfname,"w")) == NULL) { + error(_("could not open output file: %s %s"), outfname, strerror(errno)); + /*NOTREACHED*/ + } + if (mailto != NULL) { + g_fprintf(mailf, "To: %s\n", mailto); + g_fprintf(mailf, "Subject: %s\n\n", subj_str); + } - if(errsum) { - fprintf(mailf,"\nFAILURE AND STRANGE DUMP SUMMARY:\n"); - output_lines(errsum, mailf); + } else if (mailer) { + if(mailto) { + send_amreport_t send_amreport; + int do_mail; + + send_amreport = getconf_send_amreport(CNF_SEND_AMREPORT_ON); + do_mail = send_amreport == SEND_AMREPORT_ALL || + (send_amreport == SEND_AMREPORT_STRANGE && + (!got_finish || first_failed || errsum || + first_strange || errdet || strangedet)) || + (send_amreport == SEND_AMREPORT_ERROR && + (!got_finish || first_failed || errsum || errdet)); + if (do_mail) { + mail_cmd = vstralloc(mailer, + " -s", " \"", subj_str, "\"", + " ", mailto, NULL); + if((mailf = popen(mail_cmd, "w")) == NULL) { + error(_("could not open pipe to \"%s\": %s"), + mail_cmd, strerror(errno)); + /*NOTREACHED*/ + } + } + } + else { + if (mailout) { + g_printf(_("No mail sent! ")); + g_printf(_("No valid mail address has been specified in amanda.conf or on the commmand line\n")); + } + mailf = NULL; + } } - fputs("\n\n", mailf); - output_stats(); + amfree(subj_str); + + if(mailf) { - if(errdet) { - fprintf(mailf,"\n\014\nFAILED AND STRANGE DUMP DETAILS:\n"); - output_lines(errdet, mailf); - } - if(notes) { - fprintf(mailf,"\n\014\nNOTES:\n"); - output_lines(notes, mailf); - } - sort_disks(); - if(sortq.head != NULL) { - fprintf(mailf,"\n\014\nDUMP SUMMARY:\n"); - output_summary(); + if(!got_finish) fputs(_("*** THE DUMPS DID NOT FINISH PROPERLY!\n\n"), mailf); + + if (ghostname) { + g_fprintf(mailf, _("Hostname: %s\n"), ghostname); + g_fprintf(mailf, _("Org : %s\n"), getconf_str(CNF_ORG)); + g_fprintf(mailf, _("Config : %s\n"), get_config_name()); + g_fprintf(mailf, _("Date : %s\n"), + nicedate(run_datestamp ? run_datestamp : "0")); + g_fprintf(mailf,"\n"); + } + + output_tapeinfo(); + + if(first_failed || errsum) { + g_fprintf(mailf,_("\nFAILURE DUMP SUMMARY:\n")); + if(first_failed) output_X_summary(first_failed); + if(errsum) output_lines(errsum, mailf); + } + if(first_strange) { + g_fprintf(mailf,_("\nSTRANGE DUMP SUMMARY:\n")); + if(first_strange) output_X_summary(first_strange); + } + fputs("\n\n", mailf); + + output_stats(); + + if(errdet) { + g_fprintf(mailf,"\n\f\n"); + g_fprintf(mailf,_("FAILED DUMP DETAILS:\n")); + output_lines(errdet, mailf); + } + if(strangedet) { + g_fprintf(mailf,"\n\f\n"); + g_fprintf(mailf,_("STRANGE DUMP DETAILS:\n")); + output_lines(strangedet, mailf); + } + if(notes) { + g_fprintf(mailf,"\n\f\n"); + g_fprintf(mailf,_("NOTES:\n")); + output_lines(notes, mailf); + } + if(sortq.head != NULL) { + g_fprintf(mailf,"\n\f\n"); + g_fprintf(mailf,_("DUMP SUMMARY:\n")); + output_summary(); + } + g_fprintf(mailf,_("\n(brought to you by Amanda version %s)\n"), + version()); } - fprintf(mailf,"\n(brought to you by Amanda version %s)\n", - version()); if (postscript) { do_postscript_output(); @@ -620,8 +781,10 @@ char **argv; afclose(postscript); } else { - if (postscript != NULL && pclose(postscript) != 0) - error("printer command failed: %s", printer_cmd); + if (postscript != NULL && pclose(postscript) != 0) { + error(_("printer command failed: %s"), printer_cmd); + /*NOTREACHED*/ + } postscript = NULL; } @@ -629,32 +792,32 @@ char **argv; if(outfname) { afclose(mailf); } - else { - if(pclose(mailf) != 0) - error("mail command failed: %s", mail_cmd); + else if(mailf) { + int exitcode; + if((exitcode = pclose(mailf)) != 0) { + char *exitstr = str_exit_status("mail command", exitcode); + error("%s", exitstr); + /*NOTREACHED*/ + } mailf = NULL; } + clear_tapelist(); + free_disklist(&diskq); amfree(run_datestamp); amfree(tape_labels); - amfree(config_dir); - amfree(config_name); amfree(printer_cmd); amfree(mail_cmd); amfree(logfname); - malloc_size_2 = malloc_inuse(&malloc_hist_2); - - if(malloc_size_1 != malloc_size_2) { - malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2); - } - - return 0; + dbclose(); + return exit_status; } /* ----- */ -#define mb(f) ((f)/1024.0) /* kbytes -> mbytes */ +#define mb(f) ((f)/1024) /* kbytes -> mbutes */ +#define du(f) ((f)/unitdivisor) /* kbytes -> displayunit */ #define pct(f) ((f)*100.0) /* percent */ #define hrmn(f) ((int)(f)+30)/3600, (((int)(f)+30)%3600)/60 #define mnsc(f) ((int)(f+0.5))/60, ((int)(f+0.5)) % 60 @@ -662,35 +825,48 @@ char **argv; #define divzero(fp,a,b) \ do { \ double q = (b); \ - if (q == 0.0) \ - fprintf((fp)," -- "); \ - else if ((q = (a)/q) >= 999.95) \ - fprintf((fp), "###.#"); \ + if (!isnormal(q)) \ + g_fprintf((fp)," -- "); \ + else if ((q = (a)/q) >= 99999.95) \ + g_fprintf((fp), "#####"); \ + else if (q >= 999.95) \ + g_fprintf((fp), "%5.0lf",q); \ else \ - fprintf((fp), "%5.1f",q); \ + g_fprintf((fp), "%5.1lf",q); \ } while(0) #define divzero_wide(fp,a,b) \ do { \ double q = (b); \ - if (q == 0.0) \ - fprintf((fp)," -- "); \ - else if ((q = (a)/q) >= 99999.95) \ - fprintf((fp), "#####.#"); \ + if (!isnormal(q)) \ + g_fprintf((fp)," -- "); \ + else if ((q = (a)/q) >= 9999999.95) \ + g_fprintf((fp), "#######"); \ + else if (q >= 99999.95) \ + g_fprintf((fp), "%7.0lf",q); \ else \ - fprintf((fp), "%7.1f",q); \ + g_fprintf((fp), "%7.1lf",q); \ } while(0) -void output_stats() +static void +output_stats(void) { double idle_time; tapetype_t *tp = lookup_tapetype(getconf_str(CNF_TAPETYPE)); - int tapesize, marksize, lv, first; + off_t tapesize; + off_t marksize; + int lv, first; - tapesize = tp->length; - marksize = tp->filemark; + if (tp) { + tapesize = tapetype_get_length(tp); + marksize = tapetype_get_filemark(tp); + } else { + tapesize = 100 * 1024 * 1024; + marksize = 1 * 1024 * 1024; + } stats[2].dumpdisks = stats[0].dumpdisks + stats[1].dumpdisks; stats[2].tapedisks = stats[0].tapedisks + stats[1].tapedisks; + stats[2].tapechunks = stats[0].tapechunks + stats[1].tapechunks; stats[2].outsize = stats[0].outsize + stats[1].outsize; stats[2].origsize = stats[0].origsize + stats[1].origsize; stats[2].tapesize = stats[0].tapesize + stats[1].tapesize; @@ -700,219 +876,282 @@ void output_stats() stats[2].dumper_time = stats[0].dumper_time + stats[1].dumper_time; if(!got_finish) /* no driver finish line, estimate total run time */ - total_time = stats[2].taper_time + startup_time; + total_time = stats[2].taper_time + planner_time; idle_time = (total_time - startup_time) - stats[2].taper_time; if(idle_time < 0) idle_time = 0.0; - fprintf(mailf,"STATISTICS:\n"); - fprintf(mailf, - " Total Full Daily\n"); - fprintf(mailf, - " -------- -------- --------\n"); + g_fprintf(mailf,_("STATISTICS:\n")); + g_fprintf(mailf, + _(" Total Full Incr.\n")); + g_fprintf(mailf, + _(" -------- -------- --------\n")); - fprintf(mailf, - "Estimate Time (hrs:min) %2d:%02d\n", hrmn(startup_time)); + g_fprintf(mailf, + _("Estimate Time (hrs:min) %2d:%02d\n"), hrmn(planner_time)); - fprintf(mailf, - "Run Time (hrs:min) %2d:%02d\n", hrmn(total_time)); + g_fprintf(mailf, + _("Run Time (hrs:min) %2d:%02d\n"), hrmn(total_time)); - fprintf(mailf, - "Dump Time (hrs:min) %2d:%02d %2d:%02d %2d:%02d\n", + g_fprintf(mailf, + _("Dump Time (hrs:min) %2d:%02d %2d:%02d %2d:%02d\n"), hrmn(stats[2].dumper_time), hrmn(stats[0].dumper_time), hrmn(stats[1].dumper_time)); - fprintf(mailf, - "Output Size (meg) %8.1f %8.1f %8.1f\n", + g_fprintf(mailf, + _("Output Size (meg) %8.1lf %8.1lf %8.1lf\n"), mb(stats[2].outsize), mb(stats[0].outsize), mb(stats[1].outsize)); - fprintf(mailf, - "Original Size (meg) %8.1f %8.1f %8.1f\n", + g_fprintf(mailf, + _("Original Size (meg) %8.1lf %8.1lf %8.1lf\n"), mb(stats[2].origsize), mb(stats[0].origsize), mb(stats[1].origsize)); - fprintf(mailf, "Avg Compressed Size (%%) "); + g_fprintf(mailf, _("Avg Compressed Size (%%) ")); divzero(mailf, pct(stats[2].coutsize),stats[2].corigsize); - fputs(" ", mailf); + fputs(_(" "), mailf); divzero(mailf, pct(stats[0].coutsize),stats[0].corigsize); - fputs(" ", mailf); + fputs(_(" "), mailf); divzero(mailf, pct(stats[1].coutsize),stats[1].corigsize); - if(stats[1].dumpdisks > 0) fputs(" (level:#disks ...)", mailf); + if(stats[1].dumpdisks > 0) fputs(_(" (level:#disks ...)"), mailf); putc('\n', mailf); - fprintf(mailf, - "Filesystems Dumped %4d %4d %4d", + g_fprintf(mailf, + _("Filesystems Dumped %4d %4d %4d"), stats[2].dumpdisks, stats[0].dumpdisks, stats[1].dumpdisks); if(stats[1].dumpdisks > 0) { first = 1; for(lv = 1; lv < 10; lv++) if(dumpdisks[lv]) { - fputs(first?" (":" ", mailf); + fputs(first?_(" ("):_(" "), mailf); first = 0; - fprintf(mailf, "%d:%d", lv, dumpdisks[lv]); + g_fprintf(mailf, _("%d:%d"), lv, dumpdisks[lv]); } putc(')', mailf); } putc('\n', mailf); - fprintf(mailf, "Avg Dump Rate (k/s) "); + g_fprintf(mailf, _("Avg Dump Rate (k/s) ")); divzero_wide(mailf, stats[2].outsize,stats[2].dumper_time); - fputs(" ", mailf); + fputs(_(" "), mailf); divzero_wide(mailf, stats[0].outsize,stats[0].dumper_time); - fputs(" ", mailf); + fputs(_(" "), mailf); divzero_wide(mailf, stats[1].outsize,stats[1].dumper_time); putc('\n', mailf); putc('\n', mailf); - fprintf(mailf, - "Tape Time (hrs:min) %2d:%02d %2d:%02d %2d:%02d\n", + g_fprintf(mailf, + _("Tape Time (hrs:min) %2d:%02d %2d:%02d %2d:%02d\n"), hrmn(stats[2].taper_time), hrmn(stats[0].taper_time), hrmn(stats[1].taper_time)); - fprintf(mailf, - "Tape Size (meg) %8.1f %8.1f %8.1f\n", + g_fprintf(mailf, + _("Tape Size (meg) %8.1lf %8.1lf %8.1lf\n"), mb(stats[2].tapesize), mb(stats[0].tapesize), mb(stats[1].tapesize)); - fprintf(mailf, "Tape Used (%%) "); - divzero(mailf, pct(stats[2].tapesize+marksize*stats[2].tapedisks),tapesize); - fputs(" ", mailf); - divzero(mailf, pct(stats[0].tapesize+marksize*stats[0].tapedisks),tapesize); - fputs(" ", mailf); - divzero(mailf, pct(stats[1].tapesize+marksize*stats[1].tapedisks),tapesize); + g_fprintf(mailf, _("Tape Used (%%) ")); + divzero(mailf, pct(stats[2].tapesize+marksize*(stats[2].tapedisks+stats[2].tapechunks)),(double)tapesize); + fputs(_(" "), mailf); + divzero(mailf, pct(stats[0].tapesize+marksize*(stats[0].tapedisks+stats[0].tapechunks)),(double)tapesize); + fputs(_(" "), mailf); + divzero(mailf, pct(stats[1].tapesize+marksize*(stats[1].tapedisks+stats[1].tapechunks)),(double)tapesize); - if(stats[1].tapedisks > 0) fputs(" (level:#disks ...)", mailf); + if(stats[1].tapedisks > 0) fputs(_(" (level:#disks ...)"), mailf); putc('\n', mailf); - fprintf(mailf, - "Filesystems Taped %4d %4d %4d", + g_fprintf(mailf, + _("Filesystems Taped %4d %4d %4d"), stats[2].tapedisks, stats[0].tapedisks, stats[1].tapedisks); if(stats[1].tapedisks > 0) { first = 1; for(lv = 1; lv < 10; lv++) if(tapedisks[lv]) { - fputs(first?" (":" ", mailf); + fputs(first?_(" ("):_(" "), mailf); first = 0; - fprintf(mailf, "%d:%d", lv, tapedisks[lv]); + g_fprintf(mailf, _("%d:%d"), lv, tapedisks[lv]); } putc(')', mailf); } putc('\n', mailf); - fprintf(mailf, "Avg Tp Write Rate (k/s) "); + if(stats[1].tapechunks > 0) fputs(_(" (level:#chunks ...)"), mailf); + putc('\n', mailf); + + g_fprintf(mailf, + _("Chunks Taped %4d %4d %4d"), + stats[2].tapechunks, stats[0].tapechunks, stats[1].tapechunks); + + if(stats[1].tapechunks > 0) { + first = 1; + for(lv = 1; lv < 10; lv++) if(tapechunks[lv]) { + fputs(first?_(" ("):_(" "), mailf); + first = 0; + g_fprintf(mailf, _("%d:%d"), lv, tapechunks[lv]); + } + putc(')', mailf); + } + putc('\n', mailf); + + g_fprintf(mailf, _("Avg Tp Write Rate (k/s) ")); divzero_wide(mailf, stats[2].tapesize,stats[2].taper_time); - fputs(" ", mailf); + fputs(_(" "), mailf); divzero_wide(mailf, stats[0].tapesize,stats[0].taper_time); - fputs(" ", mailf); + fputs(_(" "), mailf); divzero_wide(mailf, stats[1].tapesize,stats[1].taper_time); putc('\n', mailf); if(stats_by_tape) { - int label_length = strlen(stats_by_tape->label) + 5; - fprintf(mailf,"\nUSAGE BY TAPE:\n"); - fprintf(mailf," %-*s Time Size %% Nb\n", - label_length, "Label"); + int label_length = (int)strlen(stats_by_tape->label) + 5; + g_fprintf(mailf,_("\nUSAGE BY TAPE:\n")); + g_fprintf(mailf,_(" %-*s Time Size %% Nb Nc\n"), + label_length, _("Label")); for(current_tape = stats_by_tape; current_tape != NULL; current_tape = current_tape->next) { - fprintf(mailf, " %-*s", label_length, current_tape->label); - fprintf(mailf, " %2d:%02d", hrmn(current_tape->taper_time)); - fprintf(mailf, " %9.1f ", mb(current_tape->coutsize)); - divzero(mailf, pct(current_tape->coutsize + - marksize * current_tape->tapedisks), - tapesize); - fprintf(mailf, " %4d\n", current_tape->tapedisks); + g_fprintf(mailf, _(" %-*s"), label_length, current_tape->label); + g_fprintf(mailf, _(" %2d:%02d"), hrmn(current_tape->taper_time)); + g_fprintf(mailf, _(" %8.0lf%s "), du(current_tape->coutsize), displayunit); + divzero(mailf, pct(current_tape->coutsize + marksize * + (current_tape->tapedisks+current_tape->tapechunks)), + (double)tapesize); + g_fprintf(mailf, _(" %4d"), current_tape->tapedisks); + g_fprintf(mailf, _(" %4d\n"), current_tape->tapechunks); } } - } /* ----- */ -void output_tapeinfo() +static void +output_tapeinfo(void) { - tape_t *tp, *lasttp; + tape_t *tp; int run_tapes; int skip = 0; + int i, nb_new_tape; if (last_run_tapes > 0) { if(amflush_run) - fprintf(mailf, "The dumps were flushed to tape%s %s.\n", - last_run_tapes == 1 ? "" : "s", + g_fprintf(mailf, + plural(_("The dumps were flushed to tape %s.\n"), + _("The dumps were flushed to tapes %s.\n"), + last_run_tapes), tape_labels ? tape_labels : ""); else - fprintf(mailf, "These dumps were to tape%s %s.\n", - last_run_tapes == 1 ? "" : "s", + g_fprintf(mailf, + plural(_("These dumps were to tape %s.\n"), + _("These dumps were to tapes %s.\n"), + last_run_tapes), tape_labels ? tape_labels : ""); } if(degraded_mode) { - fprintf(mailf, - "*** A TAPE ERROR OCCURRED: %s.\n", tapestart_error); - fputs("Some dumps may have been left in the holding disk.\n", mailf); - fprintf(mailf, - "Run amflush%s to flush them to tape.\n", - amflush_run ? " again" : ""); + g_fprintf(mailf, + _("*** A TAPE ERROR OCCURRED: %s.\n"), tapestart_error); + } + if (cmdlogfname == 1) { + if(degraded_mode) { + fputs(_("Some dumps may have been left in the holding disk.\n"), + mailf); + g_fprintf(mailf,"\n"); + } + } else { + GSList *holding_list, *holding_file; + off_t h_size = 0, mh_size; + + holding_list = holding_get_files_for_flush(NULL); + for(holding_file=holding_list; holding_file != NULL; + holding_file = holding_file->next) { + mh_size = holding_file_size((char *)holding_file->data, 1); + if (mh_size > 0) + h_size += mh_size; + } + + if (h_size > 0) { + g_fprintf(mailf, + _("There are %lld%s of dumps left in the holding disk.\n"), + (long long)du(h_size), displayunit); + if (getconf_boolean(CNF_AUTOFLUSH)) { + g_fprintf(mailf, _("They will be flushed on the next run.\n")); + } else { + g_fprintf(mailf, _("Run amflush to flush them to tape.\n")); + } + g_fprintf(mailf,"\n"); + } else if (degraded_mode) { + g_fprintf(mailf, _("No dumps are left in the holding disk. %lld%s\n"), (long long)h_size, displayunit); + g_fprintf(mailf,"\n"); + } } tp = lookup_last_reusable_tape(skip); run_tapes = getconf_int(CNF_RUNTAPES); - if (run_tapes <= 1) - fputs("The next tape Amanda expects to use is: ", mailf); - else - fprintf(mailf, "The next %d tapes Amanda expects to used are: ", + if (run_tapes == 1) + fputs(_("The next tape Amanda expects to use is: "), mailf); + else if(run_tapes > 1) + g_fprintf(mailf, _("The next %d tapes Amanda expects to use are: "), run_tapes); - - while(run_tapes > 0) { - if(tp != NULL) - fprintf(mailf, "%s", tp->label); - else - fputs("a new tape", mailf); - if(run_tapes > 1) fputs(", ", mailf); - - run_tapes -= 1; + nb_new_tape = 0; + for (i=0 ; i < run_tapes ; i++) { + if(tp != NULL) { + if (nb_new_tape > 0) { + if (nb_new_tape == 1) + g_fprintf(mailf, _("1 new tape, ")); + else + g_fprintf(mailf, _("%d new tapes, "), nb_new_tape); + nb_new_tape = 0; + } + g_fprintf(mailf, "%s", tp->label); + if (i < run_tapes-1) fputs(", ", mailf); + } else { + nb_new_tape++; + } skip++; + tp = lookup_last_reusable_tape(skip); } + if (nb_new_tape > 0) { + if (nb_new_tape == 1) + g_fprintf(mailf, _("1 new tape")); + else + g_fprintf(mailf, _("%d new tapes"), nb_new_tape); + } fputs(".\n", mailf); - lasttp = lookup_tapepos(lookup_nb_tape()); run_tapes = getconf_int(CNF_RUNTAPES); - if(lasttp && run_tapes > 0 && lasttp->datestamp == 0) { - int c = 0; - while(lasttp && run_tapes > 0 && lasttp->datestamp == 0) { - c++; - lasttp = lasttp->prev; - run_tapes--; - } - lasttp = lookup_tapepos(lookup_nb_tape()); - if(c == 1) { - fprintf(mailf, "The next new tape already labelled is: %s.\n", - lasttp->label); - } - else { - fprintf(mailf, "The next %d new tapes already labelled are: %s", c, - lasttp->label); - lasttp = lasttp->prev; - c--; - while(lasttp && c > 0 && lasttp->datestamp == 0) { - fprintf(mailf, ", %s", lasttp->label); - lasttp = lasttp->prev; - c--; - } - fprintf(mailf, ".\n"); - } - } + print_new_tapes(mailf, run_tapes); } /* ----- */ +static void +output_X_summary( + X_summary_t *first) +{ + size_t len_host=0, len_disk=0; + X_summary_t *strange; + char *str = NULL; + + for(strange=first; strange != NULL; strange = strange->next) { + if(strlen(strange->hostname) > len_host) + len_host = strlen(strange->hostname); + if(strlen(strange->diskname) > len_disk) + len_disk = strlen(strange->diskname); + } + for(strange=first; strange != NULL; strange = strange->next) { + str = vstralloc(" ", prefixstrange(strange->hostname, strange->diskname, strange->level, len_host, len_disk), + " ", strange->str, NULL); + g_fprintf(mailf, "%s\n", str); + amfree(str); + } +} -void output_lines(lp, f) -line_t *lp; -FILE *f; +static void +output_lines( + line_t * lp, + FILE * f) { line_t *next; @@ -928,14 +1167,10 @@ FILE *f; /* ----- */ -int sort_by_time(a, b) -disk_t *a, *b; -{ - return data(b)->dumper.sec - data(a)->dumper.sec; -} - -int sort_by_name(a, b) -disk_t *a, *b; +static int +sort_by_name( + disk_t * a, + disk_t * b) { int rc; @@ -944,13 +1179,14 @@ disk_t *a, *b; return rc; } -void sort_disks() +static void +sort_disks(void) { disk_t *dp; sortq.head = sortq.tail = NULL; - while(!empty(*diskq)) { - dp = dequeue_disk(diskq); + while(!empty(diskq)) { + dp = dequeue_disk(&diskq); if(data(dp) == NULL) { /* create one */ find_repdata(dp, run_datestamp, 0); } @@ -958,33 +1194,48 @@ void sort_disks() } } -void CheckStringMax(ColumnInfo *cd, char *s) { +static void +CheckStringMax( + ColumnInfo *cd, + char * s) +{ if (cd->MaxWidth) { - int l= strlen(s); + int l = (int)strlen(s); + if (cd->Width < l) cd->Width= l; } } -void CheckIntMax(ColumnInfo *cd, int n) { +static void +CheckIntMax( + ColumnInfo *cd, + int n) +{ if (cd->MaxWidth) { char testBuf[200]; int l; - ap_snprintf(testBuf, sizeof(testBuf), + + g_snprintf(testBuf, SIZEOF(testBuf), cd->Format, cd->Width, cd->Precision, n); - l= strlen(testBuf); + l = (int)strlen(testBuf); if (cd->Width < l) cd->Width= l; } } -void CheckFloatMax(ColumnInfo *cd, double d) { +static void +CheckFloatMax( + ColumnInfo *cd, + double d) +{ if (cd->MaxWidth) { char testBuf[200]; int l; - ap_snprintf(testBuf, sizeof(testBuf), + + g_snprintf(testBuf, SIZEOF(testBuf), cd->Format, cd->Width, cd->Precision, d); - l= strlen(testBuf); + l = (int)strlen(testBuf); if (cd->Width < l) cd->Width= l; } @@ -1001,7 +1252,9 @@ static int DumpRate; static int TapeTime; static int TapeRate; -void CalcMaxWidth() { +static void +CalcMaxWidth(void) +{ /* we have to look for columspec's, that require the recalculation. * we do here the same loops over the sortq as is done in * output_summary. So, if anything is changed there, we have to @@ -1009,66 +1262,81 @@ void CalcMaxWidth() { * ElB, 1999-02-24. */ disk_t *dp; - float f; + double f; repdata_t *repdata; + char *qdevname; + int i, l; + + for (i=0;ColumnData[i].Name != NULL; i++) { + if (ColumnData[i].MaxWidth) { + l = (int)strlen(ColumnData[i].Title); + if (ColumnData[i].Width < l) + ColumnData[i].Width= l; + } + } for(dp = sortq.head; dp != NULL; dp = dp->next) { if(dp->todo) { for(repdata = data(dp); repdata != NULL; repdata = repdata->next) { - ColumnInfo *cd; char TimeRateBuffer[40]; CheckStringMax(&ColumnData[HostName], dp->host->hostname); - CheckStringMax(&ColumnData[Disk], dp->name); + qdevname = quote_string(dp->name); + CheckStringMax(&ColumnData[Disk], qdevname); + amfree(qdevname); if (repdata->dumper.result == L_BOGUS && repdata->taper.result == L_BOGUS) continue; CheckIntMax(&ColumnData[Level], repdata->level); - if(repdata->dumper.result == L_SUCCESS) { - CheckFloatMax(&ColumnData[OrigKB], repdata->dumper.origsize); - CheckFloatMax(&ColumnData[OutKB], repdata->dumper.outsize); - if(dp->compress == COMP_NONE) + if(repdata->dumper.result == L_SUCCESS || + repdata->dumper.result == L_CHUNKSUCCESS) { + CheckFloatMax(&ColumnData[OrigKB], + (double)du(repdata->dumper.origsize)); + CheckFloatMax(&ColumnData[OutKB], + (double)du(repdata->dumper.outsize)); + if(abs(repdata->dumper.outsize - repdata->dumper.origsize)< 32) f = 0.0; else f = repdata->dumper.origsize; - CheckStringMax(&ColumnData[Disk], + CheckStringMax(&ColumnData[Compress], sDivZero(pct(repdata->dumper.outsize), f, Compress)); if(!amflush_run) - ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer), + g_snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer), "%3d:%02d", mnsc(repdata->dumper.sec)); else - ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer), - "N/A "); + g_snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer), + " "); CheckStringMax(&ColumnData[DumpTime], TimeRateBuffer); CheckFloatMax(&ColumnData[DumpRate], repdata->dumper.kps); } - cd= &ColumnData[TapeTime]; if(repdata->taper.result == L_FAIL) { - CheckStringMax(cd, "FAILED"); + CheckStringMax(&ColumnData[TapeTime], "FAILED"); continue; } - if(repdata->taper.result == L_SUCCESS) - ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer), + if(repdata->taper.result == L_SUCCESS || + repdata->taper.result == L_CHUNKSUCCESS) + g_snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer), "%3d:%02d", mnsc(repdata->taper.sec)); else - ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer), - "N/A "); - CheckStringMax(cd, TimeRateBuffer); + g_snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer), + " "); + CheckStringMax(&ColumnData[TapeTime], TimeRateBuffer); - cd= &ColumnData[TapeRate]; - if(repdata->taper.result == L_SUCCESS) - CheckFloatMax(cd, repdata->taper.kps); + if(repdata->taper.result == L_SUCCESS || + repdata->taper.result == L_CHUNKSUCCESS) + CheckFloatMax(&ColumnData[TapeRate], repdata->taper.kps); else - CheckStringMax(cd, "N/A "); + CheckStringMax(&ColumnData[TapeRate], " "); } } } } -void output_summary() +static void +output_summary(void) { disk_t *dp; repdata_t *repdata; @@ -1077,8 +1345,9 @@ void output_summary() char *tmp; int i, h, w1, wDump, wTape; - float outsize, origsize; - float f; + double outsize, origsize; + double f; + int cdWidth; HostName = StringToColumn("HostName"); Disk = StringToColumn("Disk"); @@ -1101,34 +1370,44 @@ void output_summary() wTape= ColWidth(TapeTime, TapeRate); /* print centered top titles */ - h= strlen(ds); + h = (int)strlen(ds); if (h > wDump) { - h= 0; + h = 0; } else { - h= (wDump-h)/2; + h = (wDump-h)/2; } - fprintf(mailf, "%*s", w1+h, ""); - fprintf(mailf, "%-*s", wDump-h, ds); - h= strlen(ts); + g_fprintf(mailf, "%*s", w1+h, ""); + g_fprintf(mailf, "%-*s", wDump-h, ds); + h = (int)strlen(ts); if (h > wTape) { - h= 0; + h = 0; } else { - h= (wTape-h)/2; + h = (wTape-h)/2; } - fprintf(mailf, "%*s", h, ""); - fprintf(mailf, "%-*s", wTape-h, ts); + g_fprintf(mailf, "%*s", h, ""); + g_fprintf(mailf, "%-*s", wTape-h, ts); fputc('\n', mailf); /* print the titles */ for (i=0; ColumnData[i].Name != NULL; i++) { char *fmt; ColumnInfo *cd= &ColumnData[i]; - fprintf(mailf, "%*s", cd->PrefixSpace, ""); + g_fprintf(mailf, "%*s", cd->PrefixSpace, ""); if (cd->Format[1] == '-') fmt= "%-*s"; else fmt= "%*s"; - fprintf(mailf, fmt, cd->Width, cd->Title); + if(strcmp(cd->Title,"ORIG-KB") == 0) { + /* cd->Title must be re-allocated in write-memory */ + cd->Title = stralloc("ORIG-KB"); + cd->Title[5] = displayunit[0]; + } + if(strcmp(cd->Title,"OUT-KB") == 0) { + /* cd->Title must be re-allocated in write-memory */ + cd->Title = stralloc("OUT-KB"); + cd->Title[4] = displayunit[0]; + } + g_fprintf(mailf, fmt, cd->Width, cd->Title); } fputc('\n', mailf); @@ -1143,80 +1422,101 @@ void output_summary() ColumnInfo *cd; char TimeRateBuffer[40]; for(repdata = data(dp); repdata != NULL; repdata = repdata->next) { - int devlen; + char *devname; + char *qdevname; + size_t devlen; cd= &ColumnData[HostName]; - fprintf(mailf, "%*s", cd->PrefixSpace, ""); - fprintf(mailf, cd->Format, cd->Width, cd->Width, dp->host->hostname); + g_fprintf(mailf, "%*s", cd->PrefixSpace, ""); + g_fprintf(mailf, cd->Format, cd->Width, cd->Width, dp->host->hostname); cd= &ColumnData[Disk]; - fprintf(mailf, "%*s", cd->PrefixSpace, ""); - devlen= strlen(dp->name); - if (devlen > cd->Width) { - fputc('-', mailf); - fprintf(mailf, cd->Format, cd->Width-1, cd->Precision-1, - dp->name+devlen - (cd->Width-1) ); + g_fprintf(mailf, "%*s", cd->PrefixSpace, ""); + devname = sanitize_string(dp->name); + qdevname = quote_string(devname); + devlen = strlen(qdevname); + if (devlen > (size_t)cd->Width) { + int nb = 1; + if (strcmp(devname, qdevname)) { + nb = 2; + fputc('"', mailf); + } + fputc('-', mailf); + g_fprintf(mailf, cd->Format, cd->Width-nb, cd->Precision-nb, + qdevname+devlen - (cd->Width-nb) ); } else - fprintf(mailf, cd->Format, cd->Width, cd->Width, dp->name); - + g_fprintf(mailf, cd->Format, cd->Width, cd->Width, qdevname); + amfree(devname); + amfree(qdevname); cd= &ColumnData[Level]; if (repdata->dumper.result == L_BOGUS && repdata->taper.result == L_BOGUS) { if(amflush_run){ - fprintf(mailf, "%*s%s\n", cd->PrefixSpace+cd->Width, "", + g_fprintf(mailf, "%*s%s\n", cd->PrefixSpace+cd->Width, "", tmp=TextRule(OrigKB, TapeRate, "NO FILE TO FLUSH")); } else { - fprintf(mailf, "%*s%s\n", cd->PrefixSpace+cd->Width, "", + g_fprintf(mailf, "%*s%s\n", cd->PrefixSpace+cd->Width, "", tmp=TextRule(OrigKB, TapeRate, "MISSING")); } amfree(tmp); continue; } - cd= &ColumnData[Level]; - fprintf(mailf, "%*s", cd->PrefixSpace, ""); - fprintf(mailf, cd->Format, cd->Width, cd->Precision,repdata->level); + g_fprintf(mailf, "%*s", cd->PrefixSpace, ""); + g_fprintf(mailf, cd->Format, cd->Width, cd->Precision,repdata->level); if (repdata->dumper.result == L_SKIPPED) { - fprintf(mailf, "%s\n", + g_fprintf(mailf, "%s\n", tmp=TextRule(OrigKB, TapeRate, "SKIPPED")); amfree(tmp); continue; } - if (repdata->dumper.result == L_FAIL) { - fprintf(mailf, "%s\n", + if (repdata->dumper.result == L_FAIL && (repdata->chunker.result != L_PARTIAL && repdata->taper.result != L_PARTIAL)) { + g_fprintf(mailf, "%s\n", tmp=TextRule(OrigKB, TapeRate, "FAILED")); amfree(tmp); + exit_status |= STATUS_FAILED; continue; } - if(repdata->dumper.result == L_SUCCESS) + if(repdata->dumper.result == L_SUCCESS || + repdata->dumper.result == L_CHUNKSUCCESS) origsize = repdata->dumper.origsize; - else + else if(repdata->taper.result == L_SUCCESS || + repdata->taper.result == L_PARTIAL) origsize = repdata->taper.origsize; + else + origsize = repdata->chunker.origsize; - if(repdata->taper.result == L_SUCCESS) + if(repdata->taper.result == L_SUCCESS || + repdata->taper.result == L_CHUNKSUCCESS) + outsize = repdata->taper.outsize; + else if(repdata->chunker.result == L_SUCCESS || + repdata->chunker.result == L_PARTIAL || + repdata->chunker.result == L_CHUNKSUCCESS) + outsize = repdata->chunker.outsize; + else if (repdata->taper.result == L_PARTIAL) outsize = repdata->taper.outsize; else outsize = repdata->dumper.outsize; cd= &ColumnData[OrigKB]; - fprintf(mailf, "%*s", cd->PrefixSpace, ""); - if(origsize != 0.0) - fprintf(mailf, cd->Format, cd->Width, cd->Precision, origsize); + g_fprintf(mailf, "%*s", cd->PrefixSpace, ""); + if(isnormal(origsize)) + g_fprintf(mailf, cd->Format, cd->Width, cd->Precision, du(origsize)); else - fprintf(mailf, "%*.*s", cd->Width, cd->Width, "N/A"); + g_fprintf(mailf, "%*.*s", cd->Width, cd->Width, ""); cd= &ColumnData[OutKB]; - fprintf(mailf, "%*s", cd->PrefixSpace, ""); + g_fprintf(mailf, "%*s", cd->PrefixSpace, ""); - fprintf(mailf, cd->Format, cd->Width, cd->Precision, outsize); + g_fprintf(mailf, cd->Format, cd->Width, cd->Precision, du(outsize)); cd= &ColumnData[Compress]; - fprintf(mailf, "%*s", cd->PrefixSpace, ""); + g_fprintf(mailf, "%*s", cd->PrefixSpace, ""); - if(dp->compress == COMP_NONE) + if(abs(outsize - origsize) < 32) f = 0.0; else if(origsize < 1.0) f = 0.0; @@ -1226,83 +1526,147 @@ void output_summary() fputs(sDivZero(pct(outsize), f, Compress), mailf); cd= &ColumnData[DumpTime]; - fprintf(mailf, "%*s", cd->PrefixSpace, ""); - if(repdata->dumper.result == L_SUCCESS) - ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer), - "%3d:%02d", mnsc(repdata->dumper.sec)); - else - ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer), - "N/A "); - fprintf(mailf, cd->Format, cd->Width, cd->Width, TimeRateBuffer); + cdWidth = 0; + g_fprintf(mailf, "%*s", cd->PrefixSpace, ""); + if(repdata->dumper.result == L_SUCCESS || + repdata->dumper.result == L_CHUNKSUCCESS) { + g_snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer), + "%3d:%02d", mnsc(repdata->dumper.sec)); + g_fprintf(mailf, cd->Format, cd->Width, cd->Width, + TimeRateBuffer); + } else { + cdWidth = cd->Width; + } cd= &ColumnData[DumpRate]; - fprintf(mailf, "%*s", cd->PrefixSpace, ""); - if(repdata->dumper.result == L_SUCCESS) - fprintf(mailf, cd->Format, cd->Width, cd->Precision, repdata->dumper.kps); - else - fprintf(mailf, "%*s", cd->Width, "N/A "); + g_fprintf(mailf, "%*s", cd->PrefixSpace, ""); + if (repdata->dumper.result == L_SUCCESS || + repdata->dumper.result == L_CHUNKSUCCESS) { + g_fprintf(mailf, cd->Format, cd->Width, cd->Precision, + repdata->dumper.kps); + } else if (repdata->dumper.result == L_FAIL) { + if (repdata->chunker.result == L_PARTIAL || + repdata->taper.result == L_PARTIAL) { + int i; + cdWidth += cd->Width; + i = (cdWidth - strlen("PARTIAL")) / 2; + g_fprintf(mailf, "%*s%*s", cdWidth-i, "PARTIAL", i, ""); + } else { + int i; + cdWidth += cd->Width; + i = (cdWidth - strlen("FAILED")) / 2; + g_fprintf(mailf, "%*s%*s", cdWidth-i, "FAILED", i, ""); + } + } else if (repdata->dumper.result == L_BOGUS) { + int i; + cdWidth += cd->Width; + i = (cdWidth - strlen("FLUSH")) / 2; + g_fprintf(mailf, "%*s%*s", cdWidth-i, "FLUSH", i, ""); + } else { + cdWidth += cd->Width; + g_fprintf(mailf, "%*s", cdWidth, ""); + } cd= &ColumnData[TapeTime]; - fprintf(mailf, "%*s", cd->PrefixSpace, ""); + g_fprintf(mailf, "%*s", cd->PrefixSpace, ""); if(repdata->taper.result == L_FAIL) { - fprintf(mailf, "%s\n", + g_fprintf(mailf, "%s\n", tmp=TextRule(TapeTime, TapeRate, "FAILED ")); amfree(tmp); continue; } - if(repdata->taper.result == L_SUCCESS) - ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer), + if(repdata->taper.result == L_SUCCESS || + repdata->taper.result == L_PARTIAL || + repdata->taper.result == L_CHUNKSUCCESS) + g_snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer), "%3d:%02d", mnsc(repdata->taper.sec)); else - ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer), - "N/A "); - fprintf(mailf, cd->Format, cd->Width, cd->Width, TimeRateBuffer); + g_snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer), + " "); + g_fprintf(mailf, cd->Format, cd->Width, cd->Width, TimeRateBuffer); cd= &ColumnData[TapeRate]; - fprintf(mailf, "%*s", cd->PrefixSpace, ""); - if(repdata->taper.result == L_SUCCESS) - fprintf(mailf, cd->Format, cd->Width, cd->Precision, repdata->taper.kps); + g_fprintf(mailf, "%*s", cd->PrefixSpace, ""); + if(repdata->taper.result == L_SUCCESS || + repdata->taper.result == L_PARTIAL || + repdata->taper.result == L_CHUNKSUCCESS) + g_fprintf(mailf, cd->Format, cd->Width, cd->Precision, repdata->taper.kps); else - fprintf(mailf, "%*s", cd->Width, "N/A "); + g_fprintf(mailf, "%*s", cd->Width, " "); + + if (repdata->chunker.result == L_PARTIAL) + g_fprintf(mailf, " PARTIAL"); + else if(repdata->taper.result == L_PARTIAL) + g_fprintf(mailf, " TAPE-PARTIAL"); + fputc('\n', mailf); } } } } -void bogus_line() +static void +bogus_line( + const char *err_text) { - printf("line %d of log is bogus\n", curlinenum); + char * s; + s = g_strdup_printf(_("line %d of log is bogus: <%s %s %s>\n"), + curlinenum, + logtype_str[curlog], program_str[curprog], curstr); + g_printf("%s\n", s); + g_printf(_(" Scan failed at: <%s>\n"), err_text); + addline(&errsum, s); + amfree(s); } -char *nicedate(datestamp) -int datestamp; /* - * Formats an integer of the form YYYYMMDD into the string + * Formats an integer of the form YYYYMMDDHHMMSS into the string * "Monthname DD, YYYY". A pointer to the statically allocated string * is returned, so it must be copied to other storage (or just printed) * before calling nicedate() again. */ +static char * +nicedate( + const char *datestamp) { static char nice[64]; - static char *months[13] = { "BogusMonth", - "January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December" + char date[9]; + int numdate; + static char *months[13] = { + T_("BogusMonth"), + T_("January"), + T_("February"), + T_("March"), + T_("April"), + T_("May"), + T_("June"), + T_("July"), + T_("August"), + T_("September"), + T_("October"), + T_("November"), + T_("December") }; int year, month, day; - year = datestamp / 10000; - day = datestamp % 100; - month = (datestamp / 100) % 100; + strncpy(date, datestamp, 8); + date[8] = '\0'; + numdate = atoi(date); + year = numdate / 10000; + day = numdate % 100; + month = (numdate / 100) % 100; + if (month > 12 ) + month = 0; - ap_snprintf(nice, sizeof(nice), "%s %d, %d", months[month], day, year); + g_snprintf(nice, SIZEOF(nice), "%s %d, %d", _(months[month]), day, year); return nice; } -void handle_start() +static void +handle_start(void) { static int started = 0; char *label; @@ -1315,37 +1679,31 @@ void handle_start() ch = *s++; skip_whitespace(s, ch); -#define sc "datestamp" - if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) { - bogus_line(); + if(ch == '\0' || strncmp_const_skip(s - 1, "datestamp", s, ch) != 0) { + bogus_line(s - 1); return; } - s += sizeof(sc)-1; - ch = s[-1]; -#undef sc + skip_whitespace(s, ch); if(ch == '\0') { - bogus_line(); + bogus_line(s - 1); return; } fp = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; run_datestamp = newstralloc(run_datestamp, fp); - s[-1] = ch; + s[-1] = (char)ch; skip_whitespace(s, ch); -#define sc "label" - if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) { - bogus_line(); + if(ch == '\0' || strncmp_const_skip(s - 1, "label", s, ch) != 0) { + bogus_line(s - 1); return; } - s += sizeof(sc)-1; - ch = s[-1]; -#undef sc + skip_whitespace(s, ch); if(ch == '\0') { - bogus_line(); + bogus_line(s - 1); return; } fp = s - 1; @@ -1353,7 +1711,7 @@ void handle_start() s[-1] = '\0'; label = stralloc(fp); - s[-1] = ch; + s[-1] = (char)ch; if(tape_labels) { fp = vstralloc(tape_labels, ", ", label, NULL); @@ -1366,10 +1724,10 @@ void handle_start() last_run_tapes++; if(stats_by_tape == NULL) { - stats_by_tape = current_tape = (taper_t *)alloc(sizeof(taper_t)); + stats_by_tape = current_tape = (taper_t *)alloc(SIZEOF(taper_t)); } else { - current_tape->next = (taper_t *)alloc(sizeof(taper_t)); + current_tape->next = (taper_t *)alloc(SIZEOF(taper_t)); current_tape = current_tape->next; } current_tape->label = label; @@ -1377,6 +1735,7 @@ void handle_start() current_tape->coutsize = 0.0; current_tape->corigsize = 0.0; current_tape->tapedisks = 0; + current_tape->tapechunks = 0; current_tape->next = NULL; tapefcount = 0; @@ -1398,129 +1757,242 @@ void handle_start() ch = *s++; skip_whitespace(s, ch); -#define sc "date" - if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) { + if(ch == '\0' || strncmp_const_skip(s - 1, "date", s, ch) != 0) { return; /* ignore bogus line */ } - s += sizeof(sc)-1; - ch = s[-1]; -#undef sc + skip_whitespace(s, ch); if(ch == '\0') { - bogus_line(); + bogus_line(s - 1); return; } fp = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; run_datestamp = newstralloc(run_datestamp, fp); - s[-1] = ch; + s[-1] = (char)ch; started = 1; } if(amflush_run && normal_run) { amflush_run = 0; addline(¬es, - " reporter: both amflush and planner output in log, ignoring amflush."); + _(" reporter: both amflush and planner output in log, ignoring amflush.")); } } -void handle_finish() +static void +handle_finish(void) { char *s; int ch; + double a_time; - if(curprog == P_DRIVER || curprog == P_AMFLUSH) { + if(curprog == P_DRIVER || curprog == P_AMFLUSH || curprog == P_PLANNER) { s = curstr; ch = *s++; skip_whitespace(s, ch); -#define sc "date" - if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) { - bogus_line(); + if(ch == '\0' || strncmp_const_skip(s - 1, "date", s, ch) != 0) { + bogus_line(s - 1); return; } - s += sizeof(sc)-1; - ch = s[-1]; -#undef sc skip_whitespace(s, ch); if(ch == '\0') { - bogus_line(); + bogus_line(s - 1); return; } skip_non_whitespace(s, ch); /* ignore the date string */ skip_whitespace(s, ch); -#define sc "time" - if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) { - bogus_line(); + if(ch == '\0' || strncmp_const_skip(s - 1, "time", s, ch) != 0) { + /* older planner doesn't write time */ + if(curprog == P_PLANNER) return; + bogus_line(s - 1); return; } - s += sizeof(sc)-1; - ch = s[-1]; -#undef sc skip_whitespace(s, ch); if(ch == '\0') { - bogus_line(); + bogus_line(s - 1); return; } - if(sscanf(s - 1, "%f", &total_time) != 1) { - bogus_line(); + if(sscanf(s - 1, "%lf", &a_time) != 1) { + bogus_line(s - 1); return; } - - got_finish = 1; + if(curprog == P_PLANNER) { + planner_time = a_time; + } + else { + total_time = a_time; + got_finish = 1; + } } } -void handle_stats() +static void +handle_stats(void) { - char *s; + char *s, *fp; int ch; + char *hostname, *diskname, *datestamp, *qdiskname; + int level = 0; + double sec, kps, nbytes, cbytes; + repdata_t *repdata; + disk_t *dp; if(curprog == P_DRIVER) { s = curstr; ch = *s++; skip_whitespace(s, ch); -#define sc "startup time" - if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) { - bogus_line(); - return; + if(ch != '\0' && strncmp_const_skip(s - 1, "startup time", s, ch) == 0) { + skip_whitespace(s, ch); + if(ch == '\0') { + bogus_line(s - 1); + return; + } + if(sscanf(s - 1, "%lf", &startup_time) != 1) { + bogus_line(s - 1); + return; + } + planner_time = startup_time; } - s += sizeof(sc)-1; - ch = s[-1]; -#undef sc + else if(ch != '\0' && strncmp_const_skip(s - 1, "hostname", s, ch) == 0) { + skip_whitespace(s, ch); + if(ch == '\0') { + bogus_line(s - 1); + return; + } + ghostname = stralloc(s-1); + } + else if(ch != '\0' && strncmp_const_skip(s - 1, "estimate", s, ch) == 0) { + skip_whitespace(s, ch); + if(ch == '\0') { + bogus_line(s - 1); + return; + } + fp = s - 1; + skip_non_whitespace(s, ch); + s[-1] = '\0'; + hostname = stralloc(fp); + s[-1] = (char)ch; + + skip_whitespace(s, ch); + if(ch == '\0') { + bogus_line(s - 1); + amfree(hostname); + return; + } - skip_whitespace(s, ch); - if(ch == '\0') { - bogus_line(); - return; + qdiskname = s - 1; + skip_quoted_string(s, ch); + s[-1] = '\0'; + diskname = unquote_string(qdiskname); + s[-1] = (char)ch; + + skip_whitespace(s, ch); + if(ch == '\0') { + bogus_line(s - 1); + amfree(hostname); + amfree(diskname); + return; + } + fp = s - 1; + skip_non_whitespace(s, ch); + s[-1] = '\0'; + datestamp = stralloc(fp); + s[-1] = (char)ch; + skip_whitespace(s, ch); + + if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) { + bogus_line(s - 1); + amfree(hostname); + amfree(diskname); + amfree(datestamp); + return; + } + skip_integer(s, ch); + if(level < 0 || level > 9) { + amfree(hostname); + amfree(diskname); + amfree(datestamp); + return; + } + + skip_whitespace(s, ch); + + if(sscanf(s - 1,"[sec %lf nkb %lf ckb %lf kps %lf", + &sec, &nbytes, &cbytes, &kps) != 4) { + bogus_line(s - 1); + amfree(hostname); + amfree(diskname); + amfree(datestamp); + return; + } + + dp = lookup_disk(hostname, diskname); + if(dp == NULL) { + addtoX_summary(&first_failed, &last_failed, + hostname, diskname, level, + _("ERROR [not in disklist]")); + exit_status |= STATUS_FAILED; + amfree(hostname); + amfree(diskname); + amfree(datestamp); + return; + } + + repdata = find_repdata(dp, datestamp, level); + + repdata->est_nsize = nbytes; + repdata->est_csize = cbytes; + + amfree(hostname); + amfree(diskname); + amfree(datestamp); } - if(sscanf(s - 1, "%f", &startup_time) != 1) { - bogus_line(); + else { + bogus_line(s - 1); return; } +#undef sc + } } -void handle_note() +static void +handle_note(void) { char *str = NULL; + char *pidstr; - str = vstralloc(" ", program_str[curprog], ": ", curstr, NULL); - addline(¬es, str); - amfree(str); + if (curprog == P_DRIVER && + BSTRNCMP(curstr, "Taper protocol error") == 0) { + exit_status |= STATUS_TAPE; + } + pidstr = index(curstr,' '); + if (pidstr) { + pidstr++; + } + /* Don't report the pid lines */ + if ((!pidstr || BSTRNCMP(pidstr, "pid ") != 0) && + BSTRNCMP(curstr, "pid-done ") != 0) { + str = vstrallocf(" %s: %s", program_str[curprog], curstr); + addline(¬es, str); + amfree(str); + } } /* ----- */ -void handle_error() +static void +handle_error(void) { char *s = NULL, *nl; int ch; @@ -1530,57 +2002,54 @@ void handle_error() ch = *s++; skip_whitespace(s, ch); -#define sc "no-tape" - if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) { - bogus_line(); - return; - } - s += sizeof(sc)-1; - ch = s[-1]; -#undef sc - - skip_whitespace(s, ch); - if(ch != '\0') { - if((nl = strchr(s - 1, '\n')) != NULL) { - *nl = '\0'; + if(ch != '\0' && strncmp_const_skip(s - 1, "no-tape", s, ch) == 0) { + skip_whitespace(s, ch); + if(ch != '\0') { + if((nl = strchr(s - 1, '\n')) != NULL) { + *nl = '\0'; + } + tapestart_error = newstralloc(tapestart_error, s - 1); + if(nl) *nl = '\n'; + degraded_mode = 1; + exit_status |= STATUS_TAPE;; + return; } - tapestart_error = newstralloc(tapestart_error, s - 1); - if(nl) *nl = '\n'; - degraded_mode = 1; - return; + /* else some other tape error, handle like other errors */ } /* else some other tape error, handle like other errors */ } - s = vstralloc(" ", program_str[curprog], ": ", - logtype_str[curlog], " ", curstr, NULL); + s = vstrallocf(" %s: %s %s", program_str[curprog], + logtype_str[curlog], curstr); addline(&errsum, s); amfree(s); } /* ----- */ -void handle_summary() +static void +handle_summary(void) { - bogus_line(); + bogus_line(curstr); } /* ----- */ -int nb_disk=0; -void handle_disk() +static int nb_disk=0; +static void +handle_disk(void) { disk_t *dp; - char *s, *fp; + char *s, *fp, *qdiskname; int ch; char *hostname = NULL, *diskname = NULL; if(curprog != P_PLANNER && curprog != P_AMFLUSH) { - bogus_line(); + bogus_line(curstr); return; } if(nb_disk==0) { - for(dp = diskq->head; dp != NULL; dp = dp->next) + for(dp = diskq.head; dp != NULL; dp = dp->next) dp->todo = 0; } nb_disk++; @@ -1590,29 +2059,30 @@ void handle_disk() skip_whitespace(s, ch); if(ch == '\0') { - bogus_line(); + bogus_line(s - 1); return; } fp = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; hostname = newstralloc(hostname, fp); - s[-1] = ch; + s[-1] = (char)ch; skip_whitespace(s, ch); if(ch == '\0') { - bogus_line(); + bogus_line(s - 1); + amfree(hostname); return; } - fp = s - 1; - skip_non_whitespace(s, ch); + qdiskname = s - 1; + skip_quoted_string(s, ch); s[-1] = '\0'; - diskname = newstralloc(diskname, fp); - s[-1] = ch; + diskname = unquote_string(qdiskname); + s[-1] = (char)ch; dp = lookup_disk(hostname, diskname); if(dp == NULL) { - dp = add_disk(hostname, diskname); + dp = add_disk(&diskq, hostname, diskname); } amfree(hostname); @@ -1620,10 +2090,16 @@ void handle_disk() dp->todo = 1; } -repdata_t *handle_success() +/* XXX Just a placeholder, in case we decide to do something with L_CHUNK + * log entries. Right now they're just the equivalent of L_SUCCESS, but only + * for a split chunk of the overall dumpfile. + */ +static repdata_t * +handle_chunk( + logtype_t logtype) { disk_t *dp; - float sec, kps, kbytes, origkb; + double sec, kps, kbytes; timedata_t *sp; int i; char *s, *fp; @@ -1631,11 +2107,195 @@ repdata_t *handle_success() char *hostname = NULL; char *diskname = NULL; repdata_t *repdata; - int level; + int level, chunk; + char *datestamp; + char *label = NULL; + int fileno; + int totpart; + + if(curprog != P_TAPER) { + bogus_line(curstr); + return NULL; + } + + s = curstr; + ch = *s++; + + skip_whitespace(s, ch); + if(ch == '\0') { + bogus_line(s - 1); + return NULL; + } + + if (logtype == L_PART || logtype == L_PARTPARTIAL) { + fp = s - 1; + skip_non_whitespace(s, ch); + s[-1] = '\0'; + label = stralloc(fp); + s[-1] = (char)ch; + + skip_whitespace(s, ch); + if(ch == '\0' || sscanf(s - 1, "%d", &fileno) != 1) { + bogus_line(s - 1); + amfree(label); + return NULL; + } + skip_integer(s, ch); + skip_whitespace(s, ch); + if(ch == '\0') { + bogus_line(s - 1); + amfree(label); + return NULL; + } + amfree(label); + } + + fp = s - 1; + skip_non_whitespace(s, ch); + s[-1] = '\0'; + hostname = stralloc(fp); + s[-1] = (char)ch; + + skip_whitespace(s, ch); + if(ch == '\0') { + bogus_line(s - 1); + amfree(hostname); + return NULL; + } + fp = s - 1; + skip_quoted_string(s, ch); + s[-1] = '\0'; + diskname = unquote_string(fp); + s[-1] = (char)ch; + + skip_whitespace(s, ch); + if(ch == '\0') { + bogus_line(s - 1); + amfree(hostname); + amfree(diskname); + return NULL; + } + fp = s - 1; + skip_non_whitespace(s, ch); + s[-1] = '\0'; + datestamp = stralloc(fp); + s[-1] = (char)ch; + + skip_whitespace(s, ch); + if(ch == '\0' || sscanf(s - 1, "%d", &chunk) != 1) { + bogus_line(s - 1); + amfree(hostname); + amfree(diskname); + amfree(datestamp); + return NULL; + } + skip_integer(s, ch); + + if (ch != '\0' && s[-1] == '/') { + s++; ch = s[-1]; + if (sscanf(s - 1, "%d", &totpart) != 1) { + bogus_line(s - 1); + amfree(hostname); + amfree(diskname); + amfree(datestamp); + return NULL; + } + skip_integer(s, ch); + } + + skip_whitespace(s, ch); + if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) { + bogus_line(s - 1); + amfree(hostname); + amfree(diskname); + amfree(datestamp); + return NULL; + } + skip_integer(s, ch); + + /*@ignore@*/ + if(level < 0 || level > 9) { + amfree(hostname); + amfree(diskname); + amfree(datestamp); + return NULL; + } + /*@end@*/ + + skip_whitespace(s, ch); + if(sscanf(s - 1,"[sec %lf kb %lf kps %lf", &sec, &kbytes, &kps) != 3) { + bogus_line(s - 1); + amfree(hostname); + amfree(diskname); + amfree(datestamp); + return NULL; + } + + + dp = lookup_disk(hostname, diskname); + if(dp == NULL) { + char *str = NULL; + + str = vstrallocf(_(" %s ERROR [not in disklist]"), + prefix(hostname, diskname, level)); + addline(&errsum, str); + amfree(str); + amfree(hostname); + amfree(diskname); + amfree(datestamp); + return NULL; + } + + repdata = find_repdata(dp, datestamp, level); + + sp = &(repdata->taper); + + i = level > 0; + + amfree(hostname); + amfree(diskname); + amfree(datestamp); + + if(current_tape == NULL) { + error("current_tape == NULL"); + } + if (sp->filenum == 0) { + sp->filenum = ++tapefcount; + sp->tapelabel = current_tape->label; + } + tapechunks[level] +=1; + stats[i].tapechunks +=1; + current_tape->taper_time += sec; + current_tape->coutsize += kbytes; + current_tape->tapechunks += 1; + return repdata; +} + +static repdata_t * +handle_success( + logtype_t logtype) +{ + disk_t *dp; + double sec = 0.0; + double kps = 0.0; + double kbytes = 0.0; + double origkb = 0.0; + timedata_t *sp; + int i; + char *s, *fp, *qdiskname; + int ch; + char *hostname = NULL; + char *diskname = NULL; + repdata_t *repdata; + int level = 0; + int totpart = 0; char *datestamp; - if(curprog != P_TAPER && curprog != P_DUMPER && curprog != P_PLANNER) { - bogus_line(); + (void)logtype; + + if(curprog != P_TAPER && curprog != P_DUMPER && curprog != P_PLANNER && + curprog != P_CHUNKER) { + bogus_line(curstr); return NULL; } @@ -1644,30 +2304,29 @@ repdata_t *handle_success() skip_whitespace(s, ch); if(ch == '\0') { - bogus_line(); + bogus_line(s - 1); return NULL; } fp = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; hostname = stralloc(fp); - s[-1] = ch; + s[-1] = (char)ch; skip_whitespace(s, ch); if(ch == '\0') { - bogus_line(); + bogus_line(s - 1); amfree(hostname); return NULL; } - fp = s - 1; - skip_non_whitespace(s, ch); + qdiskname = s - 1; + skip_quoted_string(s, ch); s[-1] = '\0'; - diskname = stralloc(fp); - s[-1] = ch; + diskname = unquote_string(qdiskname); skip_whitespace(s, ch); if(ch == '\0') { - bogus_line(); + bogus_line(s - 1); amfree(hostname); amfree(diskname); return NULL; @@ -1676,16 +2335,17 @@ repdata_t *handle_success() skip_non_whitespace(s, ch); s[-1] = '\0'; datestamp = stralloc(fp); - s[-1] = ch; + s[-1] = (char)ch; - level = atoi(datestamp); - if(level < 100) { + //datestamp is optional + if(strlen(datestamp) < 6) { + totpart = atoi(datestamp); datestamp = newstralloc(datestamp, run_datestamp); } else { skip_whitespace(s, ch); - if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) { - bogus_line(); + if(ch == '\0' || sscanf(s - 1, "%d", &totpart) != 1) { + bogus_line(s - 1); amfree(hostname); amfree(diskname); amfree(datestamp); @@ -1695,16 +2355,45 @@ repdata_t *handle_success() } skip_whitespace(s, ch); + + //totpart is optional + if (*(s-1) == '"') + s++; + if (*(s-1) == '[') { + level = totpart; + totpart = -1; + } else { + if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) { + bogus_line(s - 1); + amfree(hostname); + amfree(diskname); + amfree(datestamp); + return NULL; + } + skip_integer(s, ch); + skip_whitespace(s, ch); + } + + + if(level < 0 || level > 9) { + amfree(hostname); + amfree(diskname); + amfree(datestamp); + return NULL; + } + /* Planner success messages (for skipped dumps) do not contain statistics */ if(curprog != P_PLANNER) { - if(curprog != P_DUMPER || - sscanf(s - 1,"[sec %f kb %f kps %f orig-kb %f", - &sec, &kbytes, &kps, &origkb) != 4) { + if(*(s - 1) == '"') + s++; + if((curprog != P_DUMPER) + || (sscanf(s - 1,"[sec %lf kb %lf kps %lf orig-kb %lf", + &sec, &kbytes, &kps, &origkb) != 4)) { origkb = -1; - if(sscanf(s - 1,"[sec %f kb %f kps %f", + if(sscanf(s - 1,"[sec %lf kb %lf kps %lf", &sec, &kbytes, &kps) != 3) { - bogus_line(); + bogus_line(s - 1); amfree(hostname); amfree(diskname); amfree(datestamp); @@ -1712,20 +2401,28 @@ repdata_t *handle_success() } } else { - if(origkb == 0.0) origkb = 0.1; + if(!isnormal(origkb)) + origkb = 0.1; + } + if (curprog == P_TAPER && logtype == L_PARTIAL) { + char *t = index(s-1,']'); + if (t) { + char *errmsg, *u; + errmsg = unquote_string(t+1); + u = vstrallocf(" %s: partial %s: %s", + prefix(hostname, diskname, level), + program_str[curprog], errmsg); + addline(&errsum, u); + } } } dp = lookup_disk(hostname, diskname); if(dp == NULL) { - char *str = NULL; - - str = vstralloc(" ", prefix(hostname, diskname, level), - " ", "ERROR [not in disklist]", - NULL); - addline(&errsum, str); - amfree(str); + addtoX_summary(&first_failed, &last_failed, hostname, qdiskname, level, + _("ERROR [not in disklist]")); + exit_status |= STATUS_FAILED; amfree(hostname); amfree(diskname); amfree(datestamp); @@ -1744,19 +2441,30 @@ repdata_t *handle_success() if(curprog == P_TAPER) sp = &(repdata->taper); - else sp = &(repdata->dumper); + else if(curprog == P_DUMPER) + sp = &(repdata->dumper); + else sp = &(repdata->chunker); i = level > 0; - if(origkb == -1) { + if (origkb < 0.0 && (curprog == P_CHUNKER || curprog == P_TAPER) && + isnormal(repdata->dumper.outsize)) { + /* take origkb from DUMPER line */ + origkb = repdata->dumper.outsize; + } else if (origkb < 0.0) { + /* take origkb from infofile, needed for amflush */ info_t inf; struct tm *tm; int Idatestamp; get_info(hostname, diskname, &inf); tm = localtime(&inf.inf[level].date); - Idatestamp = 10000*(tm->tm_year+1900) + - 100*(tm->tm_mon+1) + tm->tm_mday; + if (tm) { + Idatestamp = 10000*(tm->tm_year+1900) + + 100*(tm->tm_mon+1) + tm->tm_mday; + } else { + Idatestamp = 19000101; + } if(atoi(datestamp) == Idatestamp) { /* grab original size from record */ @@ -1765,6 +2473,13 @@ repdata_t *handle_success() else origkb = 0.0; } + + if (curprog == P_DUMPER && + (sp->result == L_FAIL || sp->result == L_PARTIAL)) { + addtoX_summary(&first_failed, &last_failed, hostname, qdiskname, level, + _("was successfully retried")); + } + amfree(hostname); amfree(diskname); amfree(datestamp); @@ -1778,76 +2493,125 @@ repdata_t *handle_success() if(curprog == P_TAPER) { if(current_tape == NULL) { - error("current_tape == NULL"); + error(_("current_tape == NULL")); + /*NOTREACHED*/ } stats[i].taper_time += sec; sp->filenum = ++tapefcount; sp->tapelabel = current_tape->label; + sp->totpart = totpart; tapedisks[level] +=1; stats[i].tapedisks +=1; stats[i].tapesize += kbytes; - current_tape->taper_time += sec; - current_tape->coutsize += kbytes; - current_tape->corigsize += origkb; + sp->outsize = kbytes; + if(!isnormal(repdata->chunker.outsize) && isnormal(repdata->dumper.outsize)) { /* dump to tape */ + stats[i].outsize += kbytes; + if (abs(kbytes - origkb) >= 32) { + /* server compressed */ + stats[i].corigsize += origkb; + stats[i].coutsize += kbytes; + } + } current_tape->tapedisks += 1; } if(curprog == P_DUMPER) { stats[i].dumper_time += sec; - if(dp->compress == COMP_NONE) { + if (abs(kbytes - origkb) < 32) { + /* not client compressed */ sp->origsize = kbytes; } else { - stats[i].coutsize += kbytes; + /* client compressed */ stats[i].corigsize += sp->origsize; + stats[i].coutsize += kbytes; } dumpdisks[level] +=1; stats[i].dumpdisks +=1; stats[i].origsize += sp->origsize; - stats[i].outsize += kbytes; } + if(curprog == P_CHUNKER) { + sp->outsize = kbytes; + stats[i].outsize += kbytes; + if (abs(kbytes - origkb) >= 32) { + /* server compressed */ + stats[i].corigsize += origkb; + stats[i].coutsize += kbytes; + } + } return repdata; } -void handle_strange() +static void +handle_partial(void) +{ + repdata_t *repdata; + timedata_t *sp; + + repdata = handle_success(L_PARTIAL); + if (!repdata) + return; + + if(curprog == P_TAPER) + sp = &(repdata->taper); + else if(curprog == P_DUMPER) + sp = &(repdata->dumper); + else sp = &(repdata->chunker); + + sp->result = L_PARTIAL; +} + +static void +handle_strange(void) { char *str = NULL; + char *strangestr = NULL; repdata_t *repdata; + char *qdisk; - repdata = handle_success(); + repdata = handle_success(L_SUCCESS); + if (!repdata) + return; - str = vstralloc(" ", prefix(repdata->disk->host->hostname, - repdata->disk->name, repdata->level), - " ", "STRANGE", - NULL); - addline(&errsum, str); - amfree(str); + qdisk = quote_string(repdata->disk->name); - addline(&errdet,""); - str = vstralloc("/-- ", prefix(repdata->disk->host->hostname, - repdata->disk->name, repdata->level), - " ", "STRANGE", - NULL); - addline(&errdet, str); + addline(&strangedet,""); + str = vstrallocf("/-- %s STRANGE", + prefix(repdata->disk->host->hostname, qdisk, repdata->level)); + addline(&strangedet, str); amfree(str); while(contline_next()) { + char *s, ch; get_logline(logfile); - addline(&errdet, curstr); + s = curstr; + if(strncmp_const_skip(curstr, "sendbackup: warning ", s, ch) == 0) { + strangestr = newstralloc(strangestr, s); + } + addline(&strangedet, curstr); } - addline(&errdet,"\\--------"); + addline(&strangedet,"\\--------"); + + str = vstrallocf("STRANGE %s", strangestr? strangestr : _("(see below)")); + addtoX_summary(&first_strange, &last_strange, + repdata->disk->host->hostname, qdisk, repdata->level, str); + exit_status |= STATUS_STRANGE; + amfree(qdisk); + amfree(str); + amfree(strangestr); } -void handle_failed() +static void +handle_failed(void) { disk_t *dp; char *hostname; char *diskname; char *datestamp; char *errstr; - int level; - char *s, *fp; + int level = 0; + char *s, *fp, *qdiskname; int ch; char *str = NULL; repdata_t *repdata; @@ -1861,7 +2625,7 @@ void handle_failed() skip_whitespace(s, ch); if(ch == '\0') { - bogus_line(); + bogus_line(s - 1); return; } hostname = s - 1; @@ -1870,16 +2634,18 @@ void handle_failed() skip_whitespace(s, ch); if(ch == '\0') { - bogus_line(); + bogus_line(s - 1); return; } - diskname = s - 1; - skip_non_whitespace(s, ch); + qdiskname = s - 1; + skip_quoted_string(s, ch); s[-1] = '\0'; + diskname = unquote_string(qdiskname); skip_whitespace(s, ch); if(ch == '\0') { - bogus_line(); + bogus_line(s - 1); + amfree(diskname); return; } fp = s - 1; @@ -1894,8 +2660,9 @@ void handle_failed() else { /* read the level */ skip_whitespace(s, ch); if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) { - bogus_line(); + bogus_line(s - 1); amfree(datestamp); + amfree(diskname); return; } skip_integer(s, ch); @@ -1903,8 +2670,9 @@ void handle_failed() skip_whitespace(s, ch); if(ch == '\0') { - bogus_line(); + bogus_line(s - 1); amfree(datestamp); + amfree(diskname); return; } errstr = s - 1; @@ -1913,17 +2681,17 @@ void handle_failed() } dp = lookup_disk(hostname, diskname); + amfree(diskname); if(dp == NULL) { - str = vstralloc(" ", prefix(hostname, diskname, level), - " ", "ERROR [not in disklist]", - NULL); - addline(&errsum, str); - amfree(str); + addtoX_summary(&first_failed, &last_failed, hostname, qdiskname, level, + _("ERROR [not in disklist]")); } else { repdata = find_repdata(dp, datestamp, level); if(curprog == P_TAPER) sp = &(repdata->taper); + else if (curprog == P_PLANNER) + sp = &(repdata->planner); else sp = &(repdata->dumper); if(sp->result != L_SUCCESS) @@ -1931,19 +2699,23 @@ void handle_failed() } amfree(datestamp); - str = vstralloc(" ", prefix(hostname, diskname, level), - " ", "FAILED", - " ", errstr, - NULL); - addline(&errsum, str); - amfree(str); + if (!((curprog == P_CHUNKER && + strcmp(errstr, "[dumper returned FAILED]") == 0) || + (curprog == P_CHUNKER && + strcmp(errstr, "[Not enough holding disk space]") == 0) || + (curprog == P_CHUNKER && + strcmp(errstr, "[cannot read header: got 0 bytes instead of 32768]") == 0))) { + str = vstrallocf(_("FAILED %s"), errstr); + addtoX_summary(&first_failed, &last_failed, hostname, qdiskname, level, + str); + amfree(str); + } if(curprog == P_DUMPER) { addline(&errdet,""); - str = vstralloc("/-- ", prefix(hostname, diskname, level), - " ", "FAILED", - " ", errstr, - NULL); + str = vstrallocf("/-- %s FAILED %s", + prefix(hostname, qdiskname, level), + errstr); addline(&errdet, str); amfree(str); while(contline_next()) { @@ -1951,92 +2723,209 @@ void handle_failed() addline(&errdet, curstr); } addline(&errdet,"\\--------"); + exit_status |= STATUS_FAILED; } return; } -void generate_missing() + +static void +generate_missing(void) { disk_t *dp; - char *str = NULL; + char *qdisk; - for(dp = diskq->head; dp != NULL; dp = dp->next) { + for(dp = diskq.head; dp != NULL; dp = dp->next) { if(dp->todo && data(dp) == NULL) { - str = vstralloc(" ", prefix(dp->host->hostname, dp->name, -987), - " ", "RESULTS MISSING", - NULL); - addline(&errsum, str); - amfree(str); + qdisk = quote_string(dp->name); + addtoX_summary(&first_failed, &last_failed, dp->host->hostname, + qdisk, -987, _("RESULTS MISSING")); + exit_status |= STATUS_MISSING; + amfree(qdisk); + } + } +} + +static void +generate_bad_estimate(void) +{ + disk_t *dp; + repdata_t *repdata; + char s[1000]; + double outsize; + + for(dp = diskq.head; dp != NULL; dp = dp->next) { + if(dp->todo) { + for(repdata = data(dp); repdata != NULL; repdata = repdata->next) { + if(repdata->est_csize >= 0.1) { + if(repdata->taper.result == L_SUCCESS || + repdata->taper.result == L_CHUNKSUCCESS) + outsize = repdata->taper.outsize; + else if(repdata->chunker.result == L_SUCCESS || + repdata->chunker.result == L_PARTIAL || + repdata->chunker.result == L_CHUNKSUCCESS) + outsize = repdata->chunker.outsize; + else if(repdata->taper.result == L_PARTIAL) + outsize = repdata->taper.outsize; + else + outsize = repdata->dumper.outsize; + + if( (repdata->est_csize * 0.9 > outsize) && ( repdata->est_csize - outsize > 1.0e5 ) ) { + g_snprintf(s, 1000, + _(" big estimate: %s %s %d"), + repdata->disk->host->hostname, + repdata->disk->name, + repdata->level); + s[999] = '\0'; + addline(¬es, s); + g_snprintf(s, 1000, + _(" est: %.0lf%s out %.0lf%s"), + du(repdata->est_csize), displayunit, + du(outsize), displayunit); + s[999] = '\0'; + addline(¬es, s); + } + else if( (repdata->est_csize * 1.1 < outsize) && (outsize - repdata->est_csize > 1.0e5 ) ) { + g_snprintf(s, 1000, + _(" small estimate: %s %s %d"), + repdata->disk->host->hostname, + repdata->disk->name, + repdata->level); + s[999] = '\0'; + addline(¬es, s); + g_snprintf(s, 1000, + _(" est: %.0lf%s out %.0lf%s"), + du(repdata->est_csize), displayunit, + du(outsize), displayunit); + s[999] = '\0'; + addline(¬es, s); + } + } + } } } } static char * -prefix (host, disk, level) - char *host; - char *disk; - int level; +prefix ( + char * host, + char * disk, + int level) { - char h[10+1]; - int l; - char number[NUM_STR_SIZE]; static char *str = NULL; - ap_snprintf(number, sizeof(number), "%d", level); + if (level == -987) { + str = newvstrallocf(str, " %s %s", + host ? host : _("(host?)"), + disk ? disk : _("(disk?)")); + } else { + str = newvstrallocf(str, " %s %s lev %d", + host ? host : _("(host?)"), + disk ? disk : _("(disk?)"), + level); + } + return str; +} + + +static char * +prefixstrange ( + char * host, + char * disk, + int level, + size_t len_host, + size_t len_disk) +{ + char *h, *d; + size_t l; + static char *str = NULL; + + h=alloc(len_host+1); if(host) { - strncpy(h, host, sizeof(h)-1); + strncpy(h, host, len_host); } else { - strncpy(h, "(host?)", sizeof(h)-1); + strncpy(h, _("(host?)"), len_host); } - h[sizeof(h)-1] = '\0'; - for(l = strlen(h); l < sizeof(h)-1; l++) { + h[len_host] = '\0'; + for(l = strlen(h); l < len_host; l++) { h[l] = ' '; } - str = newvstralloc(str, - h, - " ", disk ? disk : "(disk?)", - level != -987 ? " lev " : "", - level != -987 ? number : "", - NULL); + d=alloc(len_disk+1); + if(disk) { + strncpy(d, disk, len_disk); + } else { + strncpy(d, _("(disk?)"), len_disk); + } + d[len_disk] = '\0'; + for(l = strlen(d); l < len_disk; l++) { + d[l] = ' '; + } + if (level == -987) { + str = newvstrallocf(str, " %s %s", h, d); + } else { + str = newvstrallocf(str, " %s %s lev %d", h, d, level); + } + amfree(h); + amfree(d); return str; } -void copy_template_file(lbl_templ) -char *lbl_templ; + +static void +addtoX_summary ( + X_summary_t **first, + X_summary_t **last, + char *host, + char *disk, + int level, + char *str) +{ + X_summary_t *X_summary; + + X_summary = alloc(SIZEOF(X_summary_t)); + X_summary->hostname = stralloc(host); + X_summary->diskname = stralloc(disk); + X_summary->level = level; + X_summary->str = stralloc(str); + X_summary->next = NULL; + if (*first == NULL) { + *first = X_summary; + } + else { + (*last)->next = X_summary; + } + *last = X_summary; +} + +static void +copy_template_file( + char * lbl_templ) { char buf[BUFSIZ]; int fd; - int numread; + ssize_t numread; - if (strchr(lbl_templ, '/') == NULL) { - lbl_templ = stralloc2(config_dir, lbl_templ); - } else { - lbl_templ = stralloc(lbl_templ); - } + lbl_templ = config_dir_relative(lbl_templ); if ((fd = open(lbl_templ, 0)) < 0) { curlog = L_ERROR; curprog = P_REPORTER; - curstr = vstralloc("could not open PostScript template file ", - lbl_templ, - ": ", - strerror(errno), - NULL); + curstr = vstrallocf(_("could not open PostScript template file %s: %s"), + lbl_templ, strerror(errno)); handle_error(); amfree(curstr); + amfree(lbl_templ); afclose(postscript); return; } - while ((numread = read(fd, buf, sizeof(buf))) > 0) { - if (fwrite(buf, numread, 1, postscript) != 1) { + while ((numread = read(fd, buf, SIZEOF(buf))) > 0) { + if (fwrite(buf, (size_t)numread, 1, postscript) != 1) { curlog = L_ERROR; curprog = P_REPORTER; - curstr = vstralloc("error copying PostScript template file ", - lbl_templ, - ": ", - strerror(errno), - NULL); + curstr = vstrallocf(_("error copying PostScript template file %s: %s"), + lbl_templ, strerror(errno)); handle_error(); amfree(curstr); + amfree(lbl_templ); afclose(postscript); return; } @@ -2044,13 +2933,11 @@ char *lbl_templ; if (numread < 0) { curlog = L_ERROR; curprog = P_REPORTER; - curstr = vstralloc("error reading PostScript template file ", - lbl_templ, - ": ", - strerror(errno), - NULL); + curstr = vstrallocf(_("error reading PostScript template file %s: %s"), + lbl_templ, strerror(errno)); handle_error(); amfree(curstr); + amfree(lbl_templ); afclose(postscript); return; } @@ -2058,10 +2945,11 @@ char *lbl_templ; amfree(lbl_templ); } -repdata_t *find_repdata(dp, datestamp, level) -disk_t *dp; -char *datestamp; -int level; +static repdata_t * +find_repdata( + /*@keep@*/ disk_t *dp, + char * datestamp, + int level) { repdata_t *repdata, *prev; @@ -2072,8 +2960,8 @@ int level; prev = repdata; } if(!repdata) { - repdata = (repdata_t *)alloc(sizeof(repdata_t)); - memset(repdata, '\0',sizeof(repdata_t)); + repdata = (repdata_t *)alloc(SIZEOF(repdata_t)); + memset(repdata, '\0', SIZEOF(repdata_t)); repdata->disk = dp; repdata->datestamp = stralloc(datestamp ? datestamp : ""); repdata->level = level; @@ -2089,16 +2977,21 @@ int level; } -void do_postscript_output() +static void +do_postscript_output(void) { tapetype_t *tp = lookup_tapetype(getconf_str(CNF_TAPETYPE)); disk_t *dp; repdata_t *repdata; - float outsize, origsize; - int tapesize, marksize; + double outsize, origsize; + off_t tapesize; + off_t marksize; - tapesize = tp->length; - marksize = tp->filemark; + if (!tp) + return; + + tapesize = tapetype_get_length(tp); + marksize = tapetype_get_filemark(tp); for(current_tape = stats_by_tape; current_tape != NULL; current_tape = current_tape->next) { @@ -2107,31 +3000,34 @@ void do_postscript_output() break; } - copy_template_file(tp->lbl_templ); + copy_template_file(tapetype_get_lbl_templ(tp)); + + if (postscript == NULL) + return; /* generate a few elements */ - fprintf(postscript,"(%s) DrawDate\n\n", - nicedate(run_datestamp ? atoi(run_datestamp) : 0)); - fprintf(postscript,"(Amanda Version %s) DrawVers\n",version()); - fprintf(postscript,"(%s) DrawTitle\n", current_tape->label); + g_fprintf(postscript,"(%s) DrawDate\n\n", + nicedate(run_datestamp ? run_datestamp : "0")); + g_fprintf(postscript,_("(Amanda Version %s) DrawVers\n"),version()); + g_fprintf(postscript,"(%s) DrawTitle\n", current_tape->label); /* Stats */ - fprintf(postscript, "(Total Size: %6.1f MB) DrawStat\n", + g_fprintf(postscript, "(Total Size: %6.1lf MB) DrawStat\n", mb(current_tape->coutsize)); - fprintf(postscript, "(Tape Used (%%) "); + g_fprintf(postscript, _("(Tape Used (%%) ")); divzero(postscript, pct(current_tape->coutsize + - marksize * current_tape->tapedisks), - tapesize); - fprintf(postscript," %%) DrawStat\n"); - fprintf(postscript, "(Compression Ratio: "); + marksize * (current_tape->tapedisks + current_tape->tapechunks)), + (double)tapesize); + g_fprintf(postscript," %%) DrawStat\n"); + g_fprintf(postscript, _("(Compression Ratio: ")); divzero(postscript, pct(current_tape->coutsize),current_tape->corigsize); - fprintf(postscript," %%) DrawStat\n"); - fprintf(postscript,"(Filesystems Taped: %4d) DrawStat\n", + g_fprintf(postscript," %%) DrawStat\n"); + g_fprintf(postscript,_("(Filesystems Taped: %4d) DrawStat\n"), current_tape->tapedisks); /* Summary */ - fprintf(postscript, + g_fprintf(postscript, "(-) (%s) (-) ( 0) ( 32) ( 32) DrawHost\n", current_tape->label); @@ -2145,33 +3041,36 @@ void do_postscript_output() continue; } - if(repdata->dumper.result == L_SUCCESS) + if(repdata->dumper.result == L_SUCCESS || + repdata->dumper.result == L_PARTIAL) origsize = repdata->dumper.origsize; else origsize = repdata->taper.origsize; - if(repdata->taper.result == L_SUCCESS) + if(repdata->taper.result == L_SUCCESS || + repdata->taper.result == L_PARTIAL) outsize = repdata->taper.outsize; else outsize = repdata->dumper.outsize; - if (repdata->taper.result == L_SUCCESS) { - if(origsize != 0.0) { - fprintf(postscript,"(%s) (%s) (%d) (%3.0d) (%8.0f) (%8.0f) DrawHost\n", + if (repdata->taper.result == L_SUCCESS || + repdata->taper.result == L_PARTIAL) { + if(isnormal(origsize)) { + g_fprintf(postscript,"(%s) (%s) (%d) (%3.0d) (%8.0lf) (%8.0lf) DrawHost\n", dp->host->hostname, dp->name, repdata->level, repdata->taper.filenum, origsize, outsize); } else { - fprintf(postscript,"(%s) (%s) (%d) (%3.0d) (%8s) (%8.0f) DrawHost\n", + g_fprintf(postscript,"(%s) (%s) (%d) (%3.0d) (%8s) (%8.0lf) DrawHost\n", dp->host->hostname, dp->name, repdata->level, - repdata->taper.filenum, "N/A", + repdata->taper.filenum, "", outsize); } } } } - fprintf(postscript,"\nshowpage\n"); + g_fprintf(postscript,"\nshowpage\n"); } }