X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Freporter.c;h=73acd3d183f1d79c8cdc095201f46691d0d39841;hb=4fd9649694a4fcb4d4f364fe66e568a889feee20;hp=a28d5b49a80830f1009d589ca57991c89cc4f45b;hpb=c9bb64dd8260123d77b6f7be0f051f450b193e66;p=debian%2Famanda diff --git a/server-src/reporter.c b/server-src/reporter.c index a28d5b4..73acd3d 100644 --- a/server-src/reporter.c +++ b/server-src/reporter.c @@ -25,19 +25,19 @@ * University of Maryland at College Park */ /* - * $Id: reporter.c,v 1.44.2.17.4.6.2.16.2.6 2005/03/29 16:35:11 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 + * summary stats + * details for errors + * notes + * success summary + */ #include "amanda.h" #include "conffile.h" @@ -58,9 +58,9 @@ typedef struct line_s { 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; } timedata_t; @@ -68,61 +68,72 @@ typedef struct timedata_s { typedef struct repdata_s { disk_t *disk; char *datestamp; + double est_nsize, est_csize; timedata_t taper; timedata_t dumper; + timedata_t chunker; 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 strange_s { + char *hostname; + char *diskname; + int level; + char *str; + struct strange_s *next; +} strange_t; + +static strange_t *first_strange=NULL, *last_strange=NULL; -float total_time, startup_time, planner_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 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; -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 *notes = NULL; static char MaxWidthsRequested = 0; /* determined via config data */ @@ -130,38 +141,55 @@ char *displayunit; 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(void); +static repdata_t *handle_success(logtype_t logtype); +static void addline(line_t **lp, char *str); +static void addtostrange(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_strange(void); +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; @@ -169,10 +197,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); + 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--) @@ -201,55 +239,75 @@ 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)) + snprintf(PrtBuf, SIZEOF(PrtBuf), "%*s", cd->Width, "-- "); else - ap_snprintf(PrtBuf, sizeof(PrtBuf), + 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->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 { + while (p->next != NULL) + p = p->next; + p->next = 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; @@ -257,7 +315,7 @@ char **argv; char *conf_infofile; char *logfname, *psfname, *outfname, *subj_str = NULL; tapetype_t *tp; - int fd, opt; + int opt; unsigned long malloc_hist_1, malloc_size_1; unsigned long malloc_hist_2, malloc_size_2; char *mail_cmd = NULL, *printer_cmd = NULL; @@ -266,19 +324,21 @@ char **argv; char *ColumnSpec = ""; char *errstr = NULL; int cn; + int mailout = 1; + char *mailto = NULL; + int new_argc, my_argc; + char **new_argv, **my_argv; + char *lbl_templ = NULL; - 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); - } + safe_fd(-1, 0); set_pname("amreport"); + dbopen(DBG_SUBDIR_SERVER); + + /* Don't die when child closes pipe */ + signal(SIGPIPE, SIG_IGN); + malloc_size_1 = malloc_inuse(&malloc_hist_1); /* Process options */ @@ -288,28 +348,48 @@ char **argv; psfname = NULL; logfname = NULL; - if (getcwd(my_cwd, sizeof(my_cwd)) == NULL) { + if (getcwd(my_cwd, SIZEOF(my_cwd)) == NULL) { error("cannot determine current working directory"); + /*NOTREACHED*/ } - if (argc < 2) { + parse_server_conf(argc, argv, &new_argc, &new_argv); + my_argc = new_argc; + my_argv = new_argv; + + if (my_argc < 2) { config_dir = stralloc2(my_cwd, "/"); if ((config_name = strrchr(my_cwd, '/')) != NULL) { config_name = stralloc(config_name + 1); } } else { - if (argv[1][0] == '-') { + if (my_argv[1][0] == '-') { usage(); return 1; } - config_name = stralloc(argv[1]); + config_name = stralloc(my_argv[1]); config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL); - --argc; ++argv; - while((opt = getopt(argc, argv, "f:l:p:")) != EOF) { + --my_argc; ++my_argv; + while((opt = getopt(my_argc, my_argv, "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"); + /*NOTREACHED*/ } if (*optarg == '/') { outfname = stralloc(optarg); @@ -320,6 +400,7 @@ char **argv; case 'l': if (logfname != NULL) { error("you may specify at most one -l"); + /*NOTREACHED*/ } if (*optarg == '/') { logfname = stralloc(optarg); @@ -330,6 +411,7 @@ char **argv; case 'p': if (psfname != NULL) { error("you may specify at most one -p"); + /*NOTREACHED*/ } if (*optarg == '/') { psfname = stralloc(optarg); @@ -338,20 +420,21 @@ char **argv; } break; case '?': - default: usage(); return 1; + default: + break; } } - argc -= optind; - argv += optind; - - if (argc > 1) { - usage(); - return 1; - } + my_argc -= optind; + my_argv += optind; } + if( !mailout && mailto ){ + printf("You cannot specify both -i & -M at the same time\n"); + exit(1); + } + #if !defined MAILER if(!outfname) { @@ -366,29 +449,38 @@ char **argv; /* read configuration files */ conffile = stralloc2(config_dir, CONFFILE_NAME); - if(read_conffile(conffile)) { - error("errors processing config file \"%s\"", conffile); - } + /* Ignore error from read_conffile */ + read_conffile(conffile); amfree(conffile); + + dbrename(config_name, DBG_SUBDIR_SERVER); + + report_bad_conf_arg(); conf_diskfile = getconf_str(CNF_DISKFILE); if (*conf_diskfile == '/') { conf_diskfile = stralloc(conf_diskfile); } else { conf_diskfile = stralloc2(config_dir, conf_diskfile); } - if((diskq = read_diskfile(conf_diskfile)) == NULL) { - error("could not load disklist \"%s\"", conf_diskfile); - } + /* Ignore error from read_diskfile */ + read_diskfile(conf_diskfile, &diskq); amfree(conf_diskfile); + 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 = 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); - } + /* Ignore error from read_tapelist */ + read_tapelist(conf_tapelist); amfree(conf_tapelist); conf_infofile = getconf_str(CNF_INFOFILE); if (*conf_infofile == '/') { @@ -398,11 +490,10 @@ char **argv; } if(open_infofile(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(); @@ -472,7 +563,10 @@ char **argv; case L_DISK: handle_disk(); break; - case L_SUCCESS: handle_success(); break; + case L_SUCCESS: handle_success(curlog); break; + case L_CHUNKSUCCESS: handle_success(curlog); break; + case L_CHUNK: handle_chunk(); break; + case L_PARTIAL: handle_partial(); break; case L_STRANGE: handle_strange(); break; case L_FAIL: handle_failed(); break; @@ -486,13 +580,15 @@ char **argv; } 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. */ @@ -508,19 +604,30 @@ char **argv; /* output to a file */ if((mailf = fopen(outfname,"w")) == NULL) { error("could not open output file: %s %s", outfname, strerror(errno)); + /*NOTREACHED*/ } - fprintf(mailf, "To: %s\n", getconf_str(CNF_MAILTO)); + fprintf(mailf, "To: %s\n", mailto); fprintf(mailf, "Subject: %s\n\n", subj_str); } else { #ifdef MAILER - mail_cmd = vstralloc(MAILER, + if(mailto) { + 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)); + " ", 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) { + printf("No mail sent! "); + printf("No valid mail address has been specified in amanda.conf or on the commmand line\n"); + } + mailf = NULL; + } #endif } @@ -530,7 +637,9 @@ char **argv; /* 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; @@ -556,8 +665,9 @@ 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; @@ -582,34 +692,37 @@ char **argv; amfree(subj_str); + if(mailf) { - if(!got_finish) fputs("*** THE DUMPS DID NOT FINISH PROPERLY!\n\n", mailf); - - output_tapeinfo(); - - if(errsum) { - fprintf(mailf,"\nFAILURE AND STRANGE DUMP SUMMARY:\n"); - output_lines(errsum, mailf); - } - fputs("\n\n", mailf); + if(!got_finish) fputs("*** THE DUMPS DID NOT FINISH PROPERLY!\n\n", mailf); - output_stats(); + output_tapeinfo(); - 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(first_strange || errsum) { + fprintf(mailf,"\nFAILURE AND STRANGE DUMP SUMMARY:\n"); + if(first_strange) output_strange(); + if(errsum) output_lines(errsum, mailf); + } + fputs("\n\n", mailf); + + output_stats(); + + 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(); + } + 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(); @@ -622,8 +735,10 @@ char **argv; afclose(postscript); } else { - if (postscript != NULL && pclose(postscript) != 0) + if (postscript != NULL && pclose(postscript) != 0) { error("printer command failed: %s", printer_cmd); + /*NOTREACHED*/ + } postscript = NULL; } @@ -631,12 +746,18 @@ char **argv; if(outfname) { afclose(mailf); } - else { - if(pclose(mailf) != 0) + else if(mailf) { + if(pclose(mailf) != 0) { error("mail command failed: %s", mail_cmd); + /*NOTREACHED*/ + } mailf = NULL; } + clear_tapelist(); + free_disklist(&diskq); + free_new_argv(new_argc, new_argv); + free_server_config(); amfree(run_datestamp); amfree(tape_labels); amfree(config_dir); @@ -651,6 +772,7 @@ char **argv; malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2); } + dbclose(); return 0; } @@ -665,34 +787,44 @@ char **argv; #define divzero(fp,a,b) \ do { \ double q = (b); \ - if (q == 0.0) \ + if (!isnormal(q)) \ fprintf((fp)," -- "); \ else if ((q = (a)/q) >= 999.95) \ fprintf((fp), "###.#"); \ else \ - fprintf((fp), "%5.1f",q); \ + fprintf((fp), "%5.1lf",q); \ } while(0) #define divzero_wide(fp,a,b) \ do { \ double q = (b); \ - if (q == 0.0) \ + if (!isnormal(q)) \ fprintf((fp)," -- "); \ else if ((q = (a)/q) >= 99999.95) \ fprintf((fp), "#####.#"); \ else \ - fprintf((fp), "%7.1f",q); \ + 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; @@ -704,6 +836,9 @@ void output_stats() if(!got_finish) /* no driver finish line, estimate total run 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 Incr.\n"); @@ -722,11 +857,11 @@ void output_stats() hrmn(stats[1].dumper_time)); fprintf(mailf, - "Output Size (meg) %8.1f %8.1f %8.1f\n", + "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", + "Original Size (meg) %8.1lf %8.1lf %8.1lf\n", mb(stats[2].origsize), mb(stats[0].origsize), mb(stats[1].origsize)); @@ -770,16 +905,16 @@ void output_stats() hrmn(stats[1].taper_time)); fprintf(mailf, - "Tape Size (meg) %8.1f %8.1f %8.1f\n", + "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); + 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),tapesize); + 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),tapesize); + divzero(mailf, pct(stats[1].tapesize+marksize*(stats[1].tapedisks+stats[1].tapechunks)),(double)tapesize); if(stats[1].tapedisks > 0) fputs(" (level:#disks ...)", mailf); putc('\n', mailf); @@ -799,6 +934,24 @@ void output_stats() } putc('\n', mailf); + if(stats[1].tapechunks > 0) fputs(" (level:#chunks ...)", mailf); + putc('\n', mailf); + + 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; + fprintf(mailf, "%d:%d", lv, tapechunks[lv]); + } + putc(')', mailf); + } + putc('\n', mailf); + fprintf(mailf, "Avg Tp Write Rate (k/s) "); divzero_wide(mailf, stats[2].tapesize,stats[2].taper_time); fputs(" ", mailf); @@ -808,27 +961,28 @@ void output_stats() putc('\n', mailf); if(stats_by_tape) { - int label_length = strlen(stats_by_tape->label) + 5; + int label_length = (int)strlen(stats_by_tape->label) + 5; fprintf(mailf,"\nUSAGE BY TAPE:\n"); - fprintf(mailf," %-*s Time Size %% Nb\n", + 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, " %8.0f%s ", du(current_tape->coutsize), displayunit); - divzero(mailf, pct(current_tape->coutsize + - marksize * current_tape->tapedisks), - tapesize); - fprintf(mailf, " %4d\n", current_tape->tapedisks); + 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); + fprintf(mailf, " %4d", current_tape->tapedisks); + fprintf(mailf, " %4d\n", current_tape->tapechunks); } } - } /* ----- */ -void output_tapeinfo() +static void +output_tapeinfo(void) { tape_t *tp, *lasttp; int run_tapes; @@ -858,17 +1012,22 @@ void output_tapeinfo() run_tapes = getconf_int(CNF_RUNTAPES); - if (run_tapes <= 1) + 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: ", + else if(run_tapes > 1) + fprintf(mailf, "The next %d tapes Amanda expects to use are: ", run_tapes); while(run_tapes > 0) { - if(tp != NULL) + if(tp != NULL) { fprintf(mailf, "%s", tp->label); - else - fputs("a new tape", mailf); + } else { + if (run_tapes == 1) + fprintf(mailf, "a new tape"); + else + fprintf(mailf, "%d new tapes", run_tapes); + run_tapes = 1; + } if(run_tapes > 1) fputs(", ", mailf); @@ -880,9 +1039,9 @@ void output_tapeinfo() lasttp = lookup_tapepos(lookup_nb_tape()); run_tapes = getconf_int(CNF_RUNTAPES); - if(lasttp && run_tapes > 0 && lasttp->datestamp == 0) { + if(lasttp && run_tapes > 0 && strcmp(lasttp->datestamp,"0") == 0) { int c = 0; - while(lasttp && run_tapes > 0 && lasttp->datestamp == 0) { + while(lasttp && run_tapes > 0 && strcmp(lasttp->datestamp,"0") == 0) { c++; lasttp = lasttp->prev; run_tapes--; @@ -897,7 +1056,7 @@ void output_tapeinfo() lasttp->label); lasttp = lasttp->prev; c--; - while(lasttp && c > 0 && lasttp->datestamp == 0) { + while(lasttp && c > 0 && strcmp(lasttp->datestamp,"0") == 0) { fprintf(mailf, ", %s", lasttp->label); lasttp = lasttp->prev; c--; @@ -908,10 +1067,31 @@ void output_tapeinfo() } /* ----- */ +static void +output_strange(void) +{ + size_t len_host=0, len_disk=0; + strange_t *strange; + char *str = NULL; + + for(strange=first_strange; 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; strange != NULL; strange = strange->next) { + str = vstralloc(" ", prefixstrange(strange->hostname, strange->diskname, strange->level, len_host, len_disk), + " ", strange->str, NULL); + 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; @@ -927,14 +1107,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; @@ -943,13 +1119,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); } @@ -957,33 +1134,47 @@ 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), + + 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), + 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; } @@ -1000,7 +1191,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 @@ -1008,12 +1201,11 @@ void CalcMaxWidth() { * ElB, 1999-02-24. */ disk_t *dp; - float f; + double f; repdata_t *repdata; 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); @@ -1022,9 +1214,12 @@ void CalcMaxWidth() { repdata->taper.result == L_BOGUS) continue; CheckIntMax(&ColumnData[Level], repdata->level); - if(repdata->dumper.result == L_SUCCESS) { - CheckFloatMax(&ColumnData[OrigKB], du(repdata->dumper.origsize)); - CheckFloatMax(&ColumnData[OutKB], du(repdata->dumper.outsize)); + 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(dp->compress == COMP_NONE) f = 0.0; else @@ -1033,40 +1228,41 @@ void CalcMaxWidth() { sDivZero(pct(repdata->dumper.outsize), f, Compress)); if(!amflush_run) - ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer), + snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer), "%3d:%02d", mnsc(repdata->dumper.sec)); else - ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer), + snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer), "N/A "); 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) + snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer), "%3d:%02d", mnsc(repdata->taper.sec)); else - ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer), + snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer), "N/A "); - CheckStringMax(cd, 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], "N/A "); } } } } -void output_summary() +static void +output_summary(void) { disk_t *dp; repdata_t *repdata; @@ -1075,8 +1271,8 @@ void output_summary() char *tmp; int i, h, w1, wDump, wTape; - float outsize, origsize; - float f; + double outsize, origsize; + double f; HostName = StringToColumn("HostName"); Disk = StringToColumn("Disk"); @@ -1099,19 +1295,19 @@ 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); + 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); @@ -1151,7 +1347,8 @@ void output_summary() ColumnInfo *cd; char TimeRateBuffer[40]; for(repdata = data(dp); repdata != NULL; repdata = repdata->next) { - int devlen; + char *devname; + size_t devlen; cd= &ColumnData[HostName]; fprintf(mailf, "%*s", cd->PrefixSpace, ""); @@ -1159,15 +1356,16 @@ void output_summary() cd= &ColumnData[Disk]; fprintf(mailf, "%*s", cd->PrefixSpace, ""); - devlen= strlen(dp->name); - if (devlen > cd->Width) { + devname = sanitize_string(dp->name); + devlen = strlen(devname); + if (devlen > (size_t)cd->Width) { fputc('-', mailf); fprintf(mailf, cd->Format, cd->Width-1, cd->Precision-1, - dp->name+devlen - (cd->Width-1) ); + devname+devlen - (cd->Width-1) ); } else - fprintf(mailf, cd->Format, cd->Width, cd->Width, dp->name); - + fprintf(mailf, cd->Format, cd->Width, cd->Width, devname); + amfree(devname); cd= &ColumnData[Level]; if (repdata->dumper.result == L_BOGUS && repdata->taper.result == L_BOGUS) { @@ -1191,26 +1389,36 @@ void output_summary() amfree(tmp); continue; } - if (repdata->dumper.result == L_FAIL) { + if (repdata->dumper.result == L_FAIL && (repdata->chunker.result != L_PARTIAL && repdata->taper.result != L_PARTIAL)) { fprintf(mailf, "%s\n", tmp=TextRule(OrigKB, TapeRate, "FAILED")); amfree(tmp); 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_PARTIAL || + 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 outsize = repdata->dumper.outsize; cd= &ColumnData[OrigKB]; fprintf(mailf, "%*s", cd->PrefixSpace, ""); - if(origsize != 0.0) + if(isnormal(origsize)) fprintf(mailf, cd->Format, cd->Width, cd->Precision, du(origsize)); else fprintf(mailf, "%*.*s", cd->Width, cd->Width, "N/A"); @@ -1234,17 +1442,19 @@ void output_summary() cd= &ColumnData[DumpTime]; fprintf(mailf, "%*s", cd->PrefixSpace, ""); - if(repdata->dumper.result == L_SUCCESS) - ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer), + if(repdata->dumper.result == L_SUCCESS || + repdata->dumper.result == L_CHUNKSUCCESS) + snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer), "%3d:%02d", mnsc(repdata->dumper.sec)); else - ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer), + snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer), "N/A "); fprintf(mailf, cd->Format, cd->Width, cd->Width, TimeRateBuffer); cd= &ColumnData[DumpRate]; fprintf(mailf, "%*s", cd->PrefixSpace, ""); - if(repdata->dumper.result == L_SUCCESS) + if(repdata->dumper.result == L_SUCCESS || + repdata->dumper.result == L_CHUNKSUCCESS) fprintf(mailf, cd->Format, cd->Width, cd->Precision, repdata->dumper.kps); else fprintf(mailf, "%*s", cd->Width, "N/A "); @@ -1258,58 +1468,79 @@ void output_summary() 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) + snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer), "%3d:%02d", mnsc(repdata->taper.sec)); else - ap_snprintf(TimeRateBuffer, sizeof(TimeRateBuffer), + snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer), "N/A "); fprintf(mailf, cd->Format, cd->Width, cd->Width, TimeRateBuffer); cd= &ColumnData[TapeRate]; fprintf(mailf, "%*s", cd->PrefixSpace, ""); - if(repdata->taper.result == L_SUCCESS) + if(repdata->taper.result == L_SUCCESS || + repdata->taper.result == L_PARTIAL || + repdata->taper.result == L_CHUNKSUCCESS) fprintf(mailf, cd->Format, cd->Width, cd->Precision, repdata->taper.kps); else fprintf(mailf, "%*s", cd->Width, "N/A "); + + if(repdata->chunker.result == L_PARTIAL || + repdata->taper.result == L_PARTIAL) { + fprintf(mailf, " PARTIAL"); + } fputc('\n', mailf); } } } } -void bogus_line() +static void +bogus_line( + const char *err_text) { - printf("line %d of log is bogus\n", curlinenum); + printf("line %d of log is bogus: <%s>\n", curlinenum, curstr); + printf(" Scan failed at: <%s>\n", err_text); } -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]; + char date[9]; + int numdate; static char *months[13] = { "BogusMonth", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "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); + 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; @@ -1323,36 +1554,36 @@ void handle_start() skip_whitespace(s, ch); #define sc "datestamp" - if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) { - bogus_line(); + if(ch == '\0' || strncmp(s - 1, sc, SIZEOF(sc)-1) != 0) { + bogus_line(s - 1); return; } - s += sizeof(sc)-1; + 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(s - 1, sc, SIZEOF(sc)-1) != 0) { + bogus_line(s - 1); return; } - s += sizeof(sc)-1; + 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; @@ -1360,7 +1591,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); @@ -1373,10 +1604,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; @@ -1384,6 +1615,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; @@ -1406,22 +1638,22 @@ void handle_start() skip_whitespace(s, ch); #define sc "date" - if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) { + if(ch == '\0' || strncmp(s - 1, sc, SIZEOF(sc)-1) != 0) { return; /* ignore bogus line */ } - s += sizeof(sc)-1; + 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; } @@ -1433,11 +1665,12 @@ void handle_start() } -void handle_finish() +static void +handle_finish(void) { char *s; int ch; - float a_time; + double a_time; if(curprog == P_DRIVER || curprog == P_AMFLUSH || curprog == P_PLANNER) { s = curstr; @@ -1445,40 +1678,40 @@ void handle_finish() skip_whitespace(s, ch); #define sc "date" - if(ch == '\0' || strncmp(s - 1, sc, sizeof(sc)-1) != 0) { - bogus_line(); + if(ch == '\0' || strncmp(s - 1, sc, SIZEOF(sc)-1) != 0) { + bogus_line(s - 1); return; } - s += sizeof(sc)-1; + 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) { + if(ch == '\0' || strncmp(s - 1, sc, SIZEOF(sc)-1) != 0) { /* older planner doesn't write time */ if(curprog == P_PLANNER) return; - bogus_line(); + bogus_line(s - 1); return; } - s += sizeof(sc)-1; + 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", &a_time) != 1) { - bogus_line(); + if(sscanf(s - 1, "%lf", &a_time) != 1) { + bogus_line(s - 1); return; } if(curprog == P_PLANNER) { @@ -1491,10 +1724,16 @@ void handle_finish() } } -void handle_stats() +static void +handle_stats(void) { - char *s; + char *s, *fp; int ch; + char *hostname, *diskname, *datestamp; + int level = 0; + double sec, kps, nbytes, cbytes; + repdata_t *repdata; + disk_t *dp; if(curprog == P_DRIVER) { s = curstr; @@ -1502,29 +1741,122 @@ void handle_stats() 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(s - 1, sc, sizeof(sc)-1) == 0) { + s += sizeof(sc)-1; + ch = s[-1]; +#undef sc + + 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]; +#define sc "estimate" + else if(ch != '\0' && strncmp(s - 1, sc, sizeof(sc)-1) == 0) { + s += sizeof(sc)-1; + ch = s[-1]; #undef sc - skip_whitespace(s, ch); - if(ch == '\0') { - bogus_line(); - return; + 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; + } + fp = s - 1; + skip_non_whitespace(s, ch); + s[-1] = '\0'; + diskname = stralloc(fp); + 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) { + addtostrange(hostname, diskname, level, + "ERROR [not in disklist]"); + 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; } - planner_time = startup_time; +#undef sc + } } -void handle_note() +static void +handle_note(void) { char *str = NULL; @@ -1536,7 +1868,8 @@ void handle_note() /* ----- */ -void handle_error() +static void +handle_error(void) { char *s = NULL, *nl; int ch; @@ -1547,23 +1880,22 @@ void handle_error() 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]; + if(ch != '\0' && strncmp(s - 1, sc, SIZEOF(sc)-1) == 0) { + 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'; + 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; + 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 */ } @@ -1575,28 +1907,30 @@ void handle_error() /* ----- */ -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++; @@ -1606,29 +1940,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); @@ -1636,10 +1971,15 @@ 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(void) { disk_t *dp; - float sec, kps, kbytes, origkb; + double sec, kps, kbytes; timedata_t *sp; int i; char *s, *fp; @@ -1647,11 +1987,154 @@ repdata_t *handle_success() char *hostname = NULL; char *diskname = NULL; repdata_t *repdata; - int level; + int level, chunk; + char *datestamp; + + 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; + } + 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); + + 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 = vstralloc(" ", prefix(hostname, diskname, level), + " ", "ERROR [not in disklist]", + NULL); + 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; char *datestamp; - if(curprog != P_TAPER && curprog != P_DUMPER && curprog != P_PLANNER) { - bogus_line(); + if(curprog != P_TAPER && curprog != P_DUMPER && curprog != P_PLANNER && + curprog != P_CHUNKER) { + bogus_line(curstr); return NULL; } @@ -1660,30 +2143,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; @@ -1692,16 +2174,16 @@ 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) { + if(strlen(datestamp) < 3) { + level = atoi(datestamp); datestamp = newstralloc(datestamp, run_datestamp); } else { skip_whitespace(s, ch); if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) { - bogus_line(); + bogus_line(s - 1); amfree(hostname); amfree(diskname); amfree(datestamp); @@ -1710,17 +2192,26 @@ repdata_t *handle_success() skip_integer(s, ch); } + if(level < 0 || level > 9) { + amfree(hostname); + amfree(diskname); + amfree(datestamp); + return NULL; + } + skip_whitespace(s, ch); /* 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); @@ -1728,20 +2219,15 @@ repdata_t *handle_success() } } else { - if(origkb == 0.0) origkb = 0.1; + if(!isnormal(origkb)) + origkb = 0.1; } } 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); + addtostrange(hostname, qdiskname, level, "ERROR [not in disklist]"); amfree(hostname); amfree(diskname); amfree(datestamp); @@ -1760,19 +2246,25 @@ 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) { 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 */ @@ -1781,6 +2273,12 @@ repdata_t *handle_success() else origkb = 0.0; } + + if (curprog == P_DUMPER && + (sp->result == L_FAIL || sp->result == L_PARTIAL)) { + addtostrange(hostname, qdiskname, level, "was successfully retried"); + } + amfree(hostname); amfree(diskname); amfree(datestamp); @@ -1795,6 +2293,7 @@ repdata_t *handle_success() if(curprog == P_TAPER) { if(current_tape == NULL) { error("current_tape == NULL"); + /*NOTREACHED*/ } stats[i].taper_time += sec; sp->filenum = ++tapefcount; @@ -1802,8 +2301,17 @@ repdata_t *handle_success() tapedisks[level] +=1; stats[i].tapedisks +=1; stats[i].tapesize += kbytes; - current_tape->taper_time += sec; - current_tape->coutsize += kbytes; + sp->outsize = kbytes; + if(!isnormal(repdata->chunker.outsize) && isnormal(repdata->dumper.outsize)) { /* dump to tape */ + stats[i].outsize += kbytes; + if(dp->compress != COMP_NONE) { + stats[i].coutsize += kbytes; + } + } + if (logtype == L_SUCCESS || logtype== L_PARTIAL) { + current_tape->taper_time += sec; + current_tape->coutsize += kbytes; + } current_tape->corigsize += origkb; current_tape->tapedisks += 1; } @@ -1814,29 +2322,59 @@ repdata_t *handle_success() sp->origsize = kbytes; } else { - stats[i].coutsize += kbytes; stats[i].corigsize += sp->origsize; } 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(dp->compress != COMP_NONE) { + 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; + + qdisk = quote_string(repdata->disk->name); addline(&errdet,""); str = vstralloc("/-- ", prefix(repdata->disk->host->hostname, - repdata->disk->name, repdata->level), + qdisk, repdata->level), " ", "STRANGE", NULL); addline(&errdet, str); @@ -1845,31 +2383,30 @@ void handle_strange() while(contline_next()) { get_logline(logfile); #define sc "sendbackup: warning " - if(strncmp(curstr, sc, sizeof(sc)-1) == 0) { - strangestr = newstralloc(strangestr, curstr+sizeof(sc)-1); + if(strncmp(curstr, sc, SIZEOF(sc)-1) == 0) { + strangestr = newstralloc(strangestr, curstr+SIZEOF(sc)-1); } addline(&errdet, curstr); } addline(&errdet,"\\--------"); - str = vstralloc(" ", prefix(repdata->disk->host->hostname, - repdata->disk->name, repdata->level), - " ", "STRANGE", " ", strangestr, - NULL); - addline(&errsum, str); + str = vstralloc("STRANGE", " ", strangestr, NULL); + addtostrange(repdata->disk->host->hostname, qdisk, repdata->level, str); + 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; @@ -1883,7 +2420,7 @@ void handle_failed() skip_whitespace(s, ch); if(ch == '\0') { - bogus_line(); + bogus_line(s - 1); return; } hostname = s - 1; @@ -1892,16 +2429,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; @@ -1916,8 +2455,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); @@ -1925,8 +2465,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; @@ -1935,12 +2476,9 @@ 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); + addtostrange(hostname, qdiskname, level, "ERROR [not in disklist]"); } else { repdata = find_repdata(dp, datestamp, level); @@ -1953,16 +2491,13 @@ void handle_failed() } amfree(datestamp); - str = vstralloc(" ", prefix(hostname, diskname, level), - " ", "FAILED", - " ", errstr, - NULL); - addline(&errsum, str); + str = vstralloc("FAILED", " ", errstr, NULL); + addtostrange(hostname, qdiskname, level, str); amfree(str); if(curprog == P_DUMPER) { addline(&errdet,""); - str = vstralloc("/-- ", prefix(hostname, diskname, level), + str = vstralloc("/-- ", prefix(hostname, qdiskname, level), " ", "FAILED", " ", errstr, NULL); @@ -1977,58 +2512,179 @@ void handle_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); + addtostrange(dp->host->hostname, qdisk, -987, "RESULTS 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_PARTIAL || + 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 + outsize = repdata->dumper.outsize; + + if(repdata->est_csize * 0.9 > outsize) { + snprintf(s, 1000, + " big estimate: %s %s %d", + repdata->disk->host->hostname, + repdata->disk->name, + repdata->level); + s[999] = '\0'; + addline(¬es, s); + 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) { + snprintf(s, 1000, + " small estimate: %s %s %d", + repdata->disk->host->hostname, + repdata->disk->name, + repdata->level); + s[999] = '\0'; + addline(¬es, s); + 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); + snprintf(number, SIZEOF(number), "%d", level); + str = newvstralloc(str, + " ", host ? host : "(host?)", + " ", disk ? disk : "(disk?)", + level != -987 ? " lev " : "", + level != -987 ? number : "", + NULL); + 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; + char number[NUM_STR_SIZE]; + static char *str = NULL; + + snprintf(number, SIZEOF(number), "%d", level); + 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] = ' '; } + 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] = ' '; + } str = newvstralloc(str, h, - " ", disk ? disk : "(disk?)", - level != -987 ? " lev " : "", + " ", d, + level != -987 ? " lev " : "", level != -987 ? number : "", NULL); + amfree(h); + amfree(d); return str; } -void copy_template_file(lbl_templ) -char *lbl_templ; + +static void +addtostrange ( + char * host, + char * disk, + int level, + char * str) +{ + strange_t *strange; + + strange = alloc(SIZEOF(strange_t)); + strange->hostname = stralloc(host); + strange->diskname = stralloc(disk); + strange->level = level; + strange->str = stralloc(str); + strange->next = NULL; + if(first_strange == NULL) { + first_strange = strange; + } + else { + last_strange->next = strange; + } + last_strange = strange; +} + + +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); @@ -2045,11 +2701,12 @@ char *lbl_templ; NULL); 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 ", @@ -2059,6 +2716,7 @@ char *lbl_templ; NULL); handle_error(); amfree(curstr); + amfree(lbl_templ); afclose(postscript); return; } @@ -2073,6 +2731,7 @@ char *lbl_templ; NULL); handle_error(); amfree(curstr); + amfree(lbl_templ); afclose(postscript); return; } @@ -2080,10 +2739,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; @@ -2094,8 +2754,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; @@ -2111,16 +2771,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; + + if (!tp) + return; - tapesize = tp->length; - marksize = tp->filemark; + tapesize = tapetype_get_length(tp); + marksize = tapetype_get_filemark(tp); for(current_tape = stats_by_tape; current_tape != NULL; current_tape = current_tape->next) { @@ -2129,21 +2794,21 @@ void do_postscript_output() break; } - copy_template_file(tp->lbl_templ); + copy_template_file(tapetype_get_lbl_templ(tp)); /* generate a few elements */ fprintf(postscript,"(%s) DrawDate\n\n", - nicedate(run_datestamp ? atoi(run_datestamp) : 0)); + nicedate(run_datestamp ? run_datestamp : "0")); fprintf(postscript,"(Amanda Version %s) DrawVers\n",version()); fprintf(postscript,"(%s) DrawTitle\n", current_tape->label); /* Stats */ - fprintf(postscript, "(Total Size: %6.1f MB) DrawStat\n", + fprintf(postscript, "(Total Size: %6.1lf MB) DrawStat\n", mb(current_tape->coutsize)); fprintf(postscript, "(Tape Used (%%) "); divzero(postscript, pct(current_tape->coutsize + - marksize * current_tape->tapedisks), - tapesize); + marksize * (current_tape->tapedisks + current_tape->tapechunks)), + (double)tapesize); fprintf(postscript," %%) DrawStat\n"); fprintf(postscript, "(Compression Ratio: "); divzero(postscript, pct(current_tape->coutsize),current_tape->corigsize); @@ -2167,25 +2832,28 @@ 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)) { + 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", + fprintf(postscript,"(%s) (%s) (%d) (%3.0d) (%8s) (%8.0lf) DrawHost\n", dp->host->hostname, dp->name, repdata->level, repdata->taper.filenum, "N/A", outsize);