wip groupMemberNames
This commit is contained in:
parent
d4d3729bf0
commit
0766175915
69
lib/DB.zig
69
lib/DB.zig
@ -218,18 +218,60 @@ pub fn fromBytes(buf: []align(8) const u8) InvalidHeader!DB {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// getgrtnam returns a Group entry by name
|
// returns a list of group member names starting at the given offset of
|
||||||
fn getgrnam(self: *const DB, name: []const u8) ?Group {
|
// groupmembers blob.
|
||||||
|
fn groupMemberNames(
|
||||||
|
self: *const DB,
|
||||||
|
allocator: Allocator,
|
||||||
|
offset: u64,
|
||||||
|
) error{OutOfMemory}![:null]const [*:0]const u8 {
|
||||||
|
var vit = compress.VarintSliceIteratorMust(self.groupmembers[offset..]);
|
||||||
|
if (vit.remaining == 0) return null;
|
||||||
|
const total_members_len = vit.nextMust().?;
|
||||||
|
|
||||||
|
// TODO (zig 0.10+) make result type sentinel-aware and stop
|
||||||
|
// the terminating-null-pointer-dances.
|
||||||
|
var result = try allocator.alloc(?[:0]const u8, vit.remaining + 1);
|
||||||
|
errdefer allocator.free(result);
|
||||||
|
result.len = vit.remaining + 1;
|
||||||
|
result[result.len] = null;
|
||||||
|
result.len = vit.remaining;
|
||||||
|
|
||||||
|
var buf = try allocator.alloc(u8, total_members_len + vit.remaining);
|
||||||
|
errdefer allocator.free(buf);
|
||||||
|
var it = compress.DeltaCompressionIterator(&vit);
|
||||||
|
var i: usize = 0;
|
||||||
|
while (it.nextMust()) |member_offset| : (i += 1) {
|
||||||
|
const entry = PackedUser.fromBytes(self.users[member_offset..]);
|
||||||
|
const name = entry.user.name();
|
||||||
|
const old_len = buf.len;
|
||||||
|
buf.len += name.len + 1;
|
||||||
|
mem.copy(u8, buf[old_len..], name);
|
||||||
|
buf[buf.len - 1] = 0;
|
||||||
|
result[i] = buf[old_len..buf.len];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// getgrtnam returns a Group entry by name. The Group must be
|
||||||
|
// deinit'ed by caller.
|
||||||
|
fn getgrnam(self: *const DB, allocator: Allocator, name: []const u8) ?Group {
|
||||||
const idx = bdz.search(self.bdz_groupname);
|
const idx = bdz.search(self.bdz_groupname);
|
||||||
const offset = self.idx_groupname2group[idx];
|
const offset = self.idx_groupname2group[idx];
|
||||||
const entry = PackedGroup.fromBytes(self.groups[offset..]);
|
const group = PackedGroup.fromBytes(self.groups[offset..]).group;
|
||||||
if (!mem.eql(name, entry.group.name()))
|
if (!mem.eql(name, group.name())) return null;
|
||||||
return null;
|
|
||||||
|
const namez = allocator.dupeZ(u8, name);
|
||||||
|
errdefer allocator.free(namez);
|
||||||
|
|
||||||
|
// this operation is the last in the function, so it doesn't have
|
||||||
|
// a complex errdefer to deallocate it if something later fails.
|
||||||
|
const members = try groupMemberNames(allocator, group.members_offset);
|
||||||
|
|
||||||
return Group{
|
return Group{
|
||||||
.name = name,
|
.name = namez,
|
||||||
.gid = entry.group.gid(),
|
.gid = group.gid(),
|
||||||
.members = null,
|
.members = members,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,7 +529,7 @@ fn assertDefinedLayout(comptime T: type) void {
|
|||||||
|
|
||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
|
|
||||||
test "test groups, group members and users" {
|
test "read/write via iovec" {
|
||||||
const allocator = testing.allocator;
|
const allocator = testing.allocator;
|
||||||
var corpus = try Corpus.testCorpus(allocator);
|
var corpus = try Corpus.testCorpus(allocator);
|
||||||
defer corpus.deinit();
|
defer corpus.deinit();
|
||||||
@ -541,6 +583,15 @@ test "test groups, group members and users" {
|
|||||||
try testing.expectEqualSlices(u32, db.idx_uid2user, db2.idx_uid2user[0..num_users]);
|
try testing.expectEqualSlices(u32, db.idx_uid2user, db2.idx_uid2user[0..num_users]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "high-level API" {
|
||||||
|
const allocator = testing.allocator;
|
||||||
|
var corpus = try Corpus.testCorpus(allocator);
|
||||||
|
defer corpus.deinit();
|
||||||
|
|
||||||
|
var db = try DB.fromCorpus(allocator, &corpus);
|
||||||
|
defer db.deinit(allocator);
|
||||||
|
}
|
||||||
|
|
||||||
test "additionalGids" {
|
test "additionalGids" {
|
||||||
const allocator = testing.allocator;
|
const allocator = testing.allocator;
|
||||||
var corpus = try Corpus.testCorpus(allocator);
|
var corpus = try Corpus.testCorpus(allocator);
|
||||||
|
@ -22,6 +22,8 @@ pub fn clone(self: *const Group, allocator: Allocator) Allocator.Error!Group {
|
|||||||
members[i] = try allocator.dupeZ(u8, member.?);
|
members[i] = try allocator.dupeZ(u8, member.?);
|
||||||
errdefer allocator.free(members[i]);
|
errdefer allocator.free(members[i]);
|
||||||
}
|
}
|
||||||
|
// workaround to include a null value at the end, even for
|
||||||
|
// non-sentinel-terminated slice type.
|
||||||
members[self.members.len] = null;
|
members[self.members.len] = null;
|
||||||
members.len = self.members.len;
|
members.len = self.members.len;
|
||||||
|
|
||||||
|
@ -111,6 +111,12 @@ const varintSliceIterator = struct {
|
|||||||
return value.value;
|
return value.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn nextMust(self: *varintSliceIterator) ?u64 {
|
||||||
|
return self.next() catch |err| switch (err) {
|
||||||
|
error.Overflow => unreachable,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// returns the number of remaining items. If called before the first
|
// returns the number of remaining items. If called before the first
|
||||||
// next(), returns the length of the slice.
|
// next(), returns the length of the slice.
|
||||||
pub fn remaining(self: *const varintSliceIterator) usize {
|
pub fn remaining(self: *const varintSliceIterator) usize {
|
||||||
@ -127,6 +133,12 @@ pub fn VarintSliceIterator(arr: []const u8) error{Overflow}!varintSliceIterator
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn VarintSliceIteratorMust(arr: []const u8) varintSliceIterator {
|
||||||
|
return VarintSliceIterator(arr) catch |err| switch (err) {
|
||||||
|
error.Overflow => unreachable,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const deltaDecompressionIterator = struct {
|
const deltaDecompressionIterator = struct {
|
||||||
vit: *varintSliceIterator,
|
vit: *varintSliceIterator,
|
||||||
prev: u64,
|
prev: u64,
|
||||||
|
Loading…
Reference in New Issue
Block a user