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

View File

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