aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-06-30 23:23:40 +0200
committerHimbeer <himbeer@disroot.org>2024-06-30 23:23:40 +0200
commitc188a18be912a03b00d501cd83eeaff63f6ff950 (patch)
treed531c48e4b855c9c6b9af8c0ceda38c51a0d116f
parent94350ea697204f4701bb9923d63158537a7fbc49 (diff)
syscall: Add provideStream (provide a VFS stream resource)
-rw-r--r--src/lib/syscall.zig56
-rw-r--r--src/lib/sysexchange.zig60
-rw-r--r--src/lib/vfs.zig42
3 files changed, 108 insertions, 50 deletions
diff --git a/src/lib/syscall.zig b/src/lib/syscall.zig
index 0e0c1f1..07c62fd 100644
--- a/src/lib/syscall.zig
+++ b/src/lib/syscall.zig
@@ -4,32 +4,20 @@
const instructions = @import("instructions.zig");
const paging = @import("paging.zig");
+const sysexchange = @import("sysexchange.zig");
const trap = @import("trap.zig");
+const vfs = @import("vfs.zig");
pub const Error = error{
UnknownSyscall,
};
-pub const Status = enum(usize) {
- success,
-};
-
-pub const ReadFn = *const fn (context: u16, buffer: []u8) Result(usize);
-pub const WriteFn = *const fn (context: u16, bytes: []const u8) Result(usize);
-
-pub fn Result(comptime T: type) type {
- return struct {
- status: Status,
- value: T,
- };
-}
-
-pub fn handle(trap_frame: *const trap.Frame) !void {
+pub fn handle(trap_frame: *trap.Frame) !void {
switch (trap_frame.general_purpose_registers[17]) {
100000 => uprint(trap_frame),
100001 => open(trap_frame),
100002 => close(trap_frame),
- 100003 => provide(trap_frame),
+ 100003 => provideStream(trap_frame),
100004 => remove(trap_frame),
else => return Error.UnknownSyscall,
}
@@ -48,9 +36,9 @@ fn uprint(trap_frame: *const trap.Frame) void {
w.print("User message: {s}\r\n", .{str}) catch unreachable;
}
-// open(path: *const [:0]u8) Result(usize)
+// open(path: [*:0]const u8) Result(usize) // fixme: Kernel panic if null pointer
fn open(trap_frame: *const trap.Frame) void {
- const path: *const [:0]u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]);
+ const path: [*:0]const u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]);
_ = path;
unreachable;
@@ -64,25 +52,27 @@ fn close(trap_frame: *const trap.Frame) void {
unreachable;
}
-// provide(
-// path: *const [:0]u8,
-// readFn: fn (context: u16, buffer: []u8) Result(usize),
-// writeFn: fn (context: u16, bytes: []const u8) Result(usize)
+// provideStream(
+// path: [*:0]const u8, // fixme: Kernel panic if null pointer
+// readFn: ?vfs.Stream.ReadFn,
+// writeFn: ?vfs.Stream.WriteFn,
// ) Result(usize)
-fn provide(trap_frame: *const trap.Frame) void {
- const path: *const [:0]u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]);
- const readFn: ReadFn = @ptrFromInt(trap_frame.general_purpose_registers[11]);
- const writeFn: WriteFn = @ptrFromInt(trap_frame.general_purpose_registers[12]);
-
- _ = path;
- _ = readFn;
- _ = writeFn;
- unreachable;
+fn provideStream(trap_frame: *trap.Frame) void {
+ const path: [*:0]const u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]);
+ const readFn: ?vfs.Stream.ReadFn = @ptrFromInt(trap_frame.general_purpose_registers[11]);
+ const writeFn: ?vfs.Stream.WriteFn = @ptrFromInt(trap_frame.general_purpose_registers[12]);
+
+ sysexchange.frameReturn(trap_frame, vfs.provideResourceZ(path, .{
+ .stream = .{
+ .readFn = readFn,
+ .writeFn = writeFn,
+ },
+ }));
}
-// remove(path: *const [:0]u8) Result(usize)
+// remove(path: [*:0]const u8) Result(usize) // fixme: Kernel panic if null pointer
fn remove(trap_frame: *const trap.Frame) void {
- const path: *const [:0]u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]);
+ const path: [*:0]const u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]);
_ = path;
unreachable;
diff --git a/src/lib/sysexchange.zig b/src/lib/sysexchange.zig
new file mode 100644
index 0000000..0359700
--- /dev/null
+++ b/src/lib/sysexchange.zig
@@ -0,0 +1,60 @@
+// SPDX-FileCopyrightText: 2024 Himbeer <himbeer@disroot.org>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+const std = @import("std");
+
+const trap = @import("trap.zig");
+
+pub const Status = enum(usize) {
+ success = 0,
+ unknown = std.math.maxInt(usize),
+
+ pub fn fromError(err: anyerror) Status {
+ return switch (err) {
+ else => .unknown,
+ };
+ }
+};
+
+pub fn Result(comptime T: type) type {
+ return struct {
+ value: T,
+ status: Status,
+
+ const Self = @This();
+
+ pub fn fromAnyTypeOrError(value: anytype) Self {
+ if (@typeInfo(@TypeOf(value)) == .ErrorUnion) {
+ if (value) |inner|
+ return .{
+ .value = inner,
+ .status = .success,
+ }
+ else |err|
+ return .{
+ .value = undefined,
+ .status = Status.fromError(err),
+ };
+ }
+ }
+ };
+}
+
+pub fn frameReturn(trap_frame: *trap.Frame, value: anytype) void {
+ const ValueType = @TypeOf(value);
+ const T = switch (@typeInfo(ValueType)) {
+ .ErrorUnion => |err_union| err_union.payload,
+ else => ValueType,
+ };
+
+ const result = Result(T).fromAnyTypeOrError(value);
+
+ const return_value = switch (@typeInfo(T)) {
+ .Void => undefined,
+ else => result.value,
+ };
+
+ trap_frame.general_purpose_registers[10] = return_value;
+ trap_frame.general_purpose_registers[11] = @intFromEnum(result.status);
+}
diff --git a/src/lib/vfs.zig b/src/lib/vfs.zig
index e44d061..c324c48 100644
--- a/src/lib/vfs.zig
+++ b/src/lib/vfs.zig
@@ -4,23 +4,26 @@
const std = @import("std");
+const sysexchange = @import("sysexchange.zig");
+
const mem = std.mem;
-var root = undefined;
+var root: Tree = undefined;
pub const Error = error{
NotFound,
RelativePathNotAllowed,
NotADirectory,
+ NoAbsoluteContainingDirectory,
};
// A stream is a resource that provides a shared data stream with a driver.
pub const Stream = struct {
- readFn: ReadFn,
- writeFn: WriteFn,
+ readFn: ?ReadFn,
+ writeFn: ?WriteFn,
- pub const ReadFn = *const fn (context: u16, buffer: []u8) Result(usize);
- pub const WriteFn = *const fn (context: u16, bytes: []const u8) Result(usize);
+ pub const ReadFn = *const fn (context: u16, buffer: []u8) sysexchange.Result(usize);
+ pub const WriteFn = *const fn (context: u16, bytes: []const u8) sysexchange.Result(usize);
};
// A file is a resource that creates a unique data stream with a driver.
@@ -41,7 +44,7 @@ pub const Resource = union(enum) {
};
pub const Inode = struct {
- name: []u8,
+ name: []const u8,
resource: Resource,
};
@@ -59,11 +62,11 @@ pub const Tree = struct {
}
pub fn find(self: *const Tree, name: []const u8) ?*Node {
- var node = self.nodes.first orelse return null;
+ var node = self.nodes.first;
while (node) |current_node| {
if (current_node.next == current_node) break;
- if (current_node.data.name == name) return current_node;
+ if (mem.eql(u8, current_node.data.name, name)) return current_node;
node = current_node.next;
}
return null;
@@ -89,14 +92,18 @@ pub fn init(allocator: mem.Allocator) void {
pub fn find(path: []const u8) ?*Node {
if (!std.fs.path.isAbsolutePosix(path)) return null;
- var it = std.fs.path.ComponentIterator(.posix, u8).init(path);
+ // Error set is empty.
+ var it = std.fs.path.ComponentIterator(.posix, u8).init(path) catch unreachable;
var tree = root;
while (it.next()) |component| {
const node = tree.find(component.name) orelse return null;
- if (component == it.last()) return node;
- if (node.data.resource == .dir) |dir| {
- tree = dir;
+ if (mem.eql(u8, component.path, (it.last() orelse return null).path)) {
+ return node;
+ }
+ switch (node.data.resource) {
+ .dir => |dir| tree = dir,
+ else => {},
}
}
@@ -107,14 +114,15 @@ pub fn find(path: []const u8) ?*Node {
pub fn provideResource(path: []const u8, resource: Resource) !void {
if (!std.fs.path.isAbsolutePosix(path)) return Error.RelativePathNotAllowed;
- const dirname = std.fs.path.dirnamePosix(path);
+ const dirname = std.fs.path.dirnamePosix(path) orelse return Error.NoAbsoluteContainingDirectory;
if (find(dirname)) |node| {
- if (node.data.resource == .dir) |dir| {
- return dir.provideResource(.{
+ return switch (node.data.resource) {
+ .dir => |dir| @constCast(&dir).provideResource(.{
.name = std.fs.path.basenamePosix(path),
.resource = resource,
- });
- } else return Error.NotADirectory;
+ }),
+ else => Error.NotADirectory,
+ };
} else return Error.NotFound;
}