dll: FspFileSystem*DirectoryBuffer API's

This commit is contained in:
Bill Zissimopoulos 2017-01-26 16:30:33 -08:00
parent 4fe72ab332
commit 55a7864173
9 changed files with 740 additions and 0 deletions

View File

@ -182,6 +182,7 @@
</ClCompile>
<ClCompile Include="..\..\..\tst\memfs\memfs.cpp" />
<ClCompile Include="..\..\..\tst\winfsp-tests\create-test.c" />
<ClCompile Include="..\..\..\tst\winfsp-tests\dirbuf-test.c" />
<ClCompile Include="..\..\..\tst\winfsp-tests\dirctl-test.c" />
<ClCompile Include="..\..\..\tst\winfsp-tests\eventlog-test.c" />
<ClCompile Include="..\..\..\tst\winfsp-tests\flush-test.c" />

View File

@ -76,6 +76,9 @@
<ClCompile Include="..\..\..\tst\winfsp-tests\oplock-test.c">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="..\..\..\tst\winfsp-tests\dirbuf-test.c">
<Filter>Source</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">

View File

@ -31,6 +31,7 @@
<ClInclude Include="..\..\src\shared\minimal.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\dll\dirbuf.c" />
<ClCompile Include="..\..\src\dll\eventlog.c" />
<ClCompile Include="..\..\src\dll\fuse\fuse.c" />
<ClCompile Include="..\..\src\dll\fuse\fuse_intf.c" />

View File

@ -103,6 +103,9 @@
<ClCompile Include="..\..\src\dll\fuse\fuse_intf.c">
<Filter>Source\fuse</Filter>
</ClCompile>
<ClCompile Include="..\..\src\dll\dirbuf.c">
<Filter>Source</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\src\dll\library.def">

View File

