sylveos

Toy Operating System
Log | Files | Refs

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 }