1
Fork 0
turbonss/lib/header.zig

111 lines
2.9 KiB
Zig
Raw Normal View History

2022-02-17 11:16:30 +02:00
const std = @import("std");
2022-03-18 18:48:33 +02:00
const mem = std.mem;
const math = std.math;
const native_endian = @import("builtin").target.cpu.arch.endian();
2022-02-17 11:16:30 +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-04-19 06:11:37 +03:00
const Endian = enum(u4) {
2022-03-18 18:48:33 +02:00
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;
pub const Invalid = error{
2022-02-18 07:16:11 +02:00
InvalidMagic,
InvalidVersion,
2022-03-18 18:48:33 +02:00
InvalidEndianess,
2022-04-19 06:11:37 +03:00
InvalidPointerSize,
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(),
2022-04-19 06:11:37 +03:00
ptr_size: u4 = @sizeOf(?[*:0]const u8),
2022-03-18 18:48:33 +02:00
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-04-19 06:11:37 +03:00
getgr_bufsize: u64,
getpw_bufsize: u64,
2022-04-18 11:15:14 +03:00
padding: [48]u8 = [1]u8{0} ** 48,
2022-03-18 18:48:33 +02:00
pub fn fromBytes(blob: *const [@sizeOf(Header)]u8) Invalid!*const Header {
2022-03-18 18:48:33 +02:00
const self = mem.bytesAsValue(Header, blob);
if (!mem.eql(u8, magic[0..4], blob[0..4]))
2022-03-18 18:48:33 +02:00
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-04-19 06:11:37 +03:00
// when ptr size is larger than on the host that constructed it the DB,
// getgr_bufsize/getpw_bufsize may return insufficient values, causing
// OutOfMemory for getgr* and getpw* calls.
if (self.ptr_size < @sizeOf(?[*:0]const u8))
return error.InvalidPointerSize;
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-04-18 11:15:14 +03:00
test "Header fits into two section" {
try testing.expect(@sizeOf(Header) == 2 * 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
}
test "header pack and unpack" {
const header1 = Header{
.nblocks_shell_blob = 0,
.num_shells = 0,
.num_groups = 0,
.num_users = 0,
.nblocks_bdz_gid = 0,
.nblocks_bdz_groupname = 0,
.nblocks_bdz_uid = 0,
.nblocks_bdz_username = 0,
.nblocks_groups = 0,
.nblocks_users = 0,
.nblocks_groupmembers = 0,
.nblocks_additional_gids = 1,
2022-04-19 06:11:37 +03:00
.getgr_bufsize = 16,
.getpw_bufsize = 32,
};
const bytes = mem.asBytes(&header1);
const header = try Header.fromBytes(bytes);
try testing.expectEqual(header1, header.*);
2022-02-17 11:16:30 +02:00
}