Files
orbithub/third_party/FreeRDP/winpr/libwinpr/file/test/TestFileFindFirstFile.c

361 lines
9.2 KiB
C

#include <stdio.h>
#include <winpr/crt.h>
#include <winpr/handle.h>
#include <winpr/file.h>
#include <winpr/path.h>
#include <winpr/tchar.h>
#include <winpr/collections.h>
#include <winpr/windows.h>
static const CHAR testFile1A[] = "TestFile1A";
static BOOL create_fileA(const char* FilePath)
{
HANDLE hdl = CreateFileA(FilePath, GENERIC_ALL, 0, nullptr, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, nullptr);
if (hdl == INVALID_HANDLE_VALUE)
return FALSE;
(void)CloseHandle(hdl);
return TRUE;
}
static BOOL create_fileW(const WCHAR* FilePath)
{
HANDLE hdl = CreateFileW(FilePath, GENERIC_ALL, 0, nullptr, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, nullptr);
if (hdl == INVALID_HANDLE_VALUE)
return FALSE;
(void)CloseHandle(hdl);
return TRUE;
}
static BOOL create_layout_files(size_t level, const char* BasePath, wArrayList* files)
{
for (size_t x = 0; x < 10; x++)
{
CHAR FilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
strncpy(FilePath, BasePath, ARRAYSIZE(FilePath));
CHAR name[64] = WINPR_C_ARRAY_INIT;
(void)_snprintf(name, ARRAYSIZE(name), "%zd-TestFile%zd", level, x);
NativePathCchAppendA(FilePath, PATHCCH_MAX_CCH, name);
if (create_fileA(FilePath))
ArrayList_Append(files, FilePath);
}
return TRUE;
}
static BOOL create_layout_directories(size_t level, size_t max_level, const char* BasePath,
wArrayList* files)
{
if (level >= max_level)
return TRUE;
CHAR FilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
strncpy(FilePath, BasePath, ARRAYSIZE(FilePath));
PathCchConvertStyleA(FilePath, ARRAYSIZE(FilePath), PATH_STYLE_NATIVE);
if (!winpr_PathMakePath(FilePath, nullptr))
return FALSE;
ArrayList_Append(files, FilePath);
if (!create_layout_files(level + 1, BasePath, files))
return FALSE;
for (size_t x = 0; x < 10; x++)
{
CHAR CurFilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
strncpy(CurFilePath, FilePath, ARRAYSIZE(CurFilePath));
PathCchConvertStyleA(CurFilePath, ARRAYSIZE(CurFilePath), PATH_STYLE_NATIVE);
CHAR name[64] = WINPR_C_ARRAY_INIT;
(void)_snprintf(name, ARRAYSIZE(name), "%zd-TestPath%zd", level, x);
NativePathCchAppendA(CurFilePath, PATHCCH_MAX_CCH, name);
if (!create_layout_directories(level + 1, max_level, CurFilePath, files))
return FALSE;
}
return TRUE;
}
static BOOL create_layout(const char* BasePath, wArrayList* files)
{
CHAR BasePathNative[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
memcpy(BasePathNative, BasePath, sizeof(BasePathNative));
PathCchConvertStyleA(BasePathNative, ARRAYSIZE(BasePathNative), PATH_STYLE_NATIVE);
return create_layout_directories(0, 3, BasePathNative, files);
}
static void cleanup_layout(const char* BasePath)
{
winpr_RemoveDirectory_RecursiveA(BasePath);
}
static BOOL find_first_file_success(const char* FilePath)
{
BOOL rc = FALSE;
WIN32_FIND_DATAA FindData = WINPR_C_ARRAY_INIT;
HANDLE hFind = FindFirstFileA(FilePath, &FindData);
if (hFind == INVALID_HANDLE_VALUE)
{
printf("FindFirstFile failure: %s (INVALID_HANDLE_VALUE -1)\n", FilePath);
goto fail;
}
printf("FindFirstFile: %s\n", FindData.cFileName);
if (strcmp(FindData.cFileName, testFile1A) != 0)
{
printf("FindFirstFile failure: Expected: %s, Actual: %s\n", testFile1A, FindData.cFileName);
goto fail;
}
rc = TRUE;
fail:
if (hFind != INVALID_HANDLE_VALUE)
FindClose(hFind);
return rc;
}
static BOOL list_directory_dot(const char* BasePath, wArrayList* files)
{
BOOL rc = FALSE;
CHAR BasePathDot[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
memcpy(BasePathDot, BasePath, ARRAYSIZE(BasePathDot));
PathCchConvertStyleA(BasePathDot, ARRAYSIZE(BasePathDot), PATH_STYLE_NATIVE);
NativePathCchAppendA(BasePathDot, PATHCCH_MAX_CCH, ".");
WIN32_FIND_DATAA FindData = WINPR_C_ARRAY_INIT;
HANDLE hFind = FindFirstFileA(BasePathDot, &FindData);
if (hFind == INVALID_HANDLE_VALUE)
return FALSE;
size_t count = 0;
do
{
count++;
if (strcmp(FindData.cFileName, ".") != 0)
goto fail;
} while (FindNextFile(hFind, &FindData));
rc = TRUE;
fail:
FindClose(hFind);
if (count != 1)
return FALSE;
return rc;
}
static BOOL list_directory_star(const char* BasePath, wArrayList* files)
{
CHAR BasePathDot[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
memcpy(BasePathDot, BasePath, ARRAYSIZE(BasePathDot));
PathCchConvertStyleA(BasePathDot, ARRAYSIZE(BasePathDot), PATH_STYLE_NATIVE);
NativePathCchAppendA(BasePathDot, PATHCCH_MAX_CCH, "*");
WIN32_FIND_DATAA FindData = WINPR_C_ARRAY_INIT;
HANDLE hFind = FindFirstFileA(BasePathDot, &FindData);
if (hFind == INVALID_HANDLE_VALUE)
return FALSE;
size_t count = 0;
size_t dotcount = 0;
size_t dotdotcount = 0;
do
{
if (strcmp(FindData.cFileName, ".") == 0)
dotcount++;
else if (strcmp(FindData.cFileName, "..") == 0)
dotdotcount++;
else
count++;
} while (FindNextFile(hFind, &FindData));
FindClose(hFind);
const char sep = PathGetSeparatorA(PATH_STYLE_NATIVE);
size_t fcount = 0;
const size_t baselen = strlen(BasePath);
const size_t total = ArrayList_Count(files);
for (size_t x = 0; x < total; x++)
{
const char* path = ArrayList_GetItem(files, x);
const size_t pathlen = strlen(path);
if (pathlen < baselen)
continue;
const char* skip = &path[baselen];
if (*skip == sep)
skip++;
const char* end = strrchr(skip, sep);
if (end)
continue;
fcount++;
}
return (fcount == count);
}
static BOOL find_first_file_fail(const char* FilePath)
{
WIN32_FIND_DATAA FindData = WINPR_C_ARRAY_INIT;
HANDLE hFind = FindFirstFileA(FilePath, &FindData);
if (hFind == INVALID_HANDLE_VALUE)
return TRUE;
FindClose(hFind);
return FALSE;
}
static int TestFileFindFirstFileA(const char* str)
{
int rc = -1;
printf("[%s] basepath: '%s'\n", __func__, str);
if (!str)
return -1;
CHAR BasePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
strncpy(BasePath, str, ARRAYSIZE(BasePath));
const size_t length = strnlen(BasePath, PATHCCH_MAX_CCH - 1);
CHAR FilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
CopyMemory(FilePath, BasePath, length * sizeof(CHAR));
PathCchConvertStyleA(BasePath, length, PATH_STYLE_WINDOWS);
wArrayList* files = ArrayList_New(FALSE);
if (!files)
return -3;
wObject* obj = ArrayList_Object(files);
obj->fnObjectFree = winpr_ObjectStringFree;
obj->fnObjectNew = winpr_ObjectStringClone;
if (!create_layout(BasePath, files))
goto fail;
NativePathCchAppendA(FilePath, PATHCCH_MAX_CCH, testFile1A);
printf("Finding file: %s\n", FilePath);
if (!find_first_file_fail(FilePath))
goto fail;
if (!create_fileA(FilePath))
goto fail;
if (!find_first_file_success(FilePath))
goto fail;
CHAR BasePathInvalid[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
memcpy(BasePathInvalid, BasePath, ARRAYSIZE(BasePathInvalid));
PathCchAddBackslashA(BasePathInvalid, PATHCCH_MAX_CCH);
if (!find_first_file_fail(BasePathInvalid))
goto fail;
if (!list_directory_dot(BasePath, files))
goto fail;
if (!list_directory_star(BasePath, files))
goto fail;
rc = 0;
fail:
winpr_DeleteFile(FilePath);
cleanup_layout(BasePath);
ArrayList_Free(files);
return rc;
}
WINPR_ATTR_FORMAT_ARG(1, 0)
static int printf1W(const char* WINPR_FORMAT_ARG fmt, const WCHAR* arg1)
{
char* var1 = ConvertWCharToUtf8Alloc(arg1, nullptr);
const int rc = printf(fmt, var1);
free(var1);
return rc;
}
WINPR_ATTR_FORMAT_ARG(1, 0)
static int printf2W(const char* WINPR_FORMAT_ARG fmt, const WCHAR* arg1, const WCHAR* arg2)
{
char* var1 = ConvertWCharToUtf8Alloc(arg1, nullptr);
char* var2 = ConvertWCharToUtf8Alloc(arg2, nullptr);
const int rc = printf(fmt, var1, var2);
free(var1);
free(var2);
return rc;
}
static int TestFileFindFirstFileW(const char* str)
{
WCHAR buffer[32] = WINPR_C_ARRAY_INIT;
const WCHAR* testFile1W = InitializeConstWCharFromUtf8("TestFile1W", buffer, ARRAYSIZE(buffer));
int rc = -1;
if (!str)
return -1;
WCHAR BasePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
printf("[%s] basepath: '%s'\n", __func__, str);
(void)ConvertUtf8ToWChar(str, BasePath, ARRAYSIZE(BasePath));
const size_t length = _wcsnlen(BasePath, PATHCCH_MAX_CCH - 1);
WCHAR FilePath[PATHCCH_MAX_CCH] = WINPR_C_ARRAY_INIT;
CopyMemory(FilePath, BasePath, length * sizeof(WCHAR));
PathCchConvertStyleW(BasePath, length, PATH_STYLE_WINDOWS);
NativePathCchAppendW(FilePath, PATHCCH_MAX_CCH, testFile1W);
HANDLE hFind = INVALID_HANDLE_VALUE;
if (!create_fileW(FilePath))
goto fail;
printf1W("Finding file: %s\n", FilePath);
WIN32_FIND_DATAW FindData = WINPR_C_ARRAY_INIT;
hFind = FindFirstFileW(FilePath, &FindData);
if (hFind == INVALID_HANDLE_VALUE)
{
printf1W("FindFirstFile failure: %s (INVALID_HANDLE_VALUE -1)\n", FilePath);
goto fail;
}
printf1W("FindFirstFile: %s\n", FindData.cFileName);
if (_wcscmp(FindData.cFileName, testFile1W) != 0)
{
printf2W("FindFirstFile failure: Expected: %s, Actual: %s\n", testFile1W,
FindData.cFileName);
goto fail;
}
rc = 0;
fail:
DeleteFileW(FilePath);
FindClose(hFind);
return rc;
}
int TestFileFindFirstFile(int argc, char* argv[])
{
char* str = GetKnownSubPath(KNOWN_PATH_TEMP, "TestFileFindFirstFile");
if (!str)
return -23;
cleanup_layout(str);
int rc1 = -1;
int rc2 = -1;
if (winpr_PathMakePath(str, nullptr))
{
rc1 = TestFileFindFirstFileA(str);
rc2 = TestFileFindFirstFileW(str);
winpr_RemoveDirectory(str);
}
free(str);
return rc1 + rc2;
}