aboutsummaryrefslogtreecommitdiff
path: root/mirai.old/fs/afs/afs.zig
blob: a7217a2225a99cd0107101da25c5383974590a54 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//! Akiba File System Driver

const cache = @import("cache.zig");
const cluster_ops = @import("cluster.zig");
const compare = @import("../../utils/string/compare.zig");
const fs = @import("../../common/constants/fs.zig");
const info = @import("info.zig");
const ptr = @import("../../utils/types/ptr.zig");
const read = @import("read.zig");
const types = @import("types.zig");
const write = @import("write.zig");

pub const BootSector = types.BootSector;
pub const Entry = types.Entry;
pub const StackItem = types.StackItem;
pub const DiskInfo = types.DiskInfo;

pub fn AFS(comptime BlockDeviceType: type) type {
    return struct {
        device: *BlockDeviceType,
        partition_offset: u64,
        bytes_per_sector: u32,
        sectors_per_cluster: u32,
        total_clusters: u32,
        root_cluster: u32,
        alloc_table_sector: u32,
        alloc_table_size: u32,
        data_area_sector: u32,
        used_clusters: u32,
        parent_cache: [fs.PARENT_CACHE_SIZE]types.ParentCacheEntry,
        parent_cache_count: usize,

        const Self = @This();

        pub fn init(device: *BlockDeviceType, partition_offset: u64) !Self {
            var sector: [fs.SECTOR_SIZE]u8 align(fs.SECTOR_ALIGN) = undefined;
            if (!device.read_sector(partition_offset, &sector)) {
                return error.ReadFailed;
            }

            const boot = ptr.of(BootSector, @intFromPtr(&sector));

            if (!compare.equals_bytes(boot.signature[0..8], fs.AFS_SIGNATURE)) {
                return error.InvalidFilesystem;
            }

            if (boot.boot_signature != fs.AFS_BOOT_SIG) {
                return error.InvalidFilesystem;
            }

            return Self{
                .device = device,
                .partition_offset = partition_offset,
                .bytes_per_sector = boot.bytes_per_sector,
                .sectors_per_cluster = boot.sectors_per_cluster,
                .total_clusters = boot.total_clusters,
                .root_cluster = boot.root_cluster,
                .alloc_table_sector = boot.alloc_table_sector,
                .alloc_table_size = boot.alloc_table_size,
                .data_area_sector = boot.data_area_sector,
                .used_clusters = boot.used_clusters,
                .parent_cache = undefined,
                .parent_cache_count = 0,
            };
        }

        // Cluster operations

        pub fn cluster_to_lba(self: *Self, cluster: u32) u64 {
            return cluster_ops.to_lba(self, cluster);
        }

        pub fn increment_used(self: *Self) void {
            self.used_clusters += 1;
        }

        pub fn decrement_used(self: *Self) void {
            if (self.used_clusters > 0) {
                self.used_clusters -= 1;
            }
        }

        // Cache operations

        pub fn get_parent_cluster(self: *Self, cluster: u32) ?u32 {
            return cache.lookup(self, cluster);
        }

        // Read operations

        pub fn find_entry(self: *Self, stack_cluster: u32, identity: []const u8) ?Entry {
            return read.find_entry(self, stack_cluster, identity);
        }

        pub fn view_unit(self: *Self, entry: Entry, buffer: []u8) !usize {
            return read.view_unit(self, entry, buffer);
        }

        pub fn list_stack(self: *Self, stack_cluster: u32, items: []StackItem) !usize {
            return read.list_stack(self, stack_cluster, items);
        }

        pub fn get_unit_size(self: *Self, location: []const u8) !u64 {
            return read.get_unit_size(self, location);
        }

        pub fn view_unit_at(self: *Self, location: []const u8, buffer: []u8) !usize {
            return read.view_unit_at(self, location, buffer);
        }

        // Write operations

        pub fn create_unit(self: *Self, location: []const u8) !void {
            return write.create_unit(self, location);
        }

        pub fn mark_unit(self: *Self, location: []const u8, data: []const u8) !void {
            return write.mark_unit(self, location, data);
        }

        pub fn get_disk_info(self: *Self) DiskInfo {
            return info.get_disk_info(self);
        }
    };
}