/* On Mac OS 8/9, one of dirSpec and dirURL must be non-NULL.  On all other platforms, one of path and dirURL must be non-NULL
If both are present, they are assumed to be in-synch; that is, they both refer to the same directory.  */
__private_extern__ CFMutableArrayRef _CFContentsOfDirectory(CFAllocatorRef alloc, char *dirPath, void *dirSpec, CFURLRef dirURL, CFStringRef matchingAbstractType) {
    CFMutableArrayRef files = NULL;
    Boolean releaseBase = false;
    CFIndex pathLength = dirPath ? strlen(dirPath) : 0;
    // MF:!!! Need to use four-letter type codes where appropriate.
    CFStringRef extension = (matchingAbstractType ? _CFCopyExtensionForAbstractType(matchingAbstractType) : NULL);
    CFIndex extLen = (extension ? CFStringGetLength(extension) : 0);
    uint8_t extBuff[CFMaxPathSize];

#if defined(__WIN32__)
    /* Windows Variables */
    /* The Win32 code has not been updated for:
        path has been renamed dirPath
        base has been renamed dirURL
        dirPath may be NULL (in which case dirURL is not)
        if dirPath is NULL, pathLength is 0
    */
    WIN32_FIND_DATA file;
    HANDLE handle;
#elif defined(__svr4__) || defined(__hpux__) || defined(__LINUX__) || defined(__FREEBSD__)
    /* Solaris and HPUX Variables */
    /* The Solaris and HPUX code has not been updated for:
        base has been renamed dirURL
        dirPath may be NULL (in which case dirURL is not)
        if dirPath is NULL, pathLength is 0
    */
    DIR *dirp;
    struct dirent *dp;
    int err;
#elif defined(__MACH__)
    /* Mac OS X Variables */
    int fd, numread;
    long basep;
    char dirge[8192];
    uint8_t pathBuf[CFMaxPathSize];
#endif

    
    if (extLen > 0) {
        CFStringGetBytes(extension, CFRangeMake(0, extLen), CFStringFileSystemEncoding(), 0, false, extBuff, CFMaxPathSize, &extLen);
        extBuff[extLen] = '\0';
    }
    
#if defined(__WIN32__)
    /* Windows Implementation */
    
    if (pathLength + 2 >= CFMaxPathLength) {
        if (extension) {
            CFRelease(extension);
        }
        return NULL;
    }
    if (NULL != dirPath) {
	dirPath[pathLength] = '\'';
	dirPath[pathLength + 1] = '*';
	dirPath[pathLength + 2] = '\0';
	handle = FindFirstFileA(dirPath, &file);
	if (INVALID_HANDLE_VALUE == handle) {
	    dirPath[pathLength] = '\0';
	    if (extension) {
		CFRelease(extension);
	    }
	    return NULL;
	}
    } else {
	pathLength = 0;
    }
    files = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks);

    do {
        CFURLRef fileURL;
        CFIndex namelen = strlen(file.cFileName);
        if (file.cFileName[0] == '.' && (namelen == 1 || (namelen == 2  && file.cFileName[1] == '.'))) {
            continue;
        }
        if (extLen > 0) {
            // Check to see if it matches the extension we're looking for.
            if (_stricmp(&(file.cFileName[namelen - extLen]), extBuff) != 0) {
                continue;
            }
        }
	if (dirURL == NULL) {
	    dirURL = CFURLCreateFromFileSystemRepresentation(alloc, dirPath, pathLength, true);
            releaseBase = true;
        }
        // MF:!!! What about the trailing slash?
        fileURL = CFURLCreateFromFileSystemRepresentationRelativeToBase(alloc, file.cFileName, namelen, false, dirURL);
        CFArrayAppendValue(files, fileURL);
        CFRelease(fileURL);
    } while (FindNextFileA(handle, &file));
    FindClose(handle);
    dirPath[pathLength] = '\0';

