static VOID PvfsFreeSetAllocationContext( IN OUT PVOID *ppContext ) { PPVFS_PENDING_SET_ALLOCATION pAllocationCtx = NULL; if (ppContext && ppContext) { pAllocationCtx = (PPVFS_PENDING_SET_ALLOCATION)(*ppContext); if (pAllocationCtx->pIrpContext) { PvfsReleaseIrpContext(&pAllocationCtx->pIrpContext); } if (pAllocationCtx->pCcb) { PvfsReleaseCCB(pAllocationCtx->pCcb); } PVFS_FREE(ppContext); } return; }
static VOID PvfsFreeSetEndOfFileContext( IN OUT PVOID *ppContext ) { PPVFS_PENDING_SET_END_OF_FILE pEoFCtx = NULL; if (ppContext && *ppContext) { pEoFCtx = (PPVFS_PENDING_SET_END_OF_FILE)(*ppContext); if (pEoFCtx->pIrpContext) { PvfsReleaseIrpContext(&pEoFCtx->pIrpContext); } if (pEoFCtx->pCcb) { PvfsReleaseCCB(pEoFCtx->pCcb); } PVFS_FREE(ppContext); } return; }
static VOID PvfsFreeFCB( PPVFS_FCB pFcb ) { if (pFcb) { LWIO_ASSERT(pFcb->BaseControlBlock.pBucket == NULL); LWIO_ASSERT(pFcb->BaseControlBlock.RefCount == 0); if (pFcb->pParentFcb) { PvfsReleaseFCB(&pFcb->pParentFcb); } RtlCStringFree(&pFcb->pszFilename); pthread_rwlock_destroy(&pFcb->rwScbLock); PvfsListDestroy(&pFcb->pScbList); PvfsListDestroy(&pFcb->pNotifyListIrp); PvfsListDestroy(&pFcb->pNotifyListBuffer); PvfsDestroyCB(&pFcb->BaseControlBlock); PVFS_FREE(&pFcb); InterlockedDecrement(&gPvfsDriverState.Counters.Fcb); } return; }
static VOID PvfsFreeIrpContext( PPVFS_IRP_CONTEXT *ppIrpContext ) { PPVFS_IRP_CONTEXT pIrpCtx = NULL; if (ppIrpContext && *ppIrpContext) { pIrpCtx = *ppIrpContext; if (pIrpCtx->pIrp && PvfsIrpContextCheckFlag(pIrpCtx, PVFS_IRP_CTX_FLAG_PENDED)) { pIrpCtx->pIrp->IoStatusBlock.Status = STATUS_FILE_CLOSED; PvfsAsyncIrpComplete(pIrpCtx); } if (pIrpCtx->pFcb) { PvfsReleaseFCB(&pIrpCtx->pFcb); } pthread_mutex_destroy(&pIrpCtx->Mutex); PVFS_FREE(ppIrpContext); InterlockedDecrement(&gPvfsIrpContextCount); } }
VOID PvfsFreeCreateContext( IN OUT PVOID *ppContext ) { PPVFS_PENDING_CREATE pCreateCtx = NULL; if (ppContext && *ppContext) { pCreateCtx = (PPVFS_PENDING_CREATE)*ppContext; if (pCreateCtx->pIrpContext) { PvfsReleaseIrpContext(&pCreateCtx->pIrpContext); } if (pCreateCtx->pCcb) { PvfsReleaseCCB(pCreateCtx->pCcb); } if (pCreateCtx->pFcb) { PvfsReleaseFCB(&pCreateCtx->pFcb); } RtlCStringFree(&pCreateCtx->pszDiskFilename); RtlCStringFree(&pCreateCtx->pszOriginalFilename); PVFS_FREE(ppContext); } return; }
VOID PvfsFreeNotifyRecord( PPVFS_NOTIFY_FILTER_RECORD *ppNotifyRecord ) { PPVFS_NOTIFY_FILTER_RECORD pFilter = NULL; if (ppNotifyRecord && *ppNotifyRecord) { pFilter = *ppNotifyRecord; if (pFilter->pIrpContext) { PvfsReleaseIrpContext(&pFilter->pIrpContext); } PvfsNotifyFreeChangeBuffer(&pFilter->Buffer); if (pFilter->pCcb) { PvfsReleaseCCB(pFilter->pCcb); } PVFS_FREE(ppNotifyRecord); } return; }
static VOID PvfsFreeReadContext( IN OUT PVOID *ppContext ) { PPVFS_PENDING_READ pReadCtx = NULL; if (ppContext && *ppContext) { pReadCtx = (PPVFS_PENDING_READ)(*ppContext); if (pReadCtx->pZctContext) { PvfsFreeZctContext(&pReadCtx->pZctContext); } if (pReadCtx->pIrpContext) { PvfsReleaseIrpContext(&pReadCtx->pIrpContext); } if (pReadCtx->pCcb) { PvfsReleaseCCB(pReadCtx->pCcb); } PVFS_FREE(ppContext); } return; }
VOID PvfsFreeZctContext( IN OUT PPVFS_ZCT_CONTEXT *ppZctContext ) { PPVFS_ZCT_CONTEXT pZctContext = *ppZctContext; // pZctContext->pCcb must be locked if the context // is in the CCB list of ZCT contexts. if (pZctContext) { switch (pZctContext->Mode) { case PVFS_ZCT_MODE_MEMORY: PVFS_FREE(&pZctContext->pBuffer); break; #ifdef HAVE_SPLICE case PVFS_ZCT_MODE_SPLICE: if (pZctContext->PipeFds[1] >= 0) { PvfsSysClose(pZctContext->PipeFds[1]); } if (pZctContext->PipeFds[0] >= 0) { PvfsSysClose(pZctContext->PipeFds[0]); } break; #endif default: // can never happen break; } if (pZctContext->pCcb) { PvfsReleaseCCB(pZctContext->pCcb); if (pZctContext->CcbLinks.Next) { PvfsListRemoveItem( pZctContext->pCcb->pZctContextList, &pZctContext->CcbLinks); } } PVFS_FREE(ppZctContext); } }
static VOID PvfsNotifyFreeChangeBuffer( PPVFS_NOTIFY_FILTER_BUFFER pBuffer ) { PVFS_FREE(&pBuffer->pData); PVFS_ZERO_MEMORY(pBuffer); }
NTSTATUS PvfsFreeCCB( PPVFS_CCB pCCB ) { LWIO_ASSERT(pCCB->RefCount == 0); if (pCCB->pScb) { PvfsRemoveCCBFromSCB(pCCB->pScb, pCCB); PvfsReleaseSCB(&pCCB->pScb); } if (pCCB->pDirContext) { PvfsFreeDirectoryContext(pCCB->pDirContext); } if (pCCB->pUserToken) { RtlReleaseAccessToken(&pCCB->pUserToken); pCCB->pUserToken = NULL; } PvfsListDestroy(&pCCB->pZctContextList); LwRtlWC16StringFree(&pCCB->pwszShareName); PVFS_FREE(&pCCB->LockTable.ExclusiveLocks.pLocks); PVFS_FREE(&pCCB->LockTable.SharedLocks.pLocks); pthread_mutex_destroy(&pCCB->ControlBlock); PVFS_FREE(&pCCB); InterlockedDecrement(&gPvfsDriverState.Counters.Ccb); return STATUS_SUCCESS; }
VOID PvfsFreeDirectoryContext( PPVFS_DIRECTORY_CONTEXT pDirCtx ) { int i = 0; if (!pDirCtx) { return; } for (i=0; i<pDirCtx->dwNumEntries; i++) { RtlCStringFree(&pDirCtx->pDirEntries[i].pszFilename); } PVFS_FREE(&pDirCtx->pDirEntries); PVFS_FREE(&pDirCtx); return; }
VOID PvfsListDestroy( PPVFS_LIST *ppList ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PPVFS_LIST pList = NULL; PLW_LIST_LINKS pData = NULL; if (ppList && *ppList) { pList = *ppList; while (!PvfsListIsEmpty(pList)) { pData = NULL; ntError = PvfsListRemoveHead(pList, &pData); /* Avoid an infinite loop in the case of an error. This means we may leak memory. */ BAIL_ON_NT_STATUS(ntError); if (pList->pfnFreeData) { pList->pfnFreeData((PVOID*)&pData); } else { PVFS_FREE(&pData); } } RTL_FREE(ppList); } cleanup: return; error: goto cleanup; }
static VOID PvfsNotifyFullReportCtxFree( PPVFS_NOTIFY_REPORT_RECORD *ppReport ) { PPVFS_NOTIFY_REPORT_RECORD pReport = NULL; if (ppReport && *ppReport) { pReport = (PPVFS_NOTIFY_REPORT_RECORD)*ppReport; if (pReport->pFcb) { PvfsReleaseFCB(&pReport->pFcb); } LwRtlCStringFree(&pReport->pszFilename); PVFS_FREE(ppReport); } return; }
BOOLEAN PvfsWildcardMatch( IN PSTR pszPathname, IN PSTR pszPattern, IN BOOLEAN bCaseSensitive ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PSTR pszString = NULL; PSTR pszMatch = NULL; PSTR pszPathUpper = NULL; PSTR pszPatternUpper = NULL; BOOLEAN bMatched = FALSE; /* Quick check for an exact match */ if (!strchr(pszPattern, '?') && !strchr(pszPattern, '*')) { return RtlCStringIsEqual(pszPathname, pszPattern, bCaseSensitive); } /* If we have a case insensitive search, upper case the Pathname and Pattern for easier comparison */ pszString = pszPathname; pszMatch = pszPattern; if (!bCaseSensitive) { ntError = RtlCStringDuplicate(&pszPathUpper, pszPathname); BAIL_ON_NT_STATUS(ntError); ntError = RtlCStringDuplicate(&pszPatternUpper, pszPattern); BAIL_ON_NT_STATUS(ntError); PvfsCStringUpper(pszPathUpper); PvfsCStringUpper(pszPatternUpper); pszString = pszPathUpper; pszMatch = pszPatternUpper; } /* Enter state machine */ for (/* already performed init */; PVFS_CSTRING_NON_NULL(pszString) && PVFS_CSTRING_NON_NULL(pszMatch); pszString++) { PVFS_WILDCARD_TYPE eState = 0; CHAR cSrc = '\0'; CHAR cMatch = '\0'; DWORD dwCount = 0; /* Save the current CHAR */ cSrc = *pszString; cMatch = *pszMatch; /* Consumes the pattern from pszMatch */ eState = NextMatchState(&pszMatch, &dwCount); switch (eState) { case PVFS_WILDCARD_TYPE_NONE: if (cSrc != cMatch) { ntError = STATUS_NO_MATCH; BAIL_ON_NT_STATUS(ntError); } break; case PVFS_WILDCARD_TYPE_SPLAT: { PSTR pszCursor = NULL; /* We are done if this is the last character in the pattern */ if (!PVFS_CSTRING_NON_NULL(pszMatch)) { pszString = NULL; goto cleanup; } /* If we don't find a match for the next character in the pattern, then fail */ if ((pszCursor = strchr(pszString, *pszMatch)) == NULL) { ntError = STATUS_NO_MATCH; BAIL_ON_NT_STATUS(ntError); } /* Have to consume at least one character here */ if (pszString == pszCursor) { ntError = STATUS_NO_MATCH; BAIL_ON_NT_STATUS(ntError); } /* Set to the previous character so that pszString is incremented properly next pass of the loop */ pszString = pszCursor-1; break; } case PVFS_WILDCARD_TYPE_SINGLE: { DWORD i = 0; /* Consume dwCount characters */ for (i=0; i<dwCount && PVFS_CSTRING_NON_NULL(pszString); i++, pszString++) { /* no loop body */; } if (*pszString == '\0') { /* backup so pszString incrent in outer loop works out */ pszString--; } break; } case PVFS_WILDCARD_TYPE_DOT: /* For now deal with the '.' as just another character */ if (cSrc != cMatch) { ntError = STATUS_NO_MATCH; BAIL_ON_NT_STATUS(ntError); } break; case PVFS_WILDCARD_TYPE_SPLAT_DOT: { PSTR pszCursor = NULL; /* Similar to "A*B" except we search for the '.' from the end. */ if ((pszCursor = strrchr(pszString, '.')) == NULL) { ntError = STATUS_NO_MATCH; BAIL_ON_NT_STATUS(ntError); } pszString = pszCursor; break; } case PVFS_WILDCARD_TYPE_SINGLE_DOT: { DWORD i = 0; /* We can match 0 - dwCount characters up to the last '.' This is really a hold over from DOS 8.3 filenames */ for (i=0; i<dwCount && PVFS_CSTRING_NON_NULL(pszString) && (*pszString != '.'); i++, pszString++) { /* no loop body */; } /* If we any path lefft, it better be on '.' for a match */ if (pszString && *pszString != '.') { ntError = STATUS_NO_MATCH; BAIL_ON_NT_STATUS(ntError); } break; } } } cleanup: /* We matched if pszString is empty AND either pszMatch is empty OR only contains wildcard characters */ if (!PVFS_CSTRING_NON_NULL(pszString) && (!PVFS_CSTRING_NON_NULL(pszMatch) || (!strchr(pszPattern, '?') && !strchr(pszPattern, '*')))) { bMatched = TRUE; } if (!bCaseSensitive) { PVFS_FREE(&pszPathUpper); PVFS_FREE(&pszPatternUpper); } /* If we have any string left to parse, we don't have a match */ return bMatched; error: goto cleanup; }
static NTSTATUS PvfsQueryFileFsVolInfo( PPVFS_IRP_CONTEXT pIrpContext ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PIRP pIrp = pIrpContext->pIrp; PPVFS_CCB pCcb = NULL; PFILE_FS_VOLUME_INFORMATION pFileInfo = NULL; IRP_ARGS_QUERY_SET_VOLUME_INFORMATION Args = pIrpContext->pIrp->Args.QuerySetVolumeInformation; PWSTR pwszVolumeName = NULL; PCSTR pszVolName = "LIKEWISE"; size_t VolNameLenBytes = RtlCStringNumChars(pszVolName) * sizeof(WCHAR); PVFS_STAT stat = { 0 }; /* Sanity checks */ ntError = PvfsAcquireCCB(pIrp->FileHandle, &pCcb); BAIL_ON_NT_STATUS(ntError); /* not sure exact access rights to check for here */ ntError = PvfsAccessCheckFileHandle(pCcb, FILE_READ_ATTRIBUTES); BAIL_ON_NT_STATUS(ntError); BAIL_ON_INVALID_PTR(Args.FsInformation, ntError); if (Args.Length < sizeof(*pFileInfo) + VolNameLenBytes) { ntError = STATUS_BUFFER_TOO_SMALL; BAIL_ON_NT_STATUS(ntError); } pFileInfo = (PFILE_FS_VOLUME_INFORMATION)Args.FsInformation; /* Real work starts here */ ntError = PvfsSysFstat(pCcb->fd, &stat); BAIL_ON_NT_STATUS(ntError); ntError = PvfsUnixToWinTime(&pFileInfo->VolumeCreationTime, stat.s_crtime); BAIL_ON_NT_STATUS(ntError); pFileInfo->VolumeSerialNumber = 0x009a9a03; pFileInfo->SupportsObjects = FALSE; ntError = RtlWC16StringAllocateFromCString(&pwszVolumeName, pszVolName); BAIL_ON_NT_STATUS(ntError); pFileInfo->VolumeLabelLength = VolNameLenBytes; memcpy(pFileInfo->VolumeLabel, pwszVolumeName, VolNameLenBytes); pIrp->IoStatusBlock.BytesTransferred = sizeof(*pFileInfo); ntError = STATUS_SUCCESS; cleanup: if (pCcb) { PvfsReleaseCCB(pCcb); } PVFS_FREE(&pwszVolumeName); return ntError; error: goto cleanup; }
BOOLEAN PvfsWildcardMatch( IN PSTR pszPathname, IN PSTR pszPattern, IN BOOLEAN bCaseSensitive ) { NTSTATUS ntError = STATUS_SUCCESS; PSTR pszString = NULL; PSTR pszMatch = NULL; PSTR pszPathUpper = NULL; PSTR pszPatternUpper = NULL; BOOLEAN bMatched = FALSE; LW_LIST_LINKS Stack; // Quick check for an exact match if (!strchr(pszPattern, '?') && !strchr(pszPattern, '*')) { return RtlCStringIsEqual(pszPathname, pszPattern, bCaseSensitive); } // If we have a case insensitive search, upper case the Pathname // and Pattern for easier comparison pszString = pszPathname; pszMatch = pszPattern; if (!bCaseSensitive) { ntError = RtlCStringDuplicate(&pszPathUpper, pszPathname); BAIL_ON_NT_STATUS(ntError); ntError = RtlCStringDuplicate(&pszPatternUpper, pszPattern); BAIL_ON_NT_STATUS(ntError); PvfsCStringUpper(pszPathUpper); PvfsCStringUpper(pszPatternUpper); pszString = pszPathUpper; pszMatch = pszPatternUpper; } // Enter state machine LwListInit(&Stack); reset_state: while (PVFS_CSTRING_NON_NULL(pszString) && PVFS_CSTRING_NON_NULL(pszMatch)) { PVFS_WILDCARD_TYPE eState = 0; CHAR cSrc = '\0'; CHAR cMatch = '\0'; DWORD dwCount = 0; // Save the current CHAR cSrc = *pszString; cMatch = *pszMatch; // Certain characters should never match and hence allow us to filter // certain file patterns if (cSrc == PVFS_STREAM_DELIMINATOR_C) { bMatched = FALSE; goto cleanup; } // Consumes the pattern from pszMatch eState = NextMatchState(&pszMatch, &dwCount); switch (eState) { case PVFS_WILDCARD_TYPE_NONE: if (cSrc != cMatch) { ntError = STATUS_NO_MATCH; pszString = NULL; } else { pszString++; } break; case PVFS_WILDCARD_TYPE_SPLAT: { // We are done if this is the last character in the pattern if (!PVFS_CSTRING_NON_NULL(pszMatch)) { pszString = NULL; } else { // Be greedy - Consume as much of the string using the '*' // as possible. This will require a stack in order to backtrack // on a failure. pszString = PvfsWildcardEatString(pszString, pszMatch); if (!pszString) { ntError = STATUS_NO_MATCH; } else { // Add next character past "String" match and the previously // match "Pattern" state (so we pick up the '*' when we pop // the stack ntError = PvfsWildcardStackPush( &Stack, pszString+1, pszMatch-1); BAIL_ON_NT_STATUS(ntError); } } break; } case PVFS_WILDCARD_TYPE_SINGLE: { DWORD i = 0; // Consume dwCount characters for (i=0; (i<dwCount) && PVFS_CSTRING_NON_NULL(pszString); i++, pszString++) { // no loop body ; } break; } case PVFS_WILDCARD_TYPE_DOT: // For now deal with the '.' as just another character if (cSrc != cMatch) { ntError = STATUS_NO_MATCH; pszString = NULL; } else { pszString++; } break; case PVFS_WILDCARD_TYPE_SPLAT_DOT: { PSTR pszCursor = NULL; // Similar to "A*B" except we search for the '.' from the end if ((pszCursor = strrchr(pszString, '.')) == NULL) { ntError = STATUS_NO_MATCH; pszString = NULL; } else { pszString = pszCursor + 1; } break; } case PVFS_WILDCARD_TYPE_SINGLE_DOT: { DWORD i = 0; // We can match 0 - dwCount characters up to the last '.' // This is really a hold over from DOS 8.3 filenames for (i=0; i<dwCount && PVFS_CSTRING_NON_NULL(pszString) && (*pszString != '.'); i++, pszString++) { // no loop body ; } // If we any path left, it better be on '.' for a match if (*pszString == '.') { pszString++; } else { ntError = STATUS_NO_MATCH; pszString = NULL; } break; } } // end of switch {...} } // end of for {...} // We matched if pszString is empty AND either pszMatch is empty // OR only contains wildcard characters if ((ntError == STATUS_SUCCESS) && !PVFS_CSTRING_NON_NULL(pszString) && (!PVFS_CSTRING_NON_NULL(pszMatch) || PvfsCStringOnlyContainsChars(pszMatch, "?*"))) { bMatched = TRUE; } else if (!LwListIsEmpty(&Stack)) { // Pop back to the earlier state, consume one character (*from '*') // and try another path ntError = PvfsWildcardStackPop(&Stack, &pszString, &pszMatch); BAIL_ON_NT_STATUS(ntError); pszString++; goto reset_state; } cleanup: PvfsWildcardStackDestroy(&Stack); if (!bCaseSensitive) { PVFS_FREE(&pszPathUpper); PVFS_FREE(&pszPatternUpper); } // If we have any string left to parse, we don't have a match return bMatched; error: goto cleanup; }
static NTSTATUS PvfsQueryFileFsAttribInfo( PPVFS_IRP_CONTEXT pIrpContext ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PIRP pIrp = pIrpContext->pIrp; PPVFS_CCB pCcb = NULL; PFILE_FS_ATTRIBUTE_INFORMATION pFileInfo = NULL; IRP_ARGS_QUERY_SET_VOLUME_INFORMATION Args = pIrpContext->pIrp->Args.QuerySetVolumeInformation; PWSTR pwszFsName = NULL; size_t FsNameLenBytes = RtlCStringNumChars(PVFS_FS_NAME) * sizeof(WCHAR); PVFS_STATFS StatFs = {0}; ULONG FsAttributeSet = PVFS_FILE_SYSTEM_ATTRIBUTES; /* Sanity checks */ ntError = PvfsAcquireCCB(pIrp->FileHandle, &pCcb); BAIL_ON_NT_STATUS(ntError); /* not sure exact access rights to check for here */ ntError = PvfsAccessCheckFileHandle(pCcb, FILE_READ_ATTRIBUTES); BAIL_ON_NT_STATUS(ntError); BAIL_ON_INVALID_PTR(Args.FsInformation, ntError); if (Args.Length < sizeof(*pFileInfo) + FsNameLenBytes) { ntError = STATUS_BUFFER_TOO_SMALL; BAIL_ON_NT_STATUS(ntError); } pFileInfo = (PFILE_FS_ATTRIBUTE_INFORMATION)Args.FsInformation; /* Real work starts here */ ntError = PvfsSysFstatFs(pCcb, &StatFs); BAIL_ON_NT_STATUS(ntError); ntError = RtlWC16StringAllocateFromCString(&pwszFsName, PVFS_FS_NAME); BAIL_ON_NT_STATUS(ntError); pFileInfo->FileSystemAttributes = FsAttributeSet; pFileInfo->MaximumComponentNameLength = StatFs.MaximumNameLength; pFileInfo->FileSystemNameLength = FsNameLenBytes; memcpy(pFileInfo->FileSystemName, pwszFsName, FsNameLenBytes); pIrp->IoStatusBlock.BytesTransferred = sizeof(*pFileInfo); ntError = STATUS_SUCCESS; cleanup: if (pCcb) { PvfsReleaseCCB(pCcb); } PVFS_FREE(&pwszFsName); return ntError; error: goto cleanup; }