os.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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, fork, execv
  24. #elif CROWN_PLATFORM_WINDOWS
  25. #include <io.h>
  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. void stat(Stat& info, const char* path)
  80. {
  81. info.file_type = Stat::NO_ENTRY;
  82. info.size = 0;
  83. info.mtime = 0;
  84. #if CROWN_PLATFORM_POSIX
  85. struct stat buf;
  86. memset(&buf, 0, sizeof(buf));
  87. int err = ::stat(path, &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. #elif CROWN_PLATFORM_WINDOWS
  95. struct _stat64 buf;
  96. int err = ::_stat64(path, &buf);
  97. if (err != 0)
  98. return;
  99. if ((buf.st_mode & _S_IFREG) != 0)
  100. info.file_type = Stat::REGULAR;
  101. else if ((buf.st_mode & _S_IFDIR) != 0)
  102. info.file_type = Stat::DIRECTORY;
  103. #endif
  104. info.size = buf.st_size;
  105. info.mtime = buf.st_mtime;
  106. }
  107. void delete_file(const char* path)
  108. {
  109. #if CROWN_PLATFORM_POSIX
  110. int err = ::unlink(path);
  111. CE_ASSERT(err == 0, "unlink: errno = %d", errno);
  112. CE_UNUSED(err);
  113. #elif CROWN_PLATFORM_WINDOWS
  114. BOOL err = DeleteFile(path);
  115. CE_ASSERT(err != 0, "DeleteFile: GetLastError = %d", GetLastError());
  116. CE_UNUSED(err);
  117. #endif
  118. }
  119. void create_directory(const char* path)
  120. {
  121. #if CROWN_PLATFORM_POSIX
  122. int err = ::mkdir(path, 0755);
  123. CE_ASSERT(err == 0, "mkdir: errno = %d", errno);
  124. CE_UNUSED(err);
  125. #elif CROWN_PLATFORM_WINDOWS
  126. BOOL err = CreateDirectory(path, NULL);
  127. CE_ASSERT(err != 0, "CreateDirectory: GetLastError = %d", GetLastError());
  128. CE_UNUSED(err);
  129. #endif
  130. }
  131. void delete_directory(const char* path)
  132. {
  133. #if CROWN_PLATFORM_POSIX
  134. int err = ::rmdir(path);
  135. CE_ASSERT(err == 0, "rmdir: errno = %d", errno);
  136. CE_UNUSED(err);
  137. #elif CROWN_PLATFORM_WINDOWS
  138. BOOL err = RemoveDirectory(path);
  139. CE_ASSERT(err != 0, "RemoveDirectory: GetLastError = %d", GetLastError());
  140. CE_UNUSED(err);
  141. #endif
  142. }
  143. const char* getcwd(char* buf, u32 size)
  144. {
  145. #if CROWN_PLATFORM_POSIX
  146. return ::getcwd(buf, size);
  147. #elif CROWN_PLATFORM_WINDOWS
  148. GetCurrentDirectory(size, buf);
  149. return buf;
  150. #endif
  151. }
  152. const char* getenv(const char* name)
  153. {
  154. #if CROWN_PLATFORM_POSIX
  155. return ::getenv(name);
  156. #elif CROWN_PLATFORM_WINDOWS
  157. // GetEnvironmentVariable(name, buf, size);
  158. return NULL;
  159. #endif
  160. }
  161. void list_files(const char* path, Vector<DynamicString>& files)
  162. {
  163. #if CROWN_PLATFORM_POSIX
  164. DIR *dir;
  165. struct dirent *entry;
  166. if (!(dir = opendir(path)))
  167. return;
  168. while ((entry = readdir(dir)))
  169. {
  170. const char* dname = entry->d_name;
  171. if (!strcmp(dname, ".") || !strcmp(dname, ".."))
  172. continue;
  173. TempAllocator512 ta;
  174. DynamicString fname(ta);
  175. fname.set(dname, strlen32(dname));
  176. vector::push_back(files, fname);
  177. }
  178. closedir(dir);
  179. #elif CROWN_PLATFORM_WINDOWS
  180. TempAllocator1024 ta;
  181. DynamicString cur_path(ta);
  182. cur_path += path;
  183. cur_path += "\\*";
  184. WIN32_FIND_DATA ffd;
  185. HANDLE file = FindFirstFile(cur_path.c_str(), &ffd);
  186. if (file == INVALID_HANDLE_VALUE)
  187. return;
  188. do
  189. {
  190. const char* dname = ffd.cFileName;
  191. if (!strcmp(dname, ".") || !strcmp(dname, ".."))
  192. continue;
  193. TempAllocator512 ta;
  194. DynamicString fname(ta);
  195. fname.set(dname, strlen32(dname));
  196. vector::push_back(files, fname);
  197. }
  198. while (FindNextFile(file, &ffd) != 0);
  199. FindClose(file);
  200. #endif
  201. }
  202. int execute_process(const char* const* argv, StringStream& output)
  203. {
  204. TempAllocator512 ta;
  205. StringStream path(ta);
  206. path << argv[0];
  207. path << ' ';
  208. #if CROWN_PLATFORM_POSIX
  209. path << "2>&1 ";
  210. #endif
  211. for (s32 i = 1; argv[i] != NULL; ++i)
  212. {
  213. const char* arg = argv[i];
  214. for (; *arg; ++arg)
  215. {
  216. if (*arg == ' ')
  217. path << '\\';
  218. path << *arg;
  219. }
  220. path << ' ';
  221. }
  222. #if CROWN_PLATFORM_POSIX
  223. FILE* file = popen(string_stream::c_str(path), "r");
  224. char buf[1024];
  225. while (fgets(buf, sizeof(buf), file) != NULL)
  226. output << buf;
  227. return pclose(file);
  228. #elif CROWN_PLATFORM_WINDOWS
  229. STARTUPINFO info;
  230. memset(&info, 0, sizeof(info));
  231. info.cb = sizeof(info);
  232. PROCESS_INFORMATION process;
  233. memset(&process, 0, sizeof(process));
  234. int err = CreateProcess(argv[0]
  235. , (LPSTR)string_stream::c_str(path)
  236. , NULL
  237. , NULL
  238. , FALSE
  239. , CREATE_NO_WINDOW
  240. , NULL
  241. , NULL
  242. , &info
  243. , &process
  244. );
  245. CE_ASSERT(err != 0, "CreateProcess: GetLastError = %d", GetLastError());
  246. CE_UNUSED(err);
  247. DWORD exitcode = 1;
  248. ::WaitForSingleObject(process.hProcess, INFINITE);
  249. GetExitCodeProcess(process.hProcess, &exitcode);
  250. CloseHandle(process.hProcess);
  251. CloseHandle(process.hThread);
  252. return (int)exitcode;
  253. #endif
  254. }
  255. } // namespace os
  256. } // namespace crown