diff --git a/src/user.zig b/src/user.zig index 2258ea3..607776a 100644 --- a/src/user.zig +++ b/src/user.zig @@ -7,10 +7,12 @@ const ArrayList = std.ArrayList; const math = std.math; const mem = std.mem; -// TODO(motiejus) move to the struct where it's used. -const shellIndexProto = fn (u6) []const u8; -const PackedUserAlignmentBits = 3; +// ShellIndexProto is a function prototype that, given a shell's index (in +// global shell section), will return a shell string. Matches ShelReader.get. +const ShellIndexProto = fn (u6) []const u8; +// User is a convenient public struct for record construction and +// serialization. Iterator can help retrieve these records. pub const User = struct { uid: u32, gid: u32, @@ -21,6 +23,7 @@ pub const User = struct { }; pub const PackedUser = struct { + const AlignmentBits = 3; const shellIndexFnType = fn ([]const u8) ?u6; const InnerSize = @divExact(@bitSizeOf(Inner), 8); @@ -87,6 +90,8 @@ pub const PackedUser = struct { } }; + // PackedUser does not allocate; it re-interprets the "bytes" blob field. + // Both of those fields are pointers to "our representation" of that field. inner: *const Inner, userdata: []const u8, @@ -98,6 +103,7 @@ pub const PackedUser = struct { pub fn fromBytes(bytes: []const u8) Entry { const inner = std.mem.bytesAsValue( Inner, + // Should use InnerSize instead of sizeOf, see // https://github.com/ziglang/zig/issues/10958 bytes[0..@sizeOf(Inner)], ); @@ -105,7 +111,7 @@ pub const PackedUser = struct { const startBlob = InnerSize; const endBlob = startBlob + inner.blobLength(); - const nextStart = pad.roundUp(usize, PackedUserAlignmentBits, endBlob); + const nextStart = pad.roundUp(usize, AlignmentBits, endBlob); var next: ?[]const u8 = null; if (nextStart < bytes.len) { next = bytes[nextStart..]; @@ -188,7 +194,7 @@ pub const PackedUser = struct { pos += user.shell.len; } - const padding = pad.roundUpPadding(u64, PackedUserAlignmentBits, pos); + const padding = pad.roundUpPadding(u64, AlignmentBits, pos); buf.*.len += padding; mem.set(u8, buf.*[pos .. pos + padding], 0); } @@ -202,7 +208,7 @@ pub const PackedUser = struct { std.math.maxInt(u5) + // name std.math.maxInt(u6) + // shell std.math.maxInt(u8); // gecos - return pad.roundUp(u64, PackedUserAlignmentBits, unpadded); + return pad.roundUp(u64, AlignmentBits, unpadded); } } @@ -230,7 +236,7 @@ pub const PackedUser = struct { return self.userdata[gecos_pos .. gecos_pos + gecos_len]; } - pub fn shell(self: *const PackedUser, shellIndex: shellIndexProto) []const u8 { + pub fn shell(self: *const PackedUser, shellIndex: ShellIndexProto) []const u8 { if (self.inner.shell_here) { const shell_pos = self.inner.maybeShellStart(); const shell_len = self.inner.shellLen(); @@ -240,7 +246,7 @@ pub const PackedUser = struct { } }; -pub fn userIterator(section: []const u8, shellIndex: shellIndexProto) Iterator { +pub fn userIterator(section: []const u8, shellIndex: ShellIndexProto) Iterator { return Iterator{ .section = section, .shellIndex = shellIndex, @@ -249,7 +255,7 @@ pub fn userIterator(section: []const u8, shellIndex: shellIndexProto) Iterator { pub const Iterator = struct { section: ?[]const u8, - shellIndex: shellIndexProto, + shellIndex: ShellIndexProto, pub fn next(it: *Iterator) ?PackedUser { if (it.section) |section| { @@ -264,7 +270,7 @@ pub const Iterator = struct { const testing = std.testing; test "PackedUser internal and external alignment" { - // External padding (PackedUserAlignmentBits) must be higher or equal to + // External padding (AlignmentBits) must be higher or equal to // the "internal" PackedUser alignment. By aligning PackedUser we are also // working around https://github.com/ziglang/zig/issues/10958 ; PackedUser // cannot be converted from/to [@bitSizeOf(PackedUser)/8]u8;