| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- /*
- * Copyright (c) 2012-2023 Daniele Bartolini et al.
- * SPDX-License-Identifier: MIT
- */
- #include "core/containers/vector.inl"
- #include "core/error/error.h"
- #include "core/memory/temp_allocator.inl"
- #include "core/os.h"
- #include "core/platform.h"
- #include "core/strings/dynamic_string.inl"
- #include "core/strings/string_stream.h"
- #include <string.h> // strcmp
- #include <sys/stat.h> // stat, mkdir
- #if CROWN_PLATFORM_WINDOWS
- #include <io.h> // _access
- #include <stdio.h>
- #ifndef WIN32_LEAN_AND_MEAN
- #define WIN32_LEAN_AND_MEAN
- #endif
- #include <windows.h>
- #else
- #include <dirent.h> // opendir, readdir
- #include <dlfcn.h> // dlopen, dlclose, dlsym
- #include <errno.h>
- #include <stdio.h> // fputs, rename
- #include <stdlib.h> // getenv
- #include <string.h> // memset
- #include <sys/wait.h> // wait
- #include <time.h> // clock_gettime
- #include <unistd.h> // unlink, rmdir, getcwd, access, chdir
- #endif // if CROWN_PLATFORM_WINDOWS
- #if CROWN_PLATFORM_ANDROID
- #include <android/log.h>
- #endif
- namespace crown
- {
- namespace os
- {
- void sleep(u32 ms)
- {
- #if CROWN_PLATFORM_WINDOWS
- Sleep(ms);
- #else
- usleep(ms * 1000);
- #endif
- }
- void *library_open(const char *path)
- {
- #if CROWN_PLATFORM_WINDOWS
- return (void *)LoadLibraryA(path);
- #else
- return ::dlopen(path, RTLD_LAZY);
- #endif
- }
- void library_close(void *library)
- {
- #if CROWN_PLATFORM_WINDOWS
- FreeLibrary((HMODULE)library);
- #else
- dlclose(library);
- #endif
- }
- void *library_symbol(void *library, const char *name)
- {
- #if CROWN_PLATFORM_WINDOWS
- return (void *)GetProcAddress((HMODULE)library, name);
- #else
- return ::dlsym(library, name);
- #endif
- }
- void log(const char *msg)
- {
- #if CROWN_PLATFORM_ANDROID
- __android_log_write(ANDROID_LOG_DEBUG, "crown", msg);
- #else
- fputs(msg, stdout);
- fflush(stdout);
- #endif
- #if CROWN_PLATFORM_WINDOWS
- OutputDebugStringA(msg);
- #endif
- }
- #if CROWN_PLATFORM_POSIX
- void stat(Stat &info, int fd)
- {
- info.file_type = Stat::NO_ENTRY;
- info.size = 0;
- info.mtime = 0;
- struct stat buf;
- memset(&buf, 0, sizeof(buf));
- int err = ::fstat(fd, &buf);
- if (err != 0)
- return;
- if (S_ISREG(buf.st_mode) == 1)
- info.file_type = Stat::REGULAR;
- else if (S_ISDIR(buf.st_mode) == 1)
- info.file_type = Stat::DIRECTORY;
- info.size = buf.st_size;
- info.mtime = buf.st_mtim.tv_sec * s64(1000000000) + buf.st_mtim.tv_nsec;
- }
- #endif // if CROWN_PLATFORM_POSIX
- void stat(Stat &info, const char *path)
- {
- info.file_type = Stat::NO_ENTRY;
- info.size = 0;
- info.mtime = 0;
- #if CROWN_PLATFORM_WINDOWS
- WIN32_FIND_DATAA wfd;
- HANDLE fh = FindFirstFileA(path, &wfd);
- if (fh == INVALID_HANDLE_VALUE)
- return;
- FindClose(fh);
- if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
- info.file_type = Stat::DIRECTORY;
- else // Assume regular file.
- info.file_type = Stat::REGULAR;
- ULARGE_INTEGER fs = {};
- fs.LowPart = wfd.nFileSizeLow;
- fs.HighPart = wfd.nFileSizeHigh;
- info.size = fs.QuadPart;
- ULARGE_INTEGER lwt = {};
- lwt.LowPart = wfd.ftLastWriteTime.dwLowDateTime;
- lwt.HighPart = wfd.ftLastWriteTime.dwHighDateTime;
- info.mtime = lwt.QuadPart * u64(100); // See https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime
- #else
- struct stat buf;
- memset(&buf, 0, sizeof(buf));
- int err = ::stat(path, &buf);
- if (err != 0)
- return;
- if (S_ISREG(buf.st_mode) == 1)
- info.file_type = Stat::REGULAR;
- else if (S_ISDIR(buf.st_mode) == 1)
- info.file_type = Stat::DIRECTORY;
- info.size = buf.st_size;
- info.mtime = buf.st_mtim.tv_sec * s64(1000000000) + buf.st_mtim.tv_nsec;
- #endif // if CROWN_PLATFORM_WINDOWS
- }
- DeleteResult delete_file(const char *path)
- {
- DeleteResult dr;
- #if CROWN_PLATFORM_WINDOWS
- if (DeleteFile(path) != 0)
- dr.error = DeleteResult::SUCCESS;
- else if (GetLastError() == ERROR_FILE_NOT_FOUND)
- dr.error = DeleteResult::NO_ENTRY;
- // else if (GetLastError() == ERROR_ACCESS_DENIED)
- // dr.error = DeleteResult::NOT_FILE;
- else
- dr.error = DeleteResult::UNKNOWN;
- #else
- if (::unlink(path) == 0)
- dr.error = DeleteResult::SUCCESS;
- else if (errno == ENOENT)
- dr.error = DeleteResult::NO_ENTRY;
- else
- dr.error = DeleteResult::UNKNOWN;
- #endif
- return dr;
- }
- CreateResult create_directory(const char *path)
- {
- CreateResult cr;
- #if CROWN_PLATFORM_WINDOWS
- if (CreateDirectory(path, NULL) != 0)
- cr.error = CreateResult::SUCCESS;
- else if (GetLastError() == ERROR_ALREADY_EXISTS)
- cr.error = CreateResult::ALREADY_EXISTS;
- else
- cr.error = CreateResult::UNKNOWN;
- #else
- if (::mkdir(path, 0755) == 0)
- cr.error = CreateResult::SUCCESS;
- else if (errno == EEXIST)
- cr.error = CreateResult::ALREADY_EXISTS;
- else
- cr.error = CreateResult::UNKNOWN;
- #endif
- return cr;
- }
- DeleteResult delete_directory(const char *path)
- {
- DeleteResult dr;
- #if CROWN_PLATFORM_WINDOWS
- if (RemoveDirectory(path) != 0)
- dr.error = DeleteResult::SUCCESS;
- else if (GetLastError() == ERROR_FILE_NOT_FOUND)
- dr.error = DeleteResult::NO_ENTRY;
- // else if (GetLastError() == ERROR_DIRECTORY
- // dr.error = DeleteResult::NOT_DIRECTORY;
- else
- dr.error = DeleteResult::UNKNOWN;
- #else
- if (::rmdir(path) == 0)
- dr.error = DeleteResult::SUCCESS;
- else if (errno == ENOENT)
- dr.error = DeleteResult::NO_ENTRY;
- else
- dr.error = DeleteResult::UNKNOWN;
- #endif
- return dr;
- }
- const char *getcwd(char *buf, u32 size)
- {
- #if CROWN_PLATFORM_WINDOWS
- GetCurrentDirectory(size, buf);
- return buf;
- #else
- return ::getcwd(buf, size);
- #endif
- }
- void setcwd(const char *cwd)
- {
- #if CROWN_PLATFORM_WINDOWS
- BOOL ret = SetCurrentDirectory(cwd);
- CE_UNUSED(ret);
- #else
- int ret = chdir(cwd);
- CE_UNUSED(ret);
- #endif
- }
- const char *getenv(const char *name)
- {
- #if CROWN_PLATFORM_WINDOWS
- // GetEnvironmentVariable(name, buf, size);
- return NULL;
- #else
- return ::getenv(name);
- #endif
- }
- void list_files(const char *path, Vector<DynamicString> &files)
- {
- #if CROWN_PLATFORM_WINDOWS
- TempAllocator256 ta_path;
- DynamicString cur_path(ta_path);
- cur_path += path;
- cur_path += "\\*";
- WIN32_FIND_DATA ffd;
- HANDLE file = FindFirstFile(cur_path.c_str(), &ffd);
- if (file != INVALID_HANDLE_VALUE) {
- do {
- const char *dname = ffd.cFileName;
- if (!strcmp(dname, ".") || !strcmp(dname, ".."))
- continue;
- TempAllocator256 ta;
- DynamicString fname(ta);
- fname.set(dname, strlen32(dname));
- vector::push_back(files, fname);
- } while (FindNextFile(file, &ffd) != 0);
- FindClose(file);
- }
- #else
- struct dirent *entry;
- DIR *dir = opendir(path);
- if (dir != NULL) {
- while ((entry = readdir(dir))) {
- const char *dname = entry->d_name;
- if (!strcmp(dname, ".") || !strcmp(dname, ".."))
- continue;
- TempAllocator256 ta;
- DynamicString fname(ta);
- fname.set(dname, strlen32(dname));
- vector::push_back(files, fname);
- }
- closedir(dir);
- }
- #endif // if CROWN_PLATFORM_WINDOWS
- }
- ///
- s32 access(const char *path, u32 flags)
- {
- #if CROWN_PLATFORM_WINDOWS
- return ::_access(path, flags == AccessFlags::EXECUTE ? AccessFlags::EXISTS : flags);
- #else
- return ::access(path, flags);
- #endif
- }
- RenameResult rename(const char *old_name, const char *new_name)
- {
- RenameResult rr;
- #if CROWN_PLATFORM_WINDOWS
- if (MoveFile(old_name, new_name) != 0)
- rr.error = RenameResult::SUCCESS;
- else
- rr.error = RenameResult::UNKNOWN;
- #else
- if (::rename(old_name, new_name) == 0)
- rr.error == RenameResult::SUCCESS;
- else
- rr.error = RenameResult::UNKNOWN;
- #endif
- return rr;
- }
- } // namespace os
- } // namespace crown
|