1
Fork 0
turbonss/src/header.zig

125 lines
3.2 KiB
Zig
Raw Normal View History

2022-02-17 11:16:30 +02:00
const std = @import("std");
2022-02-18 20:29:45 +02:00
const shell = @import("shell.zig");
2022-02-17 11:16:30 +02:00
2022-02-19 16:04:13 +02:00
const HeaderSize = @divExact(@bitSizeOf(Header), 8);
2022-02-17 11:16:30 +02:00
const Magic = [4]u8{ 0xf0, 0x9f, 0xa4, 0xb7 };
const Version = 0;
const Bom = 0x1234;
2022-02-18 15:25:10 +02:00
pub const SectionLength = 64;
2022-02-18 17:24:22 +02:00
const InvalidHeader = error{
2022-02-18 07:16:11 +02:00
InvalidMagic,
InvalidVersion,
InvalidBom,
TooManyShells,
2022-02-18 07:42:43 +02:00
InvalidOffset,
2022-02-18 07:16:11 +02:00
};
2022-02-17 11:16:30 +02:00
const Header = packed struct {
magic: [4]u8,
version: u8,
bom: u16,
num_shells: u8,
num_users: u32,
num_groups: u32,
2022-02-18 17:24:22 +02:00
offset_bdz_uid2user: u32,
offset_bdz_groupname2group: u32,
offset_bdz_username2user: u32,
2022-02-17 11:16:30 +02:00
offset_idx: u32,
offset_groups: u32,
offset_users: u32,
offset_groupmembers: u32,
offset_additional_gids: u32,
2022-02-18 17:24:22 +02:00
pub fn init(blob: [HeaderSize]u8) InvalidHeader!Header {
2022-02-18 07:42:43 +02:00
const self = @bitCast(Header, blob);
for (Magic) |item, index| {
if (self.magic[index] != item) return error.InvalidMagic;
}
if (self.version != 0) {
return error.InvalidVersion;
}
if (self.bom != Bom) {
return error.InvalidBom;
}
2022-02-18 20:29:45 +02:00
if (self.num_shells > shell.MaxShells) {
2022-02-18 07:42:43 +02:00
return error.TooManyShells;
}
const offsets = [_]u32{
2022-02-18 17:24:22 +02:00
self.offset_bdz_uid2user,
self.offset_bdz_groupname2group,
self.offset_bdz_username2user,
2022-02-18 07:42:43 +02:00
self.offset_idx,
self.offset_groups,
self.offset_users,
self.offset_groupmembers,
self.offset_additional_gids,
};
for (offsets) |offset| {
2022-02-18 15:25:10 +02:00
if (offset & (SectionLength - 1) != 0) {
2022-02-18 07:42:43 +02:00
return error.InvalidOffset;
}
}
return self;
2022-02-17 11:16:30 +02:00
}
pub fn asArray(self: *const Header) [HeaderSize]u8 {
return @bitCast([HeaderSize]u8, self.*);
}
};
const testing = std.testing;
2022-02-18 17:24:22 +02:00
test "Section length is a power of two" {
2022-02-18 15:25:10 +02:00
try testing.expect(std.math.isPowerOfTwo(SectionLength));
2022-02-17 11:16:30 +02:00
}
2022-02-18 17:24:22 +02:00
test "header pack, unpack and validation" {
2022-02-18 07:42:43 +02:00
const goodHeader = Header{
2022-02-17 11:16:30 +02:00
.magic = Magic,
.version = Version,
.bom = Bom,
.num_shells = 0,
.num_users = 0,
.num_groups = 0,
2022-02-18 17:24:22 +02:00
.offset_bdz_uid2user = 0,
.offset_bdz_groupname2group = 0,
.offset_bdz_username2user = 0,
2022-02-17 11:16:30 +02:00
.offset_idx = 0,
.offset_groups = 0,
.offset_users = 0,
.offset_groupmembers = 0,
.offset_additional_gids = 0,
};
2022-02-18 17:24:22 +02:00
const gotHeader = try Header.init(goodHeader.asArray());
2022-02-18 07:42:43 +02:00
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;
2022-02-18 20:29:45 +02:00
header.num_shells = shell.MaxShells + 1;
2022-02-18 07:42:43 +02:00
try testing.expectError(error.TooManyShells, Header.init(header.asArray()));
}
{
var header = goodHeader;
2022-02-18 17:24:22 +02:00
header.offset_bdz_uid2user = 65;
2022-02-18 07:42:43 +02:00
try testing.expectError(error.InvalidOffset, Header.init(header.asArray()));
}
2022-02-17 11:16:30 +02:00
}