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
This commit is contained in:
parent
e2e105a1f9
commit
0497beb5c6
3 changed files with 53 additions and 29 deletions
|
@ -1105,16 +1105,13 @@ pub fn Fat32FS(comptime StreamType: type) type {
|
||||||
return &self.root_node.node.Dir;
|
return &self.root_node.node.Dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See vfs.FileSystem.close
|
/// See vfs.FileSystem.closeFile
|
||||||
fn close(fs: *const vfs.FileSystem, node: *const vfs.FileNode) void {
|
fn close(fs: *const vfs.FileSystem, node: *const vfs.Node) void {
|
||||||
const self = @fieldParentPtr(Fat32Self, "instance", fs.instance);
|
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
|
// 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.
|
// the same file twice, will just do nothing.
|
||||||
if (self.opened_files.contains(cast_node)) {
|
if (self.opened_files.remove(node)) |entry_node| {
|
||||||
const opened_node = self.opened_files.remove(cast_node).?.value;
|
self.allocator.destroy(entry_node.value);
|
||||||
self.allocator.destroy(opened_node);
|
|
||||||
self.allocator.destroy(node);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1168,7 +1165,10 @@ pub fn Fat32FS(comptime StreamType: type) type {
|
||||||
node.* = switch (flags) {
|
node.* = switch (flags) {
|
||||||
.CREATE_DIR => .{ .Dir = .{ .fs = self.fs, .mount = null } },
|
.CREATE_DIR => .{ .Dir = .{ .fs = self.fs, .mount = null } },
|
||||||
.CREATE_FILE => .{ .File = .{ .fs = self.fs } },
|
.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,
|
.NO_CREATION => unreachable,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -63,22 +63,20 @@ pub const InitrdFS = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See vfs.FileSystem.close
|
/// 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);
|
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
|
// 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.
|
// the same file twice, will just do nothing.
|
||||||
if (self.opened_files.contains(cast_node)) {
|
if (self.opened_files.remove(node)) |entry_node| {
|
||||||
_ = self.opened_files.remove(cast_node);
|
|
||||||
self.allocator.destroy(node);
|
self.allocator.destroy(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See vfs.FileSystem.read
|
/// 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);
|
var self = @fieldParentPtr(InitrdFS, "instance", fs.instance);
|
||||||
const cast_node = @ptrCast(*const vfs.Node, node);
|
const node = @ptrCast(*const vfs.Node, file_node);
|
||||||
const file_header = self.opened_files.get(cast_node) orelse return vfs.Error.NotOpened;
|
const file_header = self.opened_files.get(node) orelse return vfs.Error.NotOpened;
|
||||||
const length = std.math.min(bytes.len, file_header.content.len);
|
const length = std.math.min(bytes.len, file_header.content.len);
|
||||||
std.mem.copy(u8, bytes, file_header.content[0..length]);
|
std.mem.copy(u8, bytes, file_header.content[0..length]);
|
||||||
return length;
|
return length;
|
||||||
|
@ -99,10 +97,11 @@ pub const InitrdFS = struct {
|
||||||
if (std.mem.eql(u8, file.name, name)) {
|
if (std.mem.eql(u8, file.name, name)) {
|
||||||
// Opening 2 files of the same name, will create 2 different Nodes
|
// Opening 2 files of the same name, will create 2 different Nodes
|
||||||
// Create a node
|
// Create a node
|
||||||
var file_node = try self.allocator.create(vfs.Node);
|
var node = try self.allocator.create(vfs.Node);
|
||||||
file_node.* = .{ .File = .{ .fs = self.fs } };
|
errdefer self.allocator.destroy(node);
|
||||||
try self.opened_files.put(file_node, file);
|
node.* = .{ .File = .{ .fs = self.fs } };
|
||||||
return file_node;
|
try self.opened_files.put(node, file);
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vfs.Error.NoSuchFileOrDir;
|
return vfs.Error.NoSuchFileOrDir;
|
||||||
|
@ -206,7 +205,14 @@ pub const InitrdFS = struct {
|
||||||
var root_node = try allocator.create(vfs.Node);
|
var root_node = try allocator.create(vfs.Node);
|
||||||
|
|
||||||
root_node.* = .{ .Dir = .{ .fs = fs, .mount = null } };
|
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.* = .{
|
rd_fs.* = .{
|
||||||
.opened_files = AutoHashMap(*const vfs.Node, *InitrdHeader).init(allocator),
|
.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);
|
var file1 = try vfs.openFile("/test1.txt", .NO_CREATION);
|
||||||
defer file1.close();
|
defer file1.close();
|
||||||
|
|
||||||
var file1_node = @ptrCast(*const vfs.Node, file1);
|
|
||||||
|
|
||||||
expectEqual(fs.opened_files.count(), 1);
|
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, .{});
|
var file3_node = try vfs.open("/test3.txt", true, .NO_CREATION, .{});
|
||||||
defer file3_node.File.close();
|
defer file3_node.File.close();
|
||||||
|
|
|
@ -87,13 +87,13 @@ pub const FileSystem = struct {
|
||||||
const Self = @This();
|
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:
|
/// Arguments:
|
||||||
/// IN self: *const FileSystem - The filesystem in question being operated on.
|
/// 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
|
/// Read from an open file
|
||||||
|
@ -191,7 +191,8 @@ pub const FileNode = struct {
|
||||||
|
|
||||||
/// See the documentation for FileSystem.Close
|
/// See the documentation for FileSystem.Close
|
||||||
pub fn close(self: *const FileNode) void {
|
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
|
/// See the documentation for FileSystem.Write
|
||||||
|
@ -218,6 +219,18 @@ pub const DirNode = struct {
|
||||||
}
|
}
|
||||||
return fs.open(fs, node, name, flags, args);
|
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
|
/// Errors that can be thrown by filesystem functions
|
||||||
|
@ -574,7 +587,7 @@ const TestFS = struct {
|
||||||
return &test_fs.tree.val.Dir;
|
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);
|
var test_fs = @fieldParentPtr(TestFS, "instance", fs.instance);
|
||||||
test_fs.open_files_count -= 1;
|
test_fs.open_files_count -= 1;
|
||||||
}
|
}
|
||||||
|
@ -680,7 +693,14 @@ fn testInitFs(allocator: *Allocator) !*TestFS {
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
};
|
};
|
||||||
testfs.tree.children.* = ArrayList(*TestFS.TreeNode).init(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;
|
return testfs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue