constructing header

This commit is contained in:
Motiejus Jakštys 2022-03-18 18:22:35 +01:00 committed by Motiejus Jakštys
parent bb3577f7b3
commit f4012c8694
2 changed files with 47 additions and 38 deletions

View File

@ -95,11 +95,11 @@ const Corpus = struct {
defer baseAllocator.free(user2groups);
mem.set(ArrayListUnmanaged(u32), user2groups, ArrayListUnmanaged(u32){});
for (groups.items(.members)) |group_members, i| {
var members = try allocator.alloc(u32, group_members.count());
for (groups.items(.members)) |groupmembers, i| {
var members = try allocator.alloc(u32, groupmembers.count());
members.len = 0;
var it = group_members.iterator();
var it = groupmembers.iterator();
while (it.next()) |memberName| {
if (name2user.get(memberName.*)) |user_idx| {
members.len += 1;
@ -148,7 +148,7 @@ pub fn shellSections(
return popcon.toOwnedSections(max_shells);
}
pub const UserGids = struct {
pub const AdditionalGids = struct {
// user index -> offset in blob
idx2offset: []const u64,
// compressed user gids blob. A blob contains N <= users.len items,
@ -158,7 +158,7 @@ pub const UserGids = struct {
// ... and the gid list is delta-compressed.
blob: []const u8,
pub fn deinit(self: *UserGids, allocator: Allocator) void {
pub fn deinit(self: *AdditionalGids, allocator: Allocator) void {
allocator.free(self.idx2offset);
allocator.free(self.blob);
self.* = undefined;
@ -168,7 +168,7 @@ pub const UserGids = struct {
pub fn userGids(
allocator: Allocator,
corpus: *const Corpus,
) error{ OutOfMemory, Overflow }!UserGids {
) error{ OutOfMemory, Overflow }!AdditionalGids {
var blob = ArrayList(u8).init(allocator);
errdefer blob.deinit();
var idx2offset = try allocator.alloc(u64, corpus.users.len);
@ -198,13 +198,15 @@ pub fn userGids(
try compress.appendUvarint(&blob, gid);
}
return UserGids{
return AdditionalGids{
.idx2offset = idx2offset,
.blob = blob.toOwnedSlice(),
};
}
pub const UsersSection = struct {
// number of users in this section
len: u32,
// user index -> offset in blob
idx2offset: []const u32,
blob: []const u8,
@ -219,7 +221,7 @@ pub const UsersSection = struct {
pub fn usersSection(
allocator: Allocator,
corpus: *const Corpus,
gids: *const UserGids,
gids: *const AdditionalGids,
shells: *const ShellSections,
) error{ OutOfMemory, Overflow, InvalidRecord }!UsersSection {
var idx2offset = try allocator.alloc(u32, corpus.users.len);
@ -244,6 +246,7 @@ pub fn usersSection(
try pad.arrayList(&blob, PackedUser.alignment_bits);
}
return UsersSection{
.len = @intCast(u32, corpus.users.len),
.idx2offset = idx2offset,
.blob = blob.toOwnedSlice(),
};
@ -303,6 +306,8 @@ pub fn groupMembers(
}
pub const GroupsSection = struct {
// number of groups in this section
len: u32,
// group index -> offset in blob
idx2offset: []const u32,
blob: []const u8,
@ -342,6 +347,7 @@ pub fn groupsSection(
}
return GroupsSection{
.len = @intCast(u32, corpus.groups.len),
.idx2offset = idx2offset,
.blob = blob.toOwnedSlice(),
};
@ -416,8 +422,8 @@ pub const AllSections = struct {
users: UsersSection,
shell_sections: ShellSections,
shell_reader: ShellReader,
user_gids: UserGids,
group_members: GroupMembers,
additional_gids: AdditionalGids,
groupmembers: GroupMembers,
groups: GroupsSection,
idx_gid2group: []const u32,
idx_groupname2group: []const u32,
@ -449,16 +455,16 @@ pub const AllSections = struct {
var shell_sections = try shellSections(allocator, corpus);
errdefer shell_sections.deinit();
var user_gids = try userGids(allocator, corpus);
errdefer user_gids.deinit(allocator);
var additional_gids = try userGids(allocator, corpus);
errdefer additional_gids.deinit(allocator);
var users = try usersSection(allocator, corpus, &user_gids, &shell_sections);
var users = try usersSection(allocator, corpus, &additional_gids, &shell_sections);
errdefer users.deinit(allocator);
var group_members = try groupMembers(allocator, corpus, users.idx2offset);
errdefer group_members.deinit(allocator);
var groupmembers = try groupMembers(allocator, corpus, users.idx2offset);
errdefer groupmembers.deinit(allocator);
var groups = try groupsSection(allocator, corpus, group_members.idx2offset);
var groups = try groupsSection(allocator, corpus, groupmembers.idx2offset);
errdefer groups.deinit(allocator);
var idx_gid2group = try bdzIdx(u32, allocator, bdz_gid, gids, groups.idx2offset);
@ -474,18 +480,18 @@ pub const AllSections = struct {
errdefer allocator.free(idx_name2user);
const header = Header{
.nblocks_shell_blob = undefined,
.num_shells = undefined,
.num_groups = undefined,
.num_users = undefined,
.nblocks_bdz_gid = undefined,
.nblocks_bdz_groupname = undefined,
.nblocks_bdz_uid = undefined,
.nblocks_bdz_username = undefined,
.nblocks_groups = undefined,
.nblocks_users = undefined,
.nblocks_groupmembers = undefined,
.nblocks_additional_gids = undefined,
.nblocks_shell_blob = nblocks(u8, shell_sections.blob.constSlice()),
.num_shells = shell_sections.len,
.num_groups = groups.len,
.num_users = users.len,
.nblocks_bdz_gid = nblocks(u32, bdz_gid),
.nblocks_bdz_groupname = nblocks(u32, bdz_groupname),
.nblocks_bdz_uid = nblocks(u32, bdz_uid),
.nblocks_bdz_username = nblocks(u32, bdz_username),
.nblocks_groups = nblocks(u64, groups.blob),
.nblocks_users = nblocks(u64, users.blob),
.nblocks_groupmembers = nblocks(u64, groupmembers.blob),
.nblocks_additional_gids = nblocks(u64, additional_gids.blob),
};
return AllSections{
@ -499,9 +505,9 @@ pub const AllSections = struct {
mem.sliceAsBytes(shell_sections.index.constSlice()),
mem.sliceAsBytes(shell_sections.blob.constSlice()),
),
.user_gids = user_gids,
.additional_gids = additional_gids,
.users = users,
.group_members = group_members,
.groupmembers = groupmembers,
.groups = groups,
.idx_gid2group = idx_gid2group,
.idx_groupname2group = idx_groupname2group,
@ -517,9 +523,9 @@ pub const AllSections = struct {
self.allocator.free(self.bdz_uid);
self.allocator.free(self.bdz_username);
self.shell_sections.deinit();
self.user_gids.deinit(self.allocator);
self.additional_gids.deinit(self.allocator);
self.users.deinit(self.allocator);
self.group_members.deinit(self.allocator);
self.groupmembers.deinit(self.allocator);
self.groups.deinit(self.allocator);
self.allocator.free(self.idx_gid2group);
self.allocator.free(self.idx_groupname2group);
@ -657,10 +663,10 @@ test "test groups, group members and users" {
var sections = try AllSections.init(allocator, &corpus);
defer sections.deinit();
const blob = sections.group_members.blob;
const blob = sections.groupmembers.blob;
var i: usize = 0;
while (i < corpus.groups.len) : (i += 1) {
const offset = sections.group_members.idx2offset[i];
const offset = sections.groupmembers.idx2offset[i];
var vit = try compress.VarintSliceIterator(blob[offset..]);
var it = compress.DeltaDecompressionIterator(&vit);
for (corpus.group2users[i]) |user_idx| {
@ -690,18 +696,18 @@ test "userGids" {
var corpus = try testCorpus(allocator);
defer corpus.deinit();
var user_gids = try userGids(allocator, &corpus);
defer user_gids.deinit(allocator);
var additional_gids = try userGids(allocator, &corpus);
defer additional_gids.deinit(allocator);
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];
const offset = additional_gids.idx2offset[user_idx];
if (groups.len == 0) {
try testing.expect(offset == 0);
continue;
}
var vit = try compress.VarintSliceIterator(user_gids.blob[offset..]);
var vit = try compress.VarintSliceIterator(additional_gids.blob[offset..]);
var it = compress.DeltaDecompressionIterator(&vit);
try testing.expectEqual(it.remaining(), groups.len);
var i: u64 = 0;

View File

@ -38,6 +38,8 @@ pub const ShellWriter = struct {
};
pub const ShellSections = struct {
// len is the number of shells in this section.
len: u8,
// index points the i'th shell to it's offset in blob. The last
// byte of the i'th shell is index[i+1].
index: BoundedArray(u16, max_shells),
@ -55,6 +57,7 @@ pub const ShellWriter = struct {
shells: BoundedArray([]const u8, max_shells),
) error{ Overflow, OutOfMemory }!ShellSections {
var self = ShellSections{
.len = @intCast(u8, shells.len),
.index = try BoundedArray(u16, max_shells).init(shells.len),
.blob = try BoundedArray(u8, (max_shells + 1) * max_shell_len).init(0),
.shell2idx = StringHashMap(u8).init(allocator),