2022-02-17 11:16:30 +02:00
|
|
|
const std = @import("std");
|
2022-03-18 18:48:33 +02:00
|
|
|
const mem = std.mem;
|
2022-03-23 22:14:48 +02:00
|
|
|
const math = std.math;
|
|
|
|
const native_endian = @import("builtin").target.cpu.arch.endian();
|
2022-02-17 11:16:30 +02:00
|
|
|
|
2022-03-23 22:14:48 +02:00
|
|
|
const max_shells = @import("shell.zig").max_shells;
|
2022-03-18 18:48:33 +02:00
|
|
|
const magic = [4]u8{ 0xf0, 0x9f, 0xa4, 0xb7 };
|
|
|
|
const version = 0;
|
2022-02-17 11:16:30 +02:00
|
|
|
|
2022-03-18 18:48:33 +02:00
|
|
|
const Endian = enum(u8) {
|
|
|
|
big,
|
|
|
|
little,
|
2022-02-18 15:25:10 +02:00
|
|
|
|
2022-03-18 18:48:33 +02:00
|
|
|
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;
|
|
|
|
|
2022-03-23 22:14:48 +02:00
|
|
|
pub const Invalid = error{
|
2022-02-18 07:16:11 +02:00
|
|
|
InvalidMagic,
|
|
|
|
InvalidVersion,
|
2022-03-18 18:48:33 +02:00
|
|
|
InvalidEndianess,
|
2022-02-18 07:16:11 +02:00
|
|
|
};
|
|
|
|
|
2022-03-18 18:48:33 +02:00
|
|
|
pub const Header = packed struct {
|
|
|
|
magic: [4]u8 = magic,
|
|
|
|
version: u8 = version,
|
|
|
|
endian: Endian = Endian.native(),
|
|
|
|
nblocks_shell_blob: u8,
|
2022-02-17 11:16:30 +02:00
|
|
|
num_shells: u8,
|
|
|
|
num_groups: u32,
|
2022-03-18 18:48:33 +02:00
|
|
|
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,
|
|
|
|
|
2022-03-23 22:14:48 +02:00
|
|
|
pub fn fromBytes(blob: []const u8) Invalid!Header {
|
2022-03-18 18:48:33 +02:00
|
|
|
const self = mem.bytesAsValue(Header, blob);
|
|
|
|
|
|
|
|
if (!mem.eql(magic, blob[0..4]))
|
|
|
|
return error.InvalidMagic;
|
|
|
|
|
|
|
|
if (self.version != 0)
|
2022-02-18 07:42:43 +02:00
|
|
|
return error.InvalidVersion;
|
2022-03-18 18:48:33 +02:00
|
|
|
|
|
|
|
if (self.endian != Endian.native())
|
|
|
|
return error.InvalidEndianess;
|
|
|
|
|
2022-02-18 07:42:43 +02:00
|
|
|
return self;
|
2022-02-17 11:16:30 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const testing = std.testing;
|
|
|
|
|
2022-02-18 17:24:22 +02:00
|
|
|
test "Section length is a power of two" {
|
2022-03-18 18:48:33 +02:00
|
|
|
try testing.expect(std.math.isPowerOfTwo(section_length));
|
|
|
|
}
|
|
|
|
|
2022-03-23 22:14:48 +02:00
|
|
|
test "Header fits into a section" {
|
|
|
|
try testing.expect(@sizeOf(Header) <= section_length);
|
|
|
|
}
|
|
|
|
|
2022-03-18 18:48:33 +02:00
|
|
|
test "bit header size is equal to @sizeOf(Header)" {
|
|
|
|
try testing.expectEqual(@sizeOf(Header) * 8, @bitSizeOf(Header));
|
2022-02-17 11:16:30 +02:00
|
|
|
}
|
|
|
|
|
2022-02-18 17:24:22 +02:00
|
|
|
test "header pack, unpack and validation" {
|
2022-03-18 18:48:33 +02:00
|
|
|
//const goodHeader = Header{};
|
2022-02-18 07:42:43 +02:00
|
|
|
|
2022-03-18 18:48:33 +02:00
|
|
|
//const gotHeader = try Header.init(goodHeader.asArray());
|
|
|
|
//try testing.expectEqual(goodHeader, gotHeader);
|
2022-02-18 07:42:43 +02:00
|
|
|
|
2022-03-18 18:48:33 +02:00
|
|
|
//{
|
|
|
|
// 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()));
|
|
|
|
//}
|
2022-02-17 11:16:30 +02:00
|
|
|
}
|