X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Fdriverio.c;h=ea08d31e0ab0e8e68ab1141595ea6b1b2349f0a6;hb=c21061ed466e7ee71cb21dd35010e33f6cf76424;hp=0000a3c3b2e815731e5e273d6292b897adaa6b99;hpb=1194fb66aa28d9929c3f2bef3cc6c1c3f40a60a4;p=debian%2Famanda diff --git a/server-src/driverio.c b/server-src/driverio.c index 0000a3c..ea08d31 100644 --- a/server-src/driverio.c +++ b/server-src/driverio.c @@ -25,32 +25,33 @@ * University of Maryland at College Park */ /* - * $Id: driverio.c,v 1.81 2006/03/11 21:57:18 martinea Exp $ + * $Id: driverio.c,v 1.92 2006/08/24 01:57:16 paddy_s Exp $ * * I/O-related functions for driver program */ #include "amanda.h" #include "util.h" #include "clock.h" +#include "server_util.h" #include "conffile.h" #include "diskfile.h" #include "infofile.h" #include "logfile.h" -#include "token.h" -#include "server_util.h" +#include "timestamp.h" #define GLOBAL /* the global variables defined here */ #include "driverio.h" int nb_chunker = 0; -static const char *childstr P((int)); +static const char *childstr(int); -void init_driverio() +void +init_driverio(void) { dumper_t *dumper; - taper = -1; + taper_fd = -1; for(dumper = dmptable; dumper < dmptable + MAX_DUMPERS; dumper++) { dumper->fd = -1; @@ -59,103 +60,159 @@ void init_driverio() static const char * -childstr(fd) - int fd; +childstr( + int fd) { static char buf[NUM_STR_SIZE + 32]; dumper_t *dumper; - if (fd == taper) + if (fd == taper_fd) return ("taper"); for (dumper = dmptable; dumper < dmptable + MAX_DUMPERS; dumper++) { if (dumper->fd == fd) return (dumper->name); - if (dumper->chunker->fd == fd) + if (dumper->chunker && dumper->chunker->fd == fd) return (dumper->chunker->name); } - snprintf(buf, sizeof(buf), "unknown child (fd %d)", fd); + g_snprintf(buf, SIZEOF(buf), _("unknown child (fd %d)"), fd); return (buf); } -void startup_tape_process(taper_program) -char *taper_program; +void +startup_tape_process( + char *taper_program, + int taper_parallel_write, + gboolean no_taper) { - int fd[2]; + int fd[2]; + int i; + char **config_options; + taper_t *taper; + + /* always allocate the tapetable */ + tapetable = calloc(sizeof(taper_t), taper_parallel_write+1); + + for (taper = tapetable, i = 0; i < taper_parallel_write; taper++, i++) { + taper->name = g_strdup_printf("worker%d", i); + taper->sendresult = 0; + taper->input_error = NULL; + taper->tape_error = NULL; + taper->result = 0; + taper->dumper = NULL; + taper->disk = NULL; + taper->first_label = NULL; + taper->first_fileno = 0; + taper->state = TAPER_STATE_DEFAULT; + taper->left = 0; + taper->written = 0; + + /* jump right to degraded mode if there's no taper */ + if (no_taper) { + taper->tape_error = g_strdup("no taper started (--no-taper)"); + taper->result = BOGUS; + } + } + + /* don't start the taper if we're not supposed to */ + if (no_taper) + return; - if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) - error("taper pipe: %s", strerror(errno)); - if(fd[0] < 0 || fd[0] >= FD_SETSIZE) { - error("taper socketpair 0: descriptor %d out of range (0 .. %d)\n", - fd[0], FD_SETSIZE-1); + if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) { + error(_("taper pipe: %s"), strerror(errno)); + /*NOTREACHED*/ } - if(fd[1] < 0 || fd[1] >= FD_SETSIZE) { - error("taper socketpair 1: descriptor %d out of range (0 .. %d)\n", - fd[1], FD_SETSIZE-1); + if(fd[0] < 0 || fd[0] >= (int)FD_SETSIZE) { + error(_("taper socketpair 0: descriptor %d out of range (0 .. %d)\n"), + fd[0], (int)FD_SETSIZE-1); + /*NOTREACHED*/ + } + if(fd[1] < 0 || fd[1] >= (int)FD_SETSIZE) { + error(_("taper socketpair 1: descriptor %d out of range (0 .. %d)\n"), + fd[1], (int)FD_SETSIZE-1); + /*NOTREACHED*/ } switch(taper_pid = fork()) { case -1: - error("fork taper: %s", strerror(errno)); + error(_("fork taper: %s"), strerror(errno)); + /*NOTREACHED*/ + case 0: /* child process */ aclose(fd[0]); if(dup2(fd[1], 0) == -1 || dup2(fd[1], 1) == -1) - error("taper dup2: %s", strerror(errno)); - execle(taper_program, "taper", config_name, (char *)0, safe_env()); + error(_("taper dup2: %s"), strerror(errno)); + config_options = get_config_options(2); + config_options[0] = "taper"; + config_options[1] = get_config_name(); + safe_fd(-1, 0); + execve(taper_program, config_options, safe_env()); error("exec %s: %s", taper_program, strerror(errno)); + /*NOTREACHED*/ + default: /* parent process */ aclose(fd[1]); - taper = fd[0]; + taper_fd = fd[0]; taper_ev_read = NULL; } } -void startup_dump_process(dumper, dumper_program) -dumper_t *dumper; -char *dumper_program; +void +startup_dump_process( + dumper_t *dumper, + char *dumper_program) { - int fd[2]; + int fd[2]; + char **config_options; - if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) - error("%s pipe: %s", dumper->name, strerror(errno)); + if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) { + error(_("%s pipe: %s"), dumper->name, strerror(errno)); + /*NOTREACHED*/ + } switch(dumper->pid = fork()) { case -1: - error("fork %s: %s", dumper->name, strerror(errno)); + error(_("fork %s: %s"), dumper->name, strerror(errno)); + /*NOTREACHED*/ + case 0: /* child process */ aclose(fd[0]); if(dup2(fd[1], 0) == -1 || dup2(fd[1], 1) == -1) - error("%s dup2: %s", dumper->name, strerror(errno)); - execle(dumper_program, - dumper->name ? dumper->name : "dumper", - config_name, - (char *)0, - safe_env()); - error("exec %s (%s): %s", dumper_program, + error(_("%s dup2: %s"), dumper->name, strerror(errno)); + config_options = get_config_options(2); + config_options[0] = dumper->name ? dumper->name : "dumper", + config_options[1] = get_config_name(); + safe_fd(-1, 0); + execve(dumper_program, config_options, safe_env()); + error(_("exec %s (%s): %s"), dumper_program, dumper->name, strerror(errno)); + /*NOTREACHED*/ + default: /* parent process */ aclose(fd[1]); dumper->fd = fd[0]; dumper->ev_read = NULL; dumper->busy = dumper->down = 0; dumper->dp = NULL; - fprintf(stderr,"driver: started %s pid %d\n", - dumper->name, dumper->pid); + g_fprintf(stderr,_("driver: started %s pid %u\n"), + dumper->name, (unsigned)dumper->pid); fflush(stderr); } } -void startup_dump_processes(dumper_program, inparallel) -char *dumper_program; -int inparallel; +void +startup_dump_processes( + char *dumper_program, + int inparallel, + char *timestamp) { int i; dumper_t *dumper; char number[NUM_STR_SIZE]; for(dumper = dmptable, i = 0; i < inparallel; dumper++, i++) { - snprintf(number, sizeof(number), "%d", i); + g_snprintf(number, SIZEOF(number), "%d", i); dumper->name = stralloc2("dumper", number); dumper->chunker = &chktable[i]; chktable[i].name = stralloc2("chunker", number); @@ -163,273 +220,493 @@ int inparallel; chktable[i].fd = -1; startup_dump_process(dumper, dumper_program); + dumper_cmd(dumper, START, NULL, (void *)timestamp); } } -void startup_chunk_process(chunker, chunker_program) -chunker_t *chunker; -char *chunker_program; +void +startup_chunk_process( + chunker_t *chunker, + char *chunker_program) { - int fd[2]; + int fd[2]; + char **config_options; - if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) - error("%s pipe: %s", chunker->name, strerror(errno)); + if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) { + error(_("%s pipe: %s"), chunker->name, strerror(errno)); + /*NOTREACHED*/ + } switch(chunker->pid = fork()) { case -1: - error("fork %s: %s", chunker->name, strerror(errno)); + error(_("fork %s: %s"), chunker->name, strerror(errno)); + /*NOTREACHED*/ + case 0: /* child process */ aclose(fd[0]); - if(dup2(fd[1], 0) == -1 || dup2(fd[1], 1) == -1) - error("%s dup2: %s", chunker->name, strerror(errno)); - execle(chunker_program, - chunker->name ? chunker->name : "chunker", - config_name, - (char *)0, - safe_env()); - error("exec %s (%s): %s", chunker_program, + if(dup2(fd[1], 0) == -1 || dup2(fd[1], 1) == -1) { + error(_("%s dup2: %s"), chunker->name, strerror(errno)); + /*NOTREACHED*/ + } + config_options = get_config_options(2); + config_options[0] = chunker->name ? chunker->name : "chunker", + config_options[1] = get_config_name(); + safe_fd(-1, 0); + execve(chunker_program, config_options, safe_env()); + error(_("exec %s (%s): %s"), chunker_program, chunker->name, strerror(errno)); + /*NOTREACHED*/ + default: /* parent process */ aclose(fd[1]); chunker->down = 0; chunker->fd = fd[0]; chunker->ev_read = NULL; - fprintf(stderr,"driver: started %s pid %d\n", - chunker->name, chunker->pid); + g_fprintf(stderr,_("driver: started %s pid %u\n"), + chunker->name, (unsigned)chunker->pid); fflush(stderr); } } -cmd_t getresult(fd, show, result_argc, result_argv, max_arg) -int fd; -int show; -int *result_argc; -char **result_argv; -int max_arg; +cmd_t +getresult( + int fd, + int show, + int *result_argc, + char ***result_argv) { - int arg; cmd_t t; char *line; if((line = areads(fd)) == NULL) { if(errno) { - error("reading result from %s: %s", childstr(fd), strerror(errno)); + g_fprintf(stderr, _("reading result from %s: %s"), childstr(fd), strerror(errno)); } + *result_argv = NULL; *result_argc = 0; /* EOF */ } else { - *result_argc = split(line, result_argv, max_arg, " "); + *result_argv = split_quoted_strings(line); + *result_argc = g_strv_length(*result_argv); } if(show) { - printf("driver: result time %s from %s:", + g_printf(_("driver: result time %s from %s:"), walltime_str(curclock()), childstr(fd)); if(line) { - for(arg = 1; arg <= *result_argc; arg++) { - printf(" %s", result_argv[arg]); - } + g_printf(" %s", line); putchar('\n'); } else { - printf(" (eof)\n"); + g_printf(" (eof)\n"); } fflush(stdout); } amfree(line); -#ifdef DEBUG - printf("argc = %d\n", *result_argc); - for(arg = 0; arg < *result_argc; arg++) - printf("argv[%d] = \"%s\"\n", arg, result_argv[arg]); -#endif - if(*result_argc < 1) return BOGUS; for(t = (cmd_t)(BOGUS+1); t < LAST_TOK; t++) - if(strcmp(result_argv[1], cmdstr[t]) == 0) return t; + if(strcmp((*result_argv)[0], cmdstr[t]) == 0) return t; return BOGUS; } -int taper_cmd(cmd, /* optional */ ptr, destname, level, datestamp) -cmd_t cmd; -void *ptr; -char *destname; -int level; -char *datestamp; +static char * +taper_splitting_args( + disk_t *dp) +{ + GString *args = NULL; + char *q = NULL; + dumptype_t *dt = dp->config; + tapetype_t *tt; + + tt = lookup_tapetype(getconf_str(CNF_TAPETYPE)); + g_assert(tt != NULL); + + args = g_string_new(""); + + /* old dumptype-based parameters, using empty strings when not seen */ + if (dt) { /* 'dt' may be NULL for flushes */ + if (dumptype_seen(dt, DUMPTYPE_TAPE_SPLITSIZE)) { + g_string_append_printf(args, "%ju ", + (uintmax_t)dumptype_get_tape_splitsize(dt)*1024); + } else { + g_string_append(args, "\"\" "); + } + + q = quote_string(dumptype_seen(dt, DUMPTYPE_SPLIT_DISKBUFFER)? + dumptype_get_split_diskbuffer(dt) : ""); + g_string_append_printf(args, "%s ", q); + g_free(q); + + if (dumptype_seen(dt, DUMPTYPE_FALLBACK_SPLITSIZE)) { + g_string_append_printf(args, "%ju ", + (uintmax_t)dumptype_get_fallback_splitsize(dt)*1024); + } else { + g_string_append(args, "\"\" "); + } + + if (dumptype_seen(dt, DUMPTYPE_ALLOW_SPLIT)) { + g_string_append_printf(args, "%d ", + (int)dumptype_get_allow_split(dt)); + } else { + g_string_append(args, "\"\" "); + } + } else { + g_string_append(args, "\"\" \"\" \"\" \"\" "); + } + + /* new tapetype-based parameters */ + if (tapetype_seen(tt, TAPETYPE_PART_SIZE)) { + g_string_append_printf(args, "%ju ", + (uintmax_t)tapetype_get_part_size(tt)*1024); + } else { + g_string_append(args, "\"\" "); + } + + q = ""; + if (tapetype_seen(tt, TAPETYPE_PART_CACHE_TYPE)) { + switch (tapetype_get_part_cache_type(tt)) { + default: + case PART_CACHE_TYPE_NONE: + q = "none"; + break; + + case PART_CACHE_TYPE_MEMORY: + q = "memory"; + break; + + case PART_CACHE_TYPE_DISK: + q = "disk"; + break; + } + } + q = quote_string(q); + g_string_append_printf(args, "%s ", q); + g_free(q); + + q = quote_string(tapetype_seen(tt, TAPETYPE_PART_CACHE_DIR)? + tapetype_get_part_cache_dir(tt) : ""); + g_string_append_printf(args, "%s ", q); + g_free(q); + + if (tapetype_seen(tt, TAPETYPE_PART_CACHE_MAX_SIZE)) { + g_string_append_printf(args, "%ju ", + (uintmax_t)tapetype_get_part_cache_max_size(tt)*1024); + } else { + g_string_append(args, "\"\" "); + } + + + return g_string_free(args, FALSE); +} + +int +taper_cmd( + cmd_t cmd, + void *ptr, + char *destname, + int level, + char *datestamp) { char *cmdline = NULL; char number[NUM_STR_SIZE]; - char splitsize[NUM_STR_SIZE]; - char fallback_splitsize[NUM_STR_SIZE]; - char *diskbuffer = NULL; + char orig_kb[NUM_STR_SIZE]; + char *data_path; disk_t *dp; - char *features; + char *qname; + char *qdest; + char *q; + char *splitargs; + uintmax_t origsize; switch(cmd) { case START_TAPER: - cmdline = vstralloc(cmdstr[cmd], " ", (char *)ptr, "\n", NULL); + cmdline = vstralloc(cmdstr[cmd], + " ", destname, + " ", datestamp, + "\n", NULL); break; case FILE_WRITE: dp = (disk_t *) ptr; - snprintf(number, sizeof(number), "%d", level); - snprintf(splitsize, sizeof(splitsize), "%ld", dp->tape_splitsize); - features = am_feature_to_string(dp->host->features); + qname = quote_string(dp->name); + qdest = quote_string(destname); + g_snprintf(number, SIZEOF(number), "%d", level); + if (sched(dp)->origsize >= 0) + origsize = sched(dp)->origsize; + else + origsize = 0; + g_snprintf(orig_kb, SIZEOF(orig_kb), "%ju", origsize); + splitargs = taper_splitting_args(dp); cmdline = vstralloc(cmdstr[cmd], + " ", sched(dp)->taper->name, " ", disk2serial(dp), - " ", destname, + " ", qdest, " ", dp->host->hostname, - " ", features, - " ", dp->name, + " ", qname, " ", number, " ", datestamp, - " ", splitsize, + " ", splitargs, + orig_kb, "\n", NULL); - amfree(features); + amfree(splitargs); + amfree(qdest); + amfree(qname); break; + case PORT_WRITE: dp = (disk_t *) ptr; - snprintf(number, sizeof(number), "%d", level); + qname = quote_string(dp->name); + g_snprintf(number, SIZEOF(number), "%d", level); + data_path = data_path_to_string(dp->data_path); /* If we haven't been given a place to buffer split dumps to disk, make the argument something besides and empty string so's taper won't get confused */ - if(!dp->split_diskbuffer || dp->split_diskbuffer[0] == '\0'){ - diskbuffer = "NULL"; - } else { - diskbuffer = dp->split_diskbuffer; - } - snprintf(splitsize, sizeof(splitsize), "%ld", dp->tape_splitsize); - snprintf(fallback_splitsize, sizeof(fallback_splitsize), - "%ld", dp->fallback_splitsize); - features = am_feature_to_string(dp->host->features); + splitargs = taper_splitting_args(dp); cmdline = vstralloc(cmdstr[cmd], + " ", sched(dp)->taper->name, " ", disk2serial(dp), " ", dp->host->hostname, - " ", features, - " ", dp->name, + " ", qname, " ", number, " ", datestamp, - " ", splitsize, - " ", diskbuffer, - " ", fallback_splitsize, + " ", splitargs, + data_path, + "\n", NULL); + amfree(splitargs); + amfree(qname); + break; + case DONE: /* handle */ + dp = (disk_t *) ptr; + if (sched(dp)->origsize >= 0) + origsize = sched(dp)->origsize; + else + origsize = 0; + g_snprintf(number, SIZEOF(number), "%ju", origsize); + cmdline = vstralloc(cmdstr[cmd], + " ", sched(dp)->taper->name, + " ", disk2serial(dp), + " ", number, + "\n", NULL); + break; + case FAILED: /* handle */ + dp = (disk_t *) ptr; + cmdline = vstralloc(cmdstr[cmd], + " ", sched(dp)->taper->name, + " ", disk2serial(dp), + "\n", NULL); + break; + case NO_NEW_TAPE: + dp = (disk_t *) ptr; + q = quote_string(destname); /* reason why no new tape */ + cmdline = vstralloc(cmdstr[cmd], + " ", sched(dp)->taper->name, + " ", disk2serial(dp), + " ", q, + "\n", NULL); + amfree(q); + break; + case NEW_TAPE: + dp = (disk_t *) ptr; + cmdline = vstralloc(cmdstr[cmd], + " ", sched(dp)->taper->name, + " ", disk2serial(dp), + "\n", NULL); + break; + case START_SCAN: + dp = (disk_t *) ptr; + cmdline = vstralloc(cmdstr[cmd], + " ", sched(dp)->taper->name, + " ", disk2serial(dp), + "\n", NULL); + break; + case TAKE_SCRIBE_FROM: + dp = (disk_t *) ptr; + cmdline = vstralloc(cmdstr[cmd], + " ", sched(dp)->taper->name, + " ", disk2serial(dp), + " ", destname, /* name of worker */ "\n", NULL); - amfree(features); break; case QUIT: cmdline = stralloc2(cmdstr[cmd], "\n"); break; default: - error("Don't know how to send %s command to taper", cmdstr[cmd]); + error(_("Don't know how to send %s command to taper"), cmdstr[cmd]); + /*NOTREACHED*/ } + /* * Note: cmdline already has a '\n'. */ - printf("driver: send-cmd time %s to taper: %s", + g_printf(_("driver: send-cmd time %s to taper: %s"), walltime_str(curclock()), cmdline); fflush(stdout); - if (fullwrite(taper, cmdline, strlen(cmdline)) < 0) { - printf("writing taper command: %s\n", strerror(errno)); + if ((full_write(taper_fd, cmdline, strlen(cmdline))) < strlen(cmdline)) { + g_printf(_("writing taper command '%s' failed: %s\n"), + cmdline, strerror(errno)); fflush(stdout); amfree(cmdline); return 0; } + if(cmd == QUIT) aclose(taper_fd); amfree(cmdline); return 1; } -int dumper_cmd(dumper, cmd, /* optional */ dp) -dumper_t *dumper; -cmd_t cmd; -disk_t *dp; +int +dumper_cmd( + dumper_t *dumper, + cmd_t cmd, + disk_t *dp, + char *mesg) { char *cmdline = NULL; char number[NUM_STR_SIZE]; char numberport[NUM_STR_SIZE]; - char *o; - int activehd=0; - assignedhd_t **h=NULL; + char *o, *oo; char *device; char *features; - - if(dp && sched(dp) && sched(dp)->holdp) { - h = sched(dp)->holdp; - activehd = sched(dp)->activehd; - } - - if(dp && dp->device) { - device = dp->device; - } - else { - device = "NODEVICE"; - } + char *qname; + char *qmesg; switch(cmd) { + case START: + cmdline = vstralloc(cmdstr[cmd], " ", mesg, "\n", NULL); + break; case PORT_DUMP: + if(dp && dp->device) { + device = dp->device; + } + else { + device = "NODEVICE"; + } + if (dp != NULL) { - snprintf(number, sizeof(number), "%d", sched(dp)->level); - snprintf(numberport, sizeof(numberport), "%d", dumper->output_port); + application_t *application = NULL; + char *plugin; + char *qplugin; + char *qamandad_path; + char *qclient_username; + char *qclient_port; + char *qssh_keys; + + if (dp->application != NULL) { + application = lookup_application(dp->application); + g_assert(application != NULL); + } + + device = quote_string((dp->device) ? dp->device : "NODEVICE"); + qname = quote_string(dp->name); + g_snprintf(number, SIZEOF(number), "%d", sched(dp)->level); + g_snprintf(numberport, SIZEOF(numberport), "%d", dumper->output_port); features = am_feature_to_string(dp->host->features); - o = optionstr(dp, dp->host->features, NULL); + if (am_has_feature(dp->host->features, fe_req_xml)) { + o = xml_optionstr(dp, 1); + if (application) { + char *xml_app; + xml_app = xml_application(dp, application, + dp->host->features); + vstrextend(&o, xml_app, NULL); + amfree(xml_app); + } + oo = quote_string(o); + amfree(o); + o = oo; + } else { + o = optionstr(dp); + } + + g_assert(dp->program); + if (0 == strcmp(dp->program, "APPLICATION")) { + g_assert(application != NULL); + plugin = application_get_plugin(application); + } else { + plugin = dp->program; + } + qplugin = quote_string(plugin); + qamandad_path = quote_string(dp->amandad_path); + qclient_username = quote_string(dp->client_username); + qclient_port = quote_string(dp->client_port); + qssh_keys = quote_string(dp->ssh_keys); + dbprintf("security_driver %s\n", dp->auth); + cmdline = vstralloc(cmdstr[cmd], " ", disk2serial(dp), " ", numberport, " ", dp->host->hostname, " ", features, - " ", dp->name, + " ", qname, " ", device, " ", number, " ", sched(dp)->dumpdate, - " ", dp->program, + " ", qplugin, + " ", qamandad_path, + " ", qclient_username, + " ", qclient_port, + " ", qssh_keys, + " ", dp->auth, + " ", data_path_to_string(dp->data_path), + " ", dp->dataport_list, " |", o, "\n", NULL); + amfree(qplugin); + amfree(qamandad_path); + amfree(qclient_username); + amfree(qclient_port); + amfree(qssh_keys); amfree(features); amfree(o); + amfree(qname); + amfree(device); } else { - error("PORT-DUMP without disk pointer\n"); + error(_("PORT-DUMP without disk pointer\n")); /*NOTREACHED*/ } break; case QUIT: case ABORT: - if( dp ) { - cmdline = vstralloc(cmdstr[cmd], - " ", sched(dp)->destname, - "\n", NULL ); - } else { - cmdline = stralloc2(cmdstr[cmd], "\n"); - } + qmesg = quote_string(mesg); + cmdline = vstralloc(cmdstr[cmd], " ", qmesg, "\n", NULL ); + amfree(qmesg); break; default: - error("Don't know how to send %s command to dumper", cmdstr[cmd]); + error(_("Don't know how to send %s command to dumper"), cmdstr[cmd]); + /*NOTREACHED*/ } + /* * Note: cmdline already has a '\n'. */ if(dumper->down) { - printf("driver: send-cmd time %s ignored to down dumper %s: %s", + g_printf(_("driver: send-cmd time %s ignored to down dumper %s: %s"), walltime_str(curclock()), dumper->name, cmdline); } else { - printf("driver: send-cmd time %s to %s: %s", + g_printf(_("driver: send-cmd time %s to %s: %s"), walltime_str(curclock()), dumper->name, cmdline); fflush(stdout); - if (fullwrite(dumper->fd, cmdline, strlen(cmdline)) < 0) { - printf("writing %s command: %s\n", dumper->name, strerror(errno)); + if (full_write(dumper->fd, cmdline, strlen(cmdline)) < strlen(cmdline)) { + g_printf(_("writing %s command: %s\n"), dumper->name, strerror(errno)); fflush(stdout); amfree(cmdline); return 0; } + if (cmd == QUIT) aclose(dumper->fd); } amfree(cmdline); return 1; } -int chunker_cmd(chunker, cmd, dp) -chunker_t *chunker; -cmd_t cmd; -disk_t *dp; +int +chunker_cmd( + chunker_t *chunker, + cmd_t cmd, + disk_t *dp, + char *mesg) { char *cmdline = NULL; char number[NUM_STR_SIZE]; @@ -439,27 +716,36 @@ disk_t *dp; int activehd=0; assignedhd_t **h=NULL; char *features; - - if(dp && sched(dp) && sched(dp)->holdp) { - h = sched(dp)->holdp; - activehd = sched(dp)->activehd; - } + char *qname; + char *qdest; switch(cmd) { + case START: + cmdline = vstralloc(cmdstr[cmd], " ", mesg, "\n", NULL); + break; case PORT_WRITE: + if(dp && sched(dp) && sched(dp)->holdp) { + h = sched(dp)->holdp; + activehd = sched(dp)->activehd; + } + if (dp && h) { - holdalloc(h[activehd]->disk)->allocated_dumpers++; - snprintf(number, sizeof(number), "%d", sched(dp)->level); - snprintf(chunksize, sizeof(chunksize), "%ld", h[0]->disk->chunksize); - snprintf(use, sizeof(use), "%ld", h[0]->reserved ); + qname = quote_string(dp->name); + qdest = quote_string(sched(dp)->destname); + h[activehd]->disk->allocated_dumpers++; + g_snprintf(number, SIZEOF(number), "%d", sched(dp)->level); + g_snprintf(chunksize, SIZEOF(chunksize), "%lld", + (long long)holdingdisk_get_chunksize(h[0]->disk->hdisk)); + g_snprintf(use, SIZEOF(use), "%lld", + (long long)h[0]->reserved); features = am_feature_to_string(dp->host->features); - o = optionstr(dp, dp->host->features, NULL); + o = optionstr(dp); cmdline = vstralloc(cmdstr[cmd], " ", disk2serial(dp), - " ", sched(dp)->destname, + " ", qdest, " ", dp->host->hostname, " ", features, - " ", dp->name, + " ", qname, " ", number, " ", sched(dp)->dumpdate, " ", chunksize, @@ -469,35 +755,51 @@ disk_t *dp; "\n", NULL); amfree(features); amfree(o); + amfree(qdest); + amfree(qname); } else { - error("Write command without disk and holding disk.\n", + error(_("%s command without disk and holding disk.\n"), cmdstr[cmd]); /*NOTREACHED*/ } break; case CONTINUE: - if( dp && h) { - holdalloc(h[activehd]->disk)->allocated_dumpers++; - snprintf(chunksize, sizeof(chunksize), "%ld", - h[activehd]->disk->chunksize ); - snprintf(use, sizeof(use), "%ld", - h[activehd]->reserved - h[activehd]->used ); + if(dp && sched(dp) && sched(dp)->holdp) { + h = sched(dp)->holdp; + activehd = sched(dp)->activehd; + } + + if(dp && h) { + qname = quote_string(dp->name); + qdest = quote_string(h[activehd]->destname); + h[activehd]->disk->allocated_dumpers++; + g_snprintf(chunksize, SIZEOF(chunksize), "%lld", + (long long)holdingdisk_get_chunksize(h[activehd]->disk->hdisk)); + g_snprintf(use, SIZEOF(use), "%lld", + (long long)(h[activehd]->reserved - h[activehd]->used)); cmdline = vstralloc(cmdstr[cmd], " ", disk2serial(dp), - " ", h[activehd]->destname, + " ", qdest, " ", chunksize, " ", use, "\n", NULL ); + amfree(qdest); + amfree(qname); } else { cmdline = stralloc2(cmdstr[cmd], "\n"); } break; case QUIT: - cmdline = stralloc2(cmdstr[cmd], "\n"); + case ABORT: + { + char *q = quote_string(mesg); + cmdline = vstralloc(cmdstr[cmd], " ", q, "\n", NULL); + amfree(q); + } break; case DONE: case FAILED: - if( dp) { + if( dp ) { cmdline = vstralloc(cmdstr[cmd], " ", disk2serial(dp), "\n", NULL); @@ -506,25 +808,28 @@ disk_t *dp; } break; default: - error("Don't know how to send %s command to chunker", cmdstr[cmd]); + error(_("Don't know how to send %s command to chunker"), cmdstr[cmd]); + /*NOTREACHED*/ } + /* * Note: cmdline already has a '\n'. */ - printf("driver: send-cmd time %s to %s: %s", + g_printf(_("driver: send-cmd time %s to %s: %s"), walltime_str(curclock()), chunker->name, cmdline); fflush(stdout); - if (fullwrite(chunker->fd, cmdline, strlen(cmdline)) < 0) { - printf("writing %s command: %s\n", chunker->name, strerror(errno)); + if (full_write(chunker->fd, cmdline, strlen(cmdline)) < strlen(cmdline)) { + g_printf(_("writing %s command: %s\n"), chunker->name, strerror(errno)); fflush(stdout); amfree(cmdline); return 0; } + if (cmd == QUIT) aclose(chunker->fd); amfree(cmdline); return 1; } -#define MAX_SERIAL MAX_DUMPERS+1 /* one for the taper */ +#define MAX_SERIAL MAX_DUMPERS*2 /* one for each dumper and taper */ long generation = 1; @@ -533,49 +838,54 @@ struct serial_s { disk_t *dp; } stable[MAX_SERIAL]; -disk_t *serial2disk(str) -char *str; +disk_t * +serial2disk( + char *str) { int rc, s; long gen; rc = sscanf(str, "%d-%ld", &s, &gen); if(rc != 2) { - error("error [serial2disk \"%s\" parse error]", str); + error(_("error [serial2disk \"%s\" parse error]"), str); + /*NOTREACHED*/ } else if (s < 0 || s >= MAX_SERIAL) { - error("error [serial out of range 0..%d: %d]", MAX_SERIAL, s); + error(_("error [serial out of range 0..%d: %d]"), MAX_SERIAL, s); + /*NOTREACHED*/ } if(gen != stable[s].gen) - printf("driver: error time %s serial gen mismatch %s\n", + g_printf(_("driver: serial2disk error time %s serial gen mismatch %s\n"), walltime_str(curclock()), str); return stable[s].dp; } -void free_serial(str) -char *str; +void +free_serial( + char *str) { int rc, s; long gen; - rc = sscanf(str, "%d-%ld", &s, &gen); + rc = sscanf(str, _("%d-%ld"), &s, &gen); if(!(rc == 2 && s >= 0 && s < MAX_SERIAL)) { /* nuke self to get core dump for Brett */ - fprintf(stderr, "driver: free_serial: str \"%s\" rc %d s %d\n", + g_fprintf(stderr, _("driver: free_serial: str \"%s\" rc %d s %d\n"), str, rc, s); fflush(stderr); abort(); } if(gen != stable[s].gen) - printf("driver: error time %s serial gen mismatch\n", - walltime_str(curclock())); + g_printf(_("driver: free_serial error time %s serial gen mismatch %s\n"), + walltime_str(curclock()),str); stable[s].gen = 0; stable[s].dp = NULL; } -void free_serial_dp(dp) -disk_t *dp; +void +free_serial_dp( + disk_t *dp) { int s; @@ -587,33 +897,34 @@ disk_t *dp; } } - printf("driver: error time %s serial not found\n", - walltime_str(curclock())); + g_printf(_("driver: error time %s serial not found for disk %s\n"), + walltime_str(curclock()), dp->name); } -void check_unfree_serial() +void +check_unfree_serial(void) { int s; /* find used serial number */ for(s = 0; s < MAX_SERIAL; s++) { if(stable[s].gen != 0 || stable[s].dp != NULL) { - printf("driver: error time %s bug: serial in use: %02d-%05ld\n", + g_printf(_("driver: error time %s bug: serial in use: %02d-%05ld\n"), walltime_str(curclock()), s, stable[s].gen); } } } -char *disk2serial(dp) -disk_t *dp; +char *disk2serial( + disk_t *dp) { int s; static char str[NUM_STR_SIZE]; for(s = 0; s < MAX_SERIAL; s++) { if(stable[s].dp == dp) { - snprintf(str, sizeof(str), "%02d-%05ld", s, stable[s].gen); + g_snprintf(str, SIZEOF(str), "%02d-%05ld", s, stable[s].gen); return str; } } @@ -623,7 +934,7 @@ disk_t *dp; if(stable[s].gen == 0 && stable[s].dp == NULL) break; if(s >= MAX_SERIAL) { - printf("driver: error time %s bug: out of serial numbers\n", + g_printf(_("driver: error time %s bug: out of serial numbers\n"), walltime_str(curclock())); s = 0; } @@ -631,15 +942,16 @@ disk_t *dp; stable[s].gen = generation++; stable[s].dp = dp; - snprintf(str, sizeof(str), "%02d-%05ld", s, stable[s].gen); + g_snprintf(str, SIZEOF(str), "%02d-%05ld", s, stable[s].gen); return str; } -void update_info_dumper(dp, origsize, dumpsize, dumptime) - disk_t *dp; - long origsize; - long dumpsize; - long dumptime; +void +update_info_dumper( + disk_t *dp, + off_t origsize, + off_t dumpsize, + time_t dumptime) { int level, i; info_t info; @@ -649,14 +961,10 @@ void update_info_dumper(dp, origsize, dumpsize, dumptime) level = sched(dp)->level; - 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); @@ -667,9 +975,9 @@ void update_info_dumper(dp, origsize, dumpsize, dumptime) update_info_taper(). */ for (i = level; i < DUMP_LEVELS; ++i) { infp = &info.inf[i]; - infp->size = -1; - infp->csize = -1; - infp->secs = -1; + infp->size = (off_t)-1; + infp->csize = (off_t)-1; + infp->secs = (time_t)-1; infp->date = (time_t)-1; infp->label[0] = '\0'; infp->filenum = 0; @@ -680,34 +988,34 @@ void update_info_dumper(dp, origsize, dumpsize, dumptime) infp->size = origsize; infp->csize = dumpsize; infp->secs = dumptime; - infp->date = sched(dp)->timestamp; + infp->date = get_time_from_timestamp(sched(dp)->datestamp); if(level == 0) perfp = &info.full; else perfp = &info.incr; /* Update the stats, but only if the new values are meaningful */ - if(dp->compress != COMP_NONE && origsize > 0L) { - newperf(perfp->comp, dumpsize/(float)origsize); + if(dp->compress != COMP_NONE && origsize > (off_t)0) { + newperf(perfp->comp, (double)dumpsize/(double)origsize); } - if(dumptime > 0L) { - if(dumptime >= dumpsize) + if(dumptime > (time_t)0) { + if((off_t)dumptime >= dumpsize) newperf(perfp->rate, 1); else - newperf(perfp->rate, dumpsize/dumptime); + newperf(perfp->rate, (double)dumpsize/(double)dumptime); } - if(getconf_int(CNF_RESERVE)<100) { + if(origsize >= (off_t)0 && getconf_int(CNF_RESERVE)<100) { info.command = NO_COMMAND; } - if(level == info.last_level) + if (origsize >= (off_t)0 && level == info.last_level) { info.consecutive_runs++; - else { + } else if (origsize >= (off_t)0 || level < info.last_level) { info.last_level = level; info.consecutive_runs = 1; } - if(origsize >=0 && dumpsize >=0) { + if(origsize >= (off_t)0 && dumpsize >= (off_t)0) { for(i=NB_HISTORY-1;i>0;i--) { info.history[i] = info.history[i-1]; } @@ -715,52 +1023,70 @@ void update_info_dumper(dp, origsize, dumpsize, dumptime) info.history[0].level = level; info.history[0].size = origsize; info.history[0].csize = dumpsize; - info.history[0].date = sched(dp)->timestamp; + info.history[0].date = get_time_from_timestamp(sched(dp)->datestamp); info.history[0].secs = dumptime; } - if(put_info(dp->host->hostname, dp->name, &info)) - error("infofile update failed (%s,%s)\n", dp->host->hostname, dp->name); + if (put_info(dp->host->hostname, dp->name, &info)) { + int save_errno = errno; + g_fprintf(stderr, _("infofile update failed (%s,'%s'): %s\n"), + dp->host->hostname, dp->name, strerror(save_errno)); + log_add(L_ERROR, _("infofile update failed (%s,'%s'): %s\n"), + dp->host->hostname, dp->name, strerror(save_errno)); + error(_("infofile update failed (%s,'%s'): %s\n"), + dp->host->hostname, dp->name, strerror(save_errno)); + /*NOTREACHED*/ + } close_infofile(); } -void update_info_taper(dp, label, filenum, level) -disk_t *dp; -char *label; -int filenum; -int level; +void +update_info_taper( + disk_t *dp, + char *label, + off_t filenum, + int level) { info_t info; stats_t *infp; int rc; rc = open_infofile(getconf_str(CNF_INFOFILE)); - if(rc) - error("could not open infofile %s: %s (%d)", getconf_str(CNF_INFOFILE), + if(rc) { + error(_("could not open infofile %s: %s (%d)"), getconf_str(CNF_INFOFILE), strerror(errno), rc); + /*NOTREACHED*/ + } get_info(dp->host->hostname, dp->name, &info); infp = &info.inf[level]; /* XXX - should we record these two if no-record? */ - strncpy(infp->label, label, sizeof(infp->label)-1); - infp->label[sizeof(infp->label)-1] = '\0'; + strncpy(infp->label, label, SIZEOF(infp->label)-1); + infp->label[SIZEOF(infp->label)-1] = '\0'; infp->filenum = filenum; info.command = NO_COMMAND; - if(put_info(dp->host->hostname, dp->name, &info)) - error("infofile update failed (%s,%s)\n", dp->host->hostname, dp->name); - + if (put_info(dp->host->hostname, dp->name, &info)) { + int save_errno = errno; + g_fprintf(stderr, _("infofile update failed (%s,'%s'): %s\n"), + dp->host->hostname, dp->name, strerror(save_errno)); + log_add(L_ERROR, _("infofile update failed (%s,'%s'): %s\n"), + dp->host->hostname, dp->name, strerror(save_errno)); + error(_("infofile update failed (%s,'%s'): %s\n"), + dp->host->hostname, dp->name, strerror(save_errno)); + /*NOTREACHED*/ + } close_infofile(); } /* Free an array of pointers to assignedhd_t after freeing the * assignedhd_t themselves. The array must be NULL-terminated. */ -void free_assignedhd( ahd ) -assignedhd_t **ahd; +void free_assignedhd( + assignedhd_t **ahd) { int i;