static NTSTATUS PvfsQueryFilePositionInfo( PPVFS_IRP_CONTEXT pIrpContext ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PIRP pIrp = pIrpContext->pIrp; PPVFS_CCB pCcb = NULL; PFILE_POSITION_INFORMATION pFileInfo = NULL; IRP_ARGS_QUERY_SET_INFORMATION Args = pIrpContext->pIrp->Args.QuerySetInformation; off_t CurrentOffset = 0; /* Sanity checks */ ntError = PvfsAcquireCCB(pIrp->FileHandle, &pCcb); BAIL_ON_NT_STATUS(ntError); BAIL_ON_INVALID_PTR(Args.FileInformation, ntError); ntError = PvfsAccessCheckAnyFileHandle( pCcb, (FILE_READ_DATA|FILE_WRITE_DATA)); BAIL_ON_NT_STATUS(ntError); if (Args.Length < sizeof(*pFileInfo)) { ntError = STATUS_BUFFER_TOO_SMALL; BAIL_ON_NT_STATUS(ntError); } pFileInfo = (PFILE_POSITION_INFORMATION)Args.FileInformation; /* Real work starts here */ /* Position */ ntError = PvfsSysLseek(pCcb->fd, 0, SEEK_CUR, &CurrentOffset); BAIL_ON_NT_STATUS(ntError); pFileInfo->CurrentByteOffset = CurrentOffset; pIrp->IoStatusBlock.BytesTransferred = sizeof(*pFileInfo); ntError = STATUS_SUCCESS; cleanup: if (pCcb) { PvfsReleaseCCB(pCcb); } return ntError; error: goto cleanup; }
NTSTATUS PvfsSysWrite( PPVFS_CCB pCcb, PVOID pBuffer, ULONG pBufLen, PULONG64 pOffset, PULONG pBytesWritten ) { NTSTATUS ntError = STATUS_SUCCESS; ssize_t bytesWritten = 0; int unixerr = 0; /* Use pwrite() if we have an offset, otherwise fall back to write() */ if (pOffset) { off_t offset = 0; bytesWritten = pwrite(pCcb->fd, pBuffer, pBufLen, (off_t)*pOffset); if (bytesWritten > 0) { /* pread() and pwrite() don't update the file offset */ ntError = PvfsSysLseek(pCcb->fd, bytesWritten, SEEK_CUR, &offset); BAIL_ON_NT_STATUS(ntError); } } else { bytesWritten = write(pCcb->fd, pBuffer, pBufLen); } if (bytesWritten == -1) { PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError); } *pBytesWritten = (ULONG)bytesWritten; cleanup: return ntError; error: goto cleanup; }
static NTSTATUS PvfsReadFileWithContext( PVOID pContext ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_PENDING_READ pReadCtx = (PPVFS_PENDING_READ)pContext; PIRP pIrp = pReadCtx->pIrpContext->pIrp; PPVFS_CCB pCcb = pReadCtx->pCcb; ULONG bufLen = pIrp->Args.ReadWrite.Length; ULONG Key = pIrp->Args.ReadWrite.Key ? *pIrp->Args.ReadWrite.Key : 0; ULONG totalBytesRead = 0; ULONG64 Offset = 0; BOOLEAN bMutexLocked = FALSE; /* Enter critical region - ReadFile() needs to fill the buffer atomically while it may take several read() calls */ LWIO_LOCK_MUTEX(bMutexLocked, &pCcb->ControlBlock); if (pIrp->Args.ReadWrite.ByteOffset) { Offset = *pIrp->Args.ReadWrite.ByteOffset; } else { off_t offset = 0; ntError = PvfsSysLseek(pCcb->fd, 0, SEEK_CUR, &offset); BAIL_ON_NT_STATUS(ntError); Offset = offset; } ntError = PvfsCheckLockedRegion( pCcb, PVFS_OPERATION_READ, Key, Offset, bufLen); BAIL_ON_NT_STATUS(ntError); if (pReadCtx->pZctContext) { ntError = PvfsDoZctReadIo(pReadCtx->pZctContext, pIrp->Args.ReadWrite.Zct, bufLen, Offset, &totalBytesRead); BAIL_ON_NT_STATUS(ntError); } else { ntError = PvfsDoReadIo(pCcb, pIrp->Args.ReadWrite.Buffer, bufLen, Offset, &totalBytesRead); BAIL_ON_NT_STATUS(ntError); } /* Can only get here is the I/O was completed successfully */ pIrp->IoStatusBlock.BytesTransferred = totalBytesRead; if (bufLen == 0) { ntError = STATUS_SUCCESS; } else { ntError = (totalBytesRead > 0) ? STATUS_SUCCESS : STATUS_END_OF_FILE; } if (pReadCtx->pZctContext && (STATUS_SUCCESS == ntError)) { /* Save the ZCT context for complete */ pIrp->Args.ReadWrite.ZctCompletionContext = pReadCtx->pZctContext; /* Cannot fail */ ntError = PvfsListAddTail( pCcb->pZctContextList, &pReadCtx->pZctContext->CcbLinks); BAIL_ON_NT_STATUS(ntError); pReadCtx->pZctContext = NULL; } pCcb->ChangeEvent |= FILE_NOTIFY_CHANGE_LAST_ACCESS; cleanup: LWIO_UNLOCK_MUTEX(bMutexLocked, &pCcb->ControlBlock); return ntError; error: goto cleanup; }