diff --git a/src/DB.zig b/src/DB.zig index bc254e7..daf362f 100644 --- a/src/DB.zig +++ b/src/DB.zig @@ -301,6 +301,23 @@ pub fn packCGroupNoMembers(group: PackedGroup, buf: []u8) error{BufferTooSmall}! }; } +const GroupMembersIter = struct { + it: compress.DeltaDecompressionIterator, +}; + +pub fn groupMembersIter(vit: *compress.varintSliceIterator) GroupMembersIter { + return GroupMembersIter{ + .it = compress.deltaDecompressionIterator(vit), + }; +} + +//pub fn groupMembersIter(members_slice: []const u8) GroupMembersIter { +// var vit = compress.VarintSliceIteratorMust(members_slice); +// return GroupMembersIter{ +// .it = compress.deltaDecompressionIterator(&vit), +// }; +//} + // dumps PackedGroup to []u8 and returns a CGroup. pub fn packCGroup(self: *const DB, group: PackedGroup, buf: []u8) error{BufferTooSmall}!CGroup { const members_slice = self.groupmembers[group.members_offset..]; @@ -314,8 +331,14 @@ pub fn packCGroup(self: *const DB, group: PackedGroup, buf: []u8) error{BufferTo var buf_offset: usize = ptr_end; var it = compress.deltaDecompressionIterator(&vit); + var members = groupMembersIter(&vit); + _ = members; + _ = it; + var i: usize = 0; + std.debug.print("\n", .{}); while (it.nextMust()) |member_offset| : (i += 1) { + std.debug.print("got offset: {d}\n", .{member_offset}); const entry = PackedUser.fromBytes(self.users[member_offset << 3 ..]); const start = buf_offset; const name = entry.user.name(); @@ -342,6 +365,26 @@ pub fn packCGroup(self: *const DB, group: PackedGroup, buf: []u8) error{BufferTo }; } +pub fn getGroupByName(self: *const DB, name: []const u8) ?PackedGroup { + const idx = bdz.search(self.bdz_groupname, name); + if (idx >= self.header.num_groups) return null; + const offset = self.idx_groupname2group[idx]; + const nbits = PackedGroup.alignment_bits; + const group = PackedGroup.fromBytes(self.groups[offset << nbits ..]).group; + if (!mem.eql(u8, name, group.name())) return null; + return group; +} + +pub fn getGroupByGid(self: *const DB, gid: u32) ?PackedGroup { + const idx = bdz.search_u32(self.bdz_gid, gid); + if (idx >= self.header.num_groups) return null; + const offset = self.idx_gid2group[idx]; + const nbits = PackedGroup.alignment_bits; + const group = PackedGroup.fromBytes(self.groups[offset << nbits ..]).group; + if (gid != group.gid()) return null; + return group; +} + // get a CGroup entry by name. pub fn getgrnam( self: *const DB, @@ -349,16 +392,11 @@ pub fn getgrnam( buf: []u8, omit_members: bool, ) error{BufferTooSmall}!?CGroup { - const idx = bdz.search(self.bdz_groupname, name); - if (idx >= self.header.num_groups) return null; - const offset = self.idx_groupname2group[idx]; - const nbits = PackedGroup.alignment_bits; - const group = PackedGroup.fromBytes(self.groups[offset << nbits ..]).group; - if (!mem.eql(u8, name, group.name())) return null; - return if (omit_members) - try packCGroupNoMembers(group, buf) + const group = self.getGroupByName(name) orelse return null; + if (omit_members) + return try packCGroupNoMembers(group, buf) else - try self.packCGroup(group, buf); + return try self.packCGroup(group, buf); } // get a CGroup entry by it's gid. @@ -368,16 +406,11 @@ pub fn getgrgid( buf: []u8, omit_members: bool, ) error{BufferTooSmall}!?CGroup { - const idx = bdz.search_u32(self.bdz_gid, gid); - if (idx >= self.header.num_groups) return null; - const offset = self.idx_gid2group[idx]; - const nbits = PackedGroup.alignment_bits; - const group = PackedGroup.fromBytes(self.groups[offset << nbits ..]).group; - if (gid != group.gid()) return null; - return if (omit_members) - try packCGroupNoMembers(group, buf) + const group = self.getGroupByGid(gid) orelse return null; + if (omit_members) + return try packCGroupNoMembers(group, buf) else - try self.packCGroup(group, buf); + return try self.packCGroup(group, buf); } fn pushStr(str: []const u8, buf: []u8, offset: *usize) [*:0]const u8 { diff --git a/src/compress.zig b/src/compress.zig index efeb473..a1343ba 100644 --- a/src/compress.zig +++ b/src/compress.zig @@ -103,7 +103,7 @@ pub fn putUvarint(buf: []u8, x: u64) usize { // VarintSliceIterator iterates over varint-encoded slice. // The first element is the length of the slice, in decoded numbers. -const varintSliceIterator = struct { +pub const varintSliceIterator = struct { remaining: usize, arr: []const u8, idx: usize, diff --git a/src/turbo-getent.zig b/src/turbo-getent.zig index 0d32c86..6e6584b 100644 --- a/src/turbo-getent.zig +++ b/src/turbo-getent.zig @@ -122,7 +122,8 @@ fn passwd(stdout: anytype, db: *const DB, keys: []const [*:0]const u8) u8 { } fn passwd_all(stdout: anytype, db: *const DB) u8 { - var it = PackedUser.iterator(db.users, db.header.num_users, db.shellReader()); + const shell_reader = db.shellReader(); + var it = PackedUser.iterator(db.users, db.header.num_users, shell_reader); while (it.next()) |packed_user| { const line = packed_user.toUser(db.shellReader()).toLine(); stdout.writeAll(line.constSlice()) catch return 3; @@ -133,8 +134,24 @@ fn passwd_all(stdout: anytype, db: *const DB) u8 { fn group(stdout: anytype, db: *const DB, keys: []const [*:0]const u8) u8 { if (keys.len == 0) return group_all(stdout, db); - var some_notfound = false; + + for (keys) |key| { + const keyZ = mem.span(key); + const maybe_packed_group = if (fmt.parseUnsigned(u32, keyZ, 10)) |gid| + db.getGroupByGid(gid) + else |_| + db.getGroupByName(keyZ); + + const g = maybe_packed_group orelse { + some_notfound = true; + continue; + }; + + // not converting to Group to avoid memory allocations. + stdout.print("{s}:x:{d}:", .{ g.name(), g.gid() }) catch return 3; + } + return if (some_notfound) 2 else 0; }