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

View File

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