More includes for Linux Update build script to copy assets and compile shaders Added base code directory as include path Added FS_SystemPath Made asset loading work directory agnostic
216 lines
4.3 KiB
C
216 lines
4.3 KiB
C
OS_Handle FS_FileOpen(Str8 path, FS_AccessFlags access) {
|
|
OS_Handle result = { 0 };
|
|
|
|
M_TempScope(0, 0) {
|
|
Str8 zpath = Str8_Copy(temp.arena, path);
|
|
|
|
int mode = 0644;
|
|
int flags = 0;
|
|
if (access & FS_ACCESS_READ) {
|
|
if (access & FS_ACCESS_WRITE) {
|
|
flags = O_RDWR | O_CREAT;
|
|
}
|
|
else {
|
|
flags = O_RDONLY;
|
|
}
|
|
}
|
|
else if (access & FS_ACCESS_WRITE) {
|
|
flags = O_WRONLY | O_CREAT;
|
|
}
|
|
|
|
|
|
int fd = open((const char *) zpath.data, flags, mode);
|
|
result.v[0] = (fd > 0) ? (U64) fd : 0;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
void FS_FileClose(OS_Handle file) {
|
|
int fd = cast(int) file.v[0];
|
|
if (fd > 0) {
|
|
close(fd);
|
|
}
|
|
}
|
|
|
|
void FS_FileRead(OS_Handle file, void *ptr, U64 size, U64 offset) {
|
|
int fd = cast(int) file.v[0];
|
|
if (fd > 0) {
|
|
U8 *buffer = ptr;
|
|
U64 current = offset;
|
|
U64 remainder = size;
|
|
|
|
while (remainder != 0) {
|
|
S64 nread = pread(fd, buffer, remainder, current);
|
|
if (nread <= 0) {
|
|
break;
|
|
}
|
|
|
|
buffer += nread;
|
|
current += nread;
|
|
remainder -= nread;
|
|
}
|
|
}
|
|
}
|
|
|
|
void FS_FileWrite(OS_Handle file, void *ptr, U64 size, U64 offset) {
|
|
int fd = cast(int) file.v[0];
|
|
if (fd > 0) {
|
|
U8 *buffer = ptr;
|
|
U64 current = offset;
|
|
U64 remainder = size;
|
|
|
|
while (remainder != 0) {
|
|
S64 nwritten = pwrite(fd, buffer, remainder, current);
|
|
if (nwritten <= 0) {
|
|
break;
|
|
}
|
|
|
|
buffer += nwritten;
|
|
current += nwritten;
|
|
remainder -= nwritten;
|
|
}
|
|
}
|
|
}
|
|
|
|
U64 FS_FileSize(OS_Handle file) {
|
|
U64 result = 0;
|
|
|
|
int fd = cast(int) file.v[0];
|
|
if (fd > 0) {
|
|
struct stat sb;
|
|
fstat(fd, &sb);
|
|
|
|
result = sb.st_size;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
FS_List FS_PathList(M_Arena *arena, Str8 path) {
|
|
FS_List result = { 0 };
|
|
|
|
M_TempScope(1, &arena) {
|
|
Str8 zpath = Str8_Copy(temp.arena, path);
|
|
|
|
DIR *dir = opendir((const char *) zpath.data);
|
|
|
|
struct dirent *ent = readdir(dir);
|
|
while (ent != 0) {
|
|
if (ent->d_name[0] != '.') {
|
|
FS_Entry *entry = M_ArenaPush(arena, FS_Entry);
|
|
|
|
entry->basename = Str8_Copy(arena, Sz(ent->d_name));
|
|
entry->path = Sf(arena, "%.*s/%.*s", Sv(path), Sv(entry->basename));
|
|
|
|
struct stat sb;
|
|
stat((const char *) entry->path.data, &sb);
|
|
|
|
entry->type = ((sb.st_mode & S_IFMT) == S_IFDIR) ? FS_ENTRY_TYPE_DIR : FS_ENTRY_TYPE_FILE;
|
|
entry->time = (sb.st_mtim.tv_sec * 1e9) + sb.st_mtim.tv_nsec;
|
|
entry->size = sb.st_size;
|
|
|
|
SLL_Enqueue(result.first, result.last, entry);
|
|
result.count += 1;
|
|
}
|
|
|
|
ent = readdir(dir);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
Str8 FS_SystemPath(M_Arena *arena, FS_SystemPathType path) {
|
|
Str8 result = { 0 };
|
|
|
|
switch (path) {
|
|
case FS_SYSTEM_PATH_EXE: {
|
|
U64 offset = M_ArenaOffset(arena);
|
|
|
|
Str8 buffer;
|
|
buffer.count = KB(1);
|
|
buffer.data = M_ArenaPush(arena, U8, .count = buffer.count);
|
|
|
|
ssize_t nwritten = 0;
|
|
for (;;) {
|
|
nwritten = readlink("/proc/self/exe", cast(char *) buffer.data, buffer.count);
|
|
if (nwritten < buffer.count) {
|
|
break;
|
|
}
|
|
|
|
M_ArenaPop(arena, offset);
|
|
|
|
buffer.count *= 2;
|
|
buffer.data = M_ArenaPush(arena, U8, .count = buffer.count);
|
|
}
|
|
|
|
if (nwritten > 0) {
|
|
// Walk back until the prevous slash, then null-terminate there
|
|
while (buffer.data[nwritten] != '/') { nwritten -= 1; }
|
|
buffer.data[nwritten] = 0;
|
|
|
|
M_ArenaPopSize(arena, buffer.count - nwritten - 1);
|
|
|
|
result.count = nwritten;
|
|
result.data = buffer.data;
|
|
}
|
|
else {
|
|
M_ArenaPop(arena, offset);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case FS_SYSTEM_PATH_WORKING: {
|
|
U64 offset = M_ArenaOffset(arena);
|
|
|
|
Str8 buffer;
|
|
buffer.count = KB(1);
|
|
buffer.data = M_ArenaPush(arena, U8, .count = buffer.count);
|
|
|
|
char *wd;
|
|
|
|
for (;;) {
|
|
wd = getcwd((char *) buffer.data, buffer.count);
|
|
if (wd != 0) {
|
|
break;
|
|
}
|
|
else if (errno != ERANGE) {
|
|
break;
|
|
}
|
|
|
|
M_ArenaPop(arena, offset);
|
|
|
|
buffer.count *= 2;
|
|
buffer.data = M_ArenaPush(arena, U8, .count = buffer.count);
|
|
}
|
|
|
|
if (wd) {
|
|
result = Sz(wd);
|
|
M_ArenaPopSize(arena, buffer.count - result.count - 1);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case FS_SYSTEM_PATH_USER: {
|
|
char *home = getenv("HOME");
|
|
if (home) {
|
|
result = Sf(arena, "%s/.local/share", home);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case FS_SYSTEM_PATH_TEMP: {
|
|
char *temp = getenv("TEMP");
|
|
if (temp) {
|
|
result = Str8_Copy(arena, Sz(temp));
|
|
}
|
|
else {
|
|
result = Str8_Copy(arena, S("/tmp"));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|