#elif defined(__svr4__) || defined(__hpux__) || defined(__LINUX__) || defined(__FREEBSD__)
    /* Solaris and HPUX Implementation */

    dirp = opendir(dirPath);
    if (!dirp) {
        if (extension) {
            CFRelease(extension);
        }
        return NULL;
        // raiseErrno("opendir", path);
    }
    files = CFArrayCreateMutable(alloc, 0, & kCFTypeArrayCallBacks);

    while((dp = readdir(dirp)) != NULL) {
        CFURLRef fileURL;
	unsigned namelen = strlen(dp->d_name);

        // skip . & ..; they cause descenders to go berserk
	if (dp->d_name[0] == '.' && (namelen == 1 || (namelen == 2 && dp->d_name[1] == '.'))) {
            continue;
        }

        if (extLen > 0) {
            // Check to see if it matches the extension we're looking for.
            if (strncmp(&(dp->d_name[namelen - extLen]), extBuff, extLen) != 0) {
                continue;
            }
        }
        if (dirURL == NULL) {
            dirURL = CFURLCreateFromFileSystemRepresentation(alloc, dirPath, pathLength, true);
            releaseBase = true;
        }
        // MF:!!! What about the trailing slash?
        fileURL = CFURLCreateFromFileSystemRepresentationRelativeToBase(alloc, dp->d_name, namelen, false, dirURL);
        CFArrayAppendValue(files, fileURL);
        CFRelease(fileURL);
    }
    err = closedir(dirp);
    if (err != 0) {
        CFRelease(files);
        if (releaseBase) {
            CFRelease(dirURL);
        }
        if (extension) {
            CFRelease(extension);
        }
        return NULL;
        // raiseErrno("closedir", path);
    }
    
#elif defined(__MACH__)
    /* Mac OS X Variables - repeated for convenience */
    // int fd, numread;
    // long basep;
    // char dirge[8192];
    // UInt8 pathBuf[CFMaxPathSize];
    /* Mac OS X Implementation */

    if (!dirPath) {
        if (!CFURLGetFileSystemRepresentation(dirURL, true, pathBuf, CFMaxPathLength)) {
            if (extension) CFRelease(extension);
            return NULL;
        } else {
            dirPath = pathBuf;
            pathLength = strlen(dirPath);
        }
    }
    fd = open(dirPath, O_RDONLY, 0777);
    if (fd < 0) {
        if (extension) {
            CFRelease(extension);
        }
        return NULL;
    }
    files = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks);

    while ((numread = getdirentries(fd, dirge, sizeof(dirge), &basep)) > 0) {
        struct dirent *dent;
        for (dent = (struct dirent *)dirge; dent < (struct dirent *)(dirge + numread); dent = (struct dirent *)((char *)dent + dent->d_reclen)) {
            CFURLRef fileURL;
            CFIndex nameLen;

            nameLen = dent->d_namlen;
            // skip . & ..; they cause descenders to go berserk
            if (0 == dent->d_fileno || (dent->d_name[0] == '.' && (nameLen == 1 || (nameLen == 2 && dent->d_name[1] == '.')))) {
                continue;
            }
            if (extLen > 0) {
                // Check to see if it matches the extension we're looking for.
                if (strncmp(&(dent->d_name[nameLen - extLen]), extBuff, extLen) != 0) {
                    continue;
                }
            }
            if (dirURL == NULL) {
                dirURL = CFURLCreateFromFileSystemRepresentation(alloc, dirPath, pathLength, true);
                releaseBase = true;
            }

            if (dent->d_type == DT_DIR || dent->d_type == DT_UNKNOWN) {
                Boolean isDir = (dent->d_type == DT_DIR);
                if (!isDir) {
                    // Ugh; must stat.
                    char subdirPath[CFMaxPathLength];
                    struct stat statBuf;
                    strncpy(subdirPath, dirPath, pathLength);
                    subdirPath[pathLength] = '/';
                    strncpy(subdirPath + pathLength + 1, dent->d_name, nameLen);
                    subdirPath[pathLength + nameLen + 1] = '\0';
                    if (stat(subdirPath, &statBuf) == 0) {
                        isDir = ((statBuf.st_mode & S_IFMT) == S_IFDIR);
                    }
                }
                fileURL = CFURLCreateFromFileSystemRepresentationRelativeToBase(alloc, dent->d_name, nameLen, isDir, dirURL);
            } else {
                fileURL = CFURLCreateFromFileSystemRepresentationRelativeToBase (alloc, dent->d_name, nameLen, false, dirURL);
            }
            CFArrayAppendValue(files, fileURL);
            CFRelease(fileURL);
        }
    }
    close(fd);
    if  (-1 == numread) {
        CFRelease(files);
        if (releaseBase) {
            CFRelease(dirURL);
        }
        if (extension) {
            CFRelease(extension);
        }
        return NULL;
    }
#else
    
#error _CFContentsOfDirectory() unknown architechture, not implemented
    
