- int outfd = *p_outfd;
- int rc = 0;
- char *arg_filename = NULL;
- char *new_filename = NULL;
- char *tmp_filename = NULL;
- char *pc;
- char sequence[NUM_STR_SIZE];
- int new_outfd = -1;
- struct cmdargs cmdargs;
- cmd_t cmd;
- filetype_t save_type;
- long left_in_chunk;
- int a;
- char *q;
-
- datain += size;
-
- while(rc == 0 && ((size == 0 && dataout < datain) || datain >= datalimit)) {
-
- NAUGHTY_BITS;
-
- while(size > 0 && split_size > 0 && dumpsize >= split_size) {
- amfree(new_filename);
- if(use == 0) {
- /*
- * Probably no more space on this disk. Request more.
- */
- putresult(RQ_MORE_DISK, "%s\n", handle);
- cmd = getcmd(&cmdargs);
- if(cmd == CONTINUE) {
- /*
- * CONTINUE
- * filename
- * chunksize
- * use
- */
- cmdargs.argc++; /* true count of args */
- a = 2;
-
- if(a >= cmdargs.argc) {
- error("error [dumper CONTINUE: not enough args: filename]");
- }
- arg_filename = newstralloc(arg_filename, cmdargs.argv[a++]);
-
- if(a >= cmdargs.argc) {
- error("error [dumper CONTINUE: not enough args: chunksize]");
- }
- chunksize = atoi(cmdargs.argv[a++]);
- chunksize = am_floor(chunksize, DISK_BLOCK_KB);
-
- if(a >= cmdargs.argc) {
- error("error [dumper CONTINUE: not enough args: use]");
- }
- use = atoi(cmdargs.argv[a++]);
-
- if(a != cmdargs.argc) {
- error("error [dumper CONTINUE: too many args: %d != %d]",
- cmdargs.argc, a);
- }
-
- if(strcmp(filename, arg_filename) == 0) {
- /*
- * Same disk, so use what room is left up to the
- * next chunk boundary or the amount we were given,
- * whichever is less.
- */
- left_in_chunk = chunksize - filesize;
- if(left_in_chunk > use) {
- split_size += use;
- use = 0;
- } else {
- split_size += left_in_chunk;
- use -= left_in_chunk;
- }
- if(left_in_chunk > 0) {
- /*
- * We still have space in this chunk.
- */
- break;
- }
- } else {
- /*
- * Different disk, so use new file.
- */
- filename = newstralloc(filename, arg_filename);
- }
- } else if(cmd == ABORT) {
- abort_pending = 1;
- errstr = newstralloc(errstr, "ERROR");
- rc = 1;
- goto common_exit;
- } else {
- if(cmdargs.argc >= 1) {
- q = squote(cmdargs.argv[1]);
- } else if(cmdargs.argc >= 0) {
- q = squote(cmdargs.argv[0]);
- } else {
- q = stralloc("(no input?)");
- }
- error("error [bad command after RQ-MORE-DISK: \"%s\"]", q);
- }
- }
-
- ap_snprintf(sequence, sizeof(sequence), "%d", filename_seq);
- new_filename = newvstralloc(new_filename,
- filename,
- ".",
- sequence,
- NULL);
- tmp_filename = newvstralloc(tmp_filename,
- new_filename,
- ".tmp",
- NULL);
- pc = strrchr(tmp_filename, '/');
- *pc = '\0';
- mkholdingdir(tmp_filename);
- *pc = '/';
- new_outfd = open(tmp_filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
- if(new_outfd == -1) {
- int save_errno = errno;
-
- errstr = squotef("creating chunk holding file \"%s\": %s",
- tmp_filename,
- strerror(save_errno));
- if(save_errno == ENOSPC) {
- putresult(NO_ROOM, "%s %lu\n",
- handle,
- use + split_size - dumpsize);
- use = 0; /* force RQ_MORE_DISK */
- split_size = dumpsize;
- continue;
- }
- aclose(outfd);
- rc = 1;
- goto common_exit;
- }
- save_type = file.type;
- file.type = F_CONT_DUMPFILE;
- file.cont_filename[0] = '\0';
- if(write_tapeheader(new_outfd, &file)) {
- int save_errno = errno;
-
- aclose(new_outfd);
- unlink(tmp_filename);
- if(save_errno == ENOSPC) {
- putresult(NO_ROOM, "%s %lu\n",
- handle,
- use + split_size - dumpsize);
- use = 0; /* force RQ_MORE_DISK */
- split_size = dumpsize;
- continue;
- }
- errstr = squotef("write_tapeheader file \"%s\": %s",
- tmp_filename, strerror(errno));
- rc = 1;
- goto common_exit;
- }
- if(lseek(outfd, (off_t)0, SEEK_SET) != 0) {
- errstr = squotef("cannot lseek: %s", strerror(errno));
- aclose(new_outfd);
- unlink(tmp_filename);
- rc = 1;
- goto common_exit;
- }
- strncpy(file.cont_filename, new_filename,
- sizeof(file.cont_filename));
- file.cont_filename[sizeof(file.cont_filename)-1] = '\0';
- file.type = save_type;
- if(write_tapeheader(outfd, &file)) {
- errstr = squotef("write_tapeheader file linked to \"%s\": %s",
- tmp_filename, strerror(errno));
- aclose(new_outfd);
- unlink(tmp_filename);
- rc = 1;
- goto common_exit;
- }
- file.type = F_CONT_DUMPFILE;
- strncpy(cont_filename, new_filename, sizeof(cont_filename));
- cont_filename[sizeof(cont_filename)-1] = '\0';