📄 rawfslib.c
字号:
FAST RAW_FILE_DESC *pRawFd, /* file descriptor of file to control */ int function, /* function code */ int arg /* some argument */ ) { FAST int retValue = ERROR; /* return value */ fsize_t buf64 = 0; semTake (pRawFd->rawFdSemId, WAIT_FOREVER); /* take control of fd */ /* Check that file descriptor is current */ if (pRawFd->rawFdStatus == RAWFD_OBSOLETE) { semGive (pRawFd->rawFdSemId); /* release fd */ errnoSet (S_rawFsLib_FD_OBSOLETE); return (ERROR); } /* Perform requested function */ switch (function) { case FIODISKINIT: retValue = OK; break; case FIOSEEK: { buf64 = (fsize_t)arg; retValue = rawFsSeek (pRawFd, buf64); break; } case FIOSEEK64: { retValue = rawFsSeek (pRawFd, *(fsize_t *)arg); break; } case FIOWHERE: { buf64 = rawFsWhere (pRawFd); if( rawFsIsValHuge( buf64 ) ) { errnoSet( S_rawFsLib_32BIT_OVERFLOW ); retValue = ERROR; } else retValue = (u_int)buf64; break; } case FIOWHERE64: /* position within 64 bit boundary */ { retValue = ERROR; if( (void *)arg == NULL ) { errnoSet( S_rawFsLib_INVALID_PARAMETER ); } else { *(fsize_t *)arg = rawFsWhere (pRawFd); retValue = OK; } break; } case FIOFLUSH: case FIOSYNC: retValue = rawFsFlush (pRawFd->pRawFdVd); break; case FIONREAD: { buf64 = pRawFd->rawFdEndPtr - (rawFsWhere (pRawFd)); retValue = ERROR; if( (void *)arg == NULL ) { errnoSet( S_rawFsLib_INVALID_PARAMETER ); } else if( rawFsIsValHuge( buf64 ) ) { errnoSet( S_rawFsLib_32BIT_OVERFLOW ); *(u_int *)arg = (-1); } else { *(u_long *)arg = buf64; retValue = OK; } break; } case FIONREAD64: { retValue = ERROR; if( (void *)arg == NULL ) { errnoSet( S_rawFsLib_INVALID_PARAMETER ); } else { *(fsize_t *)arg = pRawFd->rawFdEndPtr - (rawFsWhere (pRawFd)); retValue = OK; } break; } case FIODISKCHANGE: rawFsReadyChange (pRawFd->pRawFdVd); retValue = OK; break; case FIOUNMOUNT: retValue = rawFsVolUnmount (pRawFd->pRawFdVd); break; case FIOGETFL: *((int *) arg) = pRawFd->rawFdMode; retValue = OK; break; default: /* Call device driver function */ retValue = (cbioIoctl (pRawFd->pRawFdVd->rawVdCbio, function, (void *)arg)); } semGive (pRawFd->rawFdSemId); /* 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 device 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 *pVd, /* pointer to volume descriptor */ int newMode /* O_RDONLY/O_WRONLY/O_RDWR (both) */ ) { cbioModeSet (pVd->rawVdCbio, 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 *pVd, /* 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 CBIO_DEV_ID rawVdCbio = pVd->rawVdCbio; /* pointer to block device info */ CBIO_PARAMS cbioParams; /* Get CBIO device parameters */ if (ERROR == cbioParamsGet (rawVdCbio, &cbioParams)) { return ((RAW_FILE_DESC *) ERROR); } /* 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 */ } /* 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->rawFdSemId, WAIT_FOREVER); /* take control of fd */ /* Get ownership of volume */ semTake (pVd->rawVdSemId, WAIT_FOREVER); /* take volume */ /* Check that volume is available */ if (rawFsVolCheck (pVd) != OK) { semGive (pVd->rawVdSemId); rawFsFdFree (pRawFd); semGive (pRawFd->rawFdSemId); errnoSet (S_rawFsLib_VOLUME_NOT_AVAILABLE); return ((RAW_FILE_DESC *) ERROR); /* cannot access volume */ } /* Check for read-only volume opened for write/update */ if ((cbioModeGet(pVd->rawVdCbio) == O_RDONLY) && (flags == O_WRONLY || flags == O_RDWR)) { semGive (pVd->rawVdSemId); rawFsFdFree (pRawFd); semGive (pRawFd->rawFdSemId); errnoSet (S_ioLib_WRITE_PROTECTED); return ((RAW_FILE_DESC *) ERROR); /* volume not writable */ } semGive (pVd->rawVdSemId); /* release volume */ pRawFd->rawFdMode = flags; pRawFd->pRawFdVd = pVd; pRawFd->rawFdNewPtr = 0; pRawFd->rawFdEndPtr = (fsize_t) ((fsize_t)cbioParams.nBlocks * (fsize_t)cbioParams.bytesPerBlk); semGive (pRawFd->rawFdSemId); /* release fd */ return (pRawFd); }/********************************************************************************* rawFdRdWr - read from/write to a raw volume** See rawFdRead()/rawFdWrite()** RETURNS: Number of bytes actually processed, or 0 if end of file, or ERROR.*/LOCAL int rawFdRdWr ( FAST RAW_FILE_DESC *pRawFd, /* file descriptor pointer */ char *pBuf, /* addr of data buffer */ int maxBytes,/* maximum bytes to read/write into buffer */ CBIO_RW rw /* read / write */ ) { int offset; /* position in file I/O buffer */ FAST int bytesLeft; /* count of remaining bytes to process */ FAST int nBytes; /* byte count from individual process */ FAST block_t blkNum; /* starting block for read */ FAST int numBlks; /* number of blocks to read */ FAST RAW_VOL_DESC *pVd = pRawFd->pRawFdVd; /* ptr to volume descriptor */ FAST CBIO_DEV_ID rawVdCbio = pRawFd->pRawFdVd->rawVdCbio; /* ptr to block device info */ CBIO_PARAMS cbioParams; /* Get CBIO device parameters */ if (ERROR == cbioParamsGet (rawVdCbio, &cbioParams)) { return (ERROR); } assert (rw == CBIO_WRITE || rw == CBIO_READ); semTake (pRawFd->rawFdSemId, WAIT_FOREVER); /* take control of fd */ /* Check that file descriptor is current */ if (pRawFd->rawFdStatus == RAWFD_OBSOLETE) { semGive (pRawFd->rawFdSemId); errnoSet (S_rawFsLib_FD_OBSOLETE); return (ERROR); } /* Check that device was opened for writing, if write in progress */ if (rw == CBIO_WRITE && pRawFd->rawFdMode == O_RDONLY) { semGive (pRawFd->rawFdSemId); errnoSet (S_rawFsLib_READ_ONLY); return (ERROR); } /* Check for valid maxBytes */ if (maxBytes <= 0) { semGive (pRawFd->rawFdSemId); errnoSet (S_rawFsLib_INVALID_NUMBER_OF_BYTES); return (ERROR); } semTake (pVd->rawVdSemId, WAIT_FOREVER); /* take control of volume */ /* Do successive operation until requested byte count or EOF */ bytesLeft = maxBytes; /* init number remaining */ blkNum = pRawFd->rawFdNewPtr / cbioParams.bytesPerBlk; /* init current block number */ for (; bytesLeft > 0 && blkNum < cbioParams.nBlocks; bytesLeft -= nBytes, pBuf += nBytes, pRawFd->rawFdNewPtr += nBytes, blkNum += numBlks) { nBytes = 0; /* init individual read count */ /* Do direct whole-block read if possible */ if (((ULONG)bytesLeft >= cbioParams.bytesPerBlk) && (pRawFd->rawFdNewPtr %cbioParams.bytesPerBlk == 0)) { /* Calculate number of blocks to access */ numBlks = bytesLeft / cbioParams.bytesPerBlk; nBytes = numBlks * cbioParams.bytesPerBlk; /* Adjust if read would extend past end of device */ numBlks = min ((ULONG)numBlks, (cbioParams.nBlocks - blkNum)); /* execute operation on blocks */ if (rawFsBlkRdWr (pVd, blkNum, numBlks, pBuf, rw) != OK) { /* read error */ if (bytesLeft == maxBytes) /* if nothing read yet */ { semGive (pVd->rawVdSemId); semGive (pRawFd->rawFdSemId); return (ERROR); /* indicate error */ } else break; /* return number read OK */ } pRawFd->rawFdCookie = (cookie_t) NULL; /* invalidate cookie */ continue; /* goto partial blocks access */ } else /* if not whole-block transfer*/ { /* partial blocks access */ numBlks = 1; offset = pRawFd->rawFdNewPtr % cbioParams.bytesPerBlk; nBytes = min ((ULONG)bytesLeft, cbioParams.bytesPerBlk - offset); if ( rawFsBtRdWr (pVd, blkNum, offset, pBuf, nBytes, rw, & pRawFd->rawFdCookie) != OK) { /* probably nothing done */ if (bytesLeft == maxBytes) { /* if nothing read yet */ semGive (pVd->rawVdSemId); semGive (pRawFd->rawFdSemId); return (ERROR); } else break; /* return number read OK */ } } } /* end for */ semGive (pVd->rawVdSemId); /* release volume */ semGive (pRawFd->rawFdSemId); /* release fd */ return (maxBytes - bytesLeft); /* number of bytes processed */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -