static NTSTATUS PvfsNotifyAllocateFilter( PPVFS_NOTIFY_FILTER_RECORD *ppNotifyRecord, PPVFS_IRP_CONTEXT pIrpContext, PPVFS_CCB pCcb, FILE_NOTIFY_CHANGE NotifyFilter, BOOLEAN bWatchTree ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_NOTIFY_FILTER_RECORD pFilter = NULL; ntError = PvfsAllocateMemory( OUT_PPVOID(&pFilter), sizeof(PVFS_NOTIFY_FILTER_RECORD), TRUE); BAIL_ON_NT_STATUS(ntError); pFilter->pIrpContext = PvfsReferenceIrpContext(pIrpContext); pFilter->pCcb = PvfsReferenceCCB(pCcb); pFilter->NotifyFilter = NotifyFilter; pFilter->bWatchTree = bWatchTree; *ppNotifyRecord = pFilter; pFilter = NULL; cleanup: return ntError; error: goto cleanup; }
static NTSTATUS PvfsCreateSetAllocationContext( OUT PPVFS_PENDING_SET_ALLOCATION *ppSetAllocationContext, IN PPVFS_IRP_CONTEXT pIrpContext, IN PPVFS_CCB pCcb ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_PENDING_SET_ALLOCATION pSetAllocationCtx = NULL; ntError = PvfsAllocateMemory( (PVOID*)&pSetAllocationCtx, sizeof(PVFS_PENDING_READ)); BAIL_ON_NT_STATUS(ntError); pSetAllocationCtx->pIrpContext = PvfsReferenceIrpContext(pIrpContext); pSetAllocationCtx->pCcb = PvfsReferenceCCB(pCcb); *ppSetAllocationContext = pSetAllocationCtx; ntError = STATUS_SUCCESS; cleanup: return ntError; error: goto cleanup; }
NTSTATUS PvfsAllocateIrpContext( PPVFS_IRP_CONTEXT *ppIrpContext, PIRP pIrp ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_IRP_CONTEXT pIrpContext = NULL; *ppIrpContext = NULL; ntError = PvfsAllocateMemory((PVOID*)&pIrpContext, sizeof(PVFS_IRP_CONTEXT)); BAIL_ON_NT_STATUS(ntError); pthread_mutex_init(&pIrpContext->Mutex, NULL); pIrpContext->RefCount = 1; pIrpContext->Flags = PVFS_IRP_CTX_FLAG_NONE; pIrpContext->QueueType = PVFS_QUEUE_TYPE_NONE; pIrpContext->pFcb = NULL; pIrpContext->pIrp = pIrp; *ppIrpContext = pIrpContext; InterlockedIncrement(&gPvfsIrpContextCount); cleanup: return ntError; error: goto cleanup; }
static NTSTATUS PvfsCreateSetEndOfFileContext( OUT PPVFS_PENDING_SET_END_OF_FILE *ppSetEndOfFileContext, IN PPVFS_IRP_CONTEXT pIrpContext, IN PPVFS_CCB pCcb ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_PENDING_SET_END_OF_FILE pSetEndOfFileCtx = NULL; ntError = PvfsAllocateMemory( OUT_PPVOID(&pSetEndOfFileCtx), sizeof(PVFS_PENDING_SET_END_OF_FILE), TRUE); BAIL_ON_NT_STATUS(ntError); pSetEndOfFileCtx->pIrpContext = PvfsReferenceIrpContext(pIrpContext); pSetEndOfFileCtx->pCcb = PvfsReferenceCCB(pCcb); *ppSetEndOfFileContext = pSetEndOfFileCtx; ntError = STATUS_SUCCESS; cleanup: return ntError; error: goto cleanup; }
static NTSTATUS PvfsWildcardStackPush( IN OUT PLW_LIST_LINKS pStack, IN PSTR pszInputString, IN PSTR pszPattern ) { NTSTATUS ntError = STATUS_SUCCESS; PPVFS_WILDCARD_STATE_ENTRY pState = NULL; ntError = PvfsAllocateMemory(OUT_PPVOID(&pState), sizeof(*pState), TRUE); BAIL_ON_NT_STATUS(ntError); pState->pszInputString = pszInputString; pState->pszPattern = pszPattern; LwListInsertAfter(pStack, &pState->StackLinks); cleanup: return ntError; error: goto cleanup; }
NTSTATUS PvfsReallocateMemory( IN OUT PVOID *ppBuffer, IN DWORD dwNewSize ) { NTSTATUS ntError = STATUS_INSUFFICIENT_RESOURCES; PVOID pBuffer = *ppBuffer; PVOID pNewBuffer; if (dwNewSize <= 0) { return STATUS_INVALID_PARAMETER; } /* Check for a simple malloc() */ if (pBuffer == NULL) { return PvfsAllocateMemory(ppBuffer, dwNewSize); } if ((pNewBuffer = RtlMemoryRealloc(pBuffer, dwNewSize)) != NULL) { *ppBuffer = pNewBuffer; ntError = STATUS_SUCCESS; } return ntError; }
VOID PvfsNotifyScheduleFullReport( PPVFS_FCB pFcb, FILE_NOTIFY_CHANGE Filter, FILE_ACTION Action, PCSTR pszFilename ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_NOTIFY_REPORT_RECORD pReport = NULL; BAIL_ON_INVALID_PTR(pFcb, ntError); ntError = PvfsAllocateMemory( OUT_PPVOID(&pReport), sizeof(PVFS_NOTIFY_REPORT_RECORD), FALSE); BAIL_ON_NT_STATUS(ntError); pReport->pFcb = PvfsReferenceFCB(pFcb); pReport->Filter = Filter; pReport->Action = Action; ntError = LwRtlCStringDuplicate(&pReport->pszFilename, pszFilename); BAIL_ON_NT_STATUS(ntError); ntError = LwRtlQueueWorkItem( gPvfsDriverState.ThreadPool, PvfsNotifyProcessEvent, pReport, 0); BAIL_ON_NT_STATUS(ntError); error: if (!NT_SUCCESS(ntError)) { if (pReport) { PvfsNotifyFullReportCtxFree(&pReport); } } return; }
static NTSTATUS PvfsCreateReadContext( OUT PPVFS_PENDING_READ *ppReadContext, IN PPVFS_IRP_CONTEXT pIrpContext, IN PPVFS_CCB pCcb ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_PENDING_READ pReadCtx = NULL; ntError = PvfsAllocateMemory( OUT_PPVOID(&pReadCtx), sizeof(PVFS_PENDING_READ), FALSE); BAIL_ON_NT_STATUS(ntError); pReadCtx->pZctContext = NULL; pReadCtx->pIrpContext = PvfsReferenceIrpContext(pIrpContext); pReadCtx->pCcb = PvfsReferenceCCB(pCcb); if (IRP_ZCT_OPERATION_PREPARE == pIrpContext->pIrp->Args.ReadWrite.ZctOperation) { ntError = PvfsCreateZctContext( &pReadCtx->pZctContext, pIrpContext, pCcb); BAIL_ON_NT_STATUS(ntError); } *ppReadContext = pReadCtx; ntError = STATUS_SUCCESS; cleanup: return ntError; error: PvfsFreeReadContext(OUT_PPVOID(&pReadCtx)); goto cleanup; }
NTSTATUS PvfsAllocateCreateContext( OUT PPVFS_PENDING_CREATE *ppCreate, IN PPVFS_IRP_CONTEXT pIrpContext ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_PENDING_CREATE pCreateCtx = NULL; IRP_ARGS_CREATE Args = pIrpContext->pIrp->Args.Create; PIO_CREATE_SECURITY_CONTEXT pSecCtx = Args.SecurityContext; ntError = PvfsAllocateMemory( (PVOID*)&pCreateCtx, sizeof(PVFS_PENDING_CREATE)); BAIL_ON_NT_STATUS(ntError); ntError = PvfsCanonicalPathName( &pCreateCtx->pszOriginalFilename, Args.FileName); BAIL_ON_NT_STATUS(ntError); ntError = PvfsAllocateCCB(&pCreateCtx->pCcb); BAIL_ON_NT_STATUS(ntError); ntError = PvfsAcquireAccessToken(pCreateCtx->pCcb, pSecCtx); BAIL_ON_NT_STATUS(ntError); pCreateCtx->pIrpContext = PvfsReferenceIrpContext(pIrpContext); *ppCreate = pCreateCtx; pCreateCtx = NULL; cleanup: return ntError; error: PvfsFreeCreateContext((PVOID*)&pCreateCtx); goto cleanup; }
static NTSTATUS PvfsNotifyAllocateChangeBuffer( PPVFS_NOTIFY_FILTER_BUFFER pBuffer, ULONG Length ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; ntError = PvfsAllocateMemory((PVOID*)&pBuffer->pData, Length, TRUE); BAIL_ON_NT_STATUS(ntError); pBuffer->Length = Length; pBuffer->Status = STATUS_SUCCESS; pBuffer->Offset = 0; pBuffer->pNotify = NULL; cleanup: return ntError; error: goto cleanup; }
NTSTATUS PvfsCreateDirDoSysOpen( IN PVOID pContext ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_PENDING_CREATE pCreateContext = (PPVFS_PENDING_CREATE)pContext; PIRP pIrp = pCreateContext->pIrpContext->pIrp; IRP_ARGS_CREATE Args = pIrp->Args.Create; int fd = -1; int unixFlags = 0; PIO_CREATE_SECURITY_CONTEXT pSecCtx = Args.SecurityContext; FILE_CREATE_RESULT CreateResult = 0; IO_MATCH_FILE_SPEC FileSpec = {0}; WCHAR wszPattern[2] = {L'*', 0x0 }; PIO_SECURITY_CONTEXT_PROCESS_INFORMATION pProcess = NULL; PBOOLEAN pbEnableAbe = NULL; ULONG ulEcpSize = 0; pProcess = IoSecurityGetProcessInfo(pSecCtx); /* Fail any create that requires setting the security but doesn't have the Unix uid/gid information */ if ((pCreateContext->SetPropertyFlags & PVFS_SET_PROP_SECURITY) && (pProcess == NULL)) { ntError = STATUS_ACCESS_DENIED; BAIL_ON_NT_STATUS(ntError); } /* Do the open() */ ntError = MapPosixOpenFlags( &unixFlags, pCreateContext->GrantedAccess, Args); BAIL_ON_NT_STATUS(ntError); if (!pCreateContext->bFileExisted) { ntError = PvfsSysMkDir( pCreateContext->pszDiskFilename, (mode_t)gPvfsDriverConfig.CreateDirectoryMode); BAIL_ON_NT_STATUS(ntError); } /* Open the DIR* and then open a fd based on that */ ntError = PvfsAllocateMemory( (PVOID)&pCreateContext->pCcb->pDirContext, sizeof(PVFS_DIRECTORY_CONTEXT)); BAIL_ON_NT_STATUS(ntError); pCreateContext->pCcb->pszFilename = pCreateContext->pszDiskFilename; pCreateContext->pszDiskFilename = NULL; ntError = IoRtlEcpListFind( pIrp->Args.Create.EcpList, SRV_ECP_TYPE_ABE, OUT_PPVOID(&pbEnableAbe), &ulEcpSize); if (ntError != STATUS_NOT_FOUND) { BAIL_ON_NT_STATUS(ntError); if (ulEcpSize != sizeof(BOOLEAN)) { ntError = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntError); } if (*pbEnableAbe) { pCreateContext->pCcb->EcpFlags |= PVFS_ECP_ENABLE_ABE; } } do { ntError = PvfsSysOpen( &fd, pCreateContext->pCcb->pszFilename, 0, 0); } while (ntError == STATUS_MORE_PROCESSING_REQUIRED); BAIL_ON_NT_STATUS(ntError); /* Save our state */ pCreateContext->pCcb->fd = fd; pCreateContext->pCcb->ShareFlags = Args.ShareAccess; pCreateContext->pCcb->AccessGranted = pCreateContext->GrantedAccess; pCreateContext->pCcb->CreateOptions = Args.CreateOptions; ntError = PvfsAddCCBToFCB(pCreateContext->pFcb, pCreateContext->pCcb); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSaveFileDeviceInfo(pCreateContext->pCcb); BAIL_ON_NT_STATUS(ntError); if ((pCreateContext->SetPropertyFlags & PVFS_SET_PROP_SECURITY) && pSecCtx) { /* Unix Security */ ntError = PvfsSysChown( pCreateContext->pCcb, pProcess->Uid, pProcess->Gid); BAIL_ON_NT_STATUS(ntError); /* Security Descriptor */ ntError = PvfsCreateFileSecurity( pCreateContext->pCcb->pUserToken, pCreateContext->pCcb, Args.SecurityDescriptor, TRUE); BAIL_ON_NT_STATUS(ntError); } if ((pCreateContext->SetPropertyFlags & PVFS_SET_PROP_ATTRIB) && (Args.FileAttributes != 0)) { ntError = PvfsSetFileAttributes( pCreateContext->pCcb, Args.FileAttributes); BAIL_ON_NT_STATUS(ntError); } /* Save the delete-on-close flag to the FCB */ if (Args.CreateOptions & FILE_DELETE_ON_CLOSE) { LwRtlUnicodeStringInit(&FileSpec.Pattern, wszPattern); ntError = PvfsEnumerateDirectory(pCreateContext->pCcb, &FileSpec, 1, FALSE); if (ntError == STATUS_SUCCESS) { ntError = STATUS_DIRECTORY_NOT_EMPTY; BAIL_ON_NT_STATUS(ntError); } pCreateContext->pCcb->bPendingDeleteHandle = TRUE; } ntError = PvfsStoreCCB(pIrp->FileHandle, pCreateContext->pCcb); BAIL_ON_NT_STATUS(ntError); PvfsInitializeZctSupport(pCreateContext->pCcb, pIrp->FileHandle); CreateResult = PvfsSetCreateResult( Args.CreateDisposition, pCreateContext->bFileExisted, STATUS_SUCCESS); if (CreateResult == FILE_CREATED) { PvfsNotifyScheduleFullReport( pCreateContext->pCcb->pFcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_ADDED, pCreateContext->pCcb->pszFilename); } /* The CCB has been handled off to the FileHandle so make sure we don't think we still own it */ pCreateContext->pCcb = NULL; cleanup: pIrp->IoStatusBlock.CreateResult = CreateResult; return ntError; error: CreateResult = PvfsSetCreateResult( Args.CreateDisposition, pCreateContext->bFileExisted, ntError); if (fd != -1) { PSTR pszRemovePath = NULL; /* Pick up where we started the pathname */ pszRemovePath = pCreateContext->pszDiskFilename ? pCreateContext->pszDiskFilename : pCreateContext->pCcb->pszFilename; PvfsCleanupFailedCreate( fd, pszRemovePath, !pCreateContext->bFileExisted); } goto cleanup; }
NTSTATUS PvfsAllocateFCB( PPVFS_FCB *ppFcb ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_FCB pFcb = NULL; *ppFcb = NULL; ntError = PvfsAllocateMemory( OUT_PPVOID(&pFcb), sizeof(*pFcb), FALSE); BAIL_ON_NT_STATUS(ntError); PvfsInitializeCB(&pFcb->BaseControlBlock); /* Initialize mutexes and refcounts */ pthread_rwlock_init(&pFcb->rwScbLock, NULL); /* List of Notify requests */ ntError = PvfsListInit( &pFcb->pNotifyListIrp, PVFS_SCB_MAX_PENDING_NOTIFY, (PPVFS_LIST_FREE_DATA_FN)PvfsFreeNotifyRecord); BAIL_ON_NT_STATUS(ntError); ntError = PvfsListInit( &pFcb->pNotifyListBuffer, PVFS_SCB_MAX_PENDING_NOTIFY, (PPVFS_LIST_FREE_DATA_FN)PvfsFreeNotifyRecord); BAIL_ON_NT_STATUS(ntError); /* List of SCBs */ ntError = PvfsListInit( &pFcb->pScbList, 0, (PPVFS_LIST_FREE_DATA_FN)PvfsFCBFreeSCB); BAIL_ON_NT_STATUS(ntError); /* Miscellaneous */ PVFS_CLEAR_FILEID(pFcb->FileId); pFcb->LastWriteTime = 0; pFcb->OpenHandleCount = 0; pFcb->bDeleteOnClose = FALSE; pFcb->pParentFcb = NULL; pFcb->pszFilename = NULL; *ppFcb = pFcb; InterlockedIncrement(&gPvfsDriverState.Counters.Fcb); ntError = STATUS_SUCCESS; cleanup: return ntError; error: if (pFcb) { PvfsFreeFCB(pFcb); } goto cleanup; }
NTSTATUS PvfsAllocateCCB( PPVFS_CCB *ppCCB ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_CCB pCCB = NULL; *ppCCB = NULL; ntError = PvfsAllocateMemory( OUT_PPVOID(&pCCB), sizeof(PVFS_CCB), FALSE); BAIL_ON_NT_STATUS(ntError); InterlockedIncrement(&gPvfsDriverState.Counters.Ccb); /* Initialize mutexes and refcounts */ pthread_mutex_init(&pCCB->ControlBlock, NULL); PVFS_INIT_LINKS(&pCCB->ScbList); pCCB->OplockState = PVFS_OPLOCK_STATE_NONE; pCCB->CurrentLeaseState = IO_LEASE_STATE_NONE; pCCB->NewLeaseState = IO_LEASE_STATE_NONE; pCCB->fd = -1; PVFS_CLEAR_FILEID(pCCB->FileId); pCCB->pScb = NULL; pCCB->pwszShareName = NULL; pCCB->pDirContext = NULL; pCCB->pUserToken = NULL; pCCB->ChangeEvent = 0; pCCB->WriteCount = 0; pCCB->FileSize = 0; pCCB->AccessGranted = 0; pCCB->Flags = PVFS_CCB_FLAG_NONE; LwRtlZeroMemory(&pCCB->LockTable, sizeof(pCCB->LockTable)); ntError = PvfsListInit( &pCCB->pZctContextList, 0, /* no max size */ (PPVFS_LIST_FREE_DATA_FN)PvfsFreeZctContext); BAIL_ON_NT_STATUS(ntError); /* Add initial ref count */ pCCB->RefCount = 1; *ppCCB = pCCB; ntError = STATUS_SUCCESS; cleanup: return ntError; error: if (pCCB) { PvfsFreeCCB(pCCB); } goto cleanup; }
NTSTATUS PvfsCreateZctContext( OUT PPVFS_ZCT_CONTEXT *ppZctContext, IN PPVFS_IRP_CONTEXT pIrpContext, IN PPVFS_CCB pCcb ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_ZCT_CONTEXT pZctContext = NULL; PVFS_ZCT_MODE ZctMode = gPvfsDriverConfig.ZctMode; if (IRP_ZCT_OPERATION_PREPARE != pIrpContext->pIrp->Args.ReadWrite.ZctOperation) { ntError = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntError); } switch (ZctMode) { case PVFS_ZCT_MODE_MEMORY: #ifdef HAVE_SPLICE case PVFS_ZCT_MODE_SPLICE: #endif break; default: /* So the I/O does a backoff to non-ZCT */ ntError = STATUS_NOT_SUPPORTED; BAIL_ON_NT_STATUS(ntError); } ntError = PvfsAllocateMemory( (PVOID*)&pZctContext, sizeof(*pZctContext)); BAIL_ON_NT_STATUS(ntError); pZctContext->Mode = ZctMode; switch (pZctContext->Mode) { case PVFS_ZCT_MODE_MEMORY: ntError = PvfsAllocateMemory( OUT_PPVOID(&pZctContext->pBuffer), pIrpContext->pIrp->Args.ReadWrite.Length); BAIL_ON_NT_STATUS(ntError); break; #ifdef HAVE_SPLICE case PVFS_ZCT_MODE_SPLICE: if (pIrpContext->pIrp->Args.ReadWrite.Length > SPLICE_PIPE_BUFFER_SIZE) { ntError = STATUS_NOT_SUPPORTED; BAIL_ON_NT_STATUS(ntError); } // TODO: Convert to using pipe2 (Linux). ntError = PvfsSysPipe(pZctContext->PipeFds); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSysSetNonBlocking(pZctContext->PipeFds[0]); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSysSetNonBlocking(pZctContext->PipeFds[1]); BAIL_ON_NT_STATUS(ntError); break; #endif default: // can never happen ntError = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntError); } pZctContext->pCcb = PvfsReferenceCCB(pCcb); ntError = STATUS_SUCCESS; cleanup: *ppZctContext = pZctContext; return ntError; error: /* Backoff to non-ZCT because could not allocate resources */ ntError = STATUS_NOT_SUPPORTED; PvfsFreeZctContext(&pZctContext); goto cleanup; }
NTSTATUS PvfsEnumerateDirectory( PPVFS_CCB pCcb, PIO_MATCH_FILE_SPEC pFileSpec, LONG Count, BOOLEAN bRescan ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; DIR *pDir = NULL; struct dirent *pDirEntry = NULL; struct dirent dirEntry = { 0 }; PSTR pszPattern = NULL; BOOLEAN bCaseSensitive = FALSE; PSTR pszDiskFilename = NULL; PVFS_STAT Stat = { 0 }; PSTR pszResolvedDirname = NULL; PSTR pszResolvedFilename = NULL; if (Count == 0) { ntError = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntError); } ntError = AllocateCStringFileSpec(&pszPattern, pFileSpec); BAIL_ON_NT_STATUS(ntError); if (bRescan) { if (pCcb->pDirContext->pDir) { PvfsSysCloseDir(pCcb->pDirContext->pDir); } PvfsFreeDirectoryContext(pCcb->pDirContext); pCcb->pDirContext = NULL; ntError = PvfsAllocateMemory( (PVOID)&pCcb->pDirContext, sizeof(PVFS_DIRECTORY_CONTEXT), TRUE); BAIL_ON_NT_STATUS(ntError); pCcb->pDirContext->bScanned = FALSE; } if (!pCcb->pDirContext->bScanned) { if (!strchr(pszPattern, '?') && !strchr(pszPattern, '*')) { // A single file name match is the equivalent of a Windows Stat() ntError = PvfsLookupFile( &pszDiskFilename, &Stat, pCcb->pScb->pOwnerFcb->pszFilename, pszPattern, pFileSpec->Options & IO_NAME_OPTION_CASE_SENSITIVE); BAIL_ON_NT_STATUS(ntError); ntError = PvfsFileSplitPath( &pszResolvedDirname, &pszResolvedFilename, pszDiskFilename); BAIL_ON_NT_STATUS(ntError); if (IsSetFlag(pCcb->Flags, PVFS_CCB_FLAG_ENABLE_ABE)) { ntError = PvfsAccessCheckFileEnumerate( pCcb, pszResolvedFilename); BAIL_ON_NT_STATUS(ntError); } ntError = PvfsDirContextAddEntry( pCcb->pDirContext, pszResolvedFilename); BAIL_ON_NT_STATUS(ntError); pCcb->pDirContext->bScanned = TRUE; // Success goto cleanup; } else { // Prepare to enumerate the entire directory ntError = PvfsSysOpenDir( pCcb->pScb->pOwnerFcb->pszFilename, &pCcb->pDirContext->pDir); BAIL_ON_NT_STATUS(ntError); pCcb->pDirContext->bScanned = TRUE; } } /* Loop to read entries */ pDir = pCcb->pDirContext->pDir; /* -1 means to fill in whatever you can including current and parent directory entries */ if (Count == -1) { /* Always add '.' and '..' first if thet match */ if (PvfsWildcardMatch(".", pszPattern, FALSE)) { ntError = PvfsDirContextAddEntry(pCcb->pDirContext, "."); BAIL_ON_NT_STATUS(ntError); } if (PvfsWildcardMatch("..", pszPattern, FALSE)) { ntError = PvfsDirContextAddEntry(pCcb->pDirContext, ".."); BAIL_ON_NT_STATUS(ntError); } } /* Loop through directory entries */ for(ntError = PvfsSysReadDir(pDir, &dirEntry, &pDirEntry); pDirEntry && ((Count == -1) || (pCcb->pDirContext->dwNumEntries < Count)); ntError = PvfsSysReadDir(pDir, &dirEntry, &pDirEntry)) { /* First check the error return */ BAIL_ON_NT_STATUS(ntError); /* We've already added the "." and ".." directories */ if (RtlCStringIsEqual(pDirEntry->d_name, ".", FALSE) || RtlCStringIsEqual(pDirEntry->d_name, "..", FALSE)) { continue; } if (PvfsWildcardMatch(pDirEntry->d_name, pszPattern, bCaseSensitive)) { if (IsSetFlag(pCcb->Flags, PVFS_CCB_FLAG_ENABLE_ABE)) { ntError = PvfsAccessCheckFileEnumerate( pCcb, pDirEntry->d_name); if (ntError != STATUS_SUCCESS) { continue; } } ntError = PvfsDirContextAddEntry(pCcb->pDirContext, pDirEntry->d_name); BAIL_ON_NT_STATUS(ntError); } } /* Bail if there were no matches */ if (pCcb->pDirContext->dwNumEntries == 0) { ntError = STATUS_NO_SUCH_FILE; BAIL_ON_NT_STATUS(ntError); } cleanup: RtlCStringFree(&pszResolvedFilename); RtlCStringFree(&pszResolvedDirname); RtlCStringFree(&pszDiskFilename); RtlCStringFree(&pszPattern); return ntError; error: goto cleanup; }