fn os_date_t os_local_time(void) { os_date_t result = {0}; time_t t = time(NULL); struct tm *lt = localtime(&t); result.sec = lt->tm_sec; result.min = lt->tm_min; result.hour = lt->tm_hour; result.day = lt->tm_mday; result.month = lt->tm_mon; result.year = lt->tm_year; return result; } fn os_date_t os_universal_time(void) { os_date_t result = {0}; time_t t = time(NULL); struct tm u = {0}; gmtime_r(&t, &u); result.sec = u.tm_sec; result.min = u.tm_min; result.hour = u.tm_hour; result.day = u.tm_mday; result.month = u.tm_mon; result.year = u.tm_year; return result; } fn f64 os_microseconds(void) { struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); u64 result = t.tv_sec*million(1) + (t.tv_nsec/thousand(1)); return (f64)result; } fn f64 os_get_milliseconds(void) { u64 micros = os_get_microseconds(); f64 result = (f64)micros / 1000.0; return result; } fn s8_t os_exe(ma_arena_t *arena) { const i32 buffer_size = 2048; ma_temp_t temp = ma_begin_scratch1(arena); char *buffer = ma_push_array(arena, char, buffer_size); ssize_t size = readlink("/proc/self/exe", buffer, buffer_size); assert(size < buffer_size); // @todo:? assert(size != -1); s8_t string = s8_copy(arena, s8_make(buffer, size)); ma_end_scratch(temp); return string; } fn s8_t os_exe_dir(ma_arena_t *arena) { ma_temp_t temp = ma_begin_scratch1(arena); s8_t exe = os_exe(temp.arena); s8_t dir = s8_chop_last_slash(exe); dir.len += 1; s8_t result = s8_copy(arena, dir); ma_end_scratch(temp); assert(result.str[result.len - 1] == '/'); return result; } fn s8_t os_cwd(ma_arena_t *arena) { const i32 buffer_size = 2048; ma_temp_t temp = ma_begin_scratch1(arena); char *buffer = ma_push_array(arena, char, buffer_size); char *ok = getcwd(buffer, buffer_size); assert(ok); s8_t result = s8_printf(arena, "%s/", buffer); ma_end_scratch(temp); assert(result.str[result.len - 1] == '/'); return result; } fn b32 os_exists(s8_t path) { ma_temp_t temp = ma_begin_scratch(); s8_t copy = s8_copy(temp.arena, path); int ok = access(copy.str, F_OK); ma_end_scratch(temp); return ok == 0 ? true : false; } fn b32 os_is_dir(s8_t path) { b32 result = false; ma_temp_t temp = ma_begin_scratch(); s8_t copy = s8_copy(temp.arena, path); DIR *dir = opendir(copy.str); if (dir) { result = true; closedir(dir); } ma_end_scratch(temp); return result; } fn b32 os_is_file(s8_t path) { ma_temp_t temp = ma_begin_scratch(); s8_t copy = s8_copy(temp.arena, path); struct stat path_stat; stat(copy.str, &path_stat); ma_end_scratch(temp); b32 result = S_ISREG(path_stat.st_mode); return result; } fn b32 os_is_abs(s8_t path) { b32 result = path.len && path.str[0] == '/'; return result; } fn s8_t os_read(ma_arena_t *arena, s8_t path) { s8_t result = {0}; ma_temp_t temp = ma_begin_scratch1(arena); s8_t copy_path = s8_copy(temp.arena, path); FILE *fd = fopen(copy_path.str, "rb"); if (fd) { fseek(fd, 0, SEEK_END); long size = ftell(fd); fseek(fd, 0, SEEK_SET); char *string = malloc(size + 1); fread(string, size, 1, fd); fclose(fd); result = s8_make(string, size); result.str[result.len] = 0; } ma_end_scratch(temp); return result; } fn os_write_t os_write(s8_t path, s8_t content) { os_write_t result = os_write_path_not_found; ma_temp_t scratch = ma_begin_scratch(); s8_t copy_path = s8_copy(scratch.arena, path); FILE *fd = fopen(copy_path.str, "w"); if (fd) { size_t size_written = fwrite(content.str, 1, content.len, fd); assert((int64_t)size_written == content.len); fclose(fd); result = os_write_success; } ma_end_scratch(scratch); return result; }