os.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /*
  2. * Copyright (c) 2012-2018 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/dbartolini/crown/blob/master/LICENSE
  4. */
  5. #include "core/containers/vector.h"
  6. #include "core/error/error.h"
  7. #include "core/memory/temp_allocator.h"
  8. #include "core/os.h"
  9. #include "core/platform.h"
  10. #include "core/strings/dynamic_string.h"
  11. #include "core/strings/string_stream.h"
  12. #include <string.h> // strcmp
  13. #include <sys/stat.h> // stat, mkdir
  14. #if CROWN_PLATFORM_POSIX
  15. #include <dirent.h> // opendir, readdir
  16. #include <dlfcn.h> // dlopen, dlclose, dlsym
  17. #include <errno.h>
  18. #include <stdio.h> // fputs
  19. #include <stdlib.h> // getenv
  20. #include <string.h> // memset
  21. #include <sys/wait.h> // wait
  22. #include <time.h> // clock_gettime
  23. #include <unistd.h> // unlink, rmdir, getcwd, access
  24. #elif CROWN_PLATFORM_WINDOWS
  25. #include <io.h> // _access
  26. #include <stdio.h>
  27. #include <windows.h>
  28. #endif
  29. #if CROWN_PLATFORM_ANDROID
  30. #include <android/log.h>
  31. #endif
  32. namespace crown
  33. {
  34. namespace os
  35. {
  36. void sleep(u32 ms)
  37. {
  38. #if CROWN_PLATFORM_POSIX
  39. usleep(ms * 1000);
  40. #elif CROWN_PLATFORM_WINDOWS
  41. Sleep(ms);
  42. #endif
  43. }
  44. void* library_open(const char* path)
  45. {
  46. #if CROWN_PLATFORM_POSIX
  47. return ::dlopen(path, RTLD_LAZY);
  48. #elif CROWN_PLATFORM_WINDOWS
  49. return (void*)LoadLibraryA(path);
  50. #endif
  51. }
  52. void library_close(void* library)
  53. {
  54. #if CROWN_PLATFORM_POSIX
  55. dlclose(library);
  56. #elif CROWN_PLATFORM_WINDOWS
  57. FreeLibrary((HMODULE)library);
  58. #endif
  59. }
  60. void* library_symbol(void* library, const char* name)
  61. {
  62. #if CROWN_PLATFORM_POSIX
  63. return ::dlsym(library, name);
  64. #elif CROWN_PLATFORM_WINDOWS
  65. return (void*)GetProcAddress((HMODULE)library, name);
  66. #endif
  67. }
  68. void log(const char* msg)
  69. {
  70. #if CROWN_PLATFORM_ANDROID
  71. __android_log_write(ANDROID_LOG_DEBUG, "crown", msg);
  72. #elif CROWN_PLATFORM_WINDOWS
  73. OutputDebugStringA(msg);
  74. #else
  75. fputs(msg, stdout);
  76. fflush(stdout);
  77. #endif
  78. }
  79. #if CROWN_PLATFORM_POSIX
  80. void stat(Stat& info, int fd)
  81. {
  82. info.file_type = Stat::NO_ENTRY;
  83. info.size = 0;
  84. info.mtime = 0;
  85. struct stat buf;
  86. memset(&buf, 0, sizeof(buf));
  87. int err = ::fstat(fd, &buf);
  88. if (err != 0)
  89. return;
  90. if (S_ISREG(buf.st_mode) == 1)
  91. info.file_type = Stat::REGULAR;
  92. else if (S_ISDIR(buf.st_mode) == 1)
  93. info.file_type = Stat::DIRECTORY;
  94. info.size = buf.st_size;
  95. info.mtime = buf.st_mtime;
  96. }
  97. #endif
  98. void stat(Stat& info, const char* path)
  99. {
  100. info.file_type = Stat::NO_ENTRY;
  101. info.size = 0;
  102. info.mtime = 0;
  103. #if CROWN_PLATFORM_POSIX
  104. struct stat buf;
  105. memset(&buf, 0, sizeof(buf));
  106. int err = ::stat(path, &buf);
  107. if (err != 0)
  108. return;
  109. if (S_ISREG(buf.st_mode) == 1)
  110. info.file_type = Stat::REGULAR;
  111. else if (S_ISDIR(buf.st_mode) == 1)
  112. info.file_type = Stat::DIRECTORY;
  113. #elif CROWN_PLATFORM_WINDOWS
  114. struct _stat64 buf;
  115. int err = ::_stat64(path, &buf);
  116. if (err != 0)
  117. return;
  118. if ((buf.st_mode & _S_IFREG) != 0)
  119. info.file_type = Stat::REGULAR;
  120. else if ((buf.st_mode & _S_IFDIR) != 0)
  121. info.file_type = Stat::DIRECTORY;
  122. #endif
  123. info.size = buf.st_size;
  124. info.mtime = buf.st_mtime;
  125. }
  126. DeleteResult delete_file(const char* path)
  127. {
  128. DeleteResult dr;
  129. #if CROWN_PLATFORM_POSIX
  130. if (::unlink(path) == 0)
  131. dr.error = DeleteResult::SUCCESS;
  132. else if (errno == ENOENT)
  133. dr.error = DeleteResult::NO_ENTRY;
  134. else
  135. dr.error = DeleteResult::UNKNOWN;
  136. #elif CROWN_PLATFORM_WINDOWS
  137. if (DeleteFile(path) != 0)
  138. dr.error = DeleteResult::SUCCESS;
  139. else if (GetLastError() == ERROR_FILE_NOT_FOUND)
  140. dr.error = DeleteResult::NO_ENTRY;
  141. // else if (GetLastError() == ERROR_ACCESS_DENIED)
  142. // dr.error = DeleteResult::NOT_FILE;
  143. else
  144. dr.error = DeleteResult::UNKNOWN;
  145. #endif
  146. return dr;
  147. }
  148. CreateResult create_directory(const char* path)
  149. {
  150. CreateResult cr;
  151. #if CROWN_PLATFORM_POSIX
  152. if (::mkdir(path, 0755) == 0)
  153. cr.error = CreateResult::SUCCESS;
  154. else if (errno == EEXIST)
  155. cr.error = CreateResult::ALREADY_EXISTS;
  156. else
  157. cr.error = CreateResult::UNKNOWN;
  158. #elif CROWN_PLATFORM_WINDOWS
  159. if (CreateDirectory(path, NULL) != 0)
  160. cr.error = CreateResult::SUCCESS;
  161. else if (GetLastError() == ERROR_ALREADY_EXISTS)
  162. cr.error = CreateResult::ALREADY_EXISTS;
  163. else
  164. cr.error = CreateResult::UNKNOWN;
  165. #endif
  166. return cr;
  167. }
  168. DeleteResult delete_directory(const char* path)
  169. {
  170. DeleteResult dr;
  171. #if CROWN_PLATFORM_POSIX
  172. if (::rmdir(path) == 0)
  173. dr.error = DeleteResult::SUCCESS;
  174. else if (errno == ENOENT)
  175. dr.error = DeleteResult::NO_ENTRY;
  176. else
  177. dr.error = DeleteResult::UNKNOWN;
  178. #elif CROWN_PLATFORM_WINDOWS
  179. if (RemoveDirectory(path) != 0)
  180. dr.error = DeleteResult::SUCCESS;
  181. else if (GetLastError() == ERROR_FILE_NOT_FOUND)
  182. dr.error = DeleteResult::NO_ENTRY;
  183. // else if (GetLastError() == ERROR_DIRECTORY
  184. // dr.error = DeleteResult::NOT_DIRECTORY;
  185. else
  186. dr.error = DeleteResult::UNKNOWN;
  187. #endif
  188. return dr;
  189. }
  190. const char* getcwd(char* buf, u32 size)
  191. {
  192. #if CROWN_PLATFORM_POSIX
  193. return ::getcwd(buf, size);
  194. #elif CROWN_PLATFORM_WINDOWS
  195. GetCurrentDirectory(size, buf);
  196. return buf;
  197. #endif
  198. }
  199. const char* getenv(const char* name)
  200. {
  201. #if CROWN_PLATFORM_POSIX
  202. return ::getenv(name);
  203. #elif CROWN_PLATFORM_WINDOWS
  204. // GetEnvironmentVariable(name, buf, size);
  205. return NULL;
  206. #endif
  207. }
  208. void list_files(const char* path, Vector<DynamicString>& files)
  209. {
  210. #if CROWN_PLATFORM_POSIX
  211. DIR *dir;
  212. struct dirent *entry;
  213. if (!(dir = opendir(path)))
  214. return;
  215. while ((entry = readdir(dir)))
  216. {
  217. const char* dname = entry->d_name;
  218. if (!strcmp(dname, ".") || !strcmp(dname, ".."))
  219. continue;
  220. TempAllocator512 ta;
  221. DynamicString fname(ta);
  222. fname.set(dname, strlen32(dname));
  223. vector::push_back(files, fname);
  224. }
  225. closedir(dir);
  226. #elif CROWN_PLATFORM_WINDOWS
  227. TempAllocator1024 ta;
  228. DynamicString cur_path(ta);
  229. cur_path += path;
  230. cur_path += "\\*";
  231. WIN32_FIND_DATA ffd;
  232. HANDLE file = FindFirstFile(cur_path.c_str(), &ffd);
  233. if (file == INVALID_HANDLE_VALUE)
  234. return;
  235. do
  236. {
  237. const char* dname = ffd.cFileName;
  238. if (!strcmp(dname, ".") || !strcmp(dname, ".."))
  239. continue;
  240. TempAllocator512 ta;
  241. DynamicString fname(ta);
  242. fname.set(dname, strlen32(dname));
  243. vector::push_back(files, fname);
  244. }
  245. while (FindNextFile(file, &ffd) != 0);
  246. FindClose(file);
  247. #endif
  248. }
  249. ///
  250. s32 access(const char* path, u32 flags)
  251. {
  252. #if CROWN_PLATFORM_POSIX
  253. return ::access(path, flags);
  254. #elif CROWN_PLATFORM_WINDOWS
  255. return ::_access(path, flags == AccessFlags::EXECUTE ? AccessFlags::EXISTS : flags);
  256. #endif
  257. }
  258. } // namespace os
  259. } // namespace crown