#include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX && !RUNTIME_TINY && !IL2CPP_USE_PLATFORM_SPECIFIC_DIRECTORY #include "os/Directory.h" #include "os/ErrorCodes.h" #include "os/File.h" #include "os/Posix/Error.h" #include "utils/DirectoryUtils.h" #include "utils/Memory.h" #include "utils/PathUtils.h" #include "utils/StringUtils.h" #include #include #include #include #include #if IL2CPP_TARGET_QNX #include #else #include #endif #include #include namespace il2cpp { namespace os { std::string Directory::GetCurrent(int *error) { char buf[PATH_MAX + 1]; // Note: not all implementations would allocate a buffer when passing 0 to getcwd, as we used to do. // this does *not* seem to be part of the POSIX spec: // http://pubs.opengroup.org/onlinepubs/000095399/functions/getcwd.html char* cwd = getcwd(buf, PATH_MAX + 1); if (cwd == NULL) { *error = FileErrnoToErrorCode(errno); return std::string(); } std::string directory(cwd); *error = kErrorCodeSuccess; return directory; } bool Directory::SetCurrent(const std::string& path, int *error) { const int ret = chdir(path.c_str()); if (ret == -1) { *error = FileErrnoToErrorCode(errno); return false; } *error = kErrorCodeSuccess; return true; } bool Directory::Create(const std::string& path, int *error) { const int ret = mkdir(path.c_str(), 0777); if (ret == -1) { *error = PathErrnoToErrorCode(path, errno); return false; } *error = kErrorCodeSuccess; return true; } bool Directory::Remove(const std::string& path, int *error) { const int ret = rmdir(path.c_str()); if (ret == -1) { *error = PathErrnoToErrorCode(path, errno); return false; } *error = kErrorCodeSuccess; return true; } static void DirectoryGlob(DIR *dir, const std::string& pattern, std::set& result) { if (pattern.empty()) return; std::string matchPattern = il2cpp::utils::CollapseAdjacentStars(pattern); struct dirent *entry; while ((entry = readdir(dir)) != NULL) { const std::string filename(entry->d_name); if (!il2cpp::utils::Match(filename, matchPattern)) continue; result.insert(filename); } } static bool DirectoryGlob(const std::string& directoryPath, const std::string& pattern, std::set& result, int* error) { DIR* dir = opendir(directoryPath.c_str()); if (dir == NULL) { *error = PathErrnoToErrorCode(directoryPath, errno); return false; } DirectoryGlob(dir, pattern, result); closedir(dir); return true; } std::set Directory::GetFileSystemEntries(const std::string& path, const std::string& pathWithPattern, int32_t attributes, int32_t mask, int* error) { const std::string directoryPath(il2cpp::utils::PathUtils::DirectoryName(pathWithPattern)); const std::string pattern(il2cpp::utils::PathUtils::Basename(pathWithPattern)); std::set globResult; if (DirectoryGlob(directoryPath, pattern, globResult, error) == false) return std::set(); std::set result; for (std::set::const_iterator it = globResult.begin(), end = globResult.end(); it != end; ++it) { const std::string& filename = *it; if (filename == "." || filename == "..") continue; const std::string path(directoryPath + IL2CPP_DIR_SEPARATOR + filename); int attributeError; const int32_t pathAttributes = static_cast(File::GetFileAttributes(path, &attributeError)); if (attributeError != kErrorCodeSuccess) continue; if ((pathAttributes & mask) == attributes) result.insert(path); } *error = kErrorCodeSuccess; return result; } Directory::FindHandle::FindHandle(const utils::StringView& searchPathWithPattern) : osHandle(NULL), handleFlags(os::kNoFindHandleFlags) { directoryPath = il2cpp::utils::PathUtils::DirectoryName(searchPathWithPattern); pattern = il2cpp::utils::PathUtils::Basename(searchPathWithPattern); pattern = il2cpp::utils::CollapseAdjacentStars(pattern); } Directory::FindHandle::~FindHandle() { IL2CPP_ASSERT(osHandle == NULL); } int32_t Directory::FindHandle::CloseOSHandle() { int32_t result = os::kErrorCodeSuccess; if (osHandle != NULL) { int32_t ret = closedir(static_cast(osHandle)); if (ret != 0) result = FileErrnoToErrorCode(errno); osHandle = NULL; } return result; } os::ErrorCode Directory::FindFirstFile(FindHandle* findHandle, const utils::StringView& searchPathWithPattern, Il2CppNativeString* resultFileName, int32_t* resultAttributes) { DIR* dir = opendir(findHandle->directoryPath.c_str()); if (dir == NULL) return PathErrnoToErrorCode(findHandle->directoryPath, errno); findHandle->SetOSHandle(dir); return FindNextFile(findHandle, resultFileName, resultAttributes); } os::ErrorCode Directory::FindNextFile(FindHandle* findHandle, Il2CppNativeString* resultFileName, int32_t* resultAttributes) { errno = 0; dirent* entry; while ((entry = readdir(static_cast(findHandle->osHandle))) != NULL) { const Il2CppNativeString filename(entry->d_name); if (il2cpp::utils::Match(filename, findHandle->pattern)) { const Il2CppNativeString path = utils::PathUtils::Combine(findHandle->directoryPath, filename); int attributeError; const int32_t pathAttributes = static_cast(File::GetFileAttributes(path, &attributeError)); if (attributeError == kErrorCodeSuccess) { *resultFileName = filename; *resultAttributes = pathAttributes; return os::kErrorCodeSuccess; } } } if (errno != 0) return FileErrnoToErrorCode(errno); return os::kErrorCodeNoMoreFiles; } int32_t Directory::CloseOSFindHandleDirectly(intptr_t osHandle) { IL2CPP_ASSERT(0 && "This function should be called for Windows only."); return 0; } } } #endif