#include #include #include #include #include #include #include #include #include #define POSIX_PAGE_SIZE 4096 CORE_Static B32 os_write_file(String filename, String filecontent) { FILE *f = fopen((const char *)filename.str, "w"); if (f) { fwrite(filecontent.str, 1, filecontent.len, f); fclose(f); return true; } return false; } CORE_Static String os_read_file(Alloator *a, String name) { String result = {0}; FILE *f = fopen((char *)name.str, "rb"); if (f) { fseek(f, 0, SEEK_END); result.len = ftell(f); fseek(f, 0, SEEK_SET); result.str = (U8 *)allocate_size(a, result.len + 1, false); fread(result.str, result.len, 1, f); fclose(f); result.str[result.len] = 0; } return result; } CORE_Static String os_get_exe_dir(Allocator *a) { char buffer[PATH_MAX] = {}; if (readlink("/proc/self/exe", buffer, PATH_MAX) == -1) { log_info("Failed to retrieve the path of the executable, the method used is fetching /proc/self/exe, very likely you are using an OS that doesn't follow this convention and as such it is currently not supported"); } String exe = string_from_cstring(buffer); exe = string_chop_last_slash(exe); String result = string_copy(a, exe); log_trace("Retrieved executable path %Q", result); return result; } CORE_Static String os_get_absolute_path(Allocator *a, String path) { assert(path.str[path.len] == 0); char buffer[PATH_MAX] = {}; realpath((char *)path.str, buffer); String abs = string_from_cstring(buffer); String result = string_copy(a, abs); return result; } CORE_Static B32 os_does_file_exist(String path) { B32 result = false; assert(path.str[path.len] == 0); if (access((char *)path.str, F_OK) == 0) { result = true; } log_trace("Does file exist? %Q %d", path, result); return result; } CORE_Static String os_get_working_dir(Allocator *allocator) { char *buffer = allocate_array(allocator, char, PATH_MAX, false); char *result = getcwd(buffer, PATH_MAX); return string_from_cstring(result); } CORE_Static Array os_list_dir(Scratch_Arena *scratch, Allocator *a, String dir, U32 flags = LIST_RECURSE_INTO_DIRS) { Scratch_Scope _scope(scratch); Array dirs_to_read = {scratch}; dirs_to_read.add(dir); Array result = {a}; for (auto it = dirs_to_read.begin(); it != dirs_to_read.end(); it++) { assert(it->str[it->len] == 0); dirent *dir; DIR *d = opendir((char *)it->str); if (d) { while ((dir = readdir(d)) != NULL) { if (dir->d_name[0] == '.') { if (dir->d_name[1] == '.') { if (dir->d_name[2] == 0) continue; } if (dir->d_name[1] == 0) continue; } OS_File_Info entry = {}; entry.relative_path = string_fmt(a, "%Q/%s", *it, dir->d_name); entry.absolute_path = os_get_absolute_path(a, entry.relative_path); if (dir->d_type == DT_DIR) { entry.is_directory = true; if (flags & LIST_RECURSE_INTO_DIRS) { dirs_to_read.add(entry.absolute_path); } } result.add(entry); log_trace("%Q %d", entry.absolute_path, entry.is_directory); } closedir(d); } else { log_info("ERROR Failed to read dir: %Q, errno: %s", *it, strerror(errno)); } } return result; } CORE_Static U8 * os_advance_commit(OS_Memory *m, size_t *commit_size, size_t page_size) { size_t aligned_up_commit = align_up(*commit_size, page_size); size_t to_be_total_commited_size = aligned_up_commit + m->commit; size_t to_be_total_commited_size_clamped_to_reserve = clamp_top(to_be_total_commited_size, m->reserve); size_t adjusted_to_boundary_commit = to_be_total_commited_size_clamped_to_reserve - m->commit; assert_message(adjusted_to_boundary_commit, "Debug WIN32 Error: Reached the virtual memory reserved boundary"); U8 *result = m->data + m->commit; if (adjusted_to_boundary_commit == 0) result = 0; *commit_size = adjusted_to_boundary_commit; return result; } CORE_Static OS_Memory os_reserve(size_t size) { OS_Memory result = {}; size_t size_aligned = align_up(size, POSIX_PAGE_SIZE); result.data = (U8 *)mmap(0, size_aligned, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); assert_message(result.data, POSIX_ERROR "Failed to reserve memory using mmap!!"); if (result.data) { result.reserve = size_aligned; } return result; } CORE_Static B32 os_commit(OS_Memory *m, size_t commit) { B32 result = false; U8 *pointer = os_advance_commit(m, &commit, POSIX_PAGE_SIZE); if (pointer) { int mprotect_result = mprotect(pointer, commit, PROT_READ | PROT_WRITE); assert_message(mprotect_result == 0, "OS1 POSIX Debug Error: Failed to commit more memory using mmap"); if (mprotect_result == 0) { m->commit += commit; result = true; } } return result; } CORE_Static void os_release(OS_Memory *m) { int result = munmap(m->data, m->reserve); assert_message(result == 0, "OS1 POSIX Debug Error: Failed to release virtual memory using munmap"); if (result == 0) { memory_zero(m, sizeof(*m)); } } CORE_Static U64 os_get_microseconds() { timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); U64 result = (((U64)ts.tv_sec) * 1000000ull) + ((U64)ts.tv_nsec) / 1000ull; return result; } CORE_Static F64 os_time() { F64 time = (F64)os_get_microseconds(); F64 result = time / 1000000.0; // Microseconds to seconds return result; } bool os_enable_console_colors() { return true; }