group_members

This commit is contained in:
Motiejus Jakštys 2022-03-09 07:06:39 +02:00 committed by Motiejus Jakštys
parent 4cc655de24
commit d6ba7bed63
2 changed files with 43 additions and 35 deletions

View File

@ -102,17 +102,14 @@ const Corpus = struct {
members.len += 1;
members[members.len - 1] = user_idx;
try user2groups[user_idx].append(allocator, @intCast(u32, i));
} else {
return error.NotFound;
}
} else return error.NotFound;
}
group2users[i] = members;
}
for (group2users) |*groupusers| {
for (group2users) |*groupusers|
sort.sort(u32, groupusers.*, {}, comptime sort.asc(u32));
}
var user2groups_final = try allocator.alloc([]const u32, users.len);
user2groups_final.len = users.len;
@ -270,6 +267,7 @@ pub fn usersSection(
pub const GroupMembers = struct {
// group index to it's offset in blob
idx2offset: []const u64,
// members are delta-varint encoded byte-offsets to the user struct
blob: []const u8,
pub fn deinit(self: *GroupMembers, allocator: Allocator) void {
@ -291,8 +289,8 @@ pub fn groupMembers(
// zero'th entry is empty, so empty groups can refer to it
try compress.appendUvarint(&blob, 0);
var scratch = try allocator.alloc(u32, 256);
defer allocator.free(scratch);
var scratch = try ArrayList(u32).initCapacity(allocator, 1024);
defer scratch.deinit();
for (corpus.group2users) |members, group_idx| {
if (members.len == 0) {
@ -300,16 +298,18 @@ pub fn groupMembers(
continue;
}
scratch = try allocator.realloc(scratch, members.len);
scratch.len = members.len;
mem.copy(u32, scratch, members);
idx2offset[group_idx] = blob.items.len;
try scratch.ensureTotalCapacity(members.len);
scratch.items.len = members.len;
for (members) |user_idx, i|
scratch.items[i] = user2offset[user_idx];
compress.deltaCompress(u32, scratch) catch |err| switch (err) {
compress.deltaCompress(u32, scratch.items) catch |err| switch (err) {
error.NotSorted => unreachable,
};
try compress.appendUvarint(&blob, members.len);
for (scratch) |user_idx|
try compress.appendUvarint(&blob, user2offset[user_idx]);
for (scratch.items) |elem|
try compress.appendUvarint(&blob, elem);
}
return GroupMembers{
.idx2offset = idx2offset,
@ -325,9 +325,7 @@ fn cmpUser(_: void, a: User, b: User) bool {
if (utf8_b.nextCodepoint()) |codepoint_b| {
if (codepoint_a == codepoint_b) {
continue;
} else {
return codepoint_a < codepoint_b;
}
} else return codepoint_a < codepoint_b;
}
// a is a prefix of b. It is thus shorter.
@ -373,11 +371,11 @@ pub const AllSections = struct {
&user_gids,
&shell_sections,
);
//const group_members = try groupMembers(
// allocator,
// corpus,
// users.idx2offset,
//);
const group_members = try groupMembers(
allocator,
corpus,
users.idx2offset,
);
return AllSections{
.allocator = allocator,
.bdz_gid = bdz_gid,
@ -389,8 +387,7 @@ pub const AllSections = struct {
.shell_blob = mem.sliceAsBytes(shell_blob.constSlice()),
.user_gids = user_gids,
.users = users,
//.group_members = group_members,
.group_members = undefined,
.group_members = group_members,
};
}
@ -402,6 +399,7 @@ pub const AllSections = struct {
self.shell_sections.deinit();
self.user_gids.deinit(self.allocator);
self.users.deinit(self.allocator);
self.group_members.deinit(self.allocator);
self.* = undefined;
}
};
@ -512,13 +510,26 @@ test "test corpus" {
try testing.expectEqual(groupsOfVidmantas[2], g_all);
}
test "test sections" {
test "test group members" {
const allocator = testing.allocator;
var corpus = try testCorpus(allocator);
defer corpus.deinit();
var all = try AllSections.init(allocator, &corpus);
defer all.deinit();
var sections = try AllSections.init(allocator, &corpus);
defer sections.deinit();
const blob = sections.group_members.blob;
var group_idx: usize = 0;
while (group_idx < corpus.groups.len) : (group_idx += 1) {
const offset = sections.group_members.idx2offset[group_idx];
var vit = try compress.VarintSliceIterator(blob[offset..]);
var it = compress.DeltaDecompressionIterator(&vit);
for (corpus.group2users[group_idx]) |user_idx| {
const got_user_offset = (try it.next()).?;
const want_user_offset = sections.users.idx2offset[user_idx];
try testing.expectEqual(got_user_offset, want_user_offset);
}
}
}
test "userGids" {
@ -529,9 +540,10 @@ test "userGids" {
var user_gids = try userGids(allocator, &corpus);
defer user_gids.deinit(allocator);
for (corpus.users) |_, userIdx| {
const groups = corpus.user2groups[userIdx];
const offset = user_gids.idx2offset[userIdx];
var user_idx: usize = 0;
while (user_idx < corpus.users.len) : (user_idx += 1) {
const groups = corpus.user2groups[user_idx];
const offset = user_gids.idx2offset[user_idx];
if (groups.len == 0) {
try testing.expect(offset == 0);
continue;

View File

@ -105,9 +105,7 @@ fn packedUser(comptime ShellIndexType: type) type {
const name_len = self.nameLen();
if (self.name_is_a_suffix) {
return self.homeLen() - name_len;
} else {
return self.homeLen();
}
} else return self.homeLen();
}
fn nameLen(self: *const Inner) usize {
@ -117,9 +115,7 @@ fn packedUser(comptime ShellIndexType: type) type {
fn gecosStart(self: *const Inner) usize {
if (self.name_is_a_suffix) {
return self.homeLen();
} else {
return self.homeLen() + self.nameLen();
}
} else return self.homeLen() + self.nameLen();
}
fn gecosLen(self: *const Inner) usize {