diff options
author | Himbeer <himbeer@disroot.org> | 2024-07-25 11:06:49 +0200 |
---|---|---|
committer | Himbeer <himbeer@disroot.org> | 2024-07-25 11:06:49 +0200 |
commit | 801b5c029bb141dfa427fdb815b982790eea2d58 (patch) | |
tree | a84971e402892c2e470205d7da2941e3350a3817 /src | |
parent | c1e1dac051399ad7445e725f0eb8a601beafb1c2 (diff) |
vfs+syscall: Flatten nested control flow
Fixes #54.
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/syscall.zig | 38 | ||||
-rw-r--r-- | src/lib/vfs.zig | 247 |
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 { |