From 0497beb5c6cab3e0bb04845e88c3272efd6ad9ee Mon Sep 17 00:00:00 2001 From: DrDeano Date: Mon, 7 Dec 2020 17:19:35 +0000 Subject: [PATCH] Added the ability to close a directory node Updated docs Closes #270 Update doc comment Moved close to closeFile and closeDir in VFS Moved back to @ptrCast() Always forget to format Added TODO comment --- src/kernel/filesystem/fat32.zig | 16 +++++++-------- src/kernel/filesystem/initrd.zig | 34 ++++++++++++++++++-------------- src/kernel/filesystem/vfs.zig | 32 ++++++++++++++++++++++++------ 3 files changed, 53 insertions(+), 29 deletions(-) diff --git a/src/kernel/filesystem/fat32.zig b/src/kernel/filesystem/fat32.zig index 2fe629a..41b16b0 100644 --- a/src/kernel/filesystem/fat32.zig +++ b/src/kernel/filesystem/fat32.zig @@ -1105,16 +1105,13 @@ pub fn Fat32FS(comptime StreamType: type) type { return &self.root_node.node.Dir; } - /// See vfs.FileSystem.close - fn close(fs: *const vfs.FileSystem, node: *const vfs.FileNode) void { + /// See vfs.FileSystem.closeFile + fn close(fs: *const vfs.FileSystem, node: *const vfs.Node) void { const self = @fieldParentPtr(Fat32Self, "instance", fs.instance); - const cast_node = @ptrCast(*const vfs.Node, node); // As close can't error, if provided with a invalid Node that isn't opened or try to close // the same file twice, will just do nothing. - if (self.opened_files.contains(cast_node)) { - const opened_node = self.opened_files.remove(cast_node).?.value; - self.allocator.destroy(opened_node); - self.allocator.destroy(node); + if (self.opened_files.remove(node)) |entry_node| { + self.allocator.destroy(entry_node.value); } } @@ -1168,7 +1165,10 @@ pub fn Fat32FS(comptime StreamType: type) type { node.* = switch (flags) { .CREATE_DIR => .{ .Dir = .{ .fs = self.fs, .mount = null } }, .CREATE_FILE => .{ .File = .{ .fs = self.fs } }, - .CREATE_SYMLINK => if (open_args.symlink_target) |target| .{ .Symlink = target } else return vfs.Error.NoSymlinkTarget, + .CREATE_SYMLINK => if (open_args.symlink_target) |target| + .{ .Symlink = target } + else + return vfs.Error.NoSymlinkTarget, .NO_CREATION => unreachable, }; diff --git a/src/kernel/filesystem/initrd.zig b/src/kernel/filesystem/initrd.zig index 7a252d8..f7cdc24 100644 --- a/src/kernel/filesystem/initrd.zig +++ b/src/kernel/filesystem/initrd.zig @@ -63,22 +63,20 @@ pub const InitrdFS = struct { } /// See vfs.FileSystem.close - fn close(fs: *const vfs.FileSystem, node: *const vfs.FileNode) void { + fn close(fs: *const vfs.FileSystem, node: *const vfs.Node) void { var self = @fieldParentPtr(InitrdFS, "instance", fs.instance); - const cast_node = @ptrCast(*const vfs.Node, node); // As close can't error, if provided with a invalid Node that isn't opened or try to close // the same file twice, will just do nothing. - if (self.opened_files.contains(cast_node)) { - _ = self.opened_files.remove(cast_node); + if (self.opened_files.remove(node)) |entry_node| { self.allocator.destroy(node); } } /// See vfs.FileSystem.read - fn read(fs: *const vfs.FileSystem, node: *const vfs.FileNode, bytes: []u8) (Allocator.Error || vfs.Error)!usize { + fn read(fs: *const vfs.FileSystem, file_node: *const vfs.FileNode, bytes: []u8) (Allocator.Error || vfs.Error)!usize { var self = @fieldParentPtr(InitrdFS, "instance", fs.instance); - const cast_node = @ptrCast(*const vfs.Node, node); - const file_header = self.opened_files.get(cast_node) orelse return vfs.Error.NotOpened; + const node = @ptrCast(*const vfs.Node, file_node); + const file_header = self.opened_files.get(node) orelse return vfs.Error.NotOpened; const length = std.math.min(bytes.len, file_header.content.len); std.mem.copy(u8, bytes, file_header.content[0..length]); return length; @@ -99,10 +97,11 @@ pub const InitrdFS = struct { if (std.mem.eql(u8, file.name, name)) { // Opening 2 files of the same name, will create 2 different Nodes // Create a node - var file_node = try self.allocator.create(vfs.Node); - file_node.* = .{ .File = .{ .fs = self.fs } }; - try self.opened_files.put(file_node, file); - return file_node; + var node = try self.allocator.create(vfs.Node); + errdefer self.allocator.destroy(node); + node.* = .{ .File = .{ .fs = self.fs } }; + try self.opened_files.put(node, file); + return node; } } return vfs.Error.NoSuchFileOrDir; @@ -206,7 +205,14 @@ pub const InitrdFS = struct { var root_node = try allocator.create(vfs.Node); root_node.* = .{ .Dir = .{ .fs = fs, .mount = null } }; - fs.* = .{ .open = open, .close = close, .read = read, .write = write, .instance = &rd_fs.instance, .getRootNode = getRootNode }; + fs.* = .{ + .open = open, + .close = close, + .read = read, + .write = write, + .instance = &rd_fs.instance, + .getRootNode = getRootNode, + }; rd_fs.* = .{ .opened_files = AutoHashMap(*const vfs.Node, *InitrdHeader).init(allocator), @@ -370,10 +376,8 @@ test "open valid file" { var file1 = try vfs.openFile("/test1.txt", .NO_CREATION); defer file1.close(); - var file1_node = @ptrCast(*const vfs.Node, file1); - expectEqual(fs.opened_files.count(), 1); - expectEqualSlices(u8, fs.opened_files.get(file1_node).?.name, "test1.txt"); + expectEqualSlices(u8, fs.opened_files.get(@ptrCast(*const vfs.Node, file1)).?.name, "test1.txt"); var file3_node = try vfs.open("/test3.txt", true, .NO_CREATION, .{}); defer file3_node.File.close(); diff --git a/src/kernel/filesystem/vfs.zig b/src/kernel/filesystem/vfs.zig index 12a0cdb..c36f00b 100644 --- a/src/kernel/filesystem/vfs.zig +++ b/src/kernel/filesystem/vfs.zig @@ -87,13 +87,13 @@ pub const FileSystem = struct { const Self = @This(); /// - /// Close an open file, performing any last operations required to save data etc. + /// Close an open node, performing any last operations required to save data etc. /// /// Arguments: /// IN self: *const FileSystem - The filesystem in question being operated on. - /// IN node: *const FileNode - The file being closed + /// IN node: *const Node - The node being closed. /// - const Close = fn (self: *const Self, node: *const FileNode) void; + const Close = fn (self: *const Self, node: *const Node) void; /// /// Read from an open file @@ -191,7 +191,8 @@ pub const FileNode = struct { /// See the documentation for FileSystem.Close pub fn close(self: *const FileNode) void { - return self.fs.close(self.fs, self); + // TODO: Use @fieldParentPtr() once implemented for unions + return self.fs.close(self.fs, @ptrCast(*const Node, self)); } /// See the documentation for FileSystem.Write @@ -218,6 +219,18 @@ pub const DirNode = struct { } return fs.open(fs, node, name, flags, args); } + + /// See the documentation for FileSystem.Close + pub fn close(self: *const DirNode) void { + var fs = self.fs; + var node = self; + if (self.mount) |mnt| { + fs = mnt.fs; + node = mnt; + } + // TODO: Use @fieldParentPtr() once implemented for unions + return fs.close(fs, @ptrCast(*const Node, node)); + } }; /// Errors that can be thrown by filesystem functions @@ -574,7 +587,7 @@ const TestFS = struct { return &test_fs.tree.val.Dir; } - fn close(fs: *const FileSystem, node: *const FileNode) void { + fn close(fs: *const FileSystem, node: *const Node) void { var test_fs = @fieldParentPtr(TestFS, "instance", fs.instance); test_fs.open_files_count -= 1; } @@ -680,7 +693,14 @@ fn testInitFs(allocator: *Allocator) !*TestFS { .allocator = allocator, }; testfs.tree.children.* = ArrayList(*TestFS.TreeNode).init(allocator); - fs.* = .{ .open = TestFS.open, .close = TestFS.close, .read = TestFS.read, .write = TestFS.write, .instance = &testfs.instance, .getRootNode = TestFS.getRootNode }; + fs.* = .{ + .open = TestFS.open, + .close = TestFS.close, + .read = TestFS.read, + .write = TestFS.write, + .instance = &testfs.instance, + .getRootNode = TestFS.getRootNode, + }; return testfs; }