Skip to content

CoreFoundation: simplify and fix CFIterateDirectory #2020

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 29, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 36 additions & 54 deletions CoreFoundation/Base.subproj/CFFileUtilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -1024,66 +1024,48 @@ CF_PRIVATE void _CFIterateDirectory(CFStringRef directoryPath, Boolean appendSla
if (!CFStringGetFileSystemRepresentation(directoryPath, directoryPathBuf, CFMaxPathSize)) return;

#if DEPLOYMENT_TARGET_WINDOWS
CFIndex cpathLen = strlen(directoryPathBuf);
// Make sure there is room for the additional space we need in the win32 api
if (cpathLen + 2 < CFMaxPathSize) {
WIN32_FIND_DATAW file;
HANDLE handle;

directoryPathBuf[cpathLen++] = '\\';
directoryPathBuf[cpathLen++] = '*';
directoryPathBuf[cpathLen] = '\0';

// Convert UTF8 buffer to windows appropriate UTF-16LE
// Get the real length of the string in UTF16 characters
CFStringRef cfStr = CFStringCreateWithCString(kCFAllocatorSystemDefault, directoryPathBuf, kCFStringEncodingUTF8);
cpathLen = CFStringGetLength(cfStr);
// Allocate a wide buffer to hold the converted string, including space for a NULL terminator
wchar_t *wideBuf = (wchar_t *)malloc((cpathLen + 1) * sizeof(wchar_t));
// Copy the string into the buffer and terminate
CFStringGetCharacters(cfStr, CFRangeMake(0, cpathLen), (UniChar *)wideBuf);
wideBuf[cpathLen] = 0;
CFRelease(cfStr);

WCHAR directory[MAX_PATH + 1];
if (!CFStringGetCString(directoryPath, directory, MAX_PATH, kCFStringEncodingUTF16))
return;

handle = FindFirstFileW(wideBuf, (LPWIN32_FIND_DATAW)&file);
if (handle != INVALID_HANDLE_VALUE) {
WCHAR path[MAX_PATH + 1];

do {
CFIndex nameLen = wcslen(file.cFileName);
if (file.cFileName[0] == '.' && (nameLen == 1 || (nameLen == 2 && file.cFileName[1] == '.'))) {
continue;
}
if (strlen(directoryPathBuf) > CFMaxPathSize - 2) return;

if (!PathCombineW(path, directory, file.cFileName)) {
continue;
}
strlcat(directoryPathBuf, "\\*", CFMaxPathSize);

CFStringRef filePath = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (const uint8_t *)path, wcslen(path) * sizeof(WCHAR), kCFStringEncodingUTF16, NO);
if (!filePath) {
continue;
}
UniChar wideBuf[CFMaxPathSize];

CFStringRef fileName = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (const uint8_t *)file.cFileName, nameLen * sizeof(wchar_t), kCFStringEncodingUTF16, NO);
if (!fileName) {
CFRelease(filePath);
continue;
}
// Convert UTF8 buffer to windows appropriate UTF-16LE
// Get the real length of the string in UTF16 characters
CFStringRef cfStr = CFStringCreateWithCString(kCFAllocatorSystemDefault, directoryPathBuf, kCFStringEncodingUTF8);

Boolean isDirectory = file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
Boolean result = fileHandler(fileName, filePath, isDirectory ? DT_DIR : DT_REG);
CFRelease(fileName);
CFRelease(filePath);
if (!result) break;
} while (FindNextFileW(handle, &file));
// Copy the string into the buffer and terminate
CFStringGetCharacters(cfStr, CFRangeMake(0, CFStringGetLength(cfStr)), wideBuf);
wideBuf[CFStringGetLength(cfStr)] = L'\0';

FindClose(handle);
}
free(wideBuf);
CFRelease(cfStr);

WIN32_FIND_DATAW file;
HANDLE handle = FindFirstFileW(wideBuf, &file);
if (handle != INVALID_HANDLE_VALUE) {
do {
CFIndex nameLen = wcslen(file.cFileName);
if (file.cFileName[0] == '.' && (nameLen == 1 || (nameLen == 2 && file.cFileName[1] == '.'))) {
continue;
}

CFStringRef fileName = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, file.cFileName, nameLen);
if (!fileName) {
continue;
}

assert(!stuffToPrefix && "prefix not yet implemented");
CFStringRef filePath = CFRetain(fileName);

Boolean isDirectory = file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
Boolean result = fileHandler(fileName, filePath, isDirectory ? DT_DIR : DT_REG);
CFRelease(fileName);
CFRelease(filePath);
if (!result) break;
} while (FindNextFileW(handle, &file));

FindClose(handle);
}
#else
DIR *dirp;
Expand Down