📄 rawfslib.c
字号:
) { FAST BLK_DEV *pBlkDev; /* ptr to blkock dev structure */ /* Check for valid new offset */ pBlkDev = pRawFd->rawfd_vdptr->rawvd_pBlkDev; if (position < 0 || (position / pBlkDev->bd_bytesPerBlk) >= pBlkDev->bd_nBlocks) { errnoSet (S_rawFsLib_BAD_SEEK); return (ERROR); } /* Update new file byte pointer */ pRawFd->rawfd_newptr = position; return (OK); }/********************************************************************************* rawFsVolCheck - verify that volume descriptor is current** This routine is called at the beginning of most operations on* the device. The status field in the volume descriptor is examined,* and the appropriate action is taken. In particular, the disk is* mounted if it is currently unmounted or a ready-change has occurred.** If the disk is already mounted or is successfully mounted as a* result of this routine calling rawFsVolMount, this routine returns* OK. If the disk cannot be mounted, ERROR is returned.** RETURNS: OK, or ERROR.*/LOCAL STATUS rawFsVolCheck ( FAST RAW_VOL_DESC *vdptr /* pointer to volume descriptor */ ) { FAST int status; /* return status value */ status = OK; /* init return value */ /* Check if device driver announced ready-change */ if (vdptr->rawvd_pBlkDev->bd_readyChanged) { vdptr->rawvd_state = RAW_VD_READY_CHANGED; vdptr->rawvd_pBlkDev->bd_readyChanged = FALSE; } /* Check volume status */ switch (vdptr->rawvd_state) { case RAW_VD_CANT_RESET: /* This state means we tried to reset and failed so we * don't try again until a ready change occurs */ status = ERROR; /* can't reset */ break; case RAW_VD_CANT_MOUNT: /* This state means we tried to mount and failed so we * don't try again until a ready change occurs */ status = ERROR; /* can't mount */ break; case RAW_VD_READY_CHANGED: /* Ready change occurred; try to reset volume */ if (rawFsReset (vdptr) != OK) { status = ERROR; /* can't reset */ break; } vdptr->rawvd_state = RAW_VD_RESET; /* note volume reset */ /* Fall-through to try to mount */ case RAW_VD_RESET: /* Volume reset but not mounted; try mount */ if (rawFsVolMount (vdptr) != OK) { vdptr->rawvd_state = RAW_VD_CANT_MOUNT; /* can't mount */ status = ERROR; /* don't try again */ break; } vdptr->rawvd_state = RAW_VD_MOUNTED; /* note vol mounted */ break; case RAW_VD_MOUNTED: break; /* ready to go as is */ } return (status); /* return status value */ }/********************************************************************************* rawFsVolFlush - flush raw volume to disk** This routine guarantees that any changes to the volume are actually* written to disk. Since there are no data structures kept on disk,* the only possible changes are the file descriptor read/write buffers.** INTERNAL* Posession of the volume descriptor's semaphore must have been secured* before this routine is called.** RETURNS: OK, or ERROR.*/LOCAL STATUS rawFsVolFlush ( FAST RAW_VOL_DESC *vdptr /* pointer to volume descriptor */ ) { FAST RAW_FILE_DESC *pRawFd; /* pointer to file descriptor */ /* Flush all modified file descriptor I/O buffers to disk */ semTake (rawFsFdListSemId, WAIT_FOREVER); /* take control of Fd lists */ pRawFd = (RAW_FILE_DESC *) lstFirst (&rawFsFdActiveList); /* get first in-use Fd */ while (pRawFd != NULL) { if (pRawFd->rawfd_vdptr == vdptr) /* if correct volume */ { if (rawFsFdFlush (pRawFd) != OK) /* write Fd buffer to disk */ return (ERROR); /* error flushing buffer */ } pRawFd = (RAW_FILE_DESC *) lstNext (&pRawFd->rawfd_node); /* get next in-use Fd */ } semGive (rawFsFdListSemId); /* release Fd lists */ vdptr->rawvd_status = OK; return (OK); }/********************************************************************************* rawFsVolMount - prepare to use raw volume** This routine prepares the library to use the raw volume on the device* specified.** This routine should be called every time a disk is changed (i.e. a floppy* is swapped, or whatever), or before every open and create, if the driver* can't tell when disks are changed.** RETURNS: OK or ERROR.*/LOCAL STATUS rawFsVolMount ( FAST RAW_VOL_DESC *vdptr /* pointer to volume descriptor */ ) { vdptr->rawvd_status = OK; return (OK); }/********************************************************************************* rawFsVolUnmount - disable a raw device volume** This routine is called when I/O operations on a volume are to be* discontinued. This is commonly done before changing removable disks.* All buffered data for the volume is written to the device (if possible),* any open file descriptors are marked as obsolete, and the volume is* marked as not mounted.** Because this routine will flush data from memory to the physical* device, it should not be used in situations where the disk-change is* not recognized until after a new disk has been inserted. In these* circumstances, use the ready-change mechanism. (See the manual entry for * rawFsReadyChange().)** This routine may also be called by issuing an ioctl() call using the* \%FIOUNMOUNT function code.** RETURNS: OK, or ERROR if the routine cannot access the volume.** SEE ALSO: rawFsReadyChange()*/STATUS rawFsVolUnmount ( FAST RAW_VOL_DESC *vdptr /* pointer to volume descriptor */ ) { FAST RAW_FILE_DESC *pRawFd; /* pointer to file descriptor */ /* Check that volume is available */ semTake (vdptr->rawvd_semId, WAIT_FOREVER); /* get ownership of volume */ if ((rawFsVolCheck (vdptr) != OK) || (vdptr->rawvd_status != OK)) { semGive (vdptr->rawvd_semId); /* release volume */ errnoSet (S_rawFsLib_VOLUME_NOT_AVAILABLE); return (ERROR); /* cannot access volume */ } /* Flush volume structures, if possible */ (void) rawFsVolFlush (vdptr); /* flush volume */ /* Mark any open file descriptors as obsolete */ semTake (rawFsFdListSemId, WAIT_FOREVER); /* take control of Fd lists */ pRawFd = (RAW_FILE_DESC *) lstFirst (&rawFsFdActiveList); /* get first in-use Fd */ while (pRawFd != NULL) { if (pRawFd->rawfd_vdptr == vdptr) { pRawFd->rawfd_status = RAWFD_OBSOLETE; } pRawFd = (RAW_FILE_DESC *) lstNext (&pRawFd->rawfd_node); /* get next in-use Fd */ } semGive (rawFsFdListSemId); /* release Fd lists */ /* Mark volume as no longer mounted */ rawFsReadyChange (vdptr); semGive (vdptr->rawvd_semId); /* release volume */ return (OK); }/********************************************************************************* rawFsWhere - return current character position on raw device** This routine tells you where the character pointer is for a raw device.* This character position applies only to the specifed file descriptor;* other file descriptor to the save raw device may have different character* pointer values.** RETURNS: Current character position of file descriptor.*/LOCAL int rawFsWhere ( FAST RAW_FILE_DESC *pRawFd /* file descriptor pointer */ ) { return (pRawFd->rawfd_newptr); }/********************************************************************************* rawFsWrite - write to a raw volume** This routine writes to the raw volume specified by the file descriptor* from the specified buffer. If the block containing the disk locations* to be written is already in the file descriptor's read/write buffer,* the buffer won't be flushed. If another in-memory block is needed,* any block already in memory will be flushed.** This routine calls the device driver block-writing routine directly* to write (possibly multiple) whole blocks.** RETURNS: Number of bytes written (error if != maxBytes), or* ERROR if maxBytes < 0, or no more space for the file,* or can't write block.*/LOCAL int rawFsWrite ( FAST RAW_FILE_DESC *pRawFd, /* file descriptor pointer */ char *pBuf, /* data to be written */ int maxBytes /* number of bytes to write */ ) { FAST int nBytes; /* byte count for individual write */ FAST int bufIndex; /* position it file I/O buffer */ FAST int blkNum; /* starting block for write */ FAST int numBlks; /* number of blocks to write */ FAST RAW_VOL_DESC *vdptr = pRawFd->rawfd_vdptr; /* pointer to vol descriptor */ FAST BLK_DEV *pBlkDev = pRawFd->rawfd_vdptr->rawvd_pBlkDev; /* pointer to block device info */ FAST int bytesLeft; /* remaining bytes to write */ semTake (pRawFd->rawfd_semId, WAIT_FOREVER); /* take control of fd */ /* Check that file descriptor is current */ if (pRawFd->rawfd_status == RAWFD_OBSOLETE) { semGive (pRawFd->rawfd_semId); errnoSet (S_rawFsLib_FD_OBSOLETE); return (ERROR); } /* Check that device was opened for writing */ if (pRawFd->rawfd_mode == O_RDONLY) { semGive (pRawFd->rawfd_semId); errnoSet (S_rawFsLib_READ_ONLY); return (ERROR); } /* Check for valid length of write */ if (maxBytes < 0) { semGive (pRawFd->rawfd_semId); errnoSet (S_rawFsLib_INVALID_NUMBER_OF_BYTES); return (ERROR); } /* Write into successive blocks until all of caller's buffer written */ semTake (vdptr->rawvd_semId, WAIT_FOREVER); /* take control of volume */ bytesLeft = maxBytes; while (bytesLeft > 0) { nBytes = 0; /* init individual write count*/ /* Do direct whole-block write if possible */ if ((bytesLeft >= pBlkDev->bd_bytesPerBlk) && (pRawFd->rawfd_newptr % pBlkDev->bd_bytesPerBlk == 0)) { /* Calculate starting block and number to write */ blkNum = pRawFd->rawfd_newptr / pBlkDev->bd_bytesPerBlk; numBlks = bytesLeft / pBlkDev->bd_bytesPerBlk; /* Adjust if write would extend past end of device */ numBlks = min (numBlks, (pBlkDev->bd_nBlocks - blkNum)); if (numBlks == 0) { errnoSet (S_rawFsLib_END_OF_DEVICE); break; } /* Write blocks */ if (rawFsBlkWrt (vdptr, blkNum, numBlks, pBuf) != OK) break; /* If write included buffered block, invalidate buffer */ if ((pRawFd->rawfd_bufBlk >= blkNum) && (pRawFd->rawfd_bufBlk < (blkNum + numBlks))) { pRawFd->rawfd_bufBlk = NONE; pRawFd->rawfd_modified = FALSE; } nBytes = (numBlks * pBlkDev->bd_bytesPerBlk); } else { /* Get block containing new pointer into buffer */ if (rawFsBlkNew (pRawFd) <= 0) break; /* disk full */ /* Copy length = rest of caller's buffer or rest of file I/O buffer, * whichever is less. */ bufIndex = pRawFd->rawfd_newptr % pBlkDev->bd_bytesPerBlk; nBytes = min (bytesLeft, pBlkDev->bd_bytesPerBlk - bufIndex); bcopy (pBuf, &pRawFd->rawfd_buffer [bufIndex], nBytes); pRawFd->rawfd_modified = TRUE; } /* Update pointers and bytes remaining */ pRawFd->rawfd_newptr += nBytes; pBuf += nBytes; bytesLeft -= nBytes; } semGive (vdptr->rawvd_semId); /* release volume */ semGive (pRawFd->rawfd_semId); /* release fd */ return (maxBytes - bytesLeft); /* return actual copy count */ }/******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -