aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/vfs.zig67
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 {