const std = @import("std"); const native_endian = @import("builtin").target.cpu.arch.endian(); const mem = std.mem; const max_shells = @import("shell.zig").max_shells; const header_size = @sizeOf(Header); const magic = [4]u8{ 0xf0, 0x9f, 0xa4, 0xb7 }; const version = 0; const Endian = enum(u8) { big, little, fn native() Endian { return switch (native_endian) { .Little => Endian.little, .Big => Endian.big, }; } }; pub const section_length_bits = 6; pub const section_length = 1 << section_length_bits; pub const InvalidHeader = error{ InvalidMagic, InvalidVersion, InvalidEndianess, TooManyShells, }; pub const Header = packed struct { magic: [4]u8 = magic, version: u8 = version, endian: Endian = Endian.native(), nblocks_shell_blob: u8, num_shells: u8, num_groups: u32, num_users: u32, nblocks_bdz_gid: u32, nblocks_bdz_groupname: u32, nblocks_bdz_uid: u32, nblocks_bdz_username: u32, nblocks_groups: u64, nblocks_users: u64, nblocks_groupmembers: u64, nblocks_additional_gids: u64, pub fn fromBytes(blob: []const u8) InvalidHeader!Header { const self = mem.bytesAsValue(Header, blob); if (!mem.eql(magic, blob[0..4])) return error.InvalidMagic; if (self.version != 0) return error.InvalidVersion; if (self.endian != Endian.native()) return error.InvalidEndianess; if (self.num_shells > max_shells) return error.TooManyShells; return self; } pub fn asBytes(self: *const Header) []const u8 { return mem.asBytes(self); } }; const testing = std.testing; test "Section length is a power of two" { try testing.expect(std.math.isPowerOfTwo(section_length)); } test "bit header size is equal to @sizeOf(Header)" { try testing.expectEqual(@sizeOf(Header) * 8, @bitSizeOf(Header)); } test "header pack, unpack and validation" { //const goodHeader = Header{}; //const gotHeader = try Header.init(goodHeader.asArray()); //try testing.expectEqual(goodHeader, gotHeader); //{ // var header = goodHeader; // header.magic[0] = 0; // try testing.expectError(error.InvalidMagic, Header.init(header.asArray())); //} //{ // var header = goodHeader; // header.bom = 0x3412; // try testing.expectError(error.InvalidBom, Header.init(header.asArray())); //} //{ // var header = goodHeader; // header.offset_bdz_uid2user = 65; // try testing.expectError(error.InvalidOffset, Header.init(header.asArray())); //} }