@ -1293,6 +1293,19 @@ FSP_API NTSTATUS FspFileSystemCanReplaceReparsePoint(
FSP_API BOOLEAN FspFileSystemAddStreamInfo(FSP_FSCTL_STREAM_INFO *StreamInfo,
PVOID Buffer, ULONG Length, PULONG PBytesTransferred);
/*
* Directory buffering
*/
FSP_API BOOLEAN FspFileSystemAcquireDirectoryBuffer(PVOID *PDirBuffer,
BOOLEAN Reset, PNTSTATUS PResult);
FSP_API BOOLEAN FspFileSystemFillDirectoryBuffer(PVOID *PDirBuffer,
FSP_FSCTL_DIR_INFO *DirInfo, PNTSTATUS PResult);
FSP_API VOID FspFileSystemReleaseDirectoryBuffer(PVOID *PDirBuffer);
FSP_API VOID FspFileSystemReadDirectoryBuffer(PVOID *PDirBuffer,
PWSTR Marker,
PVOID Buffer, ULONG Length, PULONG PBytesTransferred);
FSP_API VOID FspFileSystemDeleteDirectoryBuffer(PVOID *PDirBuffer);
/*
* Security
*/

392
src/dll/dirbuf.c Normal file
View File

@ -0,0 +1,392 @@
/**
* @file dll/dirbuf.c
*
* @copyright 2015-2017 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this file in
* accordance with the commercial license agreement provided with the
* software.
*/
#include <dll/library.h>
#define RETURN(R, B) \
do \
{ \
if (0 != PResult) \
*PResult = R; \
return B; \
} while (0,0)
typedef struct
{
SRWLOCK Lock;
ULONG Capacity, LoMark, HiMark;
PUINT8 Buffer;
} FSP_FILE_SYSTEM_DIRECTORY_BUFFER;
static int FspFileSystemDirectoryBufferFileNameCmp(PWSTR a, int alen, PWSTR b, int blen)
{
int len, res;
if (-1 == alen)
alen = (int)lstrlenW(a);
if (-1 == blen)
blen = (int)lstrlenW(b);
len = alen < blen ? alen : blen;
/* order "." and ".." first */
switch (alen)
{
case 1:
if (L'.' == a[0])
a = L"\1";
break;
case 2:
if (L'.' == a[0] && L'.' == a[1])
a = L"\1\1";
break;
}
/* order "." and ".." first */
switch (blen)
{
case 1:
if (L'.' == b[0])
b = L"\1";
break;
case 2:
if (L'.' == b[0] && L'.' == b[1])
b = L"\1\1";
break;
}
res = invariant_wcsncmp(a, b, len);
if (0 == res)
res = alen - blen;
return res;
}
/*
* Binary search
* "I wish I had the standard library!"
*/
static BOOLEAN FspFileSystemSearchDirectoryBuffer(FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer,
PWSTR Marker, int MarkerLen, PULONG PIndexNum)
{
PULONG Index = (PULONG)(DirBuffer->Buffer + DirBuffer->HiMark);
ULONG Count = (DirBuffer->Capacity - DirBuffer->HiMark) / sizeof(ULONG);
FSP_FSCTL_DIR_INFO *DirInfo;
int Lo = 0, Hi = Count - 1, Mi;
int CmpResult;
while (Lo <= Hi)
{
Mi = (unsigned)(Lo + Hi) >> 1;
DirInfo = (PVOID)(DirBuffer->Buffer + Index[Mi]);
CmpResult = FspFileSystemDirectoryBufferFileNameCmp(
DirInfo->FileNameBuf, (DirInfo->Size - sizeof *DirInfo) / sizeof(WCHAR),
Marker, MarkerLen);
if (0 > CmpResult)
Lo = Mi + 1;
else if (0 < CmpResult)
Hi = Mi - 1;
else
{
*PIndexNum = Mi;
return TRUE;
}
}
*PIndexNum = Lo;
return FALSE;
}
/*
* Quick sort
* "I wish I had the standard library!"
*
* Based on Sedgewick's Algorithms in C++; multiple editions.
*
* Implements a non-recursive quicksort with tail-end recursion eliminated
* and median-of-three partitioning.
*/
#define less(a, b) FspFileSystemDirectoryBufferLess(Buffer, a, b)
#define exch(a, b) { ULONG t = a; a = b; b = t; }
#define compexch(a, b) if (less(b, a)) exch(a, b)
#define push(i) (stack[stackpos++] = (i))
#define pop() (stack[--stackpos])
static __forceinline
int FspFileSystemDirectoryBufferLess(PUINT8 Buffer, int a, int b)
{
FSP_FSCTL_DIR_INFO *DirInfoA = (FSP_FSCTL_DIR_INFO *)(Buffer + a);
FSP_FSCTL_DIR_INFO *DirInfoB = (FSP_FSCTL_DIR_INFO *)(Buffer + b);
return 0 > FspFileSystemDirectoryBufferFileNameCmp(
DirInfoA->FileNameBuf, (DirInfoA->Size - sizeof *DirInfoA) / sizeof(WCHAR),
DirInfoB->FileNameBuf, (DirInfoB->Size - sizeof *DirInfoB) / sizeof(WCHAR));
}
static __forceinline
int FspFileSystemPartitionDirectoryBuffer(PUINT8 Buffer, PULONG Index, int l, int r)
{
int i = l - 1, j = r;
ULONG v = Index[r];
for (;;)
{
while (less(Index[++i], v))
;
while (less(v, Index[--j]))
if (j == l)
break;
if (i >= j)
break;
exch(Index[i], Index[j]);
}
exch(Index[i], Index[r]);
return i;
}
static VOID FspFileSystemQSortDirectoryBuffer(PUINT8 Buffer, PULONG Index, int l, int r)
{
int stack[64], stackpos = 0;
int i;
for (;;)
{
while (r > l)
{
#if 0
exch(Index[(l + r) / 2], Index[r - 1]);
compexch(Index[l], Index[r - 1]);
compexch(Index[l], Index[r]);
compexch(Index[r - 1], Index[r]);
i = FspFileSystemPartitionDirectoryBuffer(Buffer, Index, l + 1, r - 1);
#else
i = FspFileSystemPartitionDirectoryBuffer(Buffer, Index, l, r);
#endif
if (i - l > r - i)
{
push(l); push(i - 1);
l = i + 1;
}
else
{
push(i + 1); push(r);
r = i - 1;
}
}
if (0 == stackpos)
break;
r = pop(); l = pop();
}
}
#undef push
#undef pop
#undef less
#undef compexch
#undef exch
static inline VOID FspFileSystemSortDirectoryBuffer(FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer)
{
PUINT8 Buffer = DirBuffer->Buffer;
PULONG Index = (PULONG)(DirBuffer->Buffer + DirBuffer->HiMark);
ULONG Count = (DirBuffer->Capacity - DirBuffer->HiMark) / sizeof(ULONG);
FspFileSystemQSortDirectoryBuffer(Buffer, Index, 0, Count - 1);
}
FSP_API BOOLEAN FspFileSystemAcquireDirectoryBuffer(PVOID *PDirBuffer,
BOOLEAN Reset, PNTSTATUS PResult)
{
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = *PDirBuffer;
MemoryBarrier();
if (0 == DirBuffer)
{
static SRWLOCK CreateLock = SRWLOCK_INIT;
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *NewDirBuffer;
NewDirBuffer = MemAlloc(sizeof *NewDirBuffer);
if (0 == NewDirBuffer)
RETURN(STATUS_INSUFFICIENT_RESOURCES, FALSE);
memset(NewDirBuffer, 0, sizeof *NewDirBuffer);
InitializeSRWLock(&NewDirBuffer->Lock);
AcquireSRWLockExclusive(&NewDirBuffer->Lock);
AcquireSRWLockExclusive(&CreateLock);
DirBuffer = *PDirBuffer;
MemoryBarrier();
if (0 == DirBuffer)
*PDirBuffer = DirBuffer = NewDirBuffer;
ReleaseSRWLockExclusive(&CreateLock);
if (DirBuffer == NewDirBuffer)
RETURN(STATUS_SUCCESS, TRUE);
ReleaseSRWLockExclusive(&NewDirBuffer->Lock);
MemFree(NewDirBuffer);
}
if (Reset)
{
AcquireSRWLockExclusive(&DirBuffer->Lock);
DirBuffer->LoMark = 0;
DirBuffer->HiMark = DirBuffer->Capacity;
RETURN(STATUS_SUCCESS, TRUE);
}
RETURN(STATUS_SUCCESS, FALSE);
}
FSP_API BOOLEAN FspFileSystemFillDirectoryBuffer(PVOID *PDirBuffer,
FSP_FSCTL_DIR_INFO *DirInfo, PNTSTATUS PResult)
{
/* assume that FspFileSystemAcquireDirectoryBuffer has been called */
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = *PDirBuffer;
ULONG Capacity, LoMark, HiMark;
PUINT8 Buffer;
if (0 == DirInfo)
RETURN(STATUS_INVALID_PARAMETER, FALSE);
for (;;)
{
LoMark = DirBuffer->LoMark;
HiMark = DirBuffer->HiMark;
Buffer = DirBuffer->Buffer;
if (FspFileSystemAddDirInfo(DirInfo,
Buffer,
HiMark > sizeof(ULONG) ? HiMark - sizeof(ULONG)/*space for new index entry*/ : HiMark,
&LoMark))
{
HiMark -= sizeof(ULONG);
*(PULONG)(Buffer + HiMark) = DirBuffer->LoMark;
DirBuffer->LoMark = LoMark;
DirBuffer->HiMark = HiMark;
RETURN (STATUS_SUCCESS, TRUE);
}
if (0 == Buffer)
{
Buffer = MemAlloc(Capacity = 512);
if (0 == Buffer)
RETURN(STATUS_INSUFFICIENT_RESOURCES, FALSE);
HiMark = Capacity;
}
else
{
Buffer = MemRealloc(Buffer, Capacity = DirBuffer->Capacity * 2);
if (0 == Buffer)
RETURN(STATUS_INSUFFICIENT_RESOURCES, FALSE);
ULONG IndexSize = DirBuffer->Capacity - HiMark;
ULONG NewHiMark = Capacity - IndexSize;
memmove(Buffer + NewHiMark, Buffer + HiMark, IndexSize);
HiMark = NewHiMark;
}
DirBuffer->Capacity = Capacity;
DirBuffer->LoMark = LoMark;
DirBuffer->HiMark = HiMark;
DirBuffer->Buffer = Buffer;
}
}
FSP_API VOID FspFileSystemReleaseDirectoryBuffer(PVOID *PDirBuffer)
{
/* assume that FspFileSystemAcquireDirectoryBuffer has been called */
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = *PDirBuffer;
FspFileSystemSortDirectoryBuffer(DirBuffer);
ReleaseSRWLockExclusive(&DirBuffer->Lock);
}
FSP_API VOID FspFileSystemReadDirectoryBuffer(PVOID *PDirBuffer,
PWSTR Marker,
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
{
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = *PDirBuffer;
MemoryBarrier();
if (0 != DirBuffer)
{
AcquireSRWLockShared(&DirBuffer->Lock);
PULONG Index = (PULONG)(DirBuffer->Buffer + DirBuffer->HiMark);
ULONG Count = (DirBuffer->Capacity - DirBuffer->HiMark) / sizeof(ULONG);
ULONG IndexNum;
FSP_FSCTL_DIR_INFO *DirInfo;
if (0 == Marker)
IndexNum = 0;
else
{
FspFileSystemSearchDirectoryBuffer(DirBuffer,
Marker, lstrlenW(Marker),
&IndexNum);
IndexNum++;
}
for (; IndexNum < Count; IndexNum++)
{
DirInfo = (PVOID)(DirBuffer->Buffer + Index[IndexNum]);
if (!FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred))
{
ReleaseSRWLockShared(&DirBuffer->Lock);
return;
}
}
ReleaseSRWLockShared(&DirBuffer->Lock);
}
FspFileSystemAddDirInfo(0, Buffer, Length, PBytesTransferred);
}
FSP_API VOID FspFileSystemDeleteDirectoryBuffer(PVOID *PDirBuffer)
{
FSP_FILE_SYSTEM_DIRECTORY_BUFFER *DirBuffer = *PDirBuffer;
MemoryBarrier();
if (0 != DirBuffer)
{
MemFree(DirBuffer->Buffer);
MemFree(DirBuffer);
*PDirBuffer = 0;
}
}

View File

@ -126,6 +126,10 @@ static inline void *MemAlloc(size_t Size)
{
return HeapAlloc(GetProcessHeap(), 0, Size);
}
static inline void *MemRealloc(void *Pointer, size_t Size)
{
return HeapReAlloc(GetProcessHeap(), 0, Pointer, Size);
}
static inline void MemFree(void *Pointer)
{
if (0 != Pointer)

View File

@ -0,0 +1,322 @@
/**
* @file dirbuf-test.c
*
* @copyright 2015-2017 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this file in
* accordance with the commercial license agreement provided with the
* software.
*/
#include <winfsp/winfsp.h>
#include <tlib/testsuite.h>
#include <time.h>
#include "winfsp-tests.h"
static void dirbuf_empty_test(void)
{
PVOID DirBuffer = 0;
NTSTATUS Result;
BOOLEAN Success;
UINT8 Buffer[64];
ULONG BytesTransferred;
BytesTransferred = 0;
FspFileSystemReadDirectoryBuffer(&DirBuffer, 0, Buffer, sizeof Buffer, &BytesTransferred);
ASSERT(sizeof(UINT16) == BytesTransferred);
Result = STATUS_UNSUCCESSFUL;
Success = FspFileSystemAcquireDirectoryBuffer(&DirBuffer, FALSE, &Result);
ASSERT(Success);
ASSERT(STATUS_SUCCESS == Result);
FspFileSystemReleaseDirectoryBuffer(&DirBuffer);
BytesTransferred = 0;
FspFileSystemReadDirectoryBuffer(&DirBuffer, 0, Buffer, sizeof Buffer, &BytesTransferred);
ASSERT(sizeof(UINT16) == BytesTransferred);
Result = STATUS_UNSUCCESSFUL;
Success = FspFileSystemAcquireDirectoryBuffer(&DirBuffer, FALSE, &Result);
ASSERT(!Success);
ASSERT(STATUS_SUCCESS == Result);
BytesTransferred = 0;
FspFileSystemReadDirectoryBuffer(&DirBuffer, 0, Buffer, sizeof Buffer, &BytesTransferred);
ASSERT(sizeof(UINT16) == BytesTransferred);
Result = STATUS_UNSUCCESSFUL;
Success = FspFileSystemAcquireDirectoryBuffer(&DirBuffer, TRUE, &Result);
ASSERT(Success);
ASSERT(STATUS_SUCCESS == Result);
FspFileSystemReleaseDirectoryBuffer(&DirBuffer);
BytesTransferred = 0;
FspFileSystemReadDirectoryBuffer(&DirBuffer, 0, Buffer, sizeof Buffer, &BytesTransferred);
ASSERT(sizeof(UINT16) == BytesTransferred);
FspFileSystemDeleteDirectoryBuffer(&DirBuffer);
FspFileSystemDeleteDirectoryBuffer(&DirBuffer);
}
static void dirbuf_dots_test(void)
{
PVOID DirBuffer = 0;
NTSTATUS Result;
BOOLEAN Success;
union
{
UINT8 B[sizeof(FSP_FSCTL_DIR_INFO) + MAX_PATH * sizeof(WCHAR)];
FSP_FSCTL_DIR_INFO D;
} DirInfoBuf;
FSP_FSCTL_DIR_INFO *DirInfo = &DirInfoBuf.D, *DirInfoEnd;
UINT8 Buffer[1024];
ULONG Length, BytesTransferred;
WCHAR CurrFileName[MAX_PATH];
ULONG N;
Length = sizeof Buffer;
Result = STATUS_UNSUCCESSFUL;
Success = FspFileSystemAcquireDirectoryBuffer(&DirBuffer, FALSE, &Result);
ASSERT(Success);
ASSERT(STATUS_SUCCESS == Result);
memset(&DirInfoBuf, 0, sizeof DirInfoBuf);
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + 1 * sizeof(WCHAR));
DirInfo->FileNameBuf[0] = L'.';
Success = FspFileSystemFillDirectoryBuffer(&DirBuffer, DirInfo, &Result);
ASSERT(Success);
ASSERT(STATUS_SUCCESS == Result);
memset(&DirInfoBuf, 0, sizeof DirInfoBuf);
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + 1 * sizeof(WCHAR));
DirInfo->FileNameBuf[0] = L' ';
Success = FspFileSystemFillDirectoryBuffer(&DirBuffer, DirInfo, &Result);
ASSERT(Success);
ASSERT(STATUS_SUCCESS == Result);
memset(&DirInfoBuf, 0, sizeof DirInfoBuf);
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + 2 * sizeof(WCHAR));
DirInfo->FileNameBuf[0] = L'.';
DirInfo->FileNameBuf[1] = L'.';
Success = FspFileSystemFillDirectoryBuffer(&DirBuffer, DirInfo, &Result);
ASSERT(Success);
ASSERT(STATUS_SUCCESS == Result);
FspFileSystemReleaseDirectoryBuffer(&DirBuffer);
BytesTransferred = 0;
FspFileSystemReadDirectoryBuffer(&DirBuffer, 0, Buffer, Length, &BytesTransferred);
N = 0;
for (
DirInfo = (PVOID)Buffer, DirInfoEnd = (PVOID)(Buffer + BytesTransferred);
DirInfoEnd > DirInfo && 0 != DirInfo->Size;
DirInfo = (PVOID)((PUINT8)DirInfo + FSP_FSCTL_DEFAULT_ALIGN_UP(DirInfo->Size)), N++)
{
memcpy(CurrFileName, DirInfo->FileNameBuf, DirInfo->Size - sizeof *DirInfo);
CurrFileName[(DirInfo->Size - sizeof *DirInfo) / sizeof(WCHAR)] = L'\0';
if (0 == N)
ASSERT(0 == wcscmp(CurrFileName, L"."));
else if (1 == N)
ASSERT(0 == wcscmp(CurrFileName, L".."));
else if (2 == N)
ASSERT(0 == wcscmp(CurrFileName, L" "));
}
ASSERT(DirInfoEnd > DirInfo);
ASSERT(0 == DirInfo->Size);
ASSERT(N == 3);
FspFileSystemDeleteDirectoryBuffer(&DirBuffer);
}
static void dirbuf_fill_dotest(unsigned seed, ULONG Count)
{
PVOID DirBuffer = 0;
NTSTATUS Result;
BOOLEAN Success;
union
{
UINT8 B[sizeof(FSP_FSCTL_DIR_INFO) + MAX_PATH * sizeof(WCHAR)];
FSP_FSCTL_DIR_INFO D;
} DirInfoBuf;
FSP_FSCTL_DIR_INFO *DirInfo = &DirInfoBuf.D, *DirInfoEnd;
PUINT8 Buffer;
ULONG Length, BytesTransferred;
WCHAR CurrFileName[MAX_PATH], PrevFileName[MAX_PATH];
ULONG DotIndex = Count / 3, DotDotIndex = Count / 3 * 2;
WCHAR Marker[MAX_PATH];
ULONG N, MarkerIndex, MarkerLength;
srand(seed);
Length = Count * FSP_FSCTL_DEFAULT_ALIGN_UP(sizeof DirInfoBuf) + sizeof(UINT16);
Buffer = malloc(Length);
ASSERT(0 != Buffer);
Result = STATUS_UNSUCCESSFUL;
Success = FspFileSystemAcquireDirectoryBuffer(&DirBuffer, FALSE, &Result);
ASSERT(Success);
ASSERT(STATUS_SUCCESS == Result);
for (ULONG I = 0; Count > I; I++)
{
memset(&DirInfoBuf, 0, sizeof DirInfoBuf);
if (I == DotIndex)
{
N = 1;
DirInfo->FileNameBuf[0] = L'.';
}
else if (I == DotDotIndex)
{
N = 2;
DirInfo->FileNameBuf[0] = L'.';
DirInfo->FileNameBuf[1] = L'.';
}
else
{
N = 24 + rand() % (32 - 24);
for (ULONG J = 0; N > J; J++)
DirInfo->FileNameBuf[J] = 'A' + rand() % 26;
}
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + N * sizeof(WCHAR));
Success = FspFileSystemFillDirectoryBuffer(&DirBuffer, DirInfo, &Result);
ASSERT(Success);
ASSERT(STATUS_SUCCESS == Result);
}
FspFileSystemReleaseDirectoryBuffer(&DirBuffer);
MarkerIndex = rand() % Count;
BytesTransferred = 0;
FspFileSystemReadDirectoryBuffer(&DirBuffer, 0, Buffer, Length, &BytesTransferred);
N = 0;
PrevFileName[0] = L'\0';
for (
DirInfo = (PVOID)Buffer, DirInfoEnd = (PVOID)(Buffer + BytesTransferred);
DirInfoEnd > DirInfo && 0 != DirInfo->Size;
DirInfo = (PVOID)((PUINT8)DirInfo + FSP_FSCTL_DEFAULT_ALIGN_UP(DirInfo->Size)), N++)
{
memcpy(CurrFileName, DirInfo->FileNameBuf, DirInfo->Size - sizeof *DirInfo);
CurrFileName[(DirInfo->Size - sizeof *DirInfo) / sizeof(WCHAR)] = L'\0';
if (0 == N)
ASSERT(0 == wcscmp(CurrFileName, L"."));
else if (1 == N)
ASSERT(0 == wcscmp(CurrFileName, L".."));
else
ASSERT(0 != wcscmp(CurrFileName, L".") && 0 != wcscmp(CurrFileName, L".."));
//ASSERT(wcscmp(PrevFileName, CurrFileName) <= 0);
/* filenames are random enought that should not happen in practice */
ASSERT(wcscmp(PrevFileName, CurrFileName) < 0);
memcpy(PrevFileName, CurrFileName, sizeof CurrFileName);
if (N == MarkerIndex)
{
memcpy(Marker, CurrFileName, sizeof CurrFileName);
MarkerLength = (ULONG)((PUINT8)DirInfo + FSP_FSCTL_DEFAULT_ALIGN_UP(DirInfo->Size) - Buffer);
}
}
ASSERT(DirInfoEnd > DirInfo);
ASSERT(0 == DirInfo->Size);
ASSERT(N == Count);
BytesTransferred = 0;
FspFileSystemReadDirectoryBuffer(&DirBuffer, Marker, Buffer, Length, &BytesTransferred);
N = 0;
PrevFileName[0] = L'\0';
for (
DirInfo = (PVOID)Buffer, DirInfoEnd = (PVOID)(Buffer + BytesTransferred);
DirInfoEnd > DirInfo && 0 != DirInfo->Size;
DirInfo = (PVOID)((PUINT8)DirInfo + FSP_FSCTL_DEFAULT_ALIGN_UP(DirInfo->Size)), N++)
{
memcpy(CurrFileName, DirInfo->FileNameBuf, DirInfo->Size - sizeof *DirInfo);
CurrFileName[(DirInfo->Size - sizeof *DirInfo) / sizeof(WCHAR)] = L'\0';
ASSERT(0 != wcscmp(CurrFileName, Marker));
//ASSERT(wcscmp(PrevFileName, CurrFileName) <= 0);
/* filenames are random enought that should not happen in practice */
ASSERT(wcscmp(PrevFileName, CurrFileName) < 0);
memcpy(PrevFileName, CurrFileName, sizeof CurrFileName);
}
ASSERT(DirInfoEnd > DirInfo);
ASSERT(0 == DirInfo->Size);
ASSERT(N == Count - MarkerIndex - 1);
BytesTransferred = 0;
FspFileSystemReadDirectoryBuffer(&DirBuffer, 0, Buffer, MarkerLength, &BytesTransferred);
N = 0;
PrevFileName[0] = L'\0';
for (
DirInfo = (PVOID)Buffer, DirInfoEnd = (PVOID)(Buffer + BytesTransferred);
DirInfoEnd > DirInfo && 0 != DirInfo->Size;
DirInfo = (PVOID)((PUINT8)DirInfo + FSP_FSCTL_DEFAULT_ALIGN_UP(DirInfo->Size)), N++)
{
memcpy(CurrFileName, DirInfo->FileNameBuf, DirInfo->Size - sizeof *DirInfo);
CurrFileName[(DirInfo->Size - sizeof *DirInfo) / sizeof(WCHAR)] = L'\0';
if (N == MarkerIndex)
ASSERT(0 == wcscmp(CurrFileName, Marker));
else
ASSERT(0 != wcscmp(CurrFileName, Marker));
//ASSERT(wcscmp(PrevFileName, CurrFileName) <= 0);
/* filenames are random enought that should not happen in practice */
ASSERT(wcscmp(PrevFileName, CurrFileName) < 0);
memcpy(PrevFileName, CurrFileName, sizeof CurrFileName);
}
ASSERT(DirInfoEnd <= DirInfo);
ASSERT(N == MarkerIndex + 1);
FspFileSystemDeleteDirectoryBuffer(&DirBuffer);
free(Buffer);
}
static void dirbuf_fill_test(void)
{
unsigned seed = (unsigned)time(0);
dirbuf_fill_dotest(1485473509, 10);
for (ULONG I = 0; 10000 > I; I++)
dirbuf_fill_dotest(seed + I, 10);
for (ULONG I = 0; 1000 > I; I++)
dirbuf_fill_dotest(seed + I, 100);
for (ULONG I = 0; 100 > I; I++)
dirbuf_fill_dotest(seed + I, 1000);
for (ULONG I = 0; 10 > I; I++)
dirbuf_fill_dotest(seed + I, 10000);
}
void dirbuf_tests(void)
{
TEST(dirbuf_empty_test);
TEST(dirbuf_dots_test);
TEST(dirbuf_fill_test);
}

View File

@ -182,6 +182,7 @@ int main(int argc, char *argv[])
TESTSUITE(posix_tests);
TESTSUITE(eventlog_tests);
TESTSUITE(path_tests);
TESTSUITE(dirbuf_tests);
TESTSUITE(mount_tests);
TESTSUITE(timeout_tests);
TESTSUITE(memfs_tests);