#endif

    if (extension) {
        CFRelease(extension);
    }
    if (releaseBase) {
        CFRelease(dirURL);
    }
    return files;
}
/* Lately, dirSpec appears to be (rightfully) unused. */
__private_extern__ CFMutableArrayRef _CFContentsOfDirectory(CFAllocatorRef alloc, char *dirPath, void *dirSpec, CFURLRef dirURL, CFStringRef matchingAbstractType) {
    CFMutableArrayRef files = NULL;
    Boolean releaseBase = false;
    CFIndex pathLength = dirPath ? strlen(dirPath) : 0;
    // MF:!!! Need to use four-letter type codes where appropriate.
    CFStringRef extension = (matchingAbstractType ? _CFCopyExtensionForAbstractType(matchingAbstractType) : NULL);
    CFIndex targetExtLen = (extension ? CFStringGetLength(extension) : 0);

#if DEPLOYMENT_TARGET_WINDOWS
    // This is a replacement for 'dirent' below, and also uses wchar_t to support unicode paths
    wchar_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 :(
    
    if (targetExtLen > 0) {
        CFIndex usedBytes = 0;
        CFStringGetBytes(extension, CFRangeMake(0, targetExtLen), kCFStringEncodingUTF16, 0, false, (uint8_t *)extBuff, CFMaxPathLength, &usedBytes);
        targetExtLen = usedBytes / sizeof(wchar_t);
        extBuff[targetExtLen] = '\0';
        wchar_t *extBuffStr = (wchar_t *)extBuff;
        if (extBuffStr[0] == '.')
            extBuffStr++; //skip the first dot, it's legitimate to have ".plist" for example
        
        wchar_t *extBuffDotPtr = extBuffStr;
        while ((extBuffDotPtr = wcschr(extBuffStr, '.'))) { //find the next . in the extension...
            extBuffInteriorDotCount++;
            extBuffStr = extBuffDotPtr + 1;
        }
    }
    
    wchar_t pathBuf[CFMaxPathSize];
    
    if (!dirPath) {
        if (!_CFURLGetWideFileSystemRepresentation(dirURL, true, pathBuf, CFMaxPathLength)) {
            if (extension) CFRelease(extension);
            return NULL;
        }
        
        pathLength = wcslen(pathBuf);

    } else {
        // Convert dirPath to a wide representation and put it into our pathBuf
        // Get the real length of the string in UTF16 characters
        CFStringRef dirPathStr = CFStringCreateWithCString(kCFAllocatorSystemDefault, dirPath, kCFStringEncodingUTF8);
        CFIndex strLen = CFStringGetLength(dirPathStr);
        
        // Copy the string into the buffer and terminate
        CFStringGetCharacters(dirPathStr, CFRangeMake(0, strLen), (UniChar *)pathBuf);
        pathBuf[strLen] = 0;
        
        CFRelease(dirPathStr);
    }
    
    WIN32_FIND_DATAW  file;
    HANDLE handle;
    
    if (pathLength + 2 >= CFMaxPathLength) {
        if (extension) {
            CFRelease(extension);
        }
        return NULL;
    }

    pathBuf[pathLength] = '\\';
    pathBuf[pathLength + 1] = '*';
    pathBuf[pathLength + 2] = '\0';
    handle = FindFirstFileW(pathBuf, (LPWIN32_FIND_DATAW)&file);
    if (INVALID_HANDLE_VALUE == handle) {
        pathBuf[pathLength] = '\0';
        if (extension) {
            CFRelease(extension);
        }
        return NULL;
    }

    files = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks);

    do {
        CFURLRef fileURL;
        CFIndex namelen = wcslen(file.cFileName);
        if (file.cFileName[0] == '.' && (namelen == 1 || (namelen == 2  && file.cFileName[1] == '.'))) {
            continue;
        }

        if (targetExtLen > namelen) continue;    // if the extension is the same length or longer than the name, it can't possibly match.

        if (targetExtLen > 0) {
	    if (file.cFileName[namelen - 1] == '.') continue; //filename ends with a dot, no extension
	    
	    wchar_t *fileExt = NULL;
            
            if (extBuffInteriorDotCount == 0) {
                fileExt = wcsrchr(file.cFileName, '.');
            } else { //find the Nth occurrence of . from the end of the string, to handle ".foo.bar"
                wchar_t *save = file.cFileName;
                while ((save = wcschr(save, '.')) && !fileExt) {
                    wchar_t *temp = save;
                    int moreDots = 0;
                    while ((temp = wcschr(temp, '.'))) {
                        if (++moreDots == extBuffInteriorDotCount) break;
                    }
                    if (moreDots == extBuffInteriorDotCount) {
                        fileExt = save;
                    }
                }
            }
	    
	    if (!fileExt) continue; //no extension
	    
	    if (((const wchar_t *)extBuff)[0] != '.')
		fileExt++; //omit the dot if the target file extension omits the dot
	    
	    CFIndex fileExtLen = wcslen(fileExt);
	    
	    //if the extensions are different lengths, they can't possibly match
	    if (fileExtLen != targetExtLen) continue;
	    
            // Check to see if it matches the extension we're looking for.
            if (_wcsicmp(fileExt, (const wchar_t *)extBuff) != 0) {
                continue;
            }
        }
	if (dirURL == NULL) {
	    CFStringRef dirURLStr = CFStringCreateWithBytes(alloc, (const uint8_t *)pathBuf, pathLength * sizeof(wchar_t), kCFStringEncodingUTF16, NO);
	    dirURL = CFURLCreateWithFileSystemPath(alloc, dirURLStr, kCFURLWindowsPathStyle, true);
	    CFRelease(dirURLStr);
            releaseBase = true;
        }
        // MF:!!! What about the trailing slash?
        CFStringRef fileURLStr = CFStringCreateWithBytes(alloc, (const uint8_t *)file.cFileName, namelen * sizeof(wchar_t), kCFStringEncodingUTF16, NO);
        fileURL = CFURLCreateWithFileSystemPathRelativeToBase(alloc, fileURLStr, kCFURLWindowsPathStyle, (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false, dirURL);
        CFArrayAppendValue(files, fileURL);
        CFRelease(fileURL);
        CFRelease(fileURLStr);
    } while (FindNextFileW(handle, &file));
    FindClose(handle);
    pathBuf[pathLength] = '\0';

#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
    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 :(
    
    if (targetExtLen > 0) {
        CFStringGetBytes(extension, CFRangeMake(0, targetExtLen), CFStringFileSystemEncoding(), 0, false, extBuff, CFMaxPathLength, &targetExtLen);
        extBuff[targetExtLen] = '\0';
        char *extBuffStr = (char *)extBuff;
        if (extBuffStr[0] == '.')
            extBuffStr++; //skip the first dot, it's legitimate to have ".plist" for example
        
        char *extBuffDotPtr = extBuffStr;
        while ((extBuffDotPtr = strchr(extBuffStr, '.'))) { //find the next . in the extension...
            extBuffInteriorDotCount++;
            extBuffStr = extBuffDotPtr + 1;
        }
    }
    
    uint8_t pathBuf[CFMaxPathSize];
    
    if (!dirPath) {
        if (!CFURLGetFileSystemRepresentation(dirURL, true, pathBuf, CFMaxPathLength)) {
            if (extension) CFRelease(extension);
            return NULL;
        } else {
            dirPath = (char *)pathBuf;
            pathLength = strlen(dirPath);
        }
    }
    
    struct dirent buffer;
    struct dirent *dp;
    int err;
   
    int no_hang_fd = __CFProphylacticAutofsAccess ? open("/dev/autofs_nowait", 0) : -1;
 
    DIR *dirp = opendir(dirPath);
    if (!dirp) {
        if (extension) {
            CFRelease(extension);
        }
	if (-1 != no_hang_fd) close(no_hang_fd);
        return NULL;
        // raiseErrno("opendir", path);
    }
    files = CFArrayCreateMutable(alloc, 0, & kCFTypeArrayCallBacks);

    while((0 == readdir_r(dirp, &buffer, &dp)) && dp) {
        CFURLRef fileURL;
	unsigned namelen = strlen(dp->d_name);

        // skip . & ..; they cause descenders to go berserk
	if (dp->d_name[0] == '.' && (namelen == 1 || (namelen == 2 && dp->d_name[1] == '.'))) {
            continue;
        }
        
        if (targetExtLen > namelen) continue;    // if the extension is the same length or longer than the name, it can't possibly match.
                
        if (targetExtLen > 0) {
	    if (dp->d_name[namelen - 1] == '.') continue; //filename ends with a dot, no extension
	      
            char *fileExt = NULL;
            if (extBuffInteriorDotCount == 0) {
                fileExt = strrchr(dp->d_name, '.'); 
            } else { //find the Nth occurrence of . from the end of the string, to handle ".foo.bar"
                char *save = dp->d_name;
                while ((save = strchr(save, '.')) && !fileExt) {
                    char *temp = save;
                    int moreDots = 0;
                    while ((temp = strchr(temp, '.'))) {
                        if (++moreDots == extBuffInteriorDotCount) break;
                    }
                    if (moreDots == extBuffInteriorDotCount) {
                        fileExt = save;
                    }
                }
            }
	    
	    if (!fileExt) continue; //no extension
	    
	    if (((char *)extBuff)[0] != '.')
		fileExt++; //omit the dot if the target extension omits the dot; safe, because we checked to make sure it isn't the last character just before
	    
	    size_t fileExtLen = strlen(fileExt);
	    
	    //if the extensions are different lengths, they can't possibly match
	    if (fileExtLen != targetExtLen) continue;
	    
	    // Check to see if it matches the extension we're looking for.
            if (strncmp(fileExt, (char *)extBuff, fileExtLen) != 0) {
                continue;
            }
        }
        if (dirURL == NULL) {
            dirURL = CFURLCreateFromFileSystemRepresentation(alloc, (uint8_t *)dirPath, pathLength, true);
            releaseBase = true;
        }
        if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN || dp->d_type == DT_LNK || dp->d_type == DT_WHT) {
            Boolean isDir = (dp->d_type == DT_DIR);
            if (!isDir) {
                // Ugh; must stat.
                char subdirPath[CFMaxPathLength];
                struct statinfo statBuf;
                strlcpy(subdirPath, dirPath, sizeof(subdirPath));
                strlcat(subdirPath, "/", sizeof(subdirPath));
                strlcat(subdirPath, dp->d_name, sizeof(subdirPath));
                if (stat(subdirPath, &statBuf) == 0) {
                    isDir = ((statBuf.st_mode & S_IFMT) == S_IFDIR);
                }
            }
#if DEPLOYMENT_TARGET_LINUX
            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 DEPLOYMENT_TARGET_LINUX
            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);
#endif
        }
        CFArrayAppendValue(files, fileURL);
        CFRelease(fileURL);
    }
    err = closedir(dirp);
    if (-1 != no_hang_fd) close(no_hang_fd);
    if (err != 0) {
        CFRelease(files);
        if (releaseBase) {
            CFRelease(dirURL);
        }
        if (extension) {
            CFRelease(extension);
        }
        return NULL;
    }
    
#else
    
#error _CFContentsOfDirectory() unknown architecture, not implemented
    
#endif

    if (extension) {
        CFRelease(extension);
    }
    if (releaseBase) {
        CFRelease(dirURL);
    }
    return files;
}
Exemple #3
0
/* Lately, dirSpec appears to be (rightfully) unused. */
__private_extern__ CFMutableArrayRef _CFContentsOfDirectory(CFAllocatorRef alloc, char *dirPath, void *dirSpec, CFURLRef dirURL, CFStringRef matchingAbstractType) {
    CFMutableArrayRef files = NULL;
    Boolean releaseBase = false;
    CFIndex pathLength = dirPath ? (CFIndex)strlen(dirPath) : 0;
    // MF:!!! Need to use four-letter type codes where appropriate.
    CFStringRef extension = (matchingAbstractType ? _CFCopyExtensionForAbstractType(matchingAbstractType) : NULL);
    CFIndex extLen = (extension ? CFStringGetLength(extension) : 0);
    uint8_t extBuff[CFMaxPathSize];
    
    if (extLen > 0) {
        CFStringGetBytes(extension, CFRangeMake(0, extLen), CFStringFileSystemEncoding(), 0, false, extBuff, CFMaxPathLength, &extLen);
        extBuff[extLen] = '\0';
    }

    uint8_t pathBuf[CFMaxPathSize];

    if (!dirPath) {
        if (!CFURLGetFileSystemRepresentation(dirURL, true, pathBuf, CFMaxPathLength)) {
            if (extension) CFRelease(extension);
            return NULL;
        } else {
            dirPath = (char *)pathBuf;
            pathLength = (CFIndex)strlen(dirPath);
        }
    }
    
#if (DEPLOYMENT_TARGET_MACOSX) || defined(__svr4__) || defined(__hpux__) || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
    struct dirent buffer;
    struct dirent *dp;
    int err;
   
    int no_hang_fd = open("/dev/autofs_nowait", 0);
 
    DIR *dirp = opendir(dirPath);
    if (!dirp) {
        if (extension) {
            CFRelease(extension);
        }
        close(no_hang_fd);
        return NULL;
        // raiseErrno("opendir", path);
    }
    files = CFArrayCreateMutable(alloc, 0, & kCFTypeArrayCallBacks);

    while((0 == readdir_r(dirp, &buffer, &dp)) && dp) {
        CFURLRef fileURL;
        unsigned namelen = strlen(dp->d_name);

        // skip . & ..; they cause descenders to go berserk
        if (dp->d_name[0] == '.' && (namelen == 1 || (namelen == 2 && dp->d_name[1] == '.'))) {
            continue;
        }
        
        if (extLen > namelen) continue;    // if the extension is the same length or longer than the name, it can't possibly match.
        
        if (extLen > 0) {
            // Check to see if it matches the extension we're looking for.
            if (strncmp(&(dp->d_name[namelen - extLen]), (char *)extBuff, extLen) != 0) {
                continue;
            }
        }
        if (dirURL == NULL) {
            dirURL = CFURLCreateFromFileSystemRepresentation(alloc, (uint8_t *)dirPath, pathLength, true);
            releaseBase = true;
        }
        if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN) {
            Boolean isDir = (dp->d_type == DT_DIR);
            if (!isDir) {
                // Ugh; must stat.
                char subdirPath[CFMaxPathLength];
                struct stat statBuf;
                strlcpy(subdirPath, dirPath, sizeof(subdirPath));
                strlcat(subdirPath, "/", sizeof(subdirPath));
                strlcat(subdirPath, dp->d_name, sizeof(subdirPath));
                if (stat(subdirPath, &statBuf) == 0) {
                    isDir = ((statBuf.st_mode & S_IFMT) == S_IFDIR);
                }
            }
            fileURL = CFURLCreateFromFileSystemRepresentationRelativeToBase(alloc, (uint8_t *)dp->d_name, namelen, isDir, dirURL);
        } else {
            fileURL = CFURLCreateFromFileSystemRepresentationRelativeToBase (alloc, (uint8_t *)dp->d_name, namelen, false, dirURL);
        }
        CFArrayAppendValue(files, fileURL);
        CFRelease(fileURL);
    }
    err = closedir(dirp);
    close(no_hang_fd);
    if (err != 0) {
        CFRelease(files);
        if (releaseBase) {
            CFRelease(dirURL);
        }
        if (extension) {
            CFRelease(extension);
        }
        return NULL;
    }

