📄 tapefslib.c
字号:
if (pSeqDev->sd_rewind == NULL) { errno = S_tapeFsLib_SERVICE_NOT_AVAILABLE; return (ERROR); } /* Rewind the tape device */ if ((*pSeqDev->sd_rewind) (pSeqDev) == ERROR) { return (ERROR); } pTapeFd->tapefd_bufIndex = 0; return (OK); /* Rewind and take the device offline */ case MTOFFL: if (pTapeFd->tapefd_mode != O_RDONLY) { /* Flush any buffered data */ if (tapeFsFdFlush (pTapeFd) == ERROR) { return (ERROR); } } if ((pSeqDev->sd_rewind == NULL) || (pSeqDev->sd_load == NULL)) { errno = S_tapeFsLib_SERVICE_NOT_AVAILABLE; return (ERROR); } /* Rewind the tape device */ if ((*pSeqDev->sd_rewind) (pSeqDev) == ERROR) { return (ERROR); } pTapeFd->tapefd_bufIndex = 0; /* Take it offline by unloading the device */ if ((*pSeqDev->sd_load) (pSeqDev, UNLOAD, FALSE, FALSE) == ERROR) { return (ERROR); } return (OK); /* No operation on device, simply sets the status */ case MTNOP: if (pSeqDev->sd_statusChk == NULL) { errno = S_tapeFsLib_SERVICE_NOT_AVAILABLE; return (ERROR); } /* Check device status (driver sets the status in SEQ_DEV) */ if ((*pSeqDev->sd_statusChk) (pSeqDev) == ERROR) { return (ERROR); } return (OK); /* Retension the tape */ case MTRETEN: if (pTapeFd->tapefd_mode != O_RDONLY) { /* Flush any buffered data */ if (tapeFsFdFlush (pTapeFd) == ERROR) { return (ERROR); } } if (pSeqDev->sd_load == NULL) { errno = S_tapeFsLib_SERVICE_NOT_AVAILABLE; return (ERROR); } /* Take it offline by unloading the device */ if ((*pSeqDev->sd_load) (pSeqDev, UNLOAD, RETEN, FALSE) == ERROR) { return (ERROR); } pTapeFd->tapefd_bufIndex = 0; return (OK); /* Erase the entire tape and rewind */ case MTERASE: if (pSeqDev->sd_erase == NULL) { errno = S_tapeFsLib_SERVICE_NOT_AVAILABLE; return (ERROR); } /* Take it offline by unloading the device */ if ((*pSeqDev->sd_erase) (pSeqDev, LONG) == ERROR) { return (ERROR); } pTapeFd->tapefd_bufIndex = 0; return (OK); /* Position the tape at the end-of-medium before unloading */ case MTEOM: if (pTapeFd->tapefd_mode != O_RDONLY) { /* Flush any buffered data */ if (tapeFsFdFlush (pTapeFd) == ERROR) { return (ERROR); } } if (pSeqDev->sd_load == NULL) { errno = S_tapeFsLib_SERVICE_NOT_AVAILABLE; return (ERROR); } /* Take it offline by unloading the device */ if ((*pSeqDev->sd_load) (pSeqDev, UNLOAD, FALSE, EOT) == ERROR) { return (ERROR); } pTapeFd->tapefd_bufIndex = 0; return (OK); /* Backward space file to beginning of file */ /* XXX Not sure how this is different that MTBSF 1 */ case MTNBSF: return (ERROR); /* Any other operation is an error */ default: return (ERROR); } /* switch */ }/********************************************************************************* tapeFsOpen - open a tape volume** This routine opens the volume with the specified mode* (O_RDONLY or O_WRONLY).** The specified `name' must be a null string, indicating that the* caller specified only the device name during open(). This is because* there is no file structure on the tape device.** If the device driver supplies a status-check routine, it will be* called before the volume state is examined.** RETURNS: Pointer to tape volume file descriptor, or ERROR.*/LOCAL TAPE_FILE_DESC *tapeFsOpen ( FAST TAPE_VOL_DESC * pTapeVol, /* pointer to volume descriptor */ FAST char * name, /* "file" name - should be empty str */ FAST int flags, /* open flags */ FAST int mode /* not used */ ) { /* file descriptor pointer */ FAST TAPE_FILE_DESC *pTapeFd = pTapeVol->tapevd_pTapeFd; /* pointer to block device info */ FAST SEQ_DEV *pSeqDev = pTapeVol->tapevd_pSeqDev; UINT16 unused; /* Check for open of other than tape volume (non-null filename) */ if (name [0] != EOS) { errno = S_tapeFsLib_ILLEGAL_FILE_SYSTEM_NAME; return ((TAPE_FILE_DESC *) ERROR); /* cannot specify filename */ } /* check the open flags for read only or write only */ if ((flags != O_RDONLY) && (flags != O_WRONLY)) { errno = S_tapeFsLib_ILLEGAL_FLAGS; TAPE_DEBUG_MSG ("tapeFsOpen: Wrong Tape Mode\n", 0,0,0,0,0,0); return ((TAPE_FILE_DESC *) ERROR); /* cannot specify filename */ } /* Get ownership of volume. If taken, return ERROR */ if (semTake (pTapeVol->tapevd_semId, NO_WAIT) == ERROR) { errno = EBUSY; /* posix errno */ TAPE_DEBUG_MSG ("tapeFsOpen: Could not get Semaphore\n", 0,0,0,0,0,0); return ((TAPE_FILE_DESC *) ERROR); } /* Check if file descriptor is in use */ if (pTapeFd->tapefd_inUse == TRUE) { errno = S_tapeFsLib_FILE_DESCRIPTOR_BUSY; semGive (pTapeVol->tapevd_semId); /* release volume */ return ((TAPE_FILE_DESC *) ERROR); /* file descriptor in use */ } /* Call driver check-status routine, if any */ if (pSeqDev->sd_statusChk != NULL) { if ((* pSeqDev->sd_statusChk) (pSeqDev) != OK) { semGive (pTapeVol->tapevd_semId); TAPE_DEBUG_MSG ("tapeFsOpen: statusChk failed\n", 0,0,0,0,0, 0); return ((TAPE_FILE_DESC *) ERROR); /* driver returned error */ } } /* Check for read-only volume opened for write/update */ if ((pSeqDev->sd_mode == O_RDONLY) && (flags == O_WRONLY )) { errno = S_ioLib_WRITE_PROTECTED; semGive (pTapeVol->tapevd_semId); TAPE_DEBUG_MSG ("tapeFsOpen: write protected. sd_mode is %x\n", pSeqDev->sd_mode,0,0,0,0, 0); return ((TAPE_FILE_DESC *) ERROR); /* volume not writable */ } /* fill in the rest of the tape volume fields */ pTapeFd->tapefd_mode = flags; pTapeFd->tapefd_pTapeVol = pTapeVol; /* Check that volume is available */ if (tapeFsVolCheck (pTapeVol) != OK) { semGive (pTapeVol->tapevd_semId); errno = S_tapeFsLib_VOLUME_NOT_AVAILABLE; TAPE_DEBUG_MSG ("tapeFsOpen: volume not available\n", 0,0,0,0,0, 0); return ((TAPE_FILE_DESC *) ERROR); /* cannot access volume */ } /* * Reserve the tape device for exclusive use unitl the file is closed. * When the file is closed, the device should be released. Reserving the * device disallows any other host from accessing the tape device. */ if ((*pSeqDev->sd_reserve) (pSeqDev) != OK) { semGive (pTapeVol->tapevd_semId); TAPE_DEBUG_MSG ("tapeFsOpen: reserve unit failed\n", 0,0,0,0,0, 0); return ((TAPE_FILE_DESC *) ERROR); /* driver returned error */ } /* mount a tape device if not already mounted */ if (pTapeVol->tapevd_state != TAPE_VD_MOUNTED) { if ((*pSeqDev->sd_load) (pSeqDev, LOAD, FALSE, FALSE) != OK) { semGive (pTapeVol->tapevd_semId); TAPE_DEBUG_MSG ("tapeFsOpen: mount failed\n", 0,0,0,0,0, 0); return ((TAPE_FILE_DESC *) ERROR); /* driver returned error */ } } /* rewind if it is a rewind device */ if (pTapeVol->tapevd_rewind) { if ((*pSeqDev->sd_rewind) (pSeqDev) != OK) { semGive (pTapeVol->tapevd_semId); TAPE_DEBUG_MSG ("tapeFsOpen: rewind failed\n", 0,0,0,0,0, 0); return ((TAPE_FILE_DESC *) ERROR); /* driver returned error */ } } /* Read block limits */ if (pSeqDev->sd_readBlkLim != NULL) { if ((*pSeqDev->sd_readBlkLim) (pSeqDev, &pSeqDev->sd_maxVarBlockLimit, &unused) != OK) { semGive (pTapeVol->tapevd_semId); TAPE_DEBUG_MSG ("tapeFsOpen: readBlkLim failed\n", 0,0,0,0,0, 0); return ((TAPE_FILE_DESC *) ERROR); /* driver returned error */ } } /* Allocate a 1 block buffer for short reads/writes if fixed block */ if (pSeqDev->sd_blkSize != 0) { pTapeFd->tapefd_buffer = (char *) calloc ((unsigned) pSeqDev->sd_blkSize, 1); if (pTapeFd->tapefd_buffer == NULL) { semGive (pTapeVol->tapevd_semId); /* release volume */ TAPE_DEBUG_MSG ("tapeFsOpen: calloc failed\n", 0,0,0,0,0, 0); return ((TAPE_FILE_DESC *) ERROR); /* mem alloc error */ } pTapeFd->tapefd_bufSize = pSeqDev->sd_blkSize; } pTapeFd->tapefd_inUse = TRUE; /* fd in use */ semGive (pTapeVol->tapevd_semId); /* release volume */ return (pTapeFd); }/********************************************************************************* tapeFsRead - read from a tape volume** This routine reads from the volume specified by the file descriptor* (returned by tapeFsOpen()) into the specified buffer.* `maxbytes' bytes will be read, if there is that much data in the file.** RETURNS: Number of bytes actually read, 0 if end of file, or ERROR.*/LOCAL int tapeFsRead ( FAST TAPE_FILE_DESC * pTapeFd, /* file descriptor pointer */ char * pBuf, /* addr of input buffer */ UINT maxBytes /* count of data units to read */ ) { int bytesLeft; /* count of remaining bytes to read */ int dataCount; /* count of remaining bytes to read */ int bytesRead; /* count of bytes read */ int blocksRead; /* count of bytes read */ int nBytes; /* byte count from individual read */ int numBytes; /* byte count from individual read */ int numBlks; /* number of blocks to read */ /* pointer to vol descriptor */ TAPE_VOL_DESC *pTapeVol = pTapeFd->tapefd_pTapeVol; /* pointer to sequential device */ SEQ_DEV *pSeqDev = pTapeFd->tapefd_pTapeVol->tapevd_pSeqDev; /* take control of volume */ semTake (pTapeVol->tapevd_semId, WAIT_FOREVER); TAPE_DEBUG_MSG ("tapeFsRead: Device block size is: %d\n", pSeqDev->sd_blkSize, 0,0,0,0,0); /* Check for valid length of read */ if (maxBytes <= 0) { semGive (pTapeVol->tapevd_semId); errno = S_tapeFsLib_INVALID_NUMBER_OF_BYTES; return (ERROR); } /* Check that device was opened for reading */ if (pTapeFd->tapefd_mode == O_WRONLY) { semGive (pTapeVol->tapevd_semId); /* errnoSet (S_tapeFsLib_READ_ONLY); */ return (ERROR); } /* Do successive reads until requested byte count or EOF */ bytesLeft = maxBytes; /* init number bytes remaining */ dataCount = maxBytes; /* Variable block read */ if (pSeqDev->sd_blkSize == VARIABLE_BLOCK_SIZE) { while (dataCount > 0) { /* Read a variable block upto a maximum size */ nBytes = (bytesLeft > pSeqDev->sd_maxVarBlockLimit) ? pSeqDev->sd_maxVarBlockLimit : bytesLeft; if ((bytesRead = tapeFsDevRd (pTapeVol, nBytes, pBuf, VARIABLE_BLK)) == ERROR) break; /* do nothing, may not be an error */ dataCount -= nBytes; bytesLeft -= bytesRead; pBuf += bytesRead; } semGive (pTapeVol->tapevd_semId); /* release volume */ return (maxBytes - bytesLeft); /* number of bytes read */ } /* Fixed block read */ while (dataCount > 0) { nBytes = 0; /* init individual read count */ /* * Do direct whole-block read, if the data is more than a blocks worth * and the FD buffer is empty. */ if ((dataCount >= pSeqDev->sd_blkSize) && (pTapeFd->tapefd_bufIndex == 0)) { /* calculate number of blocks to read */ numBlks = dataCount / pSeqDev->sd_blkSize; /* Read as many blocks as possible */ if ((blocksRead = tapeFsDevRd (pTapeVol, numBlks, pBuf, FIXED_BLK)) == ERROR) break; numBytes = numBlks * pSeqDev->sd_blkSize; /* calculate the number of bytes read */ nBytes = blocksRead * pSeqDev->sd_blkSize; } /* Handle partially read blocks (buffered) */ else /* if not whole-block transfer */ { if (pTapeFd->tapefd_bufIndex != 0) numBytes = pSeqDev->sd_blkSize - pTapeFd->tapefd_bufIndex; else numBytes = dataCount; if ((nBytes = tapeFsPartRd (pTapeFd, pBuf, dataCount)) == ERROR) break; } /* Adjust count remaining, buffer pointer, and file pointer */ dataCount -= numBytes; bytesLeft -= nBytes; pBuf += nBytes; } semGive (pTapeVol->tapevd_semId); /* release volume */ return (maxBytes - bytesLeft); /* number of bytes read */ }/********************************************************************************* tapeFsPartRd - read a partial tape block** This routine reads from a tape volume specified by the file descriptor,* to the specified buffer. When a partial block needs to be read, the entire* block is first read into the file descriptor buffer and then the desired* portion is copied into the specified buffer. If the number of bytes to be* read is more than that in the buffer then only the number of bytes left* in the buffer are read.** This routine calls the device driver block-reading routine directly* to read (possibly) a whole block.** RETURNS: Number of bytes read (error if != maxBytes), or* ERROR if maxBytes < 0, or can't read block.*/LOCAL int tapeFsPartRd ( TAPE_FILE_DESC * pTapeFd, /* pointer to a tape file descriptor */ char * pBuf, /* pointer to data buffer */ UINT nBytes /* number of partial bytes to read */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -