diff --git a/src/user.zig b/src/user.zig index 387fdf5..079adc4 100644 --- a/src/user.zig +++ b/src/user.zig @@ -19,17 +19,33 @@ pub const PackedUser = packed struct { // blobSize returns the length of the blob storing string values. pub fn blobLength(self: *const PackedUser) usize { - var result: usize = self.home_len; + var result: usize = self.realHomeLen(); if (!self.name_is_a_suffix) { - result += self.name_len; + result += self.realNameLen(); } - result += self.gecos_len; + result += self.realGecosLen(); if (self.shell_here) { - result += self.shell_len_or_idx; + result += self.realShellLen(); } return result; } + + pub fn realHomeLen(self: *const PackedUser) usize { + return self.home_len + 1; + } + + pub fn realNameLen(self: *const PackedUser) usize { + return self.name_len + 1; + } + + pub fn realShellLen(self: *const PackedUser) usize { + return self.shell_len_or_idx + 1; + } + + pub fn realGecosLen(self: *const PackedUser) usize { + return self.gecos_len; + } }; const PackedUserAlignmentBits = 3; @@ -135,9 +151,9 @@ pub const UserReader = struct { PackedUser, it.ur.blob[it.index..endUser][0..packedUserSizeHere], ); - const startBlob = endUser + 1; + const startBlob = endUser; const endBlob = startBlob + packedUser.blobLength(); - it.index = pad.roundUp(usize, PackedUserAlignmentBits, endBlob + 1); + it.index = pad.roundUp(usize, PackedUserAlignmentBits, endBlob); return PackedEntry{ .packed_user = packedUser, .blob = it.ur.blob[startBlob..endBlob], @@ -150,41 +166,43 @@ pub const UserReader = struct { } pub const Iterator = struct { - pit: *PackedIterator, + pit: PackedIterator, shellIndex: shellIndexProto, pub fn next(it: *Iterator) ?User { - const entry = it.next() orelse return null; - const home = entry.blob[0..entry.packed_user.home_len]; + const entry = it.pit.next() orelse return null; + const u = entry.packed_user; + + const home = entry.blob[0..u.realHomeLen()]; var name: []const u8 = undefined; var pos: usize = undefined; - //var name_start: usize = 0; - //var name_end: usize = 0; - - if (entry.packed_user.name_is_a_suffix) { - const name_start = entry.packed_user.home_len - entry.packed_user.name_len; - name = entry.blob[name_start..entry.packed_user.home_len]; - pos = entry.packed_user.home_len + 1; + if (u.name_is_a_suffix) { + const name_start = u.realHomeLen() - u.realNameLen(); + name = entry.blob[name_start..u.realHomeLen()]; + pos = u.home_len + 1; } else { - const name_start = entry.packed_user.home_len + 1; - name = entry.blob[name_start .. name_start + entry.packed_user.name_len]; - pos = name_start + entry.packed_user.name_len + 1; + const name_start = u.realHomeLen(); + name = entry.blob[name_start .. name_start + u.realNameLen()]; + pos = name_start + u.realNameLen(); } + const gecos = entry.blob[pos .. pos + u.realGecosLen()]; + pos += u.realGecosLen(); var shell: []const u8 = undefined; - if (entry.packed_user.shell_here) { - shell = entry.blob[pos .. pos + entry.packed_user.shell_len_or_idx]; - pos += entry.packed_user.shell_len_or_idx + 1; + if (u.shell_here) { + shell = entry.blob[pos .. pos + u.realShellLen()]; } else { - shell = it.shellIndex(entry.packed_user.shell_len_or_idx); + shell = it.shellIndex(u.shell_len_or_idx); } return User{ - .uid = entry.packed_user.uid, - .gid = entry.packed_user.gid, - .name = undefined, + .uid = u.uid, + .gid = u.gid, + .name = name, + .gecos = gecos, .home = home, + .shell = shell, }; } }; @@ -236,33 +254,52 @@ test "construct PackedUser blob" { defer buf.deinit(); var writer = UserWriter.init(&buf, testShellIndex); - const users = [_]User{ - User{ - .uid = 1000, - .gid = 1000, - .name = "vidmantas", - .gecos = "Vidmantas Kaminskas", - .home = "/home/vidmantas", - .shell = "/bin/bash", - }, - User{ - .uid = 1001, - .gid = 1001, - .name = "svc-foo", - .gecos = "Service Account", - .home = "/home/service1", - .shell = "/usr/bin/nologin", - }, - }; + const users = [_]User{ User{ + .uid = 1000, + .gid = 1000, + .name = "vidmantas", + .gecos = "Vidmantas Kaminskas", + .home = "/home/vidmantas", + .shell = "/bin/bash", + }, User{ + .uid = 1001, + .gid = 1001, + .name = "svc-foo", + .gecos = "Service Account", + .home = "/home/service1", + .shell = "/usr/bin/nologin", + }, User{ + .uid = 1002, + .gid = 1002, + .name = "user-account", + .gecos = "", + .home = "/a", + .shell = "/bin/zsh", + } }; for (users) |user| { try writer.appendUser(user); } var rd = UserReader.init(buf.items); - var it = rd.packedIterator(); - var i: u32 = 0; - while (it.next()) |entry| : (i += 1) { - try testing.expectEqual(users[i].uid, entry.packed_user.uid); - try testing.expectEqual(users[i].gid, entry.packed_user.gid); + { + var it = rd.packedIterator(); + var i: u32 = 0; + while (it.next()) |entry| : (i += 1) { + try testing.expectEqual(users[i].uid, entry.packed_user.uid); + try testing.expectEqual(users[i].gid, entry.packed_user.gid); + } + } + + { + var it = rd.iterator(testShell); + var i: u32 = 0; + while (it.next()) |user| : (i += 1) { + try testing.expectEqual(users[i].uid, user.uid); + try testing.expectEqual(users[i].gid, user.gid); + try testing.expectEqualStrings(users[i].name, user.name); + try testing.expectEqualStrings(users[i].gecos, user.gecos); + try testing.expectEqualStrings(users[i].home, user.home); + try testing.expectEqualStrings(users[i].shell, user.shell); + } } }