vfs.zig (9892B)
1 const std = @import("std"); 2 3 const uart = @import("../devices/mini-uart.zig"); 4 5 // TODO; future expansion 6 // - File locking 7 // - Writing 8 9 pub const Sector = u4096; 10 11 pub const Error = error{ 12 InvalidFileSystem, 13 InvalidSector, 14 15 ExpectedFile, 16 ExpectedDirectory, 17 18 NotInitialized, 19 20 InvalidFileName, 21 22 InitFailed, 23 ReadFailed, 24 SeekFailed, 25 WriteFailed, 26 } || std.mem.Allocator.Error; 27 28 fn TPtr(T: type, opaque_ptr: *anyopaque) T { 29 return @as(T, @ptrCast(@alignCast(opaque_ptr))); 30 } 31 32 pub const Disk = struct { 33 impl: *anyopaque, 34 v_read_sector: *const fn (*anyopaque, sector: u32) Error!Sector, 35 v_read_sectors: *const fn (*anyopaque, sector: u32, count: u32) Error![]Sector, 36 v_free_sectors: *const fn (*anyopaque, sectors: []Sector) void, 37 38 pub fn impl_by(impl_obj: anytype) Disk { 39 const delegate = DiskDelegate(impl_obj); 40 return .{ 41 .impl = impl_obj, 42 .v_read_sector = delegate.read_sector, 43 .v_read_sectors = delegate.read_sectors, 44 .v_free_sectors = delegate.free_sectors, 45 }; 46 } 47 48 pub fn read_sector(self: Disk, sector: u32) Error!Sector { 49 return self.v_read_sector(self.impl, sector); 50 } 51 52 pub fn read_sectors(self: Disk, sector: u32, count: u32) Error![]Sector { 53 return self.v_read_sectors(self.impl, sector, count); 54 } 55 56 pub fn free_sectors(self: Disk, sectors: []Sector) void { 57 return self.v_free_sectors(self.impl, sectors); 58 } 59 }; 60 61 inline fn DiskDelegate(impl_obj: anytype) type { 62 const ImplType = @TypeOf(impl_obj); 63 return struct { 64 fn read_sector(impl: *anyopaque, sector: u32) Error!Sector { 65 return try TPtr(ImplType, impl).read_sector(sector); 66 } 67 68 fn read_sectors(impl: *anyopaque, sector: u32, count: u32) Error![]Sector { 69 return try TPtr(ImplType, impl).read_sectors(sector, count); 70 } 71 72 fn free_sectors(impl: *anyopaque, sectors: []Sector) void { 73 return TPtr(ImplType, impl).free_sectors(sectors); 74 } 75 }; 76 } 77 78 pub const Stat = struct { 79 name: []const u8, 80 read_only: bool, 81 hidden: bool, 82 directory: bool, 83 84 // 2k36 wcgw 85 creation_time: i32, 86 access_time: i32, 87 modify_time: i32, 88 89 size: u32, 90 }; 91 92 pub const DirectoryEntry = struct { 93 impl: *anyopaque, 94 95 v_close: *const fn (*anyopaque) void, 96 v_stat: *const fn (*anyopaque) Stat, 97 98 pub fn impl_by(impl_obj: anytype) DirectoryEntry { 99 const delegate = DirectoryEntryDelegate(impl_obj); 100 return .{ 101 .impl = impl_obj, 102 .v_close = delegate.close, 103 .v_stat = delegate.stat, 104 }; 105 } 106 107 pub fn close(self: DirectoryEntry) void { 108 return self.v_close(self.impl); 109 } 110 111 pub fn stat(self: DirectoryEntry) Stat { 112 return self.v_stat(self.impl); 113 } 114 }; 115 116 inline fn DirectoryEntryDelegate(impl_obj: anytype) type { 117 const ImplType = @TypeOf(impl_obj); 118 return struct { 119 fn close(impl: *anyopaque) void { 120 return TPtr(ImplType, impl).close(); 121 } 122 123 fn stat(impl: *anyopaque) Stat { 124 return TPtr(ImplType, impl).stat(); 125 } 126 }; 127 } 128 129 pub const DirectoryIterator = struct { 130 impl: *anyopaque, 131 v_next: *const fn (*anyopaque) Error!?DirectoryEntry, 132 v_reset: *const fn (*anyopaque) Error!void, 133 v_close: *const fn (*anyopaque) void, 134 135 pub fn impl_by(impl_obj: anytype) DirectoryIterator { 136 const delegate = DirectoryIteratorDelegate(impl_obj); 137 return .{ 138 .impl = impl_obj, 139 .v_next = delegate.next, 140 .v_reset = delegate.reset, 141 .v_close = delegate.close, 142 }; 143 } 144 145 pub fn next(self: DirectoryIterator) Error!?DirectoryEntry { 146 return try self.v_next(self.impl); 147 } 148 149 pub fn reset(self: DirectoryIterator) Error!void { 150 return try self.v_reset(self.impl); 151 } 152 153 pub fn close(self: DirectoryIterator) void { 154 return self.v_close(self.impl); 155 } 156 }; 157 158 inline fn DirectoryIteratorDelegate(impl_obj: anytype) type { 159 const ImplType = @TypeOf(impl_obj); 160 return struct { 161 fn next(impl: *anyopaque) Error!?DirectoryEntry { 162 return try TPtr(ImplType, impl).next(); 163 } 164 165 fn reset(impl: *anyopaque) Error!void { 166 return try TPtr(ImplType, impl).reset(); 167 } 168 169 fn close(impl: *anyopaque) void { 170 return TPtr(ImplType, impl).close(); 171 } 172 }; 173 } 174 175 pub const File = struct { 176 impl: *anyopaque, 177 v_close: *const fn (*anyopaque) void, 178 v_read: *const fn (*anyopaque) Error!?[]u8, 179 v_write: *const fn (*anyopaque, []const u8) Error!u32, 180 v_reset: *const fn (*anyopaque) Error!void, 181 182 pub fn impl_by(impl_obj: anytype) File { 183 const delegate = FileDelegate(impl_obj); 184 return .{ 185 .impl = impl_obj, 186 .v_close = delegate.close, 187 .v_read = delegate.read, 188 .v_write = delegate.write, 189 .v_reset = delegate.reset, 190 }; 191 } 192 193 pub fn close(self: File) void { 194 return self.v_close(self.impl); 195 } 196 197 pub fn read(self: File) Error!?[]u8 { 198 return try self.v_read(self.impl); 199 } 200 201 pub fn write(self: File, bytes: []const u8) Error!u32 { 202 return try self.v_write(self.impl, bytes); 203 } 204 205 pub fn reset(self: File) Error!void { 206 return try self.v_reset(self.impl); 207 } 208 }; 209 210 inline fn FileDelegate(impl_obj: anytype) type { 211 const ImplType = @TypeOf(impl_obj); 212 return struct { 213 fn close(impl: *anyopaque) void { 214 return TPtr(ImplType, impl).close(); 215 } 216 217 fn read(impl: *anyopaque) Error!?[]u8 { 218 return try TPtr(ImplType, impl).read(); 219 } 220 221 fn write(impl: *anyopaque, bytes: []const u8) Error!u32 { 222 return try TPtr(ImplType, impl).write(bytes); 223 } 224 225 fn reset(impl: *anyopaque) Error!void { 226 return try TPtr(ImplType, impl).reset(); 227 } 228 }; 229 } 230 231 pub const Directory = struct { 232 impl: *anyopaque, 233 v_open_entry: *const fn (*anyopaque, []const u8) Error!?DirectoryEntry, 234 v_close: *const fn (*anyopaque) void, 235 v_iterate: *const fn (*anyopaque) Error!DirectoryIterator, 236 237 pub fn impl_by(impl_obj: anytype) Directory { 238 const delegate = DirectoryDelegate(impl_obj); 239 return .{ 240 .impl = impl_obj, 241 .v_open_entry = delegate.open_entry, 242 .v_close = delegate.close, 243 .v_iterate = delegate.iterate, 244 }; 245 } 246 247 pub fn open_entry(self: Directory, name: []const u8) Error!?DirectoryEntry { 248 return try self.v_open_entry(self.impl, name); 249 } 250 251 pub fn close(self: Directory) void { 252 return self.v_close(self.impl); 253 } 254 255 pub fn iterate(self: Directory) Error!DirectoryIterator { 256 return self.v_iterate(self.impl); 257 } 258 }; 259 260 inline fn DirectoryDelegate(impl_obj: anytype) type { 261 const ImplType = @TypeOf(impl_obj); 262 return struct { 263 fn open_entry(impl: *anyopaque, name: []const u8) Error!?DirectoryEntry { 264 return TPtr(ImplType, impl).open_entry(name); 265 } 266 267 fn close(impl: *anyopaque) void { 268 return TPtr(ImplType, impl).close(); 269 } 270 271 fn iterate(impl: *anyopaque) Error!DirectoryIterator { 272 return try TPtr(ImplType, impl).iterate(); 273 } 274 }; 275 } 276 277 pub const FileSystem = struct { 278 impl: *anyopaque, 279 v_open: *const fn (*anyopaque, alloc: std.mem.Allocator, disk: *Disk, lba: u32) Error!void, 280 v_close: *const fn (*anyopaque) void, 281 v_open_root: *const fn (*anyopaque) Error!Directory, 282 v_open_directory: *const fn (*anyopaque, *anyopaque) Error!Directory, 283 v_open_file: *const fn (*anyopaque, *anyopaque) Error!File, 284 285 pub fn impl_by(impl_obj: anytype) FileSystem { 286 const delegate = FileSystemDelegate(impl_obj); 287 return .{ 288 .impl = impl_obj, 289 .v_open = delegate.open, 290 .v_close = delegate.close, 291 .v_open_root = delegate.open_root, 292 .v_open_directory = delegate.open_directory, 293 .v_open_file = delegate.open_file, 294 }; 295 } 296 297 pub fn open(self: FileSystem, alloc: std.mem.Allocator, disk: *Disk, lba: u32) Error!void { 298 return self.v_open(self.impl, alloc, disk, lba); 299 } 300 301 pub fn close(self: FileSystem) void { 302 return self.v_close(self.impl); 303 } 304 305 pub fn open_root(self: FileSystem) Error!Directory { 306 return try self.v_open_root(self.impl); 307 } 308 309 pub fn open_directory(self: FileSystem, entry: *DirectoryEntry) Error!Directory { 310 if (!entry.stat().directory) return Error.ExpectedDirectory; 311 312 return try self.v_open_directory(self.impl, entry.impl); 313 } 314 315 pub fn open_file(self: FileSystem, entry: *DirectoryEntry) Error!File { 316 if (entry.stat().directory) return Error.ExpectedFile; 317 318 return try self.v_open_file(self.impl, entry.impl); 319 } 320 }; 321 322 inline fn FileSystemDelegate(impl_obj: anytype) type { 323 const ImplType = @TypeOf(impl_obj); 324 return struct { 325 fn open(impl: *anyopaque, alloc: std.mem.Allocator, disk: *Disk, lba: u32) Error!void { 326 return try TPtr(ImplType, impl).open(alloc, disk, lba); 327 } 328 329 fn close(impl: *anyopaque) void { 330 return TPtr(ImplType, impl).close(); 331 } 332 333 fn open_root(impl: *anyopaque) Error!Directory { 334 return try TPtr(ImplType, impl).open_root(); 335 } 336 337 fn open_directory(impl: *anyopaque, entry_impl: *anyopaque) Error!Directory { 338 return try TPtr(ImplType, impl).open_directory(@ptrCast(@alignCast(entry_impl))); 339 } 340 341 fn open_file(impl: *anyopaque, entry_impl: *anyopaque) Error!File { 342 return try TPtr(ImplType, impl).open_file(@ptrCast(@alignCast(entry_impl))); 343 } 344 }; 345 }