- bp = buftable;
- if(interactive || bufdebug) dumpstatus(bp);
-
- /* tell writer to open tape */
-
- opening = 1;
- syncpipe_put('O');
- syncpipe_putstr(datestamp);
- syncpipe_putstr(hostname);
- syncpipe_putstr(diskname);
- syncpipe_putint(level);
-
- startclock();
-
- /* read file in loop */
-
- while(1) {
- tok = syncpipe_get();
- switch(tok) {
-
- case 'O':
- assert(opening);
- opening = 0;
- err = 0;
- break;
-
- case 'R':
- bufnum = syncpipe_getint();
-
- if(bufdebug) {
- fprintf(stderr, "taper: r: got R%d\n", bufnum);
- fflush(stderr);
- }
-
- if(need_closing) {
- syncpipe_put('C');
- closing = 1;
- need_closing = 0;
- break;
- }
-
- if(closing) break; /* ignore extra read tokens */
-
- assert(!opening);
- if(bp->status != EMPTY || bufnum != bp-buftable) {
- /* XXX this SHOULD NOT HAPPEN. Famous last words. */
- fprintf(stderr,"taper: panic: buffer mismatch at ofs %ld:\n",
- filesize);
- if(bufnum != bp-buftable) {
- fprintf(stderr, " my buf %d but writer buf %d\n",
- (int)(bp-buftable), bufnum);
- }
- else {
- fprintf(stderr,"buf %d state %s (%ld) instead of EMPTY\n",
- (int)(bp-buftable),
- bp->status == FILLING? "FILLING" :
- bp->status == FULL? "FULL" : "EMPTY!?!?",
- (long)bp->status);
- }
- dumpbufs("taper");
- sleep(1);
- dumpbufs("taper: after 1 sec");
- if(bp->status == EMPTY)
- fprintf(stderr, "taper: result now correct!\n");
- fflush(stderr);
-
- errstr = newstralloc(errstr,
- "[fatal buffer mismanagement bug]");
- q = squote(errstr);
- putresult(TRYAGAIN, "%s %s\n", handle, q);
- amfree(q);
- log_add(L_INFO, "retrying %s:%s.%d on new tape: %s",
- hostname, diskname, level, errstr);
- closing = 1;
- syncpipe_put('X'); /* X == buffer snafu, bail */
- do {
- tok = syncpipe_get();
- if(tok == 'R')
- bufnum = syncpipe_getint();
- } while(tok != 'x');
- aclose(fd);
- return;
- }
-
- bp->status = FILLING;
- buflen = header_read ? tt_blocksize : DISK_BLOCK_BYTES;
- if(interactive || bufdebug) dumpstatus(bp);
- if((rc = taper_fill_buffer(fd, bp, buflen)) < 0) {
- err = errno;
- closing = 1;
- strclosing = newvstralloc(strclosing,"Can't read data: ",NULL);
- syncpipe_put('C');
- } else {
- if(rc < buflen) { /* switch to next file */
- int save_fd;
- struct stat stat_file;
-
- save_fd = fd;
- close(fd);
- if(file.cont_filename[0] == '\0') { /* no more file */
- err = 0;
- need_closing = 1;
- } else if(stat(file.cont_filename, &stat_file) != 0) {
- err = errno;
- need_closing = 1;
- strclosing = newvstralloc(strclosing,"can't stat: ",file.cont_filename,NULL);
- } else if((fd = open(file.cont_filename,O_RDONLY)) == -1) {
- err = errno;
- need_closing = 1;
- strclosing = newvstralloc(strclosing,"can't open: ",file.cont_filename,NULL);
- } else if((fd != save_fd) && dup2(fd, save_fd) == -1) {
- err = errno;
- need_closing = 1;
- strclosing = newvstralloc(strclosing,"can't dup2: ",file.cont_filename,NULL);
- } else {
- buffer_t bp1;
- int rc1;
-
- bp1.status = EMPTY;
- bp1.size = DISK_BLOCK_BYTES;
- bp1.buffer = malloc(DISK_BLOCK_BYTES);
-
- if(fd != save_fd) {
- close(fd);
- fd = save_fd;
- }
-
- rc1 = taper_fill_buffer(fd, &bp1, DISK_BLOCK_BYTES);
- if(rc1 <= 0) {
- amfree(bp1.buffer);
- err = (rc1 < 0) ? errno : 0;
- need_closing = 1;
- strclosing = newvstralloc(strclosing,
- "Can't read header: ",
- file.cont_filename,
- NULL);
- } else {
- parse_file_header(bp1.buffer, &file, rc1);
-
- amfree(bp1.buffer);
- bp1.buffer = bp->buffer + rc;
-
- rc1 = taper_fill_buffer(fd, &bp1, tt_blocksize - rc);
- if(rc1 <= 0) {
- err = (rc1 < 0) ? errno : 0;
- need_closing = 1;
- if(rc1 < 0) {
- strclosing = newvstralloc(strclosing,
- "Can't read data: ",
- file.cont_filename,
- NULL);
- }
- }
- else {
- rc += rc1;
- bp->size = rc;
- }
- }
- }
- }
- if(rc > 0) {
- bp->status = FULL;
- if(header_read == 0) {
- char *cont_filename;
-
- parse_file_header(bp->buffer, &file, rc);
- cont_filename = stralloc(file.cont_filename);
- file.cont_filename[0] = '\0';
- file.blocksize = tt_blocksize;
- build_header(bp->buffer, &file, tt_blocksize);
-
- /* add CONT_FILENAME back to in-memory header */
- strncpy(file.cont_filename, cont_filename,
- sizeof(file.cont_filename));
- if(interactive || bufdebug) dumpstatus(bp);
- bp->size = tt_blocksize; /* output a full tape block */
- header_read = 1;
- amfree(cont_filename);
- }
- else {
- filesize += am_round(rc, 1024) / 1024;
- }
- if(interactive || bufdebug) dumpstatus(bp);
- if(bufdebug) {
- fprintf(stderr,"taper: r: put W%d\n",(int)(bp-buftable));
- fflush(stderr);
- }
- syncpipe_put('W');
- syncpipe_putint(bp-buftable);
- bp = nextbuf(bp);
- }
- if(need_closing && rc <= 0) {
- syncpipe_put('C');
- need_closing = 0;
- closing = 1;
- }
- }
- break;
-
- case 'T':
- case 'E':
- syncpipe_put('e'); /* ACK error */
-
- aclose(fd);
- str = syncpipe_getstr();
- errstr = newvstralloc(errstr, "[", str ? str : "(null)", "]", NULL);
- amfree(str);
-
- q = squote(errstr);
- if(tok == 'T') {
- putresult(TRYAGAIN, "%s %s\n", handle, q);
- log_add(L_INFO, "retrying %s:%s.%d on new tape: %s",
- hostname, diskname, level, errstr);
- } else {
- putresult(TAPE_ERROR, "%s %s\n", handle, q);
- log_add(L_FAIL, "%s %s %s %d [out of tape]",
- hostname, diskname, datestamp, level);
- log_add(L_ERROR,"no-tape [%s]", errstr);
- }
- amfree(q);
- return;
-
- case 'C':
- assert(!opening);
- assert(closing);
-
- str = syncpipe_getstr();
- label = newstralloc(label, str ? str : "(null)");
- amfree(str);
- str = syncpipe_getstr();
- filenum = atoi(str ? str : "-9876"); /* ??? */
- amfree(str);
- fprintf(stderr, "taper: reader-side: got label %s filenum %d\n",
- label, filenum);
- fflush(stderr);
-
- aclose(fd);
- runtime = stopclock();
- if(err) {
- if(strclosing) {
- errstr = newvstralloc(errstr,
- "[input: ", strclosing, ": ",
- strerror(err), "]", NULL);
- amfree(strclosing);
- }
- else
- errstr = newvstralloc(errstr,
- "[input: ", strerror(err), "]",
- NULL);
- q = squote(errstr);
- putresult(TAPE_ERROR, "%s %s\n", handle, q);
- amfree(q);
- log_add(L_FAIL, "%s %s %s %d %s",
- hostname, diskname, datestamp, level, errstr);
- str = syncpipe_getstr(); /* reap stats */
- amfree(str);
- } else {
- char kb_str[NUM_STR_SIZE];
- char kps_str[NUM_STR_SIZE];
- double rt;
-
- rt = runtime.r.tv_sec+runtime.r.tv_usec/1000000.0;
- ap_snprintf(kb_str, sizeof(kb_str), "%ld", filesize);
- ap_snprintf(kps_str, sizeof(kps_str), "%3.1f",
- rt ? filesize / rt : 0.0);
- str = syncpipe_getstr();
- errstr = newvstralloc(errstr,
- "[sec ", walltime_str(runtime),
- " kb ", kb_str,
- " kps ", kps_str,
- " ", str ? str : "(null)",
- "]",
- NULL);
- amfree(str);
- q = squote(errstr);
- putresult(DONE, "%s %s %d %s\n",
- handle, label, filenum, q);
- amfree(q);
- log_add(L_SUCCESS, "%s %s %s %d %s",
- hostname, diskname, datestamp, level, errstr);
-#ifdef HAVE_LIBVTBLC
- /*
- * We have 44 characters available for the label string:
- * use max 20 characters for hostname
- * max 20 characters for diskname
- * (it could contain a samba share or dos path)
- * 2 for level
- */
- memset(desc, '\0', 45);
-
- strncpy(desc, hostname, 20);
-
- if ((len = strlen(hostname)) <= 20) {
- memset(desc + len, ' ', 1);
- offset = len + 1;
- }
- else{
- memset(desc + 20, ' ', 1);
- offset = 21;
- }