got onyx's filesystem working on windows; bugs on linux
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 11 Dec 2021 21:26:12 +0000 (15:26 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 11 Dec 2021 21:26:12 +0000 (15:26 -0600)
core/os/file.onyx
core/os/onyx_fs.onyx
core/std.onyx
include/bh.h
modules/onyx_runtime/onyx_runtime.c

index 9795e64e7c7feb59b504637907983d204e0a6281..3705ba1f771fb76d7b0ce12ff95832b1ebb9b5dd 100644 (file)
@@ -4,18 +4,19 @@ use package core
 #local fs :: package runtime.fs
 
 FileError :: enum {
-    None;
-    NotFound;
-    Exists;
-    Permission;
-    BadFile;
+    None       :: 0x00;
+    NotFound   :: 0x01;
+    Exists     :: 0x02;
+    Permission :: 0x03;
+    BadFile    :: 0x04;
+    BadMode    :: 0x05;
 }
 
 OpenMode :: enum {
-    Invalid;
-    Read;
-    Write;
-    Append;
+    Invalid :: 0x00;
+    Read    :: 0x01;
+    Write   :: 0x02;
+    Append  :: 0x03;
 }
 
 File :: struct {
index afd229cd85049bf0ebc9c5f11a541ff22f4b0091..f176a5280572540ffc260662315da6a145beecd7 100644 (file)
@@ -5,7 +5,7 @@ use package core
 FileData :: struct {
     Handle :: #distinct i64
 
-    handle: Handle;
+    handle: Handle = -1;
 }
 
 __file_open :: (path: str, mode := os.OpenMode.Read) -> (FileData, os.FileError) {
@@ -16,62 +16,59 @@ __file_open :: (path: str, mode := os.OpenMode.Read) -> (FileData, os.FileError)
     return fd, error;
 }
 
-#package {
-    #foreign "onyx_runtime" {
-        __file_open_impl :: (path: str, mode: os.OpenMode, out_handle: ^Handle) -> os.FileError ---
+#foreign "onyx_runtime" {
+    __file_open_impl :: (path: str, mode: os.OpenMode, out_handle: ^FileData.Handle) -> os.FileError ---
 
-        __file_close :: (fd: FileData) -> os.FileError ---
-        __file_exists :: (path: str) -> bool ---
+    __file_close :: (fd: FileData) -> os.FileError ---
+    __file_exists :: (path: str) -> bool ---
 
-        __file_seek  :: (handle: Handle, to: i32, whence: io.SeekFrom) -> io.Error ---
-        __file_tell  :: (handle: Handle, out_position: ^u32) -> io.Error ---
-        __file_read  :: (handle: Handle, output_buffer: [] u8, bytes_read: ^u32) -> io.Error ---
-        __file_write :: (handle: Handle, input_buffer: [] u8, bytes_wrote: ^u32) -> io.Error ---
-        __file_flush :: (handle: Handle) -> io.Error;
-    }
+    __file_seek  :: (handle: FileData.Handle, to: i32, whence: io.SeekFrom) -> i32 ---
+    __file_tell  :: (handle: FileData.Handle) -> u32 ---
+    __file_read  :: (handle: FileData.Handle, output_buffer: [] u8, bytes_read: ^u64) -> io.Error ---
+    __file_write :: (handle: FileData.Handle, input_buffer: [] u8, bytes_wrote: ^u64) -> io.Error ---
+    __file_flush :: (handle: FileData.Handle) -> io.Error ---
 }
 
 __file_stream_vtable := io.Stream_Vtable.{
     seek = (use fs: ^os.File, to: i32, whence: io.SeekFrom) -> io.Error {
-        return __file_seek(data.handle, to, whence);
+        now := __file_seek(data.handle, to, whence);
+        return (.None) if now >= 0 else .BadFile;
     },
 
     tell = (use fs: ^os.File) -> (io.Error, u32) {
-        position: u32;
-        error := __file_tell(data.handle, ^position);
-        return error, position;
+        return .None, __file_tell(data.handle);
     },
 
     read = (use fs: ^os.File, buffer: [] u8) -> (io.Error, u32) {
-        bytes_read: u32;
+        bytes_read: u64;
         error := __file_read(data.handle, buffer, ^bytes_read);
-        return error, bytes_read;
+        return error, ~~bytes_read;
     },
 
     read_at = (use fs: ^os.File, at: u32, buffer: [] u8) -> (io.Error, u32) {
         __file_seek(data.handle, at, .Start);
-        bytes_read: u32;
+        bytes_read: u64;
         error := __file_read(data.handle, buffer, ^bytes_read);
-        return error, bytes_read;
+        return error, ~~bytes_read;
     },
 
     read_byte = (use fs: ^os.File) -> (io.Error, u8) {
         byte: u8;
         error := __file_read(data.handle, ~~ cast([1] u8) ^byte, null);
-        return byte;
+        return error, byte;
     },
 
     write = (use fs: ^os.File, buffer: [] u8) -> (io.Error, u32) {
-        bytes_wrote: u32;
+        bytes_wrote: u64;
         error := __file_write(data.handle, buffer, ^bytes_wrote);
-        return error, bytes_wrote;
+        return error, ~~bytes_wrote;
     },
 
     write_at = (use fs: ^os.File, at: u32, buffer: [] u8) -> (io.Error, u32) {
         __file_seek(data.handle, at, .Start);
-        bytes_wrote: u32;
+        bytes_wrote: u64;
         error := __file_write(data.handle, buffer, ^bytes_wrote);
-        return error, bytes_wrote;
+        return error, ~~bytes_wrote;
     },
 
     write_byte = (use fs: ^os.File, byte: u8) -> io.Error {
index e951680e2f9c03377862b9e7c19f0eb8f7735897..04ece5715fd5b6af4adc92750fe447fc94650504 100644 (file)
@@ -47,7 +47,8 @@ package core
 
 #if runtime.Runtime == runtime.Runtime_Onyx   {
     #load "./runtime/onyx_run"
-    #load "core/os/process"
+    #load "./os/process"
+    #load "./os/onyx_fs"
 }
 #if runtime.Runtime == runtime.Runtime_Wasi   {
     #load "./runtime/wasi"
index 7483ff9c95303972ce430aa3b9f3cb01e9430da0..66e86433f99a60fee3de509487655313e45edfc6 100644 (file)
@@ -365,6 +365,7 @@ bh_file_error bh_file_open_mode(bh_file* file, bh_file_mode mode, const char* fi
 bh_file_error bh_file_new(bh_file* file, bh_file_descriptor fd, const char* filename);
 b32 bh_file_read_at(bh_file* file, i64 offset, void* buffer, isize buff_size, isize* bytes_read);
 b32 bh_file_write_at(bh_file* file, i64 offset, void const* buffer, isize buff_size, isize* bytes_wrote);
+i64 bh_file_seek(bh_file* file, i64 offset, bh_file_whence whence);
 i64 bh_file_seek_to(bh_file* file, i64 offset);
 i64 bh_file_seek_to_end(bh_file* file);
 i64 bh_file_skip(bh_file* file, i64 bytes);
@@ -372,6 +373,7 @@ i64 bh_file_tell(bh_file* file);
 bh_file_error bh_file_close(bh_file* file);
 i32 bh_file_read(bh_file* file, void* buffer, isize buff_size);
 i32 bh_file_write(bh_file* file, void* buffer, isize buff_size);
+void bh_file_flush(bh_file* file);
 i64 bh_file_size(bh_file* file);
 b32 bh_file_exists(char const* filename);
 char* bh_path_get_full_name(char const* filename, bh_allocator a);
@@ -1447,6 +1449,7 @@ b32 bh_file_write_at(bh_file* file, i64 offset, void const* buffer, isize buff_s
     bh__file_seek_wrapper(file->fd, 0, BH_FILE_WHENCE_CURRENT, &current_offset);
 
 #if defined(_BH_WINDOWS)
+    if (current_offset != offset) bh_file_seek_to(file, offset);
     res = (isize) WriteFile(file->fd, buffer, buff_size, (i32 *) bytes_wrote, NULL);
     return res;
 
@@ -1484,6 +1487,12 @@ static b32 bh__file_seek_wrapper(bh_file_descriptor fd, i64 offset, bh_file_when
 }
 
 // Returns new offset
+i64 bh_file_seek(bh_file* file, i64 offset, bh_file_whence whence) {
+    i64 new_offset = -1;
+    bh__file_seek_wrapper(file->fd, offset, whence, &new_offset);
+    return new_offset;
+}
+
 i64 bh_file_seek_to(bh_file* file, i64 offset) {
     i64 new_offset = -1;
     bh__file_seek_wrapper(file->fd, offset, BH_FILE_WHENCE_BEGIN, &new_offset);
@@ -1534,6 +1543,12 @@ b32 bh_file_write(bh_file* file, void* buffer, isize buff_size) {
     return bh_file_write_at(file, bh_file_tell(file), buffer, buff_size, NULL);
 }
 
+void bh_file_flush(bh_file* file) {
+    #ifdef _BH_LINUX
+    fdatasync(file->fd);
+    #endif
+}
+
 i64 bh_file_size(bh_file* file) {
     i64 size = 0;
     i64 prev = bh_file_tell(file);
index 7128cef4deaf7b7b970b13f89fbd2558cf087208..f8d52d11a63e971a0e55751bc93b1a0e13c1cd41 100644 (file)
 
 #include "types.h"  // For POINTER_SIZE
 
+#define ONYX_FILE_ERROR_NONE 0
+#define ONYX_FILE_ERROR_NOT_FOUND 1
+#define ONYX_FILE_ERROR_EXISTS 2
+#define ONYX_FILE_ERROR_PERMISSION 3
+#define ONYX_FILE_ERROR_BAD_FILE 4
+#define ONYX_FILE_ERROR_BAD_MODE 5
+
+ONYX_DEF(__file_open_impl, (WASM_I32, WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
+    char *path_ptr = ONYX_PTR(params->data[0].of.i32);
+    int   path_len = params->data[1].of.i32;
+
+    char path[512] = {0};
+    strncpy(path, path_ptr, path_len);
+    path[path_len] = 0;
+
+    int mode = params->data[2].of.i32;
+
+    bh_file_mode bh_mode;
+    switch (mode) {
+        case 1: bh_mode = BH_FILE_MODE_READ; break;
+        case 2: bh_mode = BH_FILE_MODE_WRITE; break;
+        case 3: bh_mode = BH_FILE_MODE_APPEND; break;
+    }
+
+    bh_file file;
+    bh_file_error error = bh_file_open_mode(&file, bh_mode, path);
+    if (error == BH_FILE_ERROR_INVALID) {
+        results->data[0] = WASM_I32_VAL(ONYX_FILE_ERROR_NOT_FOUND);
+        return NULL;
+    }
+
+    *(u64 *) ONYX_PTR(params->data[3].of.i32) = (u64) file.fd;
+    results->data[0] = WASM_I32_VAL(ONYX_FILE_ERROR_NONE);
+    return NULL;
+}
+
+ONYX_DEF(__file_close, (WASM_I64), (WASM_I32)) {
+    i64 fd = params->data[0].of.i64;
+
+    bh_file file = { (bh_file_descriptor) fd };
+    bh_file_error error = bh_file_close(&file);
+    if (error == BH_FILE_ERROR_INVALID) {
+        results->data[0] = WASM_I32_VAL(ONYX_FILE_ERROR_NOT_FOUND);
+        return NULL;
+    }
+
+    results->data[0] = WASM_I32_VAL(ONYX_FILE_ERROR_NONE);
+    return NULL;
+}
+
+ONYX_DEF(__file_exists, (WASM_I32, WASM_I32), (WASM_I32)) {
+    char *path_ptr = ONYX_PTR(params->data[0].of.i32);
+    int   path_len = params->data[1].of.i32;
+
+    char path[512] = {0};
+    strncpy(path, path_ptr, path_len);
+    path[path_len] = 0;
+
+    results->data[0] = WASM_I32_VAL(bh_file_exists(path));
+    return NULL;
+}
+
+ONYX_DEF(__file_seek, (WASM_I64, WASM_I32, WASM_I32), (WASM_I32)) {
+    i64 fd = params->data[0].of.i64;
+    i32 offset = params->data[1].of.i32;
+    i32 whence = params->data[2].of.i32;
+
+    bh_file file = { (bh_file_descriptor) fd };
+    bh_file_whence bh_whence;
+    switch (whence) {
+        case 0: bh_whence = BH_FILE_WHENCE_BEGIN; break;
+        case 1: bh_whence = BH_FILE_WHENCE_CURRENT; break;
+        case 2: bh_whence = BH_FILE_WHENCE_END; break;
+    }
+
+    i64 new_offset = bh_file_seek(&file, offset, whence);
+    results->data[0] = WASM_I32_VAL((i32) new_offset);
+    return NULL;
+}
+
+ONYX_DEF(__file_tell, (WASM_I64), (WASM_I32)) {
+    i64 fd = params->data[0].of.i64;
+    bh_file file = { (bh_file_descriptor) fd };
+    results->data[0] = WASM_I32_VAL(bh_file_tell(&file));
+    return NULL;
+}
+
+ONYX_DEF(__file_read, (WASM_I64, WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
+    i64 fd = params->data[0].of.i64;
+    bh_file file = { (bh_file_descriptor) fd };
+    b32 success = bh_file_read_at(&file,
+            bh_file_tell(&file),
+            ONYX_PTR(params->data[1].of.i32),
+            params->data[2].of.i32,
+            (i64 *) ONYX_PTR(params->data[3].of.i32));
+
+    results->data[0] = WASM_I32_VAL(0);
+    if (!success) results->data[0] = WASM_I32_VAL(6);
+    return NULL;
+}
+
+ONYX_DEF(__file_write, (WASM_I64, WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
+    i64 fd = params->data[0].of.i64;
+    bh_file file = { (bh_file_descriptor) fd };
+    b32 success = bh_file_write_at(&file,
+            bh_file_tell(&file),
+            ONYX_PTR(params->data[1].of.i32),
+            params->data[2].of.i32,
+            (i64 *) ONYX_PTR(params->data[3].of.i32));
+
+    results->data[0] = WASM_I32_VAL(0);
+    if (!success) results->data[0] = WASM_I32_VAL(6);
+    return NULL;
+}
+
+ONYX_DEF(__file_flush, (WASM_I64), (WASM_I32)) {
+    i64 fd = params->data[0].of.i64;
+    bh_file file = { (bh_file_descriptor) fd };
+    bh_file_flush(&file);
+    results->data[0] = WASM_I32_VAL(0);
+    return NULL;
+}
+
+
+//
+// THREADS
+//
 typedef struct OnyxThread {
     i32 id;
     i32 tls_base;
@@ -143,6 +270,12 @@ ONYX_DEF(__kill_thread, (WASM_I32), (WASM_I32)) {
     return NULL;
 }
 
+
+
+
+//
+// PROCESS
+//
 #define ONYX_PROCESS_MAGIC_NUMBER 0xdeadfadebabecafe
 typedef struct OnyxProcess {
     u64 magic_number;
@@ -458,6 +591,15 @@ ONYX_DEF(__process_destroy, (WASM_I64), ()) {
 }
 
 ONYX_LIBRARY {
+    ONYX_FUNC(__file_open_impl)
+    ONYX_FUNC(__file_close)
+    ONYX_FUNC(__file_exists)
+    ONYX_FUNC(__file_seek)
+    ONYX_FUNC(__file_tell)
+    ONYX_FUNC(__file_read)
+    ONYX_FUNC(__file_write)
+    ONYX_FUNC(__file_flush)
+
     ONYX_FUNC(__spawn_thread)
     ONYX_FUNC(__kill_thread)