diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/vfs.zig | 60 |
1 files changed, 51 insertions, 9 deletions
diff --git a/src/lib/vfs.zig b/src/lib/vfs.zig index 9dfd443..abc2f8c 100644 --- a/src/lib/vfs.zig +++ b/src/lib/vfs.zig @@ -8,6 +8,8 @@ var root = undefined; pub const Error = error{ NotFound, + RelativePathNotAllowed, + NotADirectory, }; // A stream is a resource that provides a shared data stream with a driver. @@ -19,31 +21,28 @@ pub const File = struct {}; // A hook is a resource that invokes raw driver callbacks when interacted with. pub const Hook = struct {}; -// A directory is a resource that contains other resources. -pub const Dir = struct {}; - // A directory hook is a resource that provides other resources via driver callbacks. pub const DirHook = struct {}; -pub const InodeData = union(enum) { +pub const Resource = union(enum) { stream: Stream, file: File, hook: Hook, - dir: Dir, + dir: Tree, dir_hook: DirHook, }; pub const Inode = struct { name: []u8, - data: InodeData, + resource: Resource, }; +pub const Node = std.DoublyLinkedList(Inode).Node; + pub const Tree = struct { allocator: std.mem.Allocator, nodes: std.DoublyLinkedList(Inode), - pub const Node = std.DoublyLinkedList(Inode).Node; - pub fn init(allocator: std.mem.Allocator) Tree { return .{ .allocator = allocator, @@ -51,6 +50,17 @@ pub const Tree = struct { }; } + pub fn find(self: *const Tree, name: []const u8) ?*Node { + var node = self.nodes.first orelse return null; + while (node) |current_node| { + if (current_node.next == current_node) break; + + if (current_node.data.name == name) return current_node; + node = current_node.next; + } + return null; + } + pub fn provideResource(self: *Tree, inode: Inode) !void { var node = try self.allocator.create(Node); node.data = inode; @@ -58,7 +68,7 @@ pub const Tree = struct { } pub fn remove(self: *Tree, name: []const u8) !void { - if (self.findByNameExact(name)) |node| { + if (self.find(name)) |node| { self.nodes.remove(node); } else return NotFound; } @@ -67,3 +77,35 @@ pub const Tree = struct { pub fn init(allocator: std.mem.Allocator) void { root = Tree.init(allocator); } + +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); + 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; + } + } + + // Only reached if path has no components. + return null; +} + +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); + if (find(dirname)) |node| { + if (node.data.resource == .dir) |dir| { + return dir.provideResource(.{ + .name = std.fs.path.basenamePosix(path), + .resource = resource, + }); + } else return Error.NotADirectory; + } else return Error.NotFound; +} |