static int WorkerBee(struct cmd_syndesc *as, void *arock) { char *tapedev; struct tapeLabel *label; struct fileMark *fmark; afs_int32 fmtype; struct blockMark *bmark; afs_int32 isheader, isdatablock; char *data; char *tblock; afs_int32 code; struct volumeHeader *volheaderPtr = NULL; int eod = 1; int rc; char *nextblock; /* We cycle through three tape blocks so we */ char *lastblock; /* can trim off the volume trailer from the */ char *lastblock2; /* end of each volume without having to back */ char *tapeblock1; /* up the output stream. */ char *tapeblock2; char *tapeblock3; tapedev = as->parms[0].items->data; /* -tape */ nrestore = (as->parms[1].items ? atol(as->parms[1].items->data) : 0x7fffffff); nskip = (as->parms[2].items ? atol(as->parms[2].items->data) : 0); if (as->parms[4].items) nskip = 0x7fffffff; /* -scan */ outfile = (as->parms[3].items ? as->parms[3].items->data : 0); ask = (as->parms[5].items ? 0 : 1); /* -noask */ printlabels = (as->parms[6].items ? 1 : 0); /* -label */ printheaders = (as->parms[7].items ? 1 : 0); /* -vheaders */ verbose = (as->parms[8].items ? 1 : 0); /* -verbose */ /* Open the tape device */ rc = usd_Open(tapedev, USD_OPEN_RDONLY, 0, &fd); if (rc != 0) { printf("Failed to open tape device %s. Code = %d\n", tapedev, rc); exit(1); } /* * Initialize the tape block buffers */ tapeblock1 = (char *)malloc(3 * 16384); if (tapeblock1 == NULL) { printf("Failed to allocate I/O buffers.\n"); exit(1); } tapeblock2 = tapeblock1 + 16384; tapeblock3 = tapeblock2 + 16384; nextblock = tapeblock1; lastblock = NULL; lastblock2 = NULL; /* Read each tape block deciding what to do with it */ do { /* while ((nskip!=0) && (nrestore!=0)) */ code = readblock(nextblock); if (code) { if (!eod) fprintf(stderr, "Tape device read error: %d\n", code); break; } isdatablock = 0; /* A data block can be either a volume header, volume trailer, * or actual data from a dump. */ bmark = (struct blockMark *)nextblock; label = (struct tapeLabel *)nextblock; fmark = (struct fileMark *)nextblock; if (ntohl(bmark->magic) == BLOCK_MAGIC) { if (verbose) printf("Data block\n"); isdatablock = 1; isheader = 0; data = &nextblock[sizeof(struct blockMark)]; if (strncmp(data, "H++NAME#", 8) == 0) { volheaderPtr = (struct volumeHeader *)data; printHeader(volheaderPtr, &isheader); } if (isheader) { code = openOutFile(volheaderPtr); nextblock = tapeblock1; lastblock = NULL; lastblock2 = NULL; } else { if (lastblock2 != NULL) { data = &lastblock2[sizeof(struct blockMark)]; bmark = (struct blockMark *)lastblock2; writeData(data, ntohl(bmark->count)); tblock = lastblock2; } else if (lastblock != NULL) { tblock = tapeblock2; } else { tblock = tapeblock3; } lastblock2 = lastblock; lastblock = nextblock; nextblock = tblock; } } /* Filemarks come in 3 forms: BEGIN, END, and EOD. * There is no information stored in filemarks. */ else if (ntohl(fmark->magic) == FILE_MAGIC) { fmtype = ntohl(fmark->nBytes); if (fmtype == FILE_BEGIN) { if (verbose) fprintf(stderr, "File mark volume begin\n"); } else if (fmtype == FILE_END) { if (verbose) fprintf(stderr, "File mark volume end\n"); } else if (fmtype == FILE_EOD) { if (verbose) fprintf(stderr, "File mark end-of-dump\n"); eod = 1; } } /* A dump label */ else if (ntohl(label->magic) == TAPE_MAGIC) { if (verbose) fprintf(stderr, "Dump label\n"); printLabel(label); eod = 0; } else { if (verbose) { fprintf(stderr, "Unrecognized tape block - end\n"); } } /* Anything other than a data block closes the out file. * At this point nextblock contains the end of tape file mark, * lastblock contains the last data block for the current volume, * and lastblock2 contains the second to last block for the current * volume. If the volume fits in a single block, lastblock2 will * be NULL. Call writeLastBlocks to strip off the dump trailer before * writing the last of the volume data to the dump file. The dump * trailer may span block boundaries. */ if (!isdatablock && lastblock) { writeLastBlocks(lastblock, lastblock2); closeOutFile(); nextblock = tapeblock1; lastblock = NULL; lastblock2 = NULL; } } while ((nskip != 0) || (nrestore != 0)); free(tapeblock1); return 0; }
int openOutFile(struct volumeHeader *headerPtr) { afs_int32 len; int ch; int rc; int oflag; int skip, first; afs_hyper_t size; /* If we were asked to skip this volume, then skip it */ if (nskip) { nskip--; return 0; } /* Skip if we are not to restore any */ if (!nrestore) return 0; /* Get the volume name and strip off the BK or RO extension */ if (outfile) { strcpy(filename, outfile); } else { strcpy(filename, headerPtr->volumeName); len = strlen(filename); if ((len > 7) && (strcmp(".backup", filename + len - 7) == 0)) { filename[len - 7] = 0; } else if ((len > 9) && (strcmp(".readonly", filename + len - 9) == 0)) { filename[len - 9] = 0; } } if (ask) { first = 1; skip = 0; printf("Press return to retreive volume %s (%u) to file %s; " "s" " to skip\n", headerPtr->volumeName, headerPtr->volumeID, filename); do { ch = getchar(); if ((first == 1) && (ch == 's')) skip = 1; if ((first == 1) && (ch == 'q')) exit(0); first = 0; } while (ch != '\n'); if (skip) { printf("Will not restore volume %s\n", headerPtr->volumeName); return 0; } } else { printf("Retrieve volume %s (%u) to file %s\n", headerPtr->volumeName, headerPtr->volumeID, filename); } /* Should I append the date onto the end of the name? */ /* Open the file to write to */ if (headerPtr->contd == TC_VOLCONTD) { /* Continuation of dump */ oflag = USD_OPEN_RDWR; } else { /* An all new dump */ oflag = USD_OPEN_RDWR | USD_OPEN_CREATE; } rc = usd_Open(filename, oflag, 0664, &ofd); if (rc != 0) { fprintf(stderr, "Unable to open file %s. Skipping. Code = %d\n", filename, rc); nrestore--; return 0; } if (headerPtr->contd != TC_VOLCONTD) { hzero(size); rc = USD_IOCTL(ofd, USD_IOCTL_SETSIZE, &size); if (rc != 0) { fprintf(stderr, "Unable to open file %s. Skipping. Code = %d\n", filename, rc); USD_CLOSE(ofd); nrestore--; return 0; } } ofdIsOpen = 1; return 0; }
static afs_int32 file_Mount(struct butm_tapeInfo *info, char *tape) { struct progress *p; char filename[64]; usd_handle_t fid; int xflags; afs_int32 code = 0, error = 0, rc = 0; if (!info || !tape) ERROR_EXIT(BUTM_BADARGUMENT); if (info->debug) printf("butm: Mount tape drive\n"); POLL(); info->error = 0; if (info->structVersion != BUTM_MAJORVERSION) ERROR_EXIT(BUTM_OLDINTERFACE); if (info->tmRock) ERROR_EXIT(BUTM_PARALLELMOUNTS); if (strlen(tape) >= sizeof(info->name)) ERROR_EXIT(BUTM_BADARGUMENT); strcpy(info->name, tape); strcpy(filename, config.tapedir); /* the name of the tape device */ info->position = (isafile ? 0 : 1); info->kBytes = info->nBytes = 0; info->nRecords = info->nFiles = 0; info->recordSize = 0; info->tapeSize = config.tapeSize; info->coefBytes = 1; info->coefRecords = 0; info->coefFiles = sizeof(struct fileMark); info->simultaneousTapes = 1; info->status = 0; info->error = 0; info->flags = BUTM_FLAGS_SEQUENTIAL; xflags = 0; if (isafile) { xflags |= USD_OPEN_CREATE; } else { /* * try to open in a child process first so nothing will * time out should the process block because the device * isn't ready. */ if (ForkOpen(filename)) { ERROR_EXIT(BUTM_MOUNTFAIL); } } /* Now go ahead and open the tape drive for real */ rc = usd_Open(filename, (USD_OPEN_RDWR | USD_OPEN_WLOCK | xflags), 0777, &fid); if (rc != 0) { /* try for lesser access */ rc = usd_Open(filename, (USD_OPEN_RDONLY | USD_OPEN_RLOCK), 0, &fid); if (rc) { error = rc; ERROR_EXIT(BUTM_MOUNTFAIL); } info->flags |= BUTM_FLAGS_READONLY; } (void)PrepareAccess(fid); /* for NT */ p = malloc(sizeof(*p)); info->tmRock = (char *)p; p->fid = fid; p->mountId = config.mountId = time(0); p->reading = p->writing = 0; TapeBlockSize = BUTM_BLOCKSIZE; /* Initialize */ error_exit: if (error) info->error = error; return (code); }
static int ForkOpen(char *device) { int rc; /* return code from system calls */ int i; /* loop index */ int pid; /* process ID of child process */ int status; /* exit status of child process */ int open_rc; /* return code from open */ int pipefd[2]; /* pipe for child return status */ int forkflag; /* flag set when ready to fork */ usd_handle_t fd; /* handle returned from open */ #ifdef AFS_PTHREAD_ENV forkflag = 0; /* No need to fork if using pthreads */ #else forkflag = 1; #endif /* create pipe for getting return code from child */ if (forkflag) { rc = pipe(pipefd); if (rc < 0) { printf("butm: Cannot create pipe for OPEN process. Error %d\n", errno); forkflag = 0; } } if (forkflag) { pid = fork(); if (pid < 0) { close(pipefd[0]); close(pipefd[1]); printf("butm: Cannot create child process for OPEN. Error %d\n", errno); forkflag = 0; } } if (!forkflag) { /* problem starting child process */ /* *return success, the caller will discover any problems * when it opens the device. */ open_rc = 0; } else if (pid == 0) { /* child process */ /* close all unneccessary file descriptors */ for (i = 3; i < _POSIX_OPEN_MAX; i++) { if (i != pipefd[1]) { close(i); } } /* try the open */ open_rc = usd_Open(device, USD_OPEN_RDONLY, 0, &fd); if (open_rc == 0) { USD_CLOSE(fd); } /* * Send the return code back to the parent. * If this fails, there's nothing we can do, but we must test * it in order to avoid complier warnings on some platforms. */ if (write(pipefd[1], &open_rc, sizeof(open_rc)) < 0) ; /* don't care */ exit(0); } else { /* parent process */ close(pipefd[1]); POLL(); /* read the result from the child process */ rc = read(pipefd[0], &open_rc, sizeof(open_rc)); if (rc != sizeof(open_rc)) { /* this is not a problem since we will reopen the device anyway */ printf("butm: No response from OPEN process. Error %d\n", errno); open_rc = 0; } close(pipefd[0]); /* get the completion status from the child process */ rc = waitpid(pid, &status, 0); while (rc < 0 && errno == EINTR) { rc = waitpid(pid, &status, 0); } if (rc < 0) { printf("butm: Cannot get status of OPEN process. Error %d\n", errno); } else if (status != 0) { printf ("butm: Unexpected OPEN process exit status 0x%04x. Error %d \n", status, errno); } SLEEP(1); } return (open_rc); }
int fileMarkSize(char *tapeDevice) { afs_uint32 nFileMarks, nBlocks, nbfTape; double tpSize, fmSize; afs_uint32 bufferSize = 16384; usd_handle_t hTape; FILE *logFile; int count = 0; afs_uint32 countr; afs_int32 code = 0; code = usd_Open(tapeDevice, (USD_OPEN_RDWR | USD_OPEN_WLOCK), 0777, &hTape); if (code) { printf("Can't open tape device %s\n", tapeDevice); fflush(stdout); exit(1); } logFile = fopen("fms.log", "w+"); if (logFile == NULL) { printf("Can't open log file\n"); fflush(stdout); exit(1); } fprintf(logFile, "fms test started\n"); fflush(logFile); code = rewindTape(hTape); if (code) { fprintf(logFile, "Can't rewind tape\n"); fflush(logFile); ERROR(code); } /* measure capacity of tape */ nbfTape = 0; countr = 0; while (1) { code = dataBlock(hTape, bufferSize); nbfTape++; count++; countr++; if (code) break; if (count >= 5) { count = 0; printf("\rwrote block: %d", nbfTape); } } fprintf(logFile, "wrote %d blocks\n", nbfTape); fflush(logFile); printf("\rwrote %d blocks\n", nbfTape); printf("Finished data capacity test - rewinding\n"); /* reset the tape device */ code = USD_CLOSE(hTape); if (code) { fprintf(logFile, "Can't close tape device at end of pass 1\n"); fflush(logFile); printf("Can't close tape device %s\n", tapeDevice); goto error_exit; } code = usd_Open(tapeDevice, (USD_OPEN_RDWR | USD_OPEN_WLOCK), 0777, &hTape); if (code) { fprintf(logFile, "Can't open tape device for pass 2\n"); fflush(logFile); printf("Can't open tape device %s\n", tapeDevice); goto error_exit; } code = rewindTape(hTape); if (code) { fprintf(logFile, "Can't rewind tape\n"); fflush(logFile); ERROR(code); } /* now measure file mark size */ nFileMarks = 0; nBlocks = 0; count = 0; countr = 0; while (1) { code = dataBlock(hTape, bufferSize); nBlocks++; if (code) break; code = fileMark(hTape); nFileMarks++; if (code) break; count++; countr++; if (count >= 2) { count = 0; printf("\rwrote %d blocks, %d filemarks", nBlocks, nFileMarks); } } printf("\nFinished filemark test\n"); tpSize = (double)nbfTape *(double)bufferSize; fmSize = (((double)nbfTape - (double)nBlocks) * (double)bufferSize) / (double)nFileMarks; printf("Tape capacity is %.0f bytes\n", tpSize); printf("File marks are %.0f bytes\n", fmSize); fprintf(logFile, "Tape capacity is %.0f bytes\n", tpSize); fprintf(logFile, "File marks are %.0f bytes\n", fmSize); fflush(logFile); fclose(logFile); error_exit: USD_CLOSE(hTape); return (code); }