static int ForkIoctl(usd_handle_t fd, int op, int count) { usd_tapeop_t tapeop; /* Issue requested tape control */ tapeop.tp_op = op; tapeop.tp_count = count; return (USD_IOCTL(fd, USD_IOCTL_TAPEOPERATION, (void *)&tapeop)); }
/* write an EOF marker */ int fileMark(usd_handle_t hTape) { usd_tapeop_t tapeop; int rcode; tapeop.tp_op = USDTAPE_WEOF; tapeop.tp_count = 1; rcode = USD_IOCTL(hTape, USD_IOCTL_TAPEOPERATION, (void *)&tapeop); return rcode; }
/* rewindTape() - rewinds tape to beginning */ afs_int32 rewindTape(usd_handle_t hTape) { usd_tapeop_t tapeop; int rcode; tapeop.tp_op = USDTAPE_REW; tapeop.tp_count = 1; rcode = USD_IOCTL(hTape, USD_IOCTL_TAPEOPERATION, (void *)&tapeop); return rcode; }
void incPosition(struct butm_tapeInfo *info, usd_handle_t fid, afs_uint32 dataSize) { /* Add this to the amount of data written to the tape */ incSize(info, dataSize); info->posCount += dataSize; if (info->posCount >= 2147467264) { /* 2GB - 16K */ info->posCount = 0; #if (defined(AFS_SUN_ENV) || defined(AFS_LINUX24_ENV)) if (!isafile) { afs_int64 off; off = 0; USD_IOCTL(fid, USD_IOCTL_SETSIZE, &off); } #endif } }
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 int ForkIoctl(usd_handle_t fd, int op, int count) { 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 ioctl_rc; /* return code from ioctl call */ int pipefd[2]; /* pipe for child return status */ int forkflag; /* flag set when ready to fork */ usd_tapeop_t tapeop; /* tape operation specification */ int unixfd; #ifdef AFS_PTHREAD_ENV forkflag = 0; /* No need to fork if using pthreads */ #else forkflag = 1; #endif /* initialize tape command structure */ tapeop.tp_op = op; tapeop.tp_count = count; /* create pipe for getting return code from child */ if (forkflag) { rc = pipe(pipefd); if (rc < 0) { printf("butm: Can't open pipe for IOCTL process. Error %d\n", errno); forkflag = 0; } } if (forkflag) { pid = fork(); if (pid < 0) { close(pipefd[0]); close(pipefd[1]); printf("butm: Can't fork IOCTL process. Error %d\n", errno); forkflag = 0; } } if (!forkflag) { /* problem starting child process */ /* do the ioctl anyway, it will probably work */ ioctl_rc = USD_IOCTL(fd, USD_IOCTL_TAPEOPERATION, (void *)&tapeop); } else if (pid == 0) { /* child process */ /* close all unneccessary file descriptors */ /* note: as painful as it is, we have to reach under the covers of * the usd package to implement this functionality. */ unixfd = (intptr_t)(fd->handle); for (i = 3; i < _POSIX_OPEN_MAX; i++) { if (i != unixfd && i != pipefd[1]) { close(i); } } /* do the ioctl call */ ioctl_rc = USD_IOCTL(fd, USD_IOCTL_TAPEOPERATION, (void *)&tapeop); /* * 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], &ioctl_rc, sizeof(int)) < 0) ; /* don't care */ exit(0); } else { /* parent process */ close(pipefd[1]); POLL(); /* read the result from the child process */ rc = read(pipefd[0], &ioctl_rc, sizeof(int)); if (rc != sizeof(int)) { /* tape is now in unknown state */ printf("butm: Can't determine IOCTL child status. Error %d\n", errno); ioctl_rc = EFAULT; } 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: Can't determine IOCTL child status. Error %d\n", errno); } else if (status != 0) { printf ("butm: Unexpected IOCTL process status 0x%04x . Error %d\n", status, errno); } SLEEP(1); } return (ioctl_rc); }
static afs_int32 file_WriteLabel(struct butm_tapeInfo *info, struct butm_tapeLabel *label, afs_int32 rewind) { afs_int32 code = 0; afs_int32 fcode; struct tapeLabel *tlabel; struct progress *p; afs_int64 off; /* offset */ if (info->debug) printf("butm: Write tape label\n"); POLL(); info->error = 0; code = check(info, WRITE_OP); if (code) ERROR_EXIT(code); if (!label) ERROR_EXIT(BUTM_BADARGUMENT); if (label->structVersion != CUR_TAPE_VERSION) ERROR_EXIT(BUTM_OLDINTERFACE); if (rewind) { /* Not appending, so rewind */ code = rewindFile(info); if (code) ERROR_EXIT(code); if (isafile) { p = (struct progress *)info->tmRock; off = 0; code = USD_IOCTL(p->fid, USD_IOCTL_SETSIZE, &off); if (code) ERROR_EXIT(BUTM_POSITION); } } else { if (READS || WRITES) ERROR_EXIT(BUTM_BADOP); } /* Copy the label into the tape block * ---------------------------------- */ memset(tapeBlock, 0, BUTM_BLOCKSIZE); if (!label->creationTime) label->creationTime = time(0); tlabel = (struct tapeLabel *)tapeBlock; memcpy(&tlabel->label, label, sizeof(struct butm_tapeLabel)); tlabel->label.structVersion = htonl(CUR_TAPE_VERSION); tlabel->label.creationTime = htonl(tlabel->label.creationTime); tlabel->label.expirationDate = htonl(tlabel->label.expirationDate); tlabel->label.size = htonl(tlabel->label.size); tlabel->label.useCount = htonl(tlabel->label.useCount); tlabel->label.dumpid = htonl(tlabel->label.dumpid); /* * write the tape label - For appends, the write may need to skip * over 1 or 2 EOF marks that were written when tape was closed after * the last dump. Plus, some AIX tape drives require we try forwarding * over the last EOF and take an error before we can write the new label. * ---------------------------------------------------------------------- */ code = WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE, BLOCK_LABEL); if (!isafile && !rewind && (code == BUTM_IO)) do { /* do if write failed */ fcode = SeekFile(info, 1); /* skip over the EOF */ if (fcode) break; /* leave if error */ code = WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE, BLOCK_LABEL); if (code != BUTM_IO) break; /* continue if write failed */ fcode = SeekFile(info, 1); /* skip over the EOF */ if (fcode) { /* retry 1 write if couldn't skip */ code = WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE, BLOCK_LABEL); break; } code = WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE, BLOCK_LABEL); if (code != BUTM_IO) break; /* continue if write failed */ fcode = SeekFile(info, 1); /* skip over the EOF */ if (fcode) { /* retry 1 write if couldn't skip */ code = WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE, BLOCK_LABEL); break; } break; } while (0); /* clear the write error status a failed WriteTapeBlock may have produced */ if (!code) info->status &= ~BUTM_STATUS_WRITEERROR; error_exit: return code; }