📄 rawfslib.c
字号:
{ semGive (pRawFd->rawfd_semId); /* release fd */ errnoSet (S_rawFsLib_FD_OBSOLETE); return (ERROR); } /* Perform requested function */ switch (function) { case FIODISKINIT: retValue = OK; break; case FIOSEEK: retValue = rawFsSeek (pRawFd, arg); break; case FIOWHERE: retValue = rawFsWhere (pRawFd); break; case FIOFLUSH: case FIOSYNC: retValue = rawFsFlush (pRawFd->rawfd_vdptr); break; case FIONREAD: *((int *) arg) = pRawFd->rawfd_endptr - (rawFsWhere (pRawFd)); retValue = OK; break; case FIODISKCHANGE: rawFsReadyChange (pRawFd->rawfd_vdptr); retValue = OK; break; case FIOUNMOUNT: retValue = rawFsVolUnmount (pRawFd->rawfd_vdptr); break; case FIOGETFL: *((int *) arg) = pRawFd->rawfd_mode; retValue = OK; break; default: /* Call device driver function */ retValue = (* pRawFd->rawfd_vdptr->rawvd_pBlkDev->bd_ioctl) (pRawFd->rawfd_vdptr->rawvd_pBlkDev, function, arg); } semGive (pRawFd->rawfd_semId); /* release fd */ return (retValue); /* return obtained result */ }/********************************************************************************* rawFsModeChange - modify the mode of a raw device volume** This routine sets the device's mode to <newMode> by setting the mode field in* the BLK_DEV structure. This routine should be called whenever the read* and write capabilities are determined, usually after a ready change.** The driver's device initialization routine should initially set the mode* to O_RDWR (i.e., both O_RDONLY and O_WRONLY).** RETURNS: N/A** SEE ALSO: rawFsReadyChange()*/void rawFsModeChange ( RAW_VOL_DESC *vdptr, /* pointer to volume descriptor */ int newMode /* O_RDONLY/O_WRONLY/O_RDWR (both) */ ) { vdptr->rawvd_pBlkDev->bd_mode = newMode; }/********************************************************************************* rawFsOpen - open a raw volume** This routine opens the volume with the specified mode* (O_RDONLY/O_WRONLY/O_RDWR/CREATE/TRUNC).** The specified <name> must be a null string, indicating that the* caller specified only the device name during open().** If the device driver supplies a status-check routine, it will be* called before the volume state is examined.** RETURNS: Pointer to raw volume file descriptor, or ERROR.*/LOCAL RAW_FILE_DESC *rawFsOpen ( FAST RAW_VOL_DESC *vdptr, /* pointer to volume descriptor */ char *name, /* "file" name - should be empty str */ int flags /* open flags */ ) { FAST RAW_FILE_DESC *pRawFd; /* file descriptor pointer */ FAST BLK_DEV *pBlkDev = vdptr->rawvd_pBlkDev; /* pointer to block device info */ /* Check for open of other than raw volume (non-null filename) */ if (name [0] != EOS) { errnoSet (S_rawFsLib_ILLEGAL_NAME); return ((RAW_FILE_DESC *) ERROR); /* cannot specify filename */ } /* Call driver check-status routine, if any */ if (vdptr->rawvd_pBlkDev->bd_statusChk != NULL) { if ((* vdptr->rawvd_pBlkDev->bd_statusChk) (vdptr->rawvd_pBlkDev) != OK) { return ((RAW_FILE_DESC *) ERROR); /* driver returned error */ } } /* Clear possible O_CREAT and O_TRUNC flag bits */ flags &= ~(O_CREAT | O_TRUNC); /* Get a free file descriptor */ if ((pRawFd = rawFsFdGet()) == NULL) return ((RAW_FILE_DESC *) ERROR); /* max fd's already open */ semTake (pRawFd->rawfd_semId, WAIT_FOREVER); /* take control of fd */ /* Get ownership of volume */ semTake (vdptr->rawvd_semId, WAIT_FOREVER); /* take volume */ /* Check that volume is available */ if (rawFsVolCheck (vdptr) != OK) { semGive (vdptr->rawvd_semId); rawFsFdFree (pRawFd); semGive (pRawFd->rawfd_semId); errnoSet (S_rawFsLib_VOLUME_NOT_AVAILABLE); return ((RAW_FILE_DESC *) ERROR); /* cannot access volume */ } /* Check for read-only volume opened for write/update */ if ((vdptr->rawvd_pBlkDev->bd_mode == O_RDONLY) && (flags == O_WRONLY || flags == O_RDWR)) { semGive (vdptr->rawvd_semId); rawFsFdFree (pRawFd); semGive (pRawFd->rawfd_semId); errnoSet (S_ioLib_WRITE_PROTECTED); return ((RAW_FILE_DESC *) ERROR); /* volume not writable */ } semGive (vdptr->rawvd_semId); /* release volume */ pRawFd->rawfd_mode = flags; pRawFd->rawfd_vdptr = vdptr; pRawFd->rawfd_curptr = 0; pRawFd->rawfd_newptr = 0; pRawFd->rawfd_endptr = (pBlkDev->bd_nBlocks * pBlkDev->bd_bytesPerBlk); pRawFd->rawfd_modified = FALSE; /* Allocate a 1 block buffer for short reads/writes */ pRawFd->rawfd_buffer = (char *) calloc ((unsigned) pBlkDev->bd_bytesPerBlk, 1); if (pRawFd->rawfd_buffer == NULL) { rawFsFdFree (pRawFd); return ((RAW_FILE_DESC *) ERROR); /* mem alloc error */ } pRawFd->rawfd_bufBlk = NONE; /* no block in buffer yet */ semGive (pRawFd->rawfd_semId); /* release fd */ return (pRawFd); }/********************************************************************************* rawFsRead - read from a raw volume** This routine reads from the volume specified by the file descriptor* (returned by rawFsOpen()) into the specified buffer.* <maxbytes> bytes will be read, if there is that much data in the file.** RETURNS: Number of bytes actually read, or 0 if end of file, or ERROR.*/LOCAL int rawFsRead ( FAST RAW_FILE_DESC *pRawFd, /* file descriptor pointer */ char *pBuf, /* addr of input buffer */ int maxBytes /* maximum bytes to read into buffer */ ) { STATUS status; int bufIndex; /* position in file I/O buffer */ FAST int bytesLeft; /* count of remaining bytes to read */ FAST int nBytes; /* byte count from individual read */ FAST int blkNum; /* starting block for read */ FAST int numBlks; /* number of blocks to read */ FAST RAW_VOL_DESC *vdptr = pRawFd->rawfd_vdptr; /* ptr to volume descriptor */ FAST BLK_DEV *pBlkDev = pRawFd->rawfd_vdptr->rawvd_pBlkDev; /* ptr to block device info */ FAST int bytesPerBlk = pBlkDev->bd_bytesPerBlk; /* number of bytes per block */ 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 for valid maxBytes */ if (maxBytes <= 0) { semGive (pRawFd->rawfd_semId); errnoSet (S_rawFsLib_INVALID_NUMBER_OF_BYTES); return (ERROR); } semTake (vdptr->rawvd_semId, WAIT_FOREVER); /* take control of volume */ /* Do successive reads until requested byte count or EOF */ bytesLeft = maxBytes; /* init number remaining */ while (bytesLeft > 0) { nBytes = 0; /* init individual read count */ /* Do direct whole-block read if possible */ if ((bytesLeft >= bytesPerBlk) && (pRawFd->rawfd_newptr % bytesPerBlk == 0)) { /* Calculate starting block and number to read */ blkNum = pRawFd->rawfd_newptr / bytesPerBlk; /* SPR# 9418: Check for new position past end of device */ if (blkNum >= pBlkDev->bd_nBlocks) break; /* return number read OK */ numBlks = bytesLeft / bytesPerBlk; /* Adjust if read would extend past end of device */ numBlks = min (numBlks, (pBlkDev->bd_nBlocks - blkNum)); /* Read blocks */ if (rawFsBlkRd (vdptr, blkNum, numBlks, pBuf) != OK) { /* read error */ if (bytesLeft == maxBytes) /* if nothing read yet */ { semGive (vdptr->rawvd_semId); semGive (pRawFd->rawfd_semId); return (ERROR); /* indicate error */ } else break; /* return number read OK */ } /* If file descriptor buffer contains modified data (O_RDWR mode) * and the read included the buffered block, insert buffer * contents into user's buffer at appropriate offset. */ if (pRawFd->rawfd_modified) { if ((pRawFd->rawfd_bufBlk >= blkNum) && (pRawFd->rawfd_bufBlk < (blkNum + numBlks))) { bcopy (pRawFd->rawfd_buffer, pBuf + ((pRawFd->rawfd_bufBlk - blkNum) * bytesPerBlk), bytesPerBlk); } } nBytes = (numBlks * bytesPerBlk); } else /* if not whole-block transfer*/ { /* Get new block in buffer, if necessary */ if ((status = rawFsBlkNew (pRawFd)) <= 0) { /* probably end of file */ if (bytesLeft == maxBytes) /* if nothing read yet */ { semGive (vdptr->rawvd_semId); semGive (pRawFd->rawfd_semId); return (status); /* indicate error */ } else break; /* return number read OK */ } /* Fill until end of caller's buffer, end of file buffer, or end * of volume, whichever comes first. */ bufIndex = pRawFd->rawfd_newptr % bytesPerBlk; nBytes = min (bytesLeft, bytesPerBlk - bufIndex); nBytes = min (nBytes, (pRawFd->rawfd_endptr - pRawFd->rawfd_newptr)); bcopy (&pRawFd->rawfd_buffer [bufIndex], pBuf, nBytes); } /* Adjust count remaining, buffer pointer, and file pointer */ bytesLeft -= nBytes; pBuf += nBytes; pRawFd->rawfd_newptr += nBytes; } /* end while */ semGive (vdptr->rawvd_semId); /* release volume */ semGive (pRawFd->rawfd_semId); /* release fd */ return (maxBytes - bytesLeft); /* number of bytes read */ }/********************************************************************************* rawFsReadyChange - notify rawFsLib of a change in ready status** This routine sets the volume descriptor state to RAW_VD_READY_CHANGED.* It should be called whenever a driver senses that a device has come on-line* or gone off-line, (e.g., a disk has been inserted or removed).** After this routine has been called, the next attempt to use the volume* will result in an attempted remount.** RETURNS: N/A*/void rawFsReadyChange ( RAW_VOL_DESC *vdptr /* pointer to volume descriptor */ ) { vdptr->rawvd_state = RAW_VD_READY_CHANGED; }/********************************************************************************* rawFsReset - reset a volume** This routine calls the specified volume's reset routine, if any.* If the reset fails, rawvd_state is set to (RAW_VD_CANT_RESET)* to indicate that disk won't reset.** RETURNS: OK, or ERROR if driver returned error.*/LOCAL STATUS rawFsReset ( FAST RAW_VOL_DESC *vdptr /* pointer to volume descriptor */ ) { FAST BLK_DEV *pBlkDev = vdptr->rawvd_pBlkDev; /* pointer to block device struct */ if (pBlkDev->bd_reset != NULL) { if ((* pBlkDev->bd_reset) (pBlkDev) != OK) { vdptr->rawvd_state = RAW_VD_CANT_RESET; return (ERROR); } } return (OK); }/********************************************************************************* rawFsSeek - change file descriptor's current character position** This routine sets the specified file descriptor's current character* position to the specified position. This only changes the pointer, it* doesn't affect the hardware at all.** Attempts to set the character pointer to a negative offset (i.e. before* the start of the disk) or to a point beyond the end of the device* will return ERROR.** RETURNS: OK, or ERROR if invalid character offset.*/LOCAL STATUS rawFsSeek ( FAST RAW_FILE_DESC *pRawFd, /* file descriptor pointer */ int position /* desired character position in file */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -