Directory.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #include "il2cpp-config.h"
  2. #if IL2CPP_TARGET_POSIX && !RUNTIME_TINY && !IL2CPP_USE_PLATFORM_SPECIFIC_DIRECTORY
  3. #include "os/Directory.h"
  4. #include "os/ErrorCodes.h"
  5. #include "os/File.h"
  6. #include "os/Posix/Error.h"
  7. #include "utils/DirectoryUtils.h"
  8. #include "utils/Memory.h"
  9. #include "utils/PathUtils.h"
  10. #include "utils/StringUtils.h"
  11. #include <errno.h>
  12. #include <dirent.h>
  13. #include <stdint.h>
  14. #include <stdlib.h>
  15. #include <unistd.h>
  16. #if IL2CPP_TARGET_QNX
  17. #include <errno.h>
  18. #else
  19. #include <sys/errno.h>
  20. #endif
  21. #include <sys/stat.h>
  22. #include <sys/types.h>
  23. namespace il2cpp
  24. {
  25. namespace os
  26. {
  27. std::string Directory::GetCurrent(int *error)
  28. {
  29. char buf[PATH_MAX + 1];
  30. // Note: not all implementations would allocate a buffer when passing 0 to getcwd, as we used to do.
  31. // this does *not* seem to be part of the POSIX spec:
  32. // http://pubs.opengroup.org/onlinepubs/000095399/functions/getcwd.html
  33. char* cwd = getcwd(buf, PATH_MAX + 1);
  34. if (cwd == NULL)
  35. {
  36. *error = FileErrnoToErrorCode(errno);
  37. return std::string();
  38. }
  39. std::string directory(cwd);
  40. *error = kErrorCodeSuccess;
  41. return directory;
  42. }
  43. bool Directory::SetCurrent(const std::string& path, int *error)
  44. {
  45. const int ret = chdir(path.c_str());
  46. if (ret == -1)
  47. {
  48. *error = FileErrnoToErrorCode(errno);
  49. return false;
  50. }
  51. *error = kErrorCodeSuccess;
  52. return true;
  53. }
  54. bool Directory::Create(const std::string& path, int *error)
  55. {
  56. const int ret = mkdir(path.c_str(), 0777);
  57. if (ret == -1)
  58. {
  59. *error = PathErrnoToErrorCode(path, errno);
  60. return false;
  61. }
  62. *error = kErrorCodeSuccess;
  63. return true;
  64. }
  65. bool Directory::Remove(const std::string& path, int *error)
  66. {
  67. const int ret = rmdir(path.c_str());
  68. if (ret == -1)
  69. {
  70. *error = PathErrnoToErrorCode(path, errno);
  71. return false;
  72. }
  73. *error = kErrorCodeSuccess;
  74. return true;
  75. }
  76. static void DirectoryGlob(DIR *dir, const std::string& pattern, std::set<std::string>& result)
  77. {
  78. if (pattern.empty())
  79. return;
  80. std::string matchPattern = il2cpp::utils::CollapseAdjacentStars(pattern);
  81. struct dirent *entry;
  82. while ((entry = readdir(dir)) != NULL)
  83. {
  84. const std::string filename(entry->d_name);
  85. if (!il2cpp::utils::Match(filename, matchPattern))
  86. continue;
  87. result.insert(filename);
  88. }
  89. }
  90. static bool DirectoryGlob(const std::string& directoryPath, const std::string& pattern, std::set<std::string>& result, int* error)
  91. {
  92. DIR* dir = opendir(directoryPath.c_str());
  93. if (dir == NULL)
  94. {
  95. *error = PathErrnoToErrorCode(directoryPath, errno);
  96. return false;
  97. }
  98. DirectoryGlob(dir, pattern, result);
  99. closedir(dir);
  100. return true;
  101. }
  102. std::set<std::string> Directory::GetFileSystemEntries(const std::string& path, const std::string& pathWithPattern, int32_t attributes, int32_t mask, int* error)
  103. {
  104. const std::string directoryPath(il2cpp::utils::PathUtils::DirectoryName(pathWithPattern));
  105. const std::string pattern(il2cpp::utils::PathUtils::Basename(pathWithPattern));
  106. std::set<std::string> globResult;
  107. if (DirectoryGlob(directoryPath, pattern, globResult, error) == false)
  108. return std::set<std::string>();
  109. std::set<std::string> result;
  110. for (std::set<std::string>::const_iterator it = globResult.begin(), end = globResult.end(); it != end; ++it)
  111. {
  112. const std::string& filename = *it;
  113. if (filename == "." || filename == "..")
  114. continue;
  115. const std::string path(directoryPath + IL2CPP_DIR_SEPARATOR + filename);
  116. int attributeError;
  117. const int32_t pathAttributes = static_cast<int32_t>(File::GetFileAttributes(path, &attributeError));
  118. if (attributeError != kErrorCodeSuccess)
  119. continue;
  120. if ((pathAttributes & mask) == attributes)
  121. result.insert(path);
  122. }
  123. *error = kErrorCodeSuccess;
  124. return result;
  125. }
  126. Directory::FindHandle::FindHandle(const utils::StringView<Il2CppNativeChar>& searchPathWithPattern) :
  127. osHandle(NULL),
  128. handleFlags(os::kNoFindHandleFlags)
  129. {
  130. directoryPath = il2cpp::utils::PathUtils::DirectoryName(searchPathWithPattern);
  131. pattern = il2cpp::utils::PathUtils::Basename(searchPathWithPattern);
  132. pattern = il2cpp::utils::CollapseAdjacentStars(pattern);
  133. }
  134. Directory::FindHandle::~FindHandle()
  135. {
  136. IL2CPP_ASSERT(osHandle == NULL);
  137. }
  138. int32_t Directory::FindHandle::CloseOSHandle()
  139. {
  140. int32_t result = os::kErrorCodeSuccess;
  141. if (osHandle != NULL)
  142. {
  143. int32_t ret = closedir(static_cast<DIR*>(osHandle));
  144. if (ret != 0)
  145. result = FileErrnoToErrorCode(errno);
  146. osHandle = NULL;
  147. }
  148. return result;
  149. }
  150. os::ErrorCode Directory::FindFirstFile(FindHandle* findHandle, const utils::StringView<Il2CppNativeChar>& searchPathWithPattern, Il2CppNativeString* resultFileName, int32_t* resultAttributes)
  151. {
  152. DIR* dir = opendir(findHandle->directoryPath.c_str());
  153. if (dir == NULL)
  154. return PathErrnoToErrorCode(findHandle->directoryPath, errno);
  155. findHandle->SetOSHandle(dir);
  156. return FindNextFile(findHandle, resultFileName, resultAttributes);
  157. }
  158. os::ErrorCode Directory::FindNextFile(FindHandle* findHandle, Il2CppNativeString* resultFileName, int32_t* resultAttributes)
  159. {
  160. errno = 0;
  161. dirent* entry;
  162. while ((entry = readdir(static_cast<DIR*>(findHandle->osHandle))) != NULL)
  163. {
  164. const Il2CppNativeString filename(entry->d_name);
  165. if (il2cpp::utils::Match(filename, findHandle->pattern))
  166. {
  167. const Il2CppNativeString path = utils::PathUtils::Combine(findHandle->directoryPath, filename);
  168. int attributeError;
  169. const int32_t pathAttributes = static_cast<int32_t>(File::GetFileAttributes(path, &attributeError));
  170. if (attributeError == kErrorCodeSuccess)
  171. {
  172. *resultFileName = filename;
  173. *resultAttributes = pathAttributes;
  174. return os::kErrorCodeSuccess;
  175. }
  176. }
  177. }
  178. if (errno != 0)
  179. return FileErrnoToErrorCode(errno);
  180. return os::kErrorCodeNoMoreFiles;
  181. }
  182. int32_t Directory::CloseOSFindHandleDirectly(intptr_t osHandle)
  183. {
  184. IL2CPP_ASSERT(0 && "This function should be called for Windows only.");
  185. return 0;
  186. }
  187. }
  188. }
  189. #endif