#elif DEPLOYMENT_TARGET_WINDOWS

    WIN32_FIND_DATAA file;
    HANDLE handle;

    if (pathLength + 2 >= CFMaxPathLength) {
        if (extension) {
            CFRelease(extension);
        }
        return NULL;
    }
    if (NULL != dirPath) {
        dirPath[pathLength] = '\'';
        dirPath[pathLength + 1] = '*';
        dirPath[pathLength + 2] = '\0';
        handle = FindFirstFileA(dirPath, &file);
        if (INVALID_HANDLE_VALUE == handle) {
            dirPath[pathLength] = '\0';
            if (extension) {
                CFRelease(extension);
            }
            return NULL;
        }
    } else {
        pathLength = 0;
    }
    files = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks);

    do {
        CFURLRef fileURL;
        CFIndex namelen = (CFIndex)strlen(file.cFileName);
        if (file.cFileName[0] == '.' && (namelen == 1 || (namelen == 2  && file.cFileName[1] == '.'))) {
            continue;
        }
        if (extLen > 0) {
            // Check to see if it matches the extension we're looking for.
            if (_stricmp((char*)&(file.cFileName[namelen - extLen]), (char*)extBuff) != 0) {
                continue;
            }
        }
	if (dirURL == NULL) {
	    dirURL = CFURLCreateFromFileSystemRepresentation(alloc, (UInt8*)dirPath, pathLength, true);
            releaseBase = true;
        }
        // MF:!!! What about the trailing slash?
        fileURL = CFURLCreateFromFileSystemRepresentationRelativeToBase(alloc, (UInt8*)file.cFileName, namelen, false, dirURL);
        CFArrayAppendValue(files, fileURL);
        CFRelease(fileURL);
    } while (FindNextFileA(handle, &file));
    FindClose(handle);
    dirPath[pathLength] = '\0';

#else

#error _CFContentsOfDirectory() unknown architechture, not implemented
    
#endif

    if (extension) {
        CFRelease(extension);
    }
    if (releaseBase) {
        CFRelease(dirURL);
    }
    return files;
}