From f89e31af79fb884cd6fd579d12011c6b63dc7692 Mon Sep 17 00:00:00 2001 From: Ratakor Date: Wed, 8 Nov 2023 16:18:29 +0100 Subject: [PATCH] Start devtmpfs, move memory management to mm --- kernel/acpi.zig | 4 +- kernel/debug.zig | 4 +- kernel/elf.zig | 4 +- kernel/fs/devtmpfs.zig | 117 +++++++++++++++++++++++ kernel/fs/tmpfs.zig | 8 +- kernel/fs/zero.zig | 44 +++++---- kernel/main.zig | 12 ++- kernel/mm/PageAllocator.zig | 44 +++++++++ kernel/{ => mm}/pmm.zig | 2 +- kernel/{ => mm}/vmm.zig | 51 +--------- kernel/sched.zig | 4 +- kernel/vfs.zig | 186 ++++++++++++++++++++++-------------- lib/ubik.zig | 15 +-- 13 files changed, 337 insertions(+), 158 deletions(-) create mode 100644 kernel/fs/devtmpfs.zig create mode 100644 kernel/mm/PageAllocator.zig rename kernel/{ => mm}/pmm.zig (99%) rename kernel/{ => mm}/vmm.zig (92%) diff --git a/kernel/acpi.zig b/kernel/acpi.zig index 6ce5b6d..9a48617 100644 --- a/kernel/acpi.zig +++ b/kernel/acpi.zig @@ -4,7 +4,7 @@ const std = @import("std"); const root = @import("root"); const arch = @import("arch.zig"); const apic = arch.apic; -const vmm = @import("vmm.zig"); +const vmm = root.vmm; const log = std.log.scoped(.acpi); /// System Description Table @@ -21,7 +21,7 @@ const SDT = extern struct { inline fn data(self: *const SDT) []const u8 { const ptr: [*]const u8 = @ptrCast(self); - return ptr[0..self.length][@sizeOf(SDT)..]; + return ptr[@sizeOf(SDT)..self.length]; } fn doChecksum(self: *const SDT) void { diff --git a/kernel/debug.zig b/kernel/debug.zig index 6b5a154..b51ef5f 100644 --- a/kernel/debug.zig +++ b/kernel/debug.zig @@ -171,6 +171,8 @@ const source_files = [_][]const u8{ "lib/lock.zig", "lib/term.zig", "lib/tree.zig", + "mm/pmm.zig", + "mm/vmm.zig", "acpi.zig", "arch.zig", "debug.zig", @@ -178,7 +180,6 @@ const source_files = [_][]const u8{ "event.zig", "lib.zig", "main.zig", - "pmm.zig", "ps2.zig", "rand.zig", "sched.zig", @@ -187,7 +188,6 @@ const source_files = [_][]const u8{ "time.zig", "TTY.zig", "vfs.zig", - "vmm.zig", }; // TODO: get source files from filesystem instead + zig std lib files diff --git a/kernel/elf.zig b/kernel/elf.zig index 2957c46..6e0611e 100644 --- a/kernel/elf.zig +++ b/kernel/elf.zig @@ -1,7 +1,7 @@ const std = @import("std"); const root = @import("root"); -const pmm = @import("pmm.zig"); -const vmm = @import("vmm.zig"); +const pmm = root.pmm; +const vmm = root.vmm; const page_size = std.mem.page_size; pub const AuxVal = struct { diff --git a/kernel/fs/devtmpfs.zig b/kernel/fs/devtmpfs.zig new file mode 100644 index 0000000..523a5a5 --- /dev/null +++ b/kernel/fs/devtmpfs.zig @@ -0,0 +1,117 @@ +const std = @import("std"); +const root = @import("root"); +const vfs = root.vfs; + +const Device = struct { + node: vfs.Node, + data: std.ArrayListUnmanaged(u8) = .{}, + + pub fn init(mode: std.os.mode_t) *Device { + const device = try root.allocator.create(Device); + device.* = .{ .node = try vfs.Node.init("", null, null) }; // TODO + + if (std.os.S.ISREG(mode)) { + // resource->capacity = 4096; + // resource->data = alloc(resource->capacity); + // resource->can_mmap = true; + } + + // TODO vtable is global + // device.node.vtable.read = devtmpfs_resource_read; + // device.node.vtable.write = devtmpfs_resource_write; + // device.node.vtable.mmap = devtmpfs_resource_mmap; + // device.node.vtable.msync = devtmpfs_resource_msync; + // device.node.vtable.truncate = devtmpfs_truncate; + + device.node.stat.size = 0; + device.node.stat.blocks = 0; + device.node.stat.blksize = 512; + // TODO + // device.node.stat.dev = this->dev_id; + // device.node.stat.ino = this->inode_counter++; + device.node.stat.mode = mode; + device.node.stat.nlink = 1; + // TODO set in Node.init; + // resource->stat.st_atim = time_realtime; + // resource->stat.st_ctim = time_realtime; + // resource->stat.st_mtim = time_realtime; + + return device; + } + + fn read(node: *vfs.Node, buf: []u8, offset: std.os.off_t) vfs.ReadError!usize { + const self = @fieldParentPtr(Device, "node", node); + if (offset >= self.data.items.len) { + return 0; + } + + const bytes_read = @min(buf.len, self.data.items.len - offset); + const u_offset: usize = @intCast(offset); + @memcpy(buf[0..bytes_read], self.data.items[u_offset .. u_offset + bytes_read]); + return bytes_read; + } + + fn write(node: *vfs.Node, buf: []const u8, offset: std.os.off_t) vfs.WriteError!usize { + const self = @fieldParentPtr(Device, "node", node); + try self.data.insertSlice(root.allocator, @intCast(offset), buf); + return buf.len; + } + + fn truncate(node: *vfs.Node, length: usize) vfs.DefaultError!void { + const self = @fieldParentPtr(Device, "node", node); + try self.data.resize(root.allocator, length); + } + + // stat + // mmap +}; + +// TODO: not a struct just a vtable and global dev_id/inode_counter +const FileSystem = struct { + fs: *vfs.FileSystem, + dev_id: std.os.ino_t, + inode_counter: std.os.ino_t, + + fn create(fs: *vfs.FileSystem, parent: *vfs.Node, name: []const u8, mode: std.os.mode_t) !*vfs.Node { + _ = mode; + _ = name; + _ = parent; + const self = @fieldParentPtr(FileSystem, "fs", fs); + _ = self; + // const new_node = try vfs.Node.init(fs, parent, name); + // return Device.init(mode); + } + + fn symlink(fs: *vfs.FileSystem, parent: *vfs.Node, name: []const u8, target: []const u8) !*vfs.Node { + _ = target; + _ = name; + _ = parent; + _ = fs; + // symlink_target + // const self = @fieldParentPtr(FileSystem, "fs", fs); + // const new_node = try vfs.Node.init(fs, parent, name); + // return Device.init(0o777 | std.os.S.IFLNK); + } +}; + +var root_node: *vfs.Node = undefined; + +// TODO +fn mount(parent: *vfs.Node, name: []const u8, source: *vfs.Node) *vfs.Node { + _ = source; + _ = name; + _ = parent; + return root_node; +} + +pub fn init() void { + // const root_node = FileSystem.create({}, null, "", 0o755 | std.os.S.IFDIR) catch unreachable; + vfs.registerFileSystem("devtmpfs", mount); +} + +pub fn addDevice(device: *vfs.Node, name: []const u8) !void { + _ = name; + _ = device; + // gop on devtmpfs + +} diff --git a/kernel/fs/tmpfs.zig b/kernel/fs/tmpfs.zig index ba2ac03..44fd2bf 100644 --- a/kernel/fs/tmpfs.zig +++ b/kernel/fs/tmpfs.zig @@ -56,9 +56,9 @@ const File = struct { return buf.len; } - fn stat(node: *vfs.Node, buf: *std.os.Stat) vfs.StatError!void { + fn stat(node: *vfs.Node, statbuf: *std.os.Stat) vfs.StatError!void { const self = @fieldParentPtr(File, "node", node); - buf.* = .{ + statbuf.* = .{ .dev = undefined, .ino = node.inode, .mode = node.mode, // TODO: 0o777 | std.os.S.IFREG, @@ -68,7 +68,7 @@ const File = struct { .rdev = undefined, .size = @intCast(self.data.items.len), .blksize = blksize, - .blocks = std.math.divCeil(usize, self.data.items.len, blksize), // TODO: use @divCeil + .blocks = std.math.divCeil(usize, self.data.items.len, 512), // TODO: use @divCeil .atim = node.atim, .mtim = node.mtim, .ctim = node.ctim, @@ -224,7 +224,7 @@ const FileSystem = struct { errdefer root.allocator.destroy(symlink); symlink.* = .{ - .vtable = &.{}, + // .vtable = &?, .filesystem = fs, .kind = .symlink, .symlink_target = try root.allocator.dupe(u8, target), diff --git a/kernel/fs/zero.zig b/kernel/fs/zero.zig index c319ad9..a0a081e 100644 --- a/kernel/fs/zero.zig +++ b/kernel/fs/zero.zig @@ -3,6 +3,13 @@ const root = @import("root"); const vfs = root.vfs; const Null = struct { + const vtable: vfs.Node.VTable = .{ + .open = open, + .close = close, + .read = read, + .write = write, + }; + fn open(_: *vfs.Node, _: u64) vfs.OpenError!void {} fn close(_: *vfs.Node) void {} @@ -19,15 +26,14 @@ const Null = struct { const node = try root.allocator.create(vfs.Node); node.* = .{ - .vtable = &.{ - .open = open, - .close = close, - .read = read, - .write = write, - }, + .vtable = &vtable, .name = try root.allocator.dupe(u8, "null"), - .uid = 0, - .gid = 0, + .stat = .{ + .ino = 0, + .mode = 0o666, + .uid = 0, + .gid = 0, + }, .kind = .character_device, .inode = 0, }; @@ -37,6 +43,13 @@ const Null = struct { }; const Zero = struct { + const vtable: vfs.Node.VTable = .{ + .open = open, + .close = close, + .read = read, + .write = write, + }; + fn open(_: *vfs.Node, _: u64) vfs.OpenError!void {} fn close(_: *vfs.Node) void {} @@ -54,15 +67,14 @@ const Zero = struct { const node = try root.allocator.create(vfs.Node); node.* = .{ - .vtable = &.{ - .open = open, - .close = close, - .read = read, - .write = write, - }, + .vtable = &vtable, .name = try root.allocator.dupe(u8, "zero"), - .uid = 0, - .gid = 0, + .stat = .{ + .ino = 0, + .mode = 0o666, + .uid = 0, + .gid = 0, + }, .kind = .character_device, .inode = 0, }; diff --git a/kernel/main.zig b/kernel/main.zig index 77acb67..060bf68 100644 --- a/kernel/main.zig +++ b/kernel/main.zig @@ -2,12 +2,12 @@ const std = @import("std"); const builtin = @import("builtin"); const limine = @import("limine"); const ubik = @import("ubik"); -const arch = @import("arch.zig"); +pub const arch = @import("arch.zig"); const debug = @import("debug.zig"); const serial = @import("serial.zig"); const event = @import("event.zig"); -pub const pmm = @import("pmm.zig"); -pub const vmm = @import("vmm.zig"); +pub const pmm = @import("mm/pmm.zig"); +pub const vmm = @import("mm/vmm.zig"); const acpi = @import("acpi.zig"); pub const sched = @import("sched.zig"); pub const smp = @import("smp.zig"); @@ -15,6 +15,7 @@ pub const time = @import("time.zig"); pub const vfs = @import("vfs.zig"); const ps2 = @import("ps2.zig"); const TTY = @import("TTY.zig"); +const PageAllocator = @import("mm/PageAllocator.zig"); const lib = @import("lib.zig"); pub usingnamespace lib; @@ -28,7 +29,10 @@ pub const std_options = struct { pub const os = struct { pub const system = ubik; pub const heap = struct { - pub const page_allocator = vmm.page_allocator; + pub const page_allocator = std.mem.Allocator{ + .ptr = undefined, + .vtable = &PageAllocator.vtable, + }; }; }; diff --git a/kernel/mm/PageAllocator.zig b/kernel/mm/PageAllocator.zig new file mode 100644 index 0000000..6339740 --- /dev/null +++ b/kernel/mm/PageAllocator.zig @@ -0,0 +1,44 @@ +const std = @import("std"); +const root = @import("root"); +const pmm = root.pmm; +const vmm = root.vmm; +const page_size = std.mem.page_size; +const alignForward = std.mem.alignForward; + +pub const vtable = std.mem.Allocator.VTable{ + .alloc = alloc, + .resize = resize, + .free = free, +}; + +fn alloc(_: *anyopaque, size: usize, _: u8, _: usize) ?[*]u8 { + std.debug.assert(size > 0); + std.debug.assert(size < std.math.maxInt(usize) - page_size); + + const aligned_size = alignForward(usize, size, page_size); + const pages = @divExact(aligned_size, page_size); + const address = pmm.alloc(pages, false) orelse return null; + return @ptrFromInt(address + vmm.hhdm_offset); +} + +fn resize(_: *anyopaque, buf: []u8, _: u8, new_size: usize, _: usize) bool { + const aligned_new_size = alignForward(usize, new_size, page_size); + const aligned_buf_len = alignForward(usize, buf.len, page_size); + + if (aligned_new_size == aligned_buf_len) return true; + + if (aligned_new_size < aligned_buf_len) { + const address = @intFromPtr(buf.ptr + aligned_new_size); + const pages = @divExact((aligned_buf_len - aligned_new_size), page_size); + pmm.free(address - vmm.hhdm_offset, pages); + return true; + } + + return false; +} + +fn free(_: *anyopaque, buf: []u8, _: u8, _: usize) void { + const aligned_buf_len = alignForward(usize, buf.len, page_size); + const pages = @divExact(aligned_buf_len, page_size); + pmm.free(@intFromPtr(buf.ptr) - vmm.hhdm_offset, pages); +} diff --git a/kernel/pmm.zig b/kernel/mm/pmm.zig similarity index 99% rename from kernel/pmm.zig rename to kernel/mm/pmm.zig index b1c3f77..b226c59 100644 --- a/kernel/pmm.zig +++ b/kernel/mm/pmm.zig @@ -1,6 +1,6 @@ const std = @import("std"); const root = @import("root"); -const vmm = @import("vmm.zig"); +const vmm = root.vmm; const SpinLock = root.SpinLock; const log = std.log.scoped(.pmm); const page_size = std.mem.page_size; diff --git a/kernel/vmm.zig b/kernel/mm/vmm.zig similarity index 92% rename from kernel/vmm.zig rename to kernel/mm/vmm.zig index bdfccc6..a243cb3 100644 --- a/kernel/vmm.zig +++ b/kernel/mm/vmm.zig @@ -3,12 +3,12 @@ const std = @import("std"); const root = @import("root"); -const arch = @import("arch.zig"); +const arch = root.arch; const idt = arch.idt; const apic = arch.apic; -const pmm = @import("pmm.zig"); -const smp = @import("smp.zig"); -const sched = @import("sched.zig"); +const pmm = root.pmm; +const smp = root.smp; +const sched = root.sched; const SpinLock = root.SpinLock; const log = std.log.scoped(.vmm); const alignBackward = std.mem.alignBackward; @@ -445,15 +445,6 @@ pub const AddressSpace = struct { } }; -pub const page_allocator = std.mem.Allocator{ - .ptr = undefined, - .vtable = &.{ - .alloc = alloc, - .resize = resize, - .free = free, - }, -}; - pub var hhdm_offset: u64 = undefined; // set in pmm.zig pub var kaddr_space: *AddressSpace = undefined; @@ -542,37 +533,3 @@ fn mmapPageInRange(global: *MMapRangeGlobal, vaddr: u64, paddr: u64, prot: i32) } } } - -// kernel page allocator functions - -fn alloc(_: *anyopaque, size: usize, _: u8, _: usize) ?[*]u8 { - std.debug.assert(size > 0); - std.debug.assert(size < std.math.maxInt(usize) - page_size); - - const aligned_size = alignForward(usize, size, page_size); - const pages = @divExact(aligned_size, page_size); - const address = pmm.alloc(pages, false) orelse return null; - return @ptrFromInt(address + hhdm_offset); -} - -fn resize(_: *anyopaque, buf: []u8, _: u8, new_size: usize, _: usize) bool { - const aligned_new_size = alignForward(usize, new_size, page_size); - const aligned_buf_len = alignForward(usize, buf.len, page_size); - - if (aligned_new_size == aligned_buf_len) return true; - - if (aligned_new_size < aligned_buf_len) { - const address = @intFromPtr(buf.ptr + aligned_new_size); - const pages = @divExact((aligned_buf_len - aligned_new_size), page_size); - pmm.free(address - hhdm_offset, pages); - return true; - } - - return false; -} - -fn free(_: *anyopaque, buf: []u8, _: u8, _: usize) void { - const aligned_buf_len = alignForward(usize, buf.len, page_size); - const pages = @divExact(aligned_buf_len, page_size); - pmm.free(@intFromPtr(buf.ptr) - hhdm_offset, pages); -} diff --git a/kernel/sched.zig b/kernel/sched.zig index 69c7613..418689f 100644 --- a/kernel/sched.zig +++ b/kernel/sched.zig @@ -6,8 +6,8 @@ const idt = arch.idt; const apic = arch.apic; const rand = @import("rand.zig"); const smp = @import("smp.zig"); -const pmm = @import("pmm.zig"); -const vmm = @import("vmm.zig"); +const pmm = root.pmm; +const vmm = root.vmm; const vfs = @import("vfs.zig"); const Event = @import("event.zig").Event; const SpinLock = root.SpinLock; diff --git a/kernel/vfs.zig b/kernel/vfs.zig index 189e262..1f3e2b8 100644 --- a/kernel/vfs.zig +++ b/kernel/vfs.zig @@ -21,15 +21,7 @@ pub const Node = struct { vtable: *const VTable, name: []u8, kind: Kind, - dev_id: u64, // device - inode: os.ino_t, // file serial number - mode: os.mode_t, // file mode - nlink: os.nlink_t, // hard link count - uid: os.uid_t, // owner user id - gid: os.gid_t, // owner group id - atim: os.timespec, // time of last access - mtim: os.timespec, // time of last modification - ctim: os.timespec, // time of last status change + stat: os.Stat, open_flags: u64, // TODO: read/write/append, ... mount_point: ?*Node, // TODO: symlinks <- no it's a different thing refcount: usize, @@ -37,18 +29,19 @@ pub const Node = struct { // can_mmap: bool, // TODO // status: i32, // TODO // event: Event, // TODO - filesystem: ?*const FileSystem, // TODO + nullable? + filesystem: ?*FileSystem, // TODO + nullable? + in VTable? parent: ?*Node, // TODO: nullable? children: std.StringHashMapUnmanaged(*Node) = .{}, + // symlink_target: ?[]u8, // TODO + // redirection: ?*Node // TODO pub const VTable = struct { open: *const fn (self: *Node, flags: u64) OpenError!void = @ptrCast(&stubFn), close: *const fn (self: *Node) void = @ptrCast(&stubFn), read: *const fn (self: *Node, buf: []u8, offset: os.off_t) ReadError!usize = @ptrCast(&stubFn), - write: *const fn (self: *Node, buf: []const u8, offset: os.off_t) WriteError!usize = @ptrCast(&stubFn), readLink: *const fn (self: *Node, buf: []u8) ReadLinkError!usize = @ptrCast(&stubFn), readDir: *const fn (self: *Node, index: usize) ReadDirError!*DirectoryEntry = @ptrCast(&stubFn), - findDir: *const fn (self: *Node, name: []const u8) DefaultError!*Node = @ptrCast(&stubFn), // TODO: error + write: *const fn (self: *Node, buf: []const u8, offset: os.off_t) WriteError!usize = @ptrCast(&stubFn), ioctl: *const fn (self: *Node, request: u64, arg: *anyopaque) DefaultError!u64 = @ptrCast(&stubFn), // return u64? chmod: *const fn (self: *Node, mode: os.mode_t) DefaultError!void = &stubChmod, // @ptrCast(&stubFn), // TODO: error chown: *const fn (self: *Node, uid: os.uid_t, gid: os.gid_t) DefaultError!void = @ptrCast(&stubFn), // TODO: error @@ -56,15 +49,11 @@ pub const Node = struct { unlink: *const fn (self: *Node, name: []const u8) DefaultError!void = @ptrCast(&stubFn), // TODO: error stat: *const fn (self: *Node, statbuf: *os.Stat) StatError!void = @ptrCast(&stubFn), - // TODO: filesystem - // TODO: merge createFile and makeDir? - createFile: *const fn (parent: *Node, name: []const u8, mode: os.mode_t) CreateError!void = @ptrCast(&stubFn), - makeDir: *const fn (parent: *Node, name: []const u8, mode: os.mode_t) CreateError!void = @ptrCast(&stubFn), - symlink: *const fn (parent: *Node, name: []const u8, target: []const u8) CreateError!void = @ptrCast(&stubFn), + pub const stub: VTable = .{}; fn stubChmod(self: *Node, mode: os.mode_t) DefaultError!void { - self.mode &= ~@as(os.mode_t, 0o777); - self.mode |= mode & 0o777; + self.stat.mode &= ~@as(os.mode_t, 0o777); + self.stat.mode |= mode & 0o777; } fn stubFn() !void { @@ -72,31 +61,18 @@ pub const Node = struct { } }; - pub const Kind = enum { - block_device, - character_device, - directory, - named_pipe, - symlink, - file, - unix_domain_socket, - whiteout, - unknown, + pub const Kind = enum(u8) { + block_device = os.DT.BLK, + character_device = os.DT.CHR, + directory = os.DT.DIR, + named_pipe = os.DT.FIFO, + symlink = os.DT.LNK, + file = os.DT.REG, + unix_domain_socket = os.DT.SOCK, + whiteout = os.DT.WHT, + unknown = os.DT.UNKNOWN, }; - // TODO: is DT actually used - // pub const Kind = enum(u64) { // TODO: u64? - // block_device = os.DT.BLK, - // character_device = os.DT.CHR, - // directory = os.DT.DIR, - // named_pipe = os.DT.FIFO, - // symlink = os.DT.LNK, - // file = os.DT.REG, - // unix_domain_socket = os.DT.SOCK, - // whiteout = os.DT.WHT, - // unknown = os.DT.UNKNOWN, - // }; - pub const Stream = struct { node: *Node, offset: u64 = 0, @@ -146,21 +122,27 @@ pub const Node = struct { } }; - pub fn init(name: []const u8, fs: ?*const FileSystem, parent: ?*Node) !*Node { + pub fn init(name: []const u8, fs: ?*FileSystem, parent: ?*Node) !*Node { const node = try root.allocator.create(Node); node.* = .{ - .vtable = &.{}, + .vtable = undefined, .name = try root.allocator.dupe(u8, name), .kind = undefined, - .dev_id = undefined, - .inode = undefined, - .mode = 0o666, - .nlink = 0, - .uid = 0, - .gid = 0, - .atim = time.realtime, - .mtim = time.realtime, - .ctim = time.realtime, + .stat = .{ + .dev = undefined, + .ino = undefined, + .mode = 0o666, + .nlink = 0, + .uid = 0, + .gid = 0, + .rdev = undefined, + .size = undefined, + .blksize = undefined, + .blocks = undefined, + .atim = time.realtime, + .mtim = time.realtime, + .ctim = time.realtime, + }, .open_flags = 0, .mount_point = null, .refcount = 0, @@ -206,11 +188,6 @@ pub const Node = struct { return self.vtable.read(self, buf, offset); } - pub inline fn write(self: *Node, buf: []const u8, offset: os.off_t) WriteError!usize { - // TODO check flags for open for writing - return self.vtable.write(self, buf, offset); - } - pub inline fn readLink(self: *Node, buf: []u8) ReadLinkError!void { if (self.kind != .symlink) return error.IsNotLink; return self.vtable.readLink(self, buf); @@ -221,10 +198,9 @@ pub const Node = struct { return self.vtable.readDir(self, index); } - // TODO - pub inline fn findDir(self: *Node, name: []const u8) !*Node { - if (self.kind != .directory) return error.IsNotDir; - return self.vtable.findDir(self, name); + pub inline fn write(self: *Node, buf: []const u8, offset: os.off_t) WriteError!usize { + // TODO check flags for open for writing + return self.vtable.write(self, buf, offset); } pub inline fn ioctl(self: *Node, request: u64, arg: *anyopaque) DefaultError!u64 { @@ -247,19 +223,36 @@ pub const Node = struct { // TODO pub const FileSystem = struct { vtable: *const VTable, - vnode_covered: *Node, // vnode we cover - flags: i32, // flags - bsize: i32, // native block size pub const VTable = struct { - mount: *const fn () void, - unmount: *const fn () void, - root: *const fn () void, - statfs: *const fn () void, - sync: *const fn () void, - fid: *const fn () void, - vget: *const fn () void, + // TODO: merge createFile and makeDir? + createFile: *const fn (self: *FileSystem, parent: *Node, name: []const u8, mode: os.mode_t) CreateError!void, + makeDir: *const fn (self: *FileSystem, parent: *Node, name: []const u8, mode: os.mode_t) CreateError!void, + symlink: *const fn (self: *FileSystem, parent: *Node, name: []const u8, target: []const u8) CreateError!void, }; + + // TODO + // pub fn createFile(self: *FileSystem, name: []const u8) !*VNode { + // const name_dup = try root.allocator.dupe(u8, name); + // errdefer root.allocator.free(name_dup); + // const file = try self.vtable.createFile(self, name); + // file.name = name_dup; + // return file; + // } + + // pub fn createDir(self: *FileSystem, name: []const u8) !*VNode { + // const name_dup = try root.allocator.dupe(u8, name); + // errdefer root.allocator.free(name_dup); + // const dir = try self.vtable.createDir(self, name); + // dir.name = name_dup; + // return dir; + // } + + // pub fn createSymlink(self: *FileSystem, name: []const u8, target: []const u8) !*VNode { + // const symlink = try self.vtable.createSymlink(self, name, target); + // symlink.name = try root.allocator.dupe(u8, name); + // return symlink; + // } }; pub const FileDescriptor = struct { @@ -484,3 +477,52 @@ pub fn mount(parent: *Node, source: []const u8, target: []const u8, fs_name: []c // }; // return node; // } + +// TODO +// fn resolve(cwd: ?*VNode, path: []const u8, flags: usize) (OpenError || InsertError)!*VNode { +// std.debug.assert(path.len != 0); //if (path.len == 0) return; +// if (cwd == null) { +// std.debug.assert(isAbsolute(path)); +// return resolve(root_vnode, path, flags); +// } + +// var next = if (isAbsolute(path)) root_vnode else cwd.?; +// var iter = std.mem.split(u8, path, std.fs.path.sep_str); + +// while (iter.next()) |component| { +// var next_vnode: *VNode = undefined; + +// if (component.len == 0 or std.mem.eql(u8, component, ".")) { +// continue; +// } else if (std.mem.eql(u8, component, "..")) { +// next_vnode = next.parent orelse next_vnode; // TODO +// } else { +// next_vnode = next.open(component, 0) catch |err| switch (err) { +// error.FileNotFound => blk: { +// if (flags & std.os.O.CREAT == 0) return error.FileNotFound; + +// const fs = next; // TODO +// const vnode = if (flags & std.os.O.DIRECTORY != 0 or iter.rest().len > 0) +// try fs.createDir(component) +// else +// try fs.createFile(component); +// try next.insert(vnode); +// break :blk vnode; +// }, +// else => |e| return e, +// }; +// } + +// if (flags & std.os.O.NOFOLLOW == 0 and next_vnode.kind == .symlink) { +// const old_vnode = next_vnode; +// const target = next_vnode.symlink_target.?; +// // TODO: check if isAbsolute? +// next_vnode = try resolve(if (isAbsolute(target)) null else next_vnode.parent, target, 0); +// if (next_vnode == old_vnode) return error.SymLinkLoop; +// } + +// next = next_vnode; +// } + +// return next; +// } diff --git a/lib/ubik.zig b/lib/ubik.zig index 7c29809..6455395 100644 --- a/lib/ubik.zig +++ b/lib/ubik.zig @@ -23,7 +23,6 @@ pub const nlink_t = linux.nlink_t; pub const blksize_t = linux.blksize_t; pub const blkcnt_t = linux.blkcnt_t; -// TODO: initializers pub const Stat = extern struct { /// device dev: dev_t, @@ -53,13 +52,17 @@ pub const Stat = extern struct { ctim: timespec, }; -// TODO: initializers pub const DirectoryEntry = extern struct { + /// file serial number ino: ino_t, - off: off_t, // use? - reclen: u16, // use? - type: u8, // use? - name: [255:0]u8 = undefined, + /// current location in directory stream + off: off_t, + /// file name length + reclen: u16, + /// type of file, same as vfs.Node.Kind and DT + type: u8, + /// file name component + name: [255:0]u8, }; pub const timespec = extern struct {