diff --git a/CoreFoundation/Base.subproj/CFFileUtilities.c b/CoreFoundation/Base.subproj/CFFileUtilities.c index 53596fb964..875526af2c 100644 --- a/CoreFoundation/Base.subproj/CFFileUtilities.c +++ b/CoreFoundation/Base.subproj/CFFileUtilities.c @@ -38,7 +38,11 @@ #include #include #include -#include + +#if !TARGET_OS_WASI +# include +#endif + #include #define statinfo stat @@ -341,7 +345,7 @@ CF_PRIVATE CFMutableArrayRef _CFCreateContentsOfDirectory(CFAllocatorRef alloc, FindClose(handle); pathBuf[pathLength] = '\0'; -#elif TARGET_OS_MAC || TARGET_OS_LINUX || TARGET_OS_BSD +#elif TARGET_OS_MAC || TARGET_OS_LINUX || TARGET_OS_BSD || TARGET_OS_WASI uint8_t extBuff[CFMaxPathSize]; int extBuffInteriorDotCount = 0; //people insist on using extensions like ".trace.plist", so we need to know how many dots back to look :( @@ -444,7 +448,7 @@ CF_PRIVATE CFMutableArrayRef _CFCreateContentsOfDirectory(CFAllocatorRef alloc, dirURL = CFURLCreateFromFileSystemRepresentation(alloc, (uint8_t *)dirPath, pathLength, true); releaseBase = true; } -#if !defined(__OpenBSD__) +#if !defined(__OpenBSD__) && !TARGET_OS_WASI if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN || dp->d_type == DT_LNK || dp->d_type == DT_WHT) { #else if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN || dp->d_type == DT_LNK) { @@ -461,13 +465,13 @@ CF_PRIVATE CFMutableArrayRef _CFCreateContentsOfDirectory(CFAllocatorRef alloc, isDir = ((statBuf.st_mode & S_IFMT) == S_IFDIR); } } -#if TARGET_OS_LINUX +#if TARGET_OS_LINUX || TARGET_OS_WASI fileURL = CFURLCreateFromFileSystemRepresentationRelativeToBase(alloc, (uint8_t *)dp->d_name, namelen, isDir, dirURL); #else fileURL = CFURLCreateFromFileSystemRepresentationRelativeToBase(alloc, (uint8_t *)dp->d_name, dp->d_namlen, isDir, dirURL); #endif } else { -#if TARGET_OS_LINUX +#if TARGET_OS_LINUX || TARGET_OS_WASI fileURL = CFURLCreateFromFileSystemRepresentationRelativeToBase (alloc, (uint8_t *)dp->d_name, namelen, false, dirURL); #else fileURL = CFURLCreateFromFileSystemRepresentationRelativeToBase (alloc, (uint8_t *)dp->d_name, dp->d_namlen, false, dirURL); @@ -554,7 +558,7 @@ CF_PRIVATE SInt32 _CFGetPathProperties(CFAllocatorRef alloc, char *path, Boolean if (modTime != NULL) { if (fileExists) { -#if TARGET_OS_WIN32 || TARGET_OS_LINUX +#if TARGET_OS_WIN32 || TARGET_OS_LINUX || TARGET_OS_WASI struct timespec ts = {statBuf.st_mtime, 0}; #else struct timespec ts = statBuf.st_mtimespec; @@ -1118,6 +1122,8 @@ CF_PRIVATE void _CFIterateDirectory(CFStringRef directoryPath, Boolean appendSla } } } +#elif TARGET_OS_WASI + CFIndex nameLen = strlen(dent->d_name); #else CFIndex nameLen = dent->d_namlen; #endif @@ -1130,7 +1136,25 @@ CF_PRIVATE void _CFIterateDirectory(CFStringRef directoryPath, Boolean appendSla // This buffer has to be 1 bigger than the size of the one in the dirent so we can hold the extra '/' if it's required // Be sure to initialize the first character to null, so that strlcat below works correctly - char fullPathToFile[sizeof(dent->d_name) + 1]; + #if TARGET_OS_WASI + // wasi-libc's dirent.d_name is not a fixed-size array but a pointer, so we need to calculate + // the size of buffer at first. + size_t d_name_size = nameLen; + if (stuffToPrefix) { + for (CFIndex i = 0; i < CFArrayGetCount(stuffToPrefix); i++) { + CFStringRef onePrefix = CFArrayGetValueAtIndex(stuffToPrefix, i); + size_t prefixLen = CFStringGetLength(onePrefix); + // Add 1 for concatenating '/' + if (d_name_size > nameLen) { + d_name_size += 1; + } + d_name_size += prefixLen; + } + } + #else + size_t d_name_size = sizeof(dent->d_name); + #endif + char fullPathToFile[d_name_size + 1]; fullPathToFile[0] = 0; CFIndex startAt = 0;