diff options
author | Himbeer <himbeer@disroot.org> | 2024-07-21 12:16:20 +0200 |
---|---|---|
committer | Himbeer <himbeer@disroot.org> | 2024-07-21 12:16:20 +0200 |
commit | 797fb6901a1fe386475216d79ef75f46d4361bd6 (patch) | |
tree | 3eec662d210195b0840f16c0a56aaecb95e09da5 /src | |
parent | 512256e4a3e4a77a445dbda5ca6cb692f5c92bbd (diff) |
vfs: Support reading and writing files
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/vfs.zig | 67 |
1 files changed, 53 insertions, 14 deletions
diff --git a/src/lib/vfs.zig b/src/lib/vfs.zig index f601ddb..7083c7c 100644 --- a/src/lib/vfs.zig +++ b/src/lib/vfs.zig @@ -4,11 +4,12 @@ const std = @import("std"); +const mem = @import("mem.zig"); const paging = @import("paging.zig"); const process = @import("process.zig"); const sysexchange = @import("sysexchange.zig"); -const mem = std.mem; +const Allocator = std.mem.Allocator; const TermHook = process.Info.TermHook; @@ -90,6 +91,10 @@ pub const DirHook = extern struct { pub const RemoveFn = *allowzero const fn (name_ptr: [*]const u8, name_len: usize) callconv(.C) sysexchange.Result(void); }; +pub const FileContext = extern struct { + inner: *allowzero anyopaque, +}; + pub const ResourceKind = enum(u32) { stream, file, @@ -133,10 +138,10 @@ pub const DirEntry = struct { pub const Node = std.DoublyLinkedList(DirEntry).Node; pub const Tree = struct { - allocator: mem.Allocator, + allocator: Allocator, nodes: std.DoublyLinkedList(DirEntry), - pub fn init(allocator: mem.Allocator) Tree { + pub fn init(allocator: Allocator) Tree { return .{ .allocator = allocator, .nodes = std.DoublyLinkedList(DirEntry){}, @@ -148,7 +153,7 @@ pub const Tree = struct { while (node) |current_node| { if (current_node.next == current_node) break; - if (mem.eql(u8, current_node.data.name, name)) return current_node; + if (std.mem.eql(u8, current_node.data.name, name)) return current_node; node = current_node.next; } return null; @@ -175,11 +180,15 @@ pub const OpenResult = union(enum) { pub const ResourceDescriptor = struct { inode: *Inode, + context: ?*FileContext, - pub fn init(inode: *Inode) !ResourceDescriptor { + pub fn init(allocator: Allocator, inode: *Inode) !ResourceDescriptor { inode.refs = std.math.add(usize, inode.refs, 1) catch return Error.TooManyReferences; + + const context = if (inode.resource.tag == .file) try allocator.create(FileContext) else null; return .{ .inode = inode, + .context = context, }; } @@ -221,7 +230,24 @@ pub const ResourceDescriptor = struct { .copy = copy, }, hook); }, - .hook => Error.ReadNotSupported, + .file => { + const file = self.inode.resource.data.file; + + const readFn = file.readFn orelse return Error.ReadNotSupported; + if (self.inode.pid == 0) { + return readFn(self.context.?, buffer.ptr, buffer.len).toErrorUnion(); + } + + const driver = process.latestThread(self.inode.pid).?; + const copy = try driver.copyBuffer(buffer); + + proc.state = .suspended; + try call(driver, readFn, .{ self.context.?, copy.ptr, copy.len }, .{ + .cleanupFn = moveBack, + .buffer = buffer, + .copy = copy, + }, hook); + }, else => Error.ReadNotSupported, }; } @@ -256,7 +282,20 @@ pub const ResourceDescriptor = struct { proc.state = .suspended; try call(driver, writeFn, .{ copy.ptr, copy.len }, null, hook); }, - .hook => Error.WriteNotSupported, + .file => { + const file = self.inode.resource.data.file; + + const writeFn = file.writeFn orelse return Error.WriteNotSupported; + if (self.inode.pid == 0) { + return writeFn(self.context.?, bytes.ptr, bytes.len).toErrorUnion(); + } + + const driver = process.latestThread(self.inode.pid).?; + const copy = try driver.copyBytes(bytes); + + proc.state = .suspended; + try call(driver, writeFn, .{ self.context.?, copy.ptr, copy.len }, null, hook); + }, else => Error.WriteNotSupported, }; } @@ -280,7 +319,7 @@ pub const UserInfo = union(enum) { value: sysexchange.Result(usize), }; -pub fn init(allocator: mem.Allocator) !void { +pub fn init(allocator: Allocator) !void { const tree = try allocator.create(Tree); tree.* = Tree.init(allocator); root.data.inode.resource.data.dir = tree; @@ -305,7 +344,7 @@ pub fn find(path: []const u8) ?*Inode { else => null, // Not a directory (or directory hook). } orelse return null; - if (mem.eql(u8, component.path, path)) { + if (std.mem.eql(u8, component.path, path)) { return inode; } resource = inode.resource; @@ -365,7 +404,7 @@ pub fn provideResource(path: []const u8, resource: Resource, pid: u16, options: } pub fn provideResourceZ(path_c: [*:0]const u8, resource: Resource, pid: u16, options: Options) !void { - return provideResource(mem.sliceTo(path_c, 0), resource, pid, options); + return provideResource(std.mem.sliceTo(path_c, 0), resource, pid, options); } pub fn open(proc: *process.Info, path: []const u8, data: usize) !OpenResult { @@ -387,23 +426,23 @@ pub fn open(proc: *process.Info, path: []const u8, data: usize) !OpenResult { .context = proc, }); }, - else => .{ .rd = try ResourceDescriptor.init(inode) }, + else => .{ .rd = try ResourceDescriptor.init(mem.page_allocator, inode) }, }; } pub fn openZ(proc: *process.Info, path_c: [*:0]const u8, data: usize) !OpenResult { - return open(proc, mem.sliceTo(path_c, 0), data); + return open(proc, std.mem.sliceTo(path_c, 0), data); } pub fn openNonHook(path: []const u8) !ResourceDescriptor { const inode = find(path) orelse return Error.NotFound; if (inode.resource.tag == .hook) return Error.IsAHook; - return ResourceDescriptor.init(inode); + return ResourceDescriptor.init(mem.page_allocator, inode); } pub fn openNonHookZ(path_c: [*:0]const u8) !ResourceDescriptor { - return openNonHook(mem.sliceTo(path_c, 0)); + return openNonHook(std.mem.sliceTo(path_c, 0)); } fn call(proc: *process.Info, function: *const anyopaque, args: anytype, cleanup_hook: ?process.Info.CleanupHook, term_hook: ?process.Info.TermHook) !noreturn { |