summaryrefslogtreecommitdiff
path: root/src/user/knob/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/user/knob/file.c')
-rw-r--r--src/user/knob/file.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/user/knob/file.c b/src/user/knob/file.c
new file mode 100644
index 0000000..8ab7acd
--- /dev/null
+++ b/src/user/knob/file.c
@@ -0,0 +1,82 @@
+#include <pland/syscall.h>
+#include <knob/format.h>
+#include <knob/heap.h>
+#include <knob/env.h>
+
+struct file {
+ _file_handle_t handle;
+ uint32_t position;
+ uint32_t length;
+};
+
+static const char *try_remove_prefix(const char *path, uint8_t *dn_out) {
+ if ((path[0] != 's') || (path[1] != 'd'))
+ return 0;
+
+ const char *num_part = path + 2;
+ for (uint32_t i = 0; num_part[i]; ++i)
+ if (num_part[i] == ':') {
+
+ uint32_t dn_large;
+ if (!try_sntoi(num_part, i, &dn_large) || dn_large > 255)
+ return 0;
+
+ *dn_out = (uint8_t)dn_large;
+ return num_part + i + 1;
+ }
+
+ return 0;
+}
+
+struct file *open_file(const char *path) {
+ uint8_t dn;
+ const char *path_part = try_remove_prefix(path, &dn);
+ if (path_part)
+ path = path_part;
+ else
+ dn = current_drive;
+
+ _file_handle_t h = _open_file(dn, path);
+ if (!h)
+ return 0;
+
+ struct file *f = get_block(sizeof(struct file));
+ f->handle = h;
+ f->position = 0;
+ f->length = _file_size(h);
+
+ return f;
+}
+
+void close_file(struct file *f) {
+ _close_file(f->handle);
+ free_block(f);
+}
+
+uint32_t read_from_file(struct file *f, uint32_t max, void *buf) {
+ if (f->position + max > f->length)
+ max = f->length - f->position;
+
+ uint32_t read = _file_read(f->handle, f->position, max, buf);
+
+ f->position += read;
+ return read;
+}
+
+uint32_t seek_file_to(struct file *f, uint32_t to) {
+ if (to > f->length)
+ to = f->length;
+ return f->position = to;
+}
+
+int32_t seek_file_by(struct file *f, int32_t by) {
+ uint32_t old = f->position;
+ uint32_t to = old + by > f->length ? f->length : old + by;
+ f->position = to;
+ return to - old;
+}
+
+__attribute__ ((pure))
+uint32_t file_size(struct file *f) {
+ return f->length;
+} \ No newline at end of file