/* Editor Settings: expandtabs and use 4 spaces for indentation * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: * * -*- mode: c, c-basic-offset: 4 -*- */ /* * Copyright Likewise Software * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. You should have received a copy of the GNU General * Public License along with this program. If not, see * . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ /* * Copyright (C) Likewise Software. All rights reserved. * * Module Name: * * ioctlOpenFileInfo.c * * Abstract: * * Likewise Posix File System Driver (PVFS) * * Device I/O Control handler * Open File Information * * Authors: Gerald Carter */ #include "pvfs.h" /*********************************************************************** **********************************************************************/ static NTSTATUS PvfsFillOpenFileInfo( OUT PVOID pBuffer, IN ULONG BufLen, OUT PULONG BytesConsumed, IN ULONG Level ); NTSTATUS PvfsIoCtlOpenFileInfo( IN PPVFS_IRP_CONTEXT pIrpContext, IN PVOID InputBuffer, IN ULONG InputBufferLength, OUT PVOID OutputBuffer, IN OUT PULONG pOutputBufferLength ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PIO_OPEN_FILE_INFO_INPUT_BUFFER pOpenFileInfoInput = NULL; PPVFS_CCB pCcb = NULL; PIRP pIrp = pIrpContext->pIrp; ULONG BytesConsumed = 0; ntError = PvfsAcquireCCB(pIrp->FileHandle, &pCcb); BAIL_ON_NT_STATUS(ntError); /* Sanity checks */ BAIL_ON_INVALID_PTR(InputBuffer, ntError); BAIL_ON_INVALID_PTR(OutputBuffer, ntError); if (InputBufferLength < sizeof(IO_OPEN_FILE_INFO_INPUT_BUFFER)) { ntError = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntError); } pOpenFileInfoInput = (PIO_OPEN_FILE_INFO_INPUT_BUFFER)InputBuffer; switch(pOpenFileInfoInput->Level) { case 0: case 100: ntError = PvfsFillOpenFileInfo( OutputBuffer, *pOutputBufferLength, &BytesConsumed, pOpenFileInfoInput->Level); break; default: ntError = STATUS_INVALID_INFO_CLASS; break; } BAIL_ON_NT_STATUS(ntError); *pOutputBufferLength = BytesConsumed; cleanup: if (pCcb) { PvfsReleaseCCB(pCcb); } return ntError; error: goto cleanup; } /*********************************************************************** **********************************************************************/ static NTSTATUS PvfsOpenFileInfo( PVOID pKey, PVOID pData, PVOID pUserData, PBOOLEAN pbContinue ); static NTSTATUS PvfsFillOpenFileInfo( OUT PVOID pBuffer, IN ULONG BufLen, OUT PULONG pBytesConsumed, IN ULONG Level ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PVFS_OPEN_FILE_INFO OpenFileInfo = {0}; BOOLEAN bLocked = FALSE; LWIO_LOCK_RWMUTEX_SHARED(bLocked, &gFcbTable.rwLock); /* Setup the traversal structure. Pass in the PVOID output buffer we were originally given */ OpenFileInfo.Level = Level; OpenFileInfo.BytesAvailable = BufLen; OpenFileInfo.Offset = 0; OpenFileInfo.pData = pBuffer; OpenFileInfo.pPreviousEntry = NULL; ntError = LwRtlRBTreeTraverse( gFcbTable.pFcbTree, LWRTL_TREE_TRAVERSAL_TYPE_IN_ORDER, PvfsOpenFileInfo, &OpenFileInfo); BAIL_ON_NT_STATUS(ntError); *pBytesConsumed = BufLen - OpenFileInfo.BytesAvailable; cleanup: LWIO_UNLOCK_RWMUTEX(bLocked, &gFcbTable.rwLock); return ntError; error: goto cleanup; } /*********************************************************************** **********************************************************************/ static NTSTATUS PvfsFillOpenFileInfo0( PVOID pBuffer, ULONG BufferLength, PVOID pPreviousEntry, PPVFS_FCB pFcb, PULONG pBytesUsed ); static NTSTATUS PvfsFillOpenFileInfo100( PVOID pBuffer, ULONG BufferLength, PVOID pPreviousEntry, PPVFS_FCB pFcb, PULONG pBytesUsed ); static NTSTATUS PvfsOpenFileInfo( PVOID pKey, PVOID pData, PVOID pUserData, PBOOLEAN pbContinue ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_FCB pFcb = (PPVFS_FCB)pData; PPVFS_OPEN_FILE_INFO pOpenFileInfo = (PPVFS_OPEN_FILE_INFO)pUserData; ULONG BytesUsed = 0; switch(pOpenFileInfo->Level) { case 0: ntError = PvfsFillOpenFileInfo0( pOpenFileInfo->pData + pOpenFileInfo->Offset, pOpenFileInfo->BytesAvailable, pOpenFileInfo->pPreviousEntry, pFcb, &BytesUsed); break; case 100: ntError = PvfsFillOpenFileInfo100( pOpenFileInfo->pData + pOpenFileInfo->Offset, pOpenFileInfo->BytesAvailable, pOpenFileInfo->pPreviousEntry, pFcb, &BytesUsed); break; default: ntError = STATUS_INVALID_INFO_CLASS; } BAIL_ON_NT_STATUS(ntError); pOpenFileInfo->pPreviousEntry = pOpenFileInfo->pData + pOpenFileInfo->Offset; pOpenFileInfo->BytesAvailable -= BytesUsed; pOpenFileInfo->Offset += BytesUsed; *pbContinue = TRUE; cleanup: return ntError; error: *pbContinue = FALSE; goto cleanup; } /*********************************************************************** **********************************************************************/ static NTSTATUS PvfsFillOpenFileInfo0( PVOID pBuffer, ULONG BufferLength, PVOID pPreviousEntry, PPVFS_FCB pFcb, PULONG pBytesUsed ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PIO_OPEN_FILE_INFO_0 pInfo0 = (PIO_OPEN_FILE_INFO_0)pBuffer; PIO_OPEN_FILE_INFO_0 pPrev = (PIO_OPEN_FILE_INFO_0)pPreviousEntry; PWSTR pwszFilename = NULL; ULONG FilenameByteCount = 0; BOOLEAN bControlLocked = FALSE; BOOLEAN bCcbListLocked = FALSE; LWIO_LOCK_MUTEX(bControlLocked, &pFcb->ControlBlock); ntError = LwRtlWC16StringAllocateFromCString( &pwszFilename, pFcb->pszFilename); LWIO_UNLOCK_MUTEX(bControlLocked, &pFcb->ControlBlock); BAIL_ON_NT_STATUS(ntError); FilenameByteCount = (LwRtlWC16StringNumChars(pwszFilename)+1) * sizeof(WCHAR); if (BufferLength < (sizeof(IO_OPEN_FILE_INFO_0)+FilenameByteCount)) { ntError = STATUS_BUFFER_TOO_SMALL; BAIL_ON_NT_STATUS(ntError); } pInfo0->NextEntryOffset = 0; pInfo0->FileNameLength = FilenameByteCount; memcpy(pInfo0->pwszFileName, pwszFilename, FilenameByteCount); LWIO_LOCK_RWMUTEX_SHARED(bCcbListLocked, &pFcb->rwCcbLock); pInfo0->OpenHandleCount = PvfsListLength(pFcb->pCcbList); LWIO_UNLOCK_RWMUTEX(bCcbListLocked, &pFcb->rwCcbLock); if (pPrev) { pPrev->NextEntryOffset = PVFS_PTR_DIFF(pPreviousEntry, pBuffer); } *pBytesUsed = sizeof(IO_OPEN_FILE_INFO_0) + FilenameByteCount - sizeof(WCHAR); cleanup: LwRtlWC16StringFree(&pwszFilename); return ntError; error: goto cleanup; } /*********************************************************************** **********************************************************************/ static NTSTATUS PvfsFillOpenFileInfo100( PVOID pBuffer, ULONG BufferLength, PVOID pPreviousEntry, PPVFS_FCB pFcb, PULONG pBytesUsed ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PIO_OPEN_FILE_INFO_100 pInfo100 = (PIO_OPEN_FILE_INFO_100)pBuffer; PIO_OPEN_FILE_INFO_100 pPrev = (PIO_OPEN_FILE_INFO_100)pPreviousEntry; PWSTR pwszFilename = NULL; ULONG FilenameByteCount = 0; BOOLEAN bControlLocked = FALSE; BOOLEAN bCcbListLocked = FALSE; LWIO_LOCK_MUTEX(bControlLocked, &pFcb->ControlBlock); ntError = LwRtlWC16StringAllocateFromCString( &pwszFilename, pFcb->pszFilename); BAIL_ON_NT_STATUS(ntError); LWIO_UNLOCK_MUTEX(bControlLocked, &pFcb->ControlBlock); FilenameByteCount = (LwRtlWC16StringNumChars(pwszFilename)+1) * sizeof(WCHAR); if (BufferLength < (sizeof(IO_OPEN_FILE_INFO_100)+FilenameByteCount)) { ntError = STATUS_BUFFER_TOO_SMALL; BAIL_ON_NT_STATUS(ntError); } pInfo100->bDeleteOnClose = PvfsFcbIsPendingDelete(pFcb); pInfo100->NextEntryOffset = 0; pInfo100->FileNameLength = FilenameByteCount; memcpy(pInfo100->pwszFileName, pwszFilename, FilenameByteCount); LWIO_LOCK_RWMUTEX_SHARED(bCcbListLocked, &pFcb->rwCcbLock); pInfo100->OpenHandleCount = PvfsListLength(pFcb->pCcbList); LWIO_UNLOCK_RWMUTEX(bCcbListLocked, &pFcb->rwCcbLock); if (pPrev) { pPrev->NextEntryOffset = PVFS_PTR_DIFF(pPreviousEntry, pBuffer); } *pBytesUsed = sizeof(IO_OPEN_FILE_INFO_100) + FilenameByteCount - sizeof(WCHAR); cleanup: LWIO_UNLOCK_MUTEX(bControlLocked, &pFcb->ControlBlock); LwRtlWC16StringFree(&pwszFilename); return ntError; error: goto cleanup; } /* local variables: mode: c c-basic-offset: 4 indent-tabs-mode: nil tab-width: 4 end: */