X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Fchunker.c;h=caaf0bfb02b6f4955fcb50cc667f94cd73224427;hb=2627875b7d18858bc1f9f7652811e4d8c15a23eb;hp=5e6c1ef45c7619ec9bb761fe871494d8714a5e5f;hpb=fb2bd066c2f8b34addafe48d62550e3033a59431;p=debian%2Famanda diff --git a/server-src/chunker.c b/server-src/chunker.c index 5e6c1ef..caaf0bf 100644 --- a/server-src/chunker.c +++ b/server-src/chunker.c @@ -37,7 +37,6 @@ #include "protocol.h" #include "security.h" #include "stream.h" -#include "token.h" #include "version.h" #include "fileheader.h" #include "amfeatures.h" @@ -93,7 +92,7 @@ static char *options = NULL; static char *progname = NULL; static int level; static char *dumpdate = NULL; -static int command_in_transit; +static struct cmdargs *command_in_transit = NULL; static char *chunker_timestamp = NULL; static dumpfile_t file; @@ -114,18 +113,17 @@ main( char ** argv) { static struct databuf db; - struct cmdargs cmdargs; - cmd_t cmd; + struct cmdargs *cmdargs; int infd; char *q = NULL; char *filename = NULL; - char *qfilename = NULL; off_t chunksize, use; times_t runtime; am_feature_t *their_features = NULL; int a; config_overwrites_t *cfg_ovr = NULL; char *cfg_opt = NULL; + char *m; /* * Configure program for internationalization: @@ -153,16 +151,23 @@ main( if (argc > 1) cfg_opt = argv[1]; - config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD | CONFIG_INIT_FATAL, - cfg_opt); + config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD, cfg_opt); apply_config_overwrites(cfg_ovr); + if (config_errors(NULL) >= CFGERR_WARNINGS) { + config_print_errors(); + if (config_errors(NULL) >= CFGERR_ERRORS) { + g_critical(_("errors processing config file")); + } + } + safe_cd(); /* do this *after* config_init() */ check_running_as(RUNNING_AS_DUMPUSER); - dbrename(config_name, DBG_SUBDIR_SERVER); + dbrename(get_config_name(), DBG_SUBDIR_SERVER); + log_add(L_INFO, "%s pid %ld", get_pname(), (long)getpid()); g_fprintf(stderr, _("%s: pid %ld executable %s version %s\n"), get_pname(), (long) getpid(), @@ -174,20 +179,21 @@ main( signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, SIG_IGN); - cmd = getcmd(&cmdargs); - if(cmd == START) { - if(cmdargs.argc <= 1) + cmdargs = getcmd(); + if(cmdargs->cmd == START) { + if(cmdargs->argc <= 1) error(_("error [dumper START: not enough args: timestamp]")); - chunker_timestamp = newstralloc(chunker_timestamp, cmdargs.argv[2]); + chunker_timestamp = newstralloc(chunker_timestamp, cmdargs->argv[1]); } else { + log_add(L_INFO, "%s pid %ld", get_pname(), (long)getpid()); error(_("Didn't get START command")); } /* do {*/ - cmd = getcmd(&cmdargs); + cmdargs = getcmd(); - switch(cmd) { + switch(cmdargs->cmd) { case QUIT: break; @@ -206,96 +212,91 @@ main( * use * options */ - cmdargs.argc++; /* true count of args */ - a = 2; + a = 1; - if(a >= cmdargs.argc) { + if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: handle]")); /*NOTREACHED*/ } - handle = newstralloc(handle, cmdargs.argv[a++]); + handle = newstralloc(handle, cmdargs->argv[a++]); - if(a >= cmdargs.argc) { + if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: filename]")); /*NOTREACHED*/ } - qfilename = newstralloc(qfilename, cmdargs.argv[a++]); - if (filename != NULL) - amfree(filename); - filename = unquote_string(qfilename); - amfree(qfilename); + filename = newstralloc(filename, cmdargs->argv[a++]); - if(a >= cmdargs.argc) { + if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: hostname]")); /*NOTREACHED*/ } - hostname = newstralloc(hostname, cmdargs.argv[a++]); + hostname = newstralloc(hostname, cmdargs->argv[a++]); - if(a >= cmdargs.argc) { + if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: features]")); /*NOTREACHED*/ } am_release_feature_set(their_features); - their_features = am_string_to_feature(cmdargs.argv[a++]); + their_features = am_string_to_feature(cmdargs->argv[a++]); - if(a >= cmdargs.argc) { + if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: diskname]")); /*NOTREACHED*/ } - qdiskname = newstralloc(qdiskname, cmdargs.argv[a++]); - if (diskname != NULL) - amfree(diskname); - diskname = unquote_string(qdiskname); + diskname = newstralloc(diskname, cmdargs->argv[a++]); + if (qdiskname) + amfree(qdiskname); + qdiskname = quote_string(diskname); /* qdiskname is a global */ - if(a >= cmdargs.argc) { + if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: level]")); /*NOTREACHED*/ } - level = atoi(cmdargs.argv[a++]); + level = atoi(cmdargs->argv[a++]); - if(a >= cmdargs.argc) { + if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: dumpdate]")); /*NOTREACHED*/ } - dumpdate = newstralloc(dumpdate, cmdargs.argv[a++]); + dumpdate = newstralloc(dumpdate, cmdargs->argv[a++]); - if(a >= cmdargs.argc) { + if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: chunksize]")); /*NOTREACHED*/ } - chunksize = OFF_T_ATOI(cmdargs.argv[a++]); + chunksize = OFF_T_ATOI(cmdargs->argv[a++]); chunksize = am_floor(chunksize, (off_t)DISK_BLOCK_KB); - if(a >= cmdargs.argc) { + if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: progname]")); /*NOTREACHED*/ } - progname = newstralloc(progname, cmdargs.argv[a++]); + progname = newstralloc(progname, cmdargs->argv[a++]); - if(a >= cmdargs.argc) { + if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: use]")); /*NOTREACHED*/ } - use = am_floor(OFF_T_ATOI(cmdargs.argv[a++]), DISK_BLOCK_KB); + use = am_floor(OFF_T_ATOI(cmdargs->argv[a++]), DISK_BLOCK_KB); - if(a >= cmdargs.argc) { + if(a >= cmdargs->argc) { error(_("error [chunker PORT-WRITE: not enough args: options]")); /*NOTREACHED*/ } - options = newstralloc(options, cmdargs.argv[a++]); + options = newstralloc(options, cmdargs->argv[a++]); - if(a != cmdargs.argc) { + if(a != cmdargs->argc) { error(_("error [chunker PORT-WRITE: too many args: %d != %d]"), - cmdargs.argc, a); + cmdargs->argc, a); /*NOTREACHED*/ } if((infd = startup_chunker(filename, use, chunksize, &db)) < 0) { - q = squotef(_("[chunker startup failed: %s]"), errstr); + q = quote_string(vstrallocf(_("[chunker startup failed: %s]"), errstr)); putresult(TRYAGAIN, "%s %s\n", handle, q); - error("startup_chunker failed"); + error("startup_chunker failed: %s", errstr); } - command_in_transit = -1; + command_in_transit = NULL; if(infd >= 0 && do_chunk(infd, &db)) { char kb_str[NUM_STR_SIZE]; char kps_str[NUM_STR_SIZE]; @@ -309,12 +310,16 @@ main( isnormal(rt) ? (double)dumpsize / rt : 0.0); errstr = newvstrallocf(errstr, "sec %s kb %s kps %s", walltime_str(runtime), kb_str, kps_str); - q = squotef("[%s]", errstr); - if(command_in_transit != -1) - cmd = command_in_transit; - else - cmd = getcmd(&cmdargs); - switch(cmd) { + m = vstrallocf("[%s]", errstr); + q = quote_string(m); + amfree(m); + if(command_in_transit != NULL) { + cmdargs = command_in_transit; + command_in_transit = NULL; + } else { + cmdargs = getcmd(); + } + switch(cmdargs->cmd) { case DONE: putresult(DONE, "%s %lld %s\n", handle, (long long)(dumpsize - (off_t)headersize), q); @@ -334,9 +339,11 @@ main( } else { errstr = newvstrallocf(errstr, - _("dumper returned %s"), cmdstr[cmd]); + _("dumper returned %s"), cmdstr[cmdargs->cmd]); amfree(q); - q = squotef("[%s]",errstr); + m = vstrallocf("[%s]",errstr); + q = quote_string(m); + amfree(m); putresult(FAILED, "%s %s\n", handle, q); log_add(L_FAIL, "%s %s %s %d [%s]", hostname, qdiskname, chunker_timestamp, level, errstr); @@ -345,25 +352,25 @@ main( } amfree(q); } else if(infd != -2) { + if(q == NULL) { + m = vstrallocf("[%s]", errstr); + q = quote_string(m); + amfree(m); + } if(!abort_pending) { - if(q == NULL) { - q = squotef("[%s]", errstr); - } putresult(FAILED, "%s %s\n", handle, q); - log_add(L_FAIL, "%s %s %s %d [%s]", - hostname, qdiskname, chunker_timestamp, level, errstr); - amfree(q); } + log_add(L_FAIL, "%s %s %s %d [%s]", + hostname, qdiskname, chunker_timestamp, level, errstr); + amfree(q); } amfree(filename); amfree(db.filename); break; default: - if(cmdargs.argc >= 1) { - q = squote(cmdargs.argv[1]); - } else if(cmdargs.argc >= 0) { - q = squote(cmdargs.argv[0]); + if(cmdargs->argc >= 1) { + q = quote_string(cmdargs->argv[0]); } else { q = stralloc(_("(no input?)")); } @@ -372,7 +379,9 @@ main( break; } -/* } while(cmd != QUIT); */ +/* } while(cmdargs->cmd != QUIT); */ + + log_add(L_INFO, "pid-done %ld", (long)getpid()); amfree(errstr); amfree(chunker_timestamp); @@ -383,6 +392,9 @@ main( amfree(dumpdate); amfree(progname); amfree(options); + free_cmdargs(cmdargs); + if (command_in_transit) + free_cmdargs(command_in_transit); am_release_feature_set(their_features); their_features = NULL; @@ -417,6 +429,7 @@ startup_chunker( } data_socket = stream_server(res->ai_family, &data_port, 0, STREAM_BUFSIZE, 0); + if (res) freeaddrinfo(res); if(data_socket < 0) { errstr = vstrallocf(_("error creating stream server: %s"), strerror(errno)); @@ -426,6 +439,7 @@ startup_chunker( putresult(PORT, "%d\n", data_port); infd = stream_accept(data_socket, CONNECT_TIMEOUT, 0, STREAM_BUFSIZE); + aclose(data_socket); if(infd == -1) { errstr = vstrallocf(_("error accepting stream: %s"), strerror(errno)); return -1; @@ -433,15 +447,18 @@ startup_chunker( tmp_filename = vstralloc(filename, ".tmp", NULL); pc = strrchr(tmp_filename, '/'); + g_assert(pc != NULL); *pc = '\0'; mkholdingdir(tmp_filename); *pc = '/'; if ((outfd = open(tmp_filename, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0) { int save_errno = errno; - - errstr = squotef(_("holding file \"%s\": %s"), + char *m = vstrallocf(_("holding file \"%s\": %s"), tmp_filename, strerror(errno)); + + errstr = quote_string(m); + amfree(m); amfree(tmp_filename); aclose(infd); if(save_errno == ENOSPC) { @@ -463,7 +480,7 @@ do_chunk( int infd, struct databuf * db) { - ssize_t nread; + size_t nread; char header_buf[DISK_BLOCK_BYTES]; startclock(); @@ -477,23 +494,23 @@ do_chunk( * need to save into "file", as well as write out. Later, the * chunk code will rewrite it. */ - nread = fullread(infd, header_buf, SIZEOF(header_buf)); - if (nread != DISK_BLOCK_BYTES) { - if(nread < 0) { + nread = full_read(infd, header_buf, SIZEOF(header_buf)); + if (nread != sizeof(header_buf)) { + if(errno != 0) { errstr = vstrallocf(_("cannot read header: %s"), strerror(errno)); } else { - errstr = vstrallocf(_("cannot read header: got %zd bytes instead of %d"), - nread, - DISK_BLOCK_BYTES); + errstr = vstrallocf(_("cannot read header: got %zd bytes instead of %zd"), + nread, sizeof(header_buf)); } return 0; } parse_file_header(header_buf, &file, (size_t)nread); if(write_tapeheader(db->fd, &file)) { int save_errno = errno; - - errstr = squotef(_("write_tapeheader file %s: %s"), + char *m = vstrallocf(_("write_tapeheader file %s: %s"), db->filename, strerror(errno)); + errstr = quote_string(m); + amfree(m); if(save_errno == ENOSPC) { putresult(NO_ROOM, "%s %lld\n", handle, (long long)(db->use+db->split_size-dumpsize)); @@ -508,7 +525,7 @@ do_chunk( * We've written the file header. Now, just write data until the * end. */ - while ((nread = fullread(infd, db->buf, + while ((nread = full_read(infd, db->buf, (size_t)(db->datalimit - db->datain))) > 0) { db->datain += nread; while(db->dataout < db->datain) { @@ -558,12 +575,11 @@ static int databuf_flush( struct databuf * db) { - struct cmdargs cmdargs; + struct cmdargs *cmdargs = NULL; int rc = 1; - ssize_t written; + size_t written; off_t left_in_chunk; char *arg_filename = NULL; - char *qarg_filename = NULL; char *new_filename = NULL; char *tmp_filename = NULL; char sequence[NUM_STR_SIZE]; @@ -588,16 +604,14 @@ databuf_flush( /* * Probably no more space on this disk. Request some more. */ - cmd_t cmd; - putresult(RQ_MORE_DISK, "%s\n", handle); - cmd = getcmd(&cmdargs); - if(command_in_transit == -1 && - (cmd == DONE || cmd == TRYAGAIN || cmd == FAILED)) { - command_in_transit = cmd; - cmd = getcmd(&cmdargs); + cmdargs = getcmd(); + if(command_in_transit == NULL && + (cmdargs->cmd == DONE || cmdargs->cmd == TRYAGAIN || cmdargs->cmd == FAILED)) { + command_in_transit = cmdargs; + cmdargs = getcmd(); } - if(cmd == CONTINUE) { + if(cmdargs->cmd == CONTINUE) { /* * CONTINUE * serial @@ -605,34 +619,30 @@ databuf_flush( * chunksize * use */ - cmdargs.argc++; /* true count of args */ - a = 3; + a = 2; /* skip CONTINUE and serial */ - if(a >= cmdargs.argc) { + if(a >= cmdargs->argc) { error(_("error [chunker CONTINUE: not enough args: filename]")); /*NOTREACHED*/ } - qarg_filename = newstralloc(qarg_filename, cmdargs.argv[a++]); - if (arg_filename != NULL) - amfree(arg_filename); - arg_filename = unquote_string(qarg_filename); + arg_filename = newstralloc(arg_filename, cmdargs->argv[a++]); - if(a >= cmdargs.argc) { + if(a >= cmdargs->argc) { error(_("error [chunker CONTINUE: not enough args: chunksize]")); /*NOTREACHED*/ } - db->chunk_size = OFF_T_ATOI(cmdargs.argv[a++]); + db->chunk_size = OFF_T_ATOI(cmdargs->argv[a++]); db->chunk_size = am_floor(db->chunk_size, (off_t)DISK_BLOCK_KB); - if(a >= cmdargs.argc) { + if(a >= cmdargs->argc) { error(_("error [chunker CONTINUE: not enough args: use]")); /*NOTREACHED*/ } - db->use = OFF_T_ATOI(cmdargs.argv[a++]); + db->use = OFF_T_ATOI(cmdargs->argv[a++]); - if(a != cmdargs.argc) { + if(a != cmdargs->argc) { error(_("error [chunker CONTINUE: too many args: %d != %d]"), - cmdargs.argc, a); + cmdargs->argc, a); /*NOTREACHED*/ } @@ -662,17 +672,15 @@ databuf_flush( */ db->filename = newstralloc(db->filename, arg_filename); } - } else if(cmd == ABORT) { + } else if(cmdargs->cmd == ABORT) { abort_pending = 1; - errstr = newstralloc(errstr, "ERROR"); + errstr = newstralloc(errstr, cmdargs->argv[1]); putresult(ABORT_FINISHED, "%s\n", handle); rc = 0; goto common_exit; } else { - if(cmdargs.argc >= 1) { - q = squote(cmdargs.argv[1]); - } else if(cmdargs.argc >= 0) { - q = squote(cmdargs.argv[0]); + if(cmdargs->argc >= 1) { + q = quote_string(cmdargs->argv[0]); } else { q = stralloc(_("(no input?)")); } @@ -700,12 +708,14 @@ databuf_flush( ".tmp", NULL); pc = strrchr(tmp_filename, '/'); + g_assert(pc != NULL); /* Only a problem if db->filename has no /. */ *pc = '\0'; mkholdingdir(tmp_filename); *pc = '/'; newfd = open(tmp_filename, O_RDWR|O_CREAT|O_TRUNC, 0600); if (newfd == -1) { int save_errno = errno; + char *m; if(save_errno == ENOSPC) { putresult(NO_ROOM, "%s %lld\n", handle, @@ -714,9 +724,11 @@ databuf_flush( db->split_size = dumpsize; continue; } - errstr = squotef(_("creating chunk holding file \"%s\": %s"), + m = vstrallocf(_("creating chunk holding file \"%s\": %s"), tmp_filename, strerror(errno)); + errstr = quote_string(m); + amfree(m); aclose(db->fd); rc = 0; goto common_exit; @@ -726,6 +738,7 @@ databuf_flush( file.cont_filename[0] = '\0'; if(write_tapeheader(newfd, &file)) { int save_errno = errno; + char *m; aclose(newfd); if(save_errno == ENOSPC) { @@ -735,9 +748,11 @@ databuf_flush( db->split_size = dumpsize; continue; } - errstr = squotef(_("write_tapeheader file %s: %s"), + m = vstrallocf(_("write_tapeheader file %s: %s"), tmp_filename, strerror(errno)); + errstr = quote_string(m); + amfree(m); rc = 0; goto common_exit; } @@ -747,9 +762,11 @@ databuf_flush( * to the next chunk, and then close it. */ if (lseek(db->fd, (off_t)0, SEEK_SET) < (off_t)0) { - errstr = squotef(_("lseek holding file %s: %s"), + char *m = vstrallocf(_("lseek holding file %s: %s"), db->filename, strerror(errno)); + errstr = quote_string(m); + amfree(m); aclose(newfd); rc = 0; goto common_exit; @@ -759,9 +776,11 @@ databuf_flush( strncpy(file.cont_filename, new_filename, SIZEOF(file.cont_filename)); file.cont_filename[SIZEOF(file.cont_filename)-1] = '\0'; if(write_tapeheader(db->fd, &file)) { - errstr = squotef(_("write_tapeheader file \"%s\": %s"), + char * m = vstrallocf(_("write_tapeheader file \"%s\": %s"), db->filename, strerror(errno)); + errstr = quote_string(m); + amfree(m); aclose(newfd); unlink(tmp_filename); rc = 0; @@ -806,7 +825,7 @@ databuf_flush( /* * Write out the buffer */ - written = fullwrite(db->fd, db->dataout, + written = full_write(db->fd, db->dataout, (size_t)(db->datain - db->dataout)); if (written > 0) { db->dataout += written; @@ -815,9 +834,11 @@ databuf_flush( dumpsize += (dumpbytes / (off_t)1024); filesize += (dumpbytes / (off_t)1024); dumpbytes %= 1024; - if (written < 0) { + if (written == 0) { if (errno != ENOSPC) { - errstr = squotef(_("data write: %s"), strerror(errno)); + char *m = vstrallocf(_("data write: %s"), strerror(errno)); + errstr = quote_string(m); + amfree(m); rc = 0; goto common_exit; } @@ -841,10 +862,11 @@ databuf_flush( common_exit: + if (cmdargs) + free_cmdargs(cmdargs); amfree(new_filename); /*@i@*/ amfree(tmp_filename); amfree(arg_filename); - amfree(qarg_filename); return rc; } @@ -858,15 +880,18 @@ write_tapeheader( dumpfile_t *file) { char *buffer; - ssize_t written; + size_t written; file->blocksize = DISK_BLOCK_BYTES; buffer = build_header(file, DISK_BLOCK_BYTES); - written = fullwrite(outfd, buffer, DISK_BLOCK_BYTES); + written = full_write(outfd, buffer, DISK_BLOCK_BYTES); amfree(buffer); if(written == DISK_BLOCK_BYTES) return 0; - if(written < 0) return written; - errno = ENOSPC; + + /* fake ENOSPC when we get a short write without errno set */ + if(errno == 0) + errno = ENOSPC; + return (ssize_t)-1; }