aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/syscall.zig38
-rw-r--r--src/lib/vfs.zig247
2 files changed, 147 insertions, 138 deletions
diff --git a/src/lib/syscall.zig b/src/lib/syscall.zig
index 21934b6..4600a2d 100644
--- a/src/lib/syscall.zig
+++ b/src/lib/syscall.zig
@@ -213,28 +213,32 @@ fn remove(trap_frame: *trap.Frame) void {
if (vfs.find(dirname)) |inode| {
const basename = std.fs.path.basenamePosix(path);
- switch (inode.resource.tag) {
- .dir => {
- const dir = inode.resource.data.dir;
- sysexchange.frameReturn(null, trap_frame, dir.remove(basename));
- },
- .dir_hook => {
- const dir_hook = inode.resource.data.dir_hook;
-
- if (dir_hook.removeFn) |removeFn| {
- const result = removeFn(basename.ptr, basename.len);
- sysexchange.frameReturnResult(void, trap_frame, result);
- } else {
- sysexchange.frameReturn(void, trap_frame, vfs.Error.RemoveNotSupported);
- }
- },
- else => sysexchange.frameReturn(void, trap_frame, vfs.Error.NotADirectory),
- }
+ removeFrom(trap_frame, inode, basename);
} else {
sysexchange.frameReturn(void, trap_frame, vfs.Error.NotFound);
}
}
+fn removeFrom(trap_frame: *trap.Frame, inode: *vfs.Inode, basename: []const u8) void {
+ switch (inode.resource.tag) {
+ .dir => {
+ const dir = inode.resource.data.dir;
+ sysexchange.frameReturn(null, trap_frame, dir.remove(basename));
+ },
+ .dir_hook => {
+ const dir_hook = inode.resource.data.dir_hook;
+
+ const removeFn = dir_hook.removeFn orelse {
+ sysexchange.frameReturn(void, trap_frame, vfs.Error.RemoveNotSupported);
+ return;
+ };
+ const result = removeFn(basename.ptr, basename.len);
+ sysexchange.frameReturnResult(void, trap_frame, result);
+ },
+ else => sysexchange.frameReturn(void, trap_frame, vfs.Error.NotADirectory),
+ }
+}
+
// read(handle: usize, buffer: [*]u8, len: usize) Result(usize)
fn read(proc: *process.Info, trap_frame: *trap.Frame) void {
paging.setUserMemoryAccess(true);
diff --git a/src/lib/vfs.zig b/src/lib/vfs.zig
index bf1ac85..ccfd5ff 100644
--- a/src/lib/vfs.zig
+++ b/src/lib/vfs.zig
@@ -237,44 +237,44 @@ pub const ResourceDescriptor = struct {
}
return switch (self.inode.resource.tag) {
- .stream => {
- const stream = self.inode.resource.data.stream;
+ .stream => self.readStream(self.inode.resource.data.stream, proc, buffer, hook),
+ .file => self.readFile(self.inode.resource.data.file, proc, buffer, hook),
+ else => Error.ReadNotSupported,
+ };
+ }
- const readFn = stream.readFn orelse return Error.ReadNotSupported;
- if (self.inode.pid == 0) {
- return readFn(buffer.ptr, buffer.len).toErrorUnion();
- }
+ fn readStream(self: ResourceDescriptor, stream: Stream, proc: *process.Info, buffer: []u8, hook: TermHook) !usize {
+ const readFn = stream.readFn orelse return Error.ReadNotSupported;
+ if (self.inode.pid == 0) {
+ return readFn(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, .{ copy.ptr, copy.len }, .{
- .cleanupFn = moveBack,
- .buffer = buffer,
- .copy = copy,
- }, hook);
- },
- .file => {
- const file = self.inode.resource.data.file;
+ const driver = process.latestThread(self.inode.pid).?;
+ const copy = try driver.copyBuffer(buffer);
- const readFn = file.readFn orelse return Error.ReadNotSupported;
- if (self.inode.pid == 0) {
- return readFn(self.context.?, buffer.ptr, buffer.len).toErrorUnion();
- }
+ proc.state = .suspended;
+ try call(driver, readFn, .{ copy.ptr, copy.len }, .{
+ .cleanupFn = moveBack,
+ .buffer = buffer,
+ .copy = copy,
+ }, hook);
+ }
- 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,
- };
+ fn readFile(self: ResourceDescriptor, file: File, proc: *process.Info, buffer: []u8, hook: TermHook) !usize {
+ 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);
}
pub fn write(self: ResourceDescriptor, proc: *process.Info, bytes: []const u8) !usize {
@@ -293,36 +293,36 @@ pub const ResourceDescriptor = struct {
}
return switch (self.inode.resource.tag) {
- .stream => {
- const stream = self.inode.resource.data.stream;
+ .stream => self.writeStream(self.inode.resource.data.stream, proc, bytes, hook),
+ .file => self.writeFile(self.inode.resource.data.file, proc, bytes, hook),
+ else => Error.WriteNotSupported,
+ };
+ }
- const writeFn = stream.writeFn orelse return Error.WriteNotSupported;
- if (self.inode.pid == 0) {
- return writeFn(bytes.ptr, bytes.len).toErrorUnion();
- }
+ fn writeStream(self: ResourceDescriptor, stream: Stream, proc: *process.Info, bytes: []const u8, hook: TermHook) !usize {
+ const writeFn = stream.writeFn orelse return Error.WriteNotSupported;
+ if (self.inode.pid == 0) {
+ return writeFn(bytes.ptr, bytes.len).toErrorUnion();
+ }
- const driver = process.latestThread(self.inode.pid).?;
- const copy = try driver.copyBytes(bytes);
+ const driver = process.latestThread(self.inode.pid).?;
+ const copy = try driver.copyBytes(bytes);
- proc.state = .suspended;
- try call(driver, writeFn, .{ copy.ptr, copy.len }, null, hook);
- },
- .file => {
- const file = self.inode.resource.data.file;
+ proc.state = .suspended;
+ try call(driver, writeFn, .{ copy.ptr, copy.len }, null, hook);
+ }
- const writeFn = file.writeFn orelse return Error.WriteNotSupported;
- if (self.inode.pid == 0) {
- return writeFn(self.context.?, bytes.ptr, bytes.len).toErrorUnion();
- }
+ fn writeFile(self: ResourceDescriptor, file: File, proc: *process.Info, bytes: []const u8, hook: TermHook) !usize {
+ 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);
+ 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,
- };
+ proc.state = .suspended;
+ try call(driver, writeFn, .{ self.context.?, copy.ptr, copy.len }, null, hook);
}
fn moveBack(driver: *const process.Info, buffer: []u8, copy: []const u8) void {
@@ -379,83 +379,88 @@ pub fn find(path: []const u8) ?*Inode {
return &root.data.inode;
}
+fn reclaim(node: *Node, resource: Resource, pid: u16, options: Options) !void {
+ if (node.data.inode.flags.detached and node.data.inode.options.reclaimable) {
+ node.data.inode = .{
+ .resource = resource,
+ .pid = pid,
+ .options = options,
+ .flags = .{},
+ };
+ } else return Error.AlreadyExists;
+}
+
+fn provideInDir(dir: *Tree, basename: []const u8, resource: Resource, pid: u16, options: Options) !void {
+ if (dir.find(basename)) |node| {
+ return reclaim(node, resource, pid, options);
+ }
+
+ return dir.provideResource(.{
+ .name = basename,
+ .inode = .{
+ .resource = resource,
+ .pid = pid,
+ .options = options,
+ .flags = .{},
+ },
+ });
+}
+
+fn provideInDirHook(dir_hook: DirHook, basename: []const u8, resource: Resource, pid: u16, options: Options) !void {
+ // fixme: Check for duplicate resources with the same path
+ // fixme: Doesn't call into U-mode drivers correctly
+
+ return if (dir_hook.provideFn) |provideFn|
+ provideFn(basename.ptr, basename.len, .{
+ .resource = resource,
+ .pid = pid,
+ .options = options,
+ .flags = .{},
+ }).toErrorUnion()
+ else
+ Error.ProvideNotSupported;
+}
+
pub fn provideResource(path: []const u8, resource: Resource, pid: u16, options: Options) !void {
if (!std.fs.path.isAbsolutePosix(path)) return Error.RelativePathNotAllowed;
const dirname = std.fs.path.dirnamePosix(path) orelse return Error.NoAbsoluteContainingDirectory;
- if (find(dirname)) |inode| {
- const basename = std.fs.path.basenamePosix(path);
- return switch (inode.resource.tag) {
- .dir => blk: {
- const dir = inode.resource.data.dir;
-
- if (dir.find(basename)) |node| {
- if (node.data.inode.flags.detached and node.data.inode.options.reclaimable) {
- node.data.inode = .{
- .resource = resource,
- .pid = pid,
- .options = options,
- .flags = .{},
- };
- break :blk;
- } else break :blk Error.AlreadyExists;
- }
+ const basename = std.fs.path.basenamePosix(path);
- break :blk dir.provideResource(.{
- .name = basename,
- .inode = .{
- .resource = resource,
- .pid = pid,
- .options = options,
- .flags = .{},
- },
- });
- },
- .dir_hook => blk: {
- const dir_hook = inode.resource.data.dir_hook;
-
- // fixme: Check for duplicate resources with the same path
-
- break :blk if (dir_hook.provideFn) |provideFn|
- provideFn(basename.ptr, basename.len, .{
- .resource = resource,
- .pid = pid,
- .options = options,
- .flags = .{},
- }).toErrorUnion()
- else
- Error.ProvideNotSupported;
- },
- else => Error.NotADirectory,
- };
- } else return Error.NotFound;
+ const inode = find(dirname) orelse return Error.NotFound;
+ return switch (inode.resource.tag) {
+ .dir => provideInDir(inode.resource.data.dir, basename, resource, pid, options),
+ .dir_hook => provideInDirHook(inode.resource.data.dir_hook, basename, resource, pid, options),
+ else => Error.NotADirectory,
+ };
}
pub fn provideResourceZ(path_c: [*:0]const u8, resource: Resource, pid: u16, options: Options) !void {
return provideResource(std.mem.sliceTo(path_c, 0), resource, pid, options);
}
-pub fn open(proc: *process.Info, path: []const u8, data: usize) !OpenResult {
- const inode = find(path) orelse return Error.NotFound;
- return switch (inode.resource.tag) {
- .hook => blk: {
- const hook = inode.resource.data.hook;
+fn callHook(hook: Hook, pid: u16, proc: *process.Info, data: usize) !usize {
+ if (pid == 0) {
+ return hook.callback(proc.id, proc.thread_id, data).toErrorUnion();
+ }
- if (inode.pid == 0) {
- const result = hook.callback(proc.id, proc.thread_id, data);
- break :blk .{ .data = try result.toErrorUnion() };
- }
+ const driver = process.latestThread(pid).?;
- const driver = process.latestThread(inode.pid).?;
+ proc.state = .suspended;
+ try call(driver, hook.callback, .{ proc.id, proc.thread_id, data }, null, .{
+ .hookFn = crossProcessReturn,
+ .context = proc,
+ });
+}
- proc.state = .suspended;
- try call(driver, hook.callback, .{ proc.id, proc.thread_id, data }, null, .{
- .hookFn = crossProcessReturn,
- .context = proc,
- });
- },
- else => .{ .rd = try ResourceDescriptor.init(mem.page_allocator, inode) },
- };
+pub fn open(proc: *process.Info, path: []const u8, data: usize) !OpenResult {
+ const inode = find(path) orelse return Error.NotFound;
+ if (inode.resource.tag == .hook) {
+ const data_out = try callHook(inode.resource.data.hook, inode.pid, proc, data);
+ return .{ .data = data_out };
+ }
+
+ return .{ .rd = try ResourceDescriptor.init(mem.page_allocator, inode) };
}
pub fn openZ(proc: *process.Info, path_c: [*:0]const u8, data: usize) !OpenResult {