📄 nfsdrv.c
字号:
nCacheRead = nfsFileRead (nfsFd->nfsDev->host, &nfsFd->fileHandle, nfsFd->fileCurByte, nfsCacheSize, nfsFd->cacheBuf, &nfsFd->fileAttr); if (nCacheRead < 0) { semGive (nfsFd->nfsFdSem); return (ERROR); } nfsFd->cacheCurByte = nfsFd->cacheBuf; /* update cache ptrs */ nfsFd->cacheBytesLeft = nCacheRead; nfsFd->cacheValid = TRUE; /* cache is valid */ } /* read as many bytes as possible from what's left in the cache, * up to the amount requested */ if (nfsFd->cacheBytesLeft > 0) { if (maxBytes - readCount < nfsFd->cacheBytesLeft) nRead = maxBytes - readCount; else nRead = nfsFd->cacheBytesLeft; /* copy bytes into user's buffer */ bcopy (nfsFd->cacheCurByte, (char *) ((int) buf + readCount), nRead); /* update file pointer */ status = nfsSeek (nfsFd, (int) nfsFd->fileCurByte + nRead); /* how many bytes have we read so far? */ readCount += nRead; } else break; /* we've hit the end of the file */ } /* while */ } /* else */ semGive (nfsFd->nfsFdSem); return (status == ERROR ? ERROR : readCount); }/********************************************************************************* nfsWrite - write bytes to remote file** nfsWrite copies the specified number of bytes from the buffer* to the nfs file. Bytes are written starting at the current file pointer.* The file pointer is updated to point immediately after the last* character that was written.** A cache is used for keeping nfs network reads and writes down to a minimum.* If all goes well, the entire buffer is written to the cache and/or actual* file.** Called only by the I/O system.** SIDE EFFECTS: moves file pointer** RETURNS:* Number of bytes written (error if != nBytes)* ERROR if nBytes < 0, or nfs write is not successful*/LOCAL int nfsWrite ( FAST NFS_FD *nfsFd, /* open file descriptor */ char *buf, /* buffer being written from */ FAST int nBytes /* number of bytes to write to file */ ) { FAST unsigned int nWrite; /* number of bytes to write */ FAST unsigned int newPos; /* new position of file pointer */ unsigned int cacheMargin; /* margin left in cache for writing */ int nCacheRead; /* number of bytes read into cache */ FAST char *pBuf = buf; /* ptr to spot in user's buffer */ FAST int writeCount = 0; /* number of bytes written so far */ /* check for valid number of bytes */ if (nBytes < 0) { errnoSet (S_nfsDrv_INVALID_NUMBER_OF_BYTES); return (ERROR); } /* if file opened for O_RDONLY, don't write */ if (nfsFd->mode == O_RDONLY) { errnoSet (S_nfsDrv_READ_ONLY_CANNOT_WRITE); return (ERROR); } semTake (nfsFd->nfsFdSem, WAIT_FOREVER); /* do the write, until entire buffer has been written out */ if (nfsCacheSize == 0) { writeCount = nfsFileWrite (nfsFd->nfsDev->host, &nfsFd->fileHandle, nfsFd->fileCurByte, (unsigned) nBytes, buf, &nfsFd->fileAttr); if (writeCount == ERROR) { semGive (nfsFd->nfsFdSem); return (ERROR); } /* where will the new file pointer be? */ newPos = nfsFd->fileCurByte + writeCount; /* update the file pointer. */ if (nfsSeek (nfsFd, (int) newPos) == ERROR) { semGive (nfsFd->nfsFdSem); return (ERROR); } } else { while (writeCount < nBytes) { /* fill cache before writing to it, keep cache in sync w/file */ if (!nfsFd->cacheValid) { if ((nBytes - writeCount) < nfsCacheSize) { nCacheRead = nfsFileRead (nfsFd->nfsDev->host, &nfsFd->fileHandle, nfsFd->fileCurByte, nfsCacheSize, nfsFd->cacheBuf, &nfsFd->fileAttr); if (nCacheRead < 0) { semGive (nfsFd->nfsFdSem); return (ERROR); } nfsFd->cacheBytesLeft = nCacheRead; } else { nfsFd->cacheBytesLeft = nfsCacheSize; } /* update cache pointers */ nfsFd->cacheCurByte = nfsFd->cacheBuf; nfsFd->cacheDirty = FALSE; nfsFd->cacheValid = TRUE; } /* margin allowable for writing */ cacheMargin = (unsigned) nfsFd->cacheBuf + nfsCacheSize - (unsigned) nfsFd->cacheCurByte; if (nBytes - writeCount < cacheMargin) nWrite = nBytes - writeCount; else nWrite = cacheMargin; /* copy the bytes into the cache */ bcopy (pBuf, nfsFd->cacheCurByte, (int) nWrite); if (nWrite > nfsFd->cacheBytesLeft) nfsFd->cacheBytesLeft = nWrite; /* cache has been written in, it is soiled */ nfsFd->cacheDirty = TRUE; /* what's the new position of the file pointer? */ newPos = nfsFd->fileCurByte + nWrite; /* if the new file pointer reaches past the end of the file, * the file has grown, update the size of the file */ if (newPos > nfsFd->fileAttr.size) nfsFd->fileAttr.size = newPos; /* update the file pointer. * any cache flushes will occur during the seek. */ if (nfsSeek (nfsFd, (int) newPos) == ERROR) { semGive (nfsFd->nfsFdSem); return (ERROR); } writeCount += nWrite; pBuf += nWrite; } /* while entire buffer has not been written */ } /* else */ semGive (nfsFd->nfsFdSem); return (writeCount); }/********************************************************************************* nfsIoctl - do device specific control function** Called only by the I/O system.** RETURNS: whatever the called function returns*/LOCAL int nfsIoctl ( FAST NFS_FD *nfsFd, /* open nfs file descriptor */ FAST int function, /* function code */ FAST int arg /* argument for function */ ) { FAST struct stat *pStat; int status = OK; switch (function) { case FIOSYNC: semTake (nfsFd->nfsFdSem, WAIT_FOREVER); if (nfsFd->cacheDirty) status = nfsCacheFlush (nfsFd); semGive (nfsFd->nfsFdSem); break; case FIOSEEK: status = nfsSeek (nfsFd, arg); break; case FIOWHERE: status = nfsFd->fileCurByte; break; case FIONREAD: *((int *) arg) = nfsFd->fileAttr.size - nfsFd->fileCurByte; break; case FIOREADDIR: /* read a directory entry */ status = nfsDirReadOne (nfsFd->nfsDev->host, &nfsFd->fileHandle, (DIR *) arg); break; case FIOFSTATGET: /* get status of a file */ pStat = (struct stat *) arg; /* get file attributes returned in pStat */ nfsFileAttrGet (&nfsFd->fileAttr, pStat); pStat->st_dev = (ULONG) nfsFd->nfsDev; break; case FIOFSTATFSGET: status = nfsFsAttrGet(nfsFd->nfsDev->host, &nfsFd->fileHandle, (struct statfs *)arg); break; case FIOGETFL: *((int *) arg) = nfsFd->mode; break; default: errnoSet (S_ioLib_UNKNOWN_REQUEST); status = ERROR; break; } return (status); }/********************************************************************************* nfsSeek - change file's current character position** This routine moves the file pointer by the offset to a new position.* If the new position moves the file pointer out of the range of what's* in the cache and the cache is dirty (i.e. the cache has been written* in), then the cache is written out to the nfs file and the cache is* marked as invalid. If the new position is beyond EOF, then an empty* area is created that will read as zeros.** Called only by the I/O system.** RETURNS: OK | ERROR*/LOCAL int nfsSeek ( FAST NFS_FD *nfsFd, FAST int newPos ) { FAST int interval; if (newPos < 0) return (ERROR); if (newPos == nfsFd->fileCurByte) return (OK); semTake (nfsFd->nfsFdSem, WAIT_FOREVER); if (nfsFd->cacheValid) /* if cache is valid, update cache pointer */ { /* how far will file pointer be moved? */ interval = newPos - nfsFd->fileCurByte; /* if the new pointer precedes what's in the cache, * OR if the new ptr points past what's in the cache, * OR if the new ptr points past the end of the valid cache bytes, * THEN the cache is no longer valid. * * NOTE: The cache is still valid if the new pointer points * IMMEDIATELY after the valid bytes in the cache, but still * hasn't reached the end of the cache buffer. The cache can * still be written to and should not be flushed until it is full * or the file is closed (a similar technique is used in some states * during drought conditions). */ if (((interval < 0) && (nfsFd->cacheCurByte + interval < nfsFd->cacheBuf)) || ((interval > 0) && (interval > nfsFd->cacheBytesLeft)) || ((nfsFd->cacheBuf + nfsCacheSize) <= (nfsFd->cacheCurByte + interval))) { /* if the new cache pointer goes out of range of the cache, * mark the cache as invalid, and flush if necessary. */ if (nfsFd->cacheDirty) if (nfsCacheFlush (nfsFd) == ERROR) { semGive (nfsFd->nfsFdSem); return (ERROR); } nfsFd->cacheValid = FALSE; nfsFd->cacheBytesLeft = 0; nfsFd->cacheCurByte = nfsFd->cacheBuf; nfsFd->cacheDirty = FALSE; } else { /* if the new position stays within range of the cache, * update the cache pointers. */ nfsFd->cacheCurByte += interval; nfsFd->cacheBytesLeft -= interval; } } nfsFd->fileCurByte = newPos; semGive (nfsFd->nfsFdSem); return (OK); }/********************************************************************************* nfsCacheFlush - flush the cache to the remote NFS file** Called only by the I/O system.** RETURNS: number of bytes written or ERROR*/LOCAL int nfsCacheFlush ( FAST NFS_FD *nfsFd ) { int nWrite; /* how many bytes are written with nfs? */ unsigned int offset;/* offset in the file where cache gets written */ unsigned int count; /* number of bytes to write with nfs */ unsigned int dist; /* distance between beginning of cache and current file * pointer (number of bytes) */ if (!nfsFd->cacheValid) { errnoSet (S_nfsDrv_FATAL_ERR_FLUSH_INVALID_CACHE); return (ERROR); } dist = nfsFd->cacheCurByte - nfsFd->cacheBuf; offset = nfsFd->fileCurByte - dist; count = dist + nfsFd->cacheBytesLeft; nWrite = nfsFileWrite (nfsFd->nfsDev->host, &nfsFd->fileHandle, offset, count, nfsFd->cacheBuf, &nfsFd->fileAttr); return (nWrite); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -