This commit is contained in:
Motiejus Jakštys 2022-03-20 08:42:51 +01:00 committed by Motiejus Jakštys
parent 787fbcf375
commit b220dd92e3
3 changed files with 78 additions and 31 deletions

View File

@ -46,7 +46,7 @@ pub const Header = packed struct {
nblocks_groupmembers: u64, nblocks_groupmembers: u64,
nblocks_additional_gids: u64, nblocks_additional_gids: u64,
pub fn fromBytes(blob: [header_size]u8) InvalidHeader!Header { pub fn fromBytes(blob: []const u8) InvalidHeader!Header {
const self = mem.bytesAsValue(Header, blob); const self = mem.bytesAsValue(Header, blob);
if (!mem.eql(magic, blob[0..4])) if (!mem.eql(magic, blob[0..4]))
@ -64,7 +64,7 @@ pub const Header = packed struct {
return self; return self;
} }
pub fn asBytes(self: *const Header) [header_size]u8 { pub fn asBytes(self: *const Header) []const u8 {
return mem.asBytes(self); return mem.asBytes(self);
} }
}; };

View File

@ -12,31 +12,31 @@ pub fn roundUp(comptime T: type, comptime nbits: u8, n: T) T {
// rounds up an integer to the nearest factor of nbits and returns the // rounds up an integer to the nearest factor of nbits and returns the
// difference (padding) // difference (padding)
pub fn roundUpPadding(comptime T: type, comptime nbits: u8, n: T) T { pub fn until(comptime T: type, comptime nbits: u8, n: T) T {
return roundUp(T, nbits, n) - n; return roundUp(T, nbits, n) - n;
} }
// arrayList adds padding to an ArrayList(u8) for a given number of nbits // arrayList adds padding to an ArrayList(u8) for a given number of nbits
pub fn arrayList(arr: *ArrayList(u8), comptime nbits: u8) Allocator.Error!void { pub fn arrayList(arr: *ArrayList(u8), comptime nbits: u8) Allocator.Error!void {
const padding = roundUpPadding(u64, nbits, arr.items.len); const padding = until(u64, nbits, arr.items.len);
try arr.*.appendNTimes(0, padding); try arr.*.appendNTimes(0, padding);
} }
const testing = std.testing; const testing = std.testing;
test "padding" { test "padding" {
try testing.expectEqual(roundUpPadding(u12, 2, 0), 0); try testing.expectEqual(until(u12, 2, 0), 0);
try testing.expectEqual(roundUpPadding(u12, 2, 1), 3); try testing.expectEqual(until(u12, 2, 1), 3);
try testing.expectEqual(roundUpPadding(u12, 2, 2), 2); try testing.expectEqual(until(u12, 2, 2), 2);
try testing.expectEqual(roundUpPadding(u12, 2, 3), 1); try testing.expectEqual(until(u12, 2, 3), 1);
try testing.expectEqual(roundUpPadding(u12, 2, 4), 0); try testing.expectEqual(until(u12, 2, 4), 0);
try testing.expectEqual(roundUpPadding(u12, 2, 40), 0); try testing.expectEqual(until(u12, 2, 40), 0);
try testing.expectEqual(roundUpPadding(u12, 2, 41), 3); try testing.expectEqual(until(u12, 2, 41), 3);
try testing.expectEqual(roundUpPadding(u12, 2, 42), 2); try testing.expectEqual(until(u12, 2, 42), 2);
try testing.expectEqual(roundUpPadding(u12, 2, 43), 1); try testing.expectEqual(until(u12, 2, 43), 1);
try testing.expectEqual(roundUpPadding(u12, 2, 44), 0); try testing.expectEqual(until(u12, 2, 44), 0);
try testing.expectEqual(roundUpPadding(u12, 2, 4091), 1); try testing.expectEqual(until(u12, 2, 4091), 1);
try testing.expectEqual(roundUpPadding(u12, 2, 4092), 0); try testing.expectEqual(until(u12, 2, 4092), 0);
} }
test "arrayList" { test "arrayList" {

View File

@ -1,4 +1,5 @@
const std = @import("std"); const std = @import("std");
const os = std.os;
const fmt = std.fmt; const fmt = std.fmt;
const mem = std.mem; const mem = std.mem;
const math = std.math; const math = std.math;
@ -6,6 +7,7 @@ const sort = std.sort;
const assert = std.debug.assert; const assert = std.debug.assert;
const unicode = std.unicode; const unicode = std.unicode;
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const ArenaAllocator = std.heap.ArenaAllocator;
const ArrayListUnmanaged = std.ArrayListUnmanaged; const ArrayListUnmanaged = std.ArrayListUnmanaged;
const ArrayList = std.ArrayList; const ArrayList = std.ArrayList;
const MultiArrayList = std.MultiArrayList; const MultiArrayList = std.MultiArrayList;
@ -30,8 +32,10 @@ const section_length = @import("header.zig").section_length;
const cmph = @import("cmph.zig"); const cmph = @import("cmph.zig");
const bdz = @import("bdz.zig"); const bdz = @import("bdz.zig");
const zeroes = &[_]u8{0} ** section_length;
const Corpus = struct { const Corpus = struct {
arena: std.heap.ArenaAllocator, arena: ArenaAllocator,
// sorted by name, by unicode codepoint // sorted by name, by unicode codepoint
users: MultiArrayList(User), users: MultiArrayList(User),
@ -48,7 +52,7 @@ const Corpus = struct {
usersConst: []const User, usersConst: []const User,
groupsConst: []const Group, groupsConst: []const Group,
) error{ OutOfMemory, InvalidUtf8, Duplicate, NotFound }!Corpus { ) error{ OutOfMemory, InvalidUtf8, Duplicate, NotFound }!Corpus {
var arena = std.heap.ArenaAllocator.init(baseAllocator); var arena = ArenaAllocator.init(baseAllocator);
var allocator = arena.allocator(); var allocator = arena.allocator();
errdefer arena.deinit(); errdefer arena.deinit();
@ -100,8 +104,8 @@ const Corpus = struct {
members.len = 0; members.len = 0;
var it = groupmembers.iterator(); var it = groupmembers.iterator();
while (it.next()) |memberName| { while (it.next()) |member_name| {
if (name2user.get(memberName.*)) |user_idx| { if (name2user.get(member_name.*)) |user_idx| {
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));
@ -429,7 +433,7 @@ pub const AllSections = struct {
idx_groupname2group: []const u32, idx_groupname2group: []const u32,
idx_uid2user: []const u32, idx_uid2user: []const u32,
idx_name2user: []const u32, idx_name2user: []const u32,
header: Header, header: []const u8,
pub fn init( pub fn init(
allocator: Allocator, allocator: Allocator,
@ -452,13 +456,13 @@ pub const AllSections = struct {
const bdz_username = try cmph.packStr(allocator, unames); const bdz_username = try cmph.packStr(allocator, unames);
errdefer allocator.free(bdz_username); errdefer allocator.free(bdz_username);
var shell_sections = try shellSections(allocator, corpus); var shell = try shellSections(allocator, corpus);
errdefer shell_sections.deinit(); errdefer shell.deinit();
var additional_gids = try userGids(allocator, corpus); var additional_gids = try userGids(allocator, corpus);
errdefer additional_gids.deinit(allocator); errdefer additional_gids.deinit(allocator);
var users = try usersSection(allocator, corpus, &additional_gids, &shell_sections); var users = try usersSection(allocator, corpus, &additional_gids, &shell);
errdefer users.deinit(allocator); errdefer users.deinit(allocator);
var groupmembers = try groupMembers(allocator, corpus, users.idx2offset); var groupmembers = try groupMembers(allocator, corpus, users.idx2offset);
@ -480,8 +484,8 @@ pub const AllSections = struct {
errdefer allocator.free(idx_name2user); errdefer allocator.free(idx_name2user);
const header = Header{ const header = Header{
.nblocks_shell_blob = nblocks(u8, shell_sections.blob.constSlice()), .nblocks_shell_blob = nblocks(u8, shell.blob.constSlice()),
.num_shells = shell_sections.len, .num_shells = shell.len,
.num_groups = groups.len, .num_groups = groups.len,
.num_users = users.len, .num_users = users.len,
.nblocks_bdz_gid = nblocks(u32, bdz_gid), .nblocks_bdz_gid = nblocks(u32, bdz_gid),
@ -500,10 +504,10 @@ pub const AllSections = struct {
.bdz_groupname = bdz_groupname, .bdz_groupname = bdz_groupname,
.bdz_uid = bdz_uid, .bdz_uid = bdz_uid,
.bdz_username = bdz_username, .bdz_username = bdz_username,
.shell_sections = shell_sections, .shell_sections = shell,
.shell_reader = ShellReader.init( .shell_reader = ShellReader.init(
mem.sliceAsBytes(shell_sections.index.constSlice()), mem.sliceAsBytes(shell.index.constSlice()),
mem.sliceAsBytes(shell_sections.blob.constSlice()), mem.sliceAsBytes(shell.blob.constSlice()),
), ),
.additional_gids = additional_gids, .additional_gids = additional_gids,
.users = users, .users = users,
@ -513,10 +517,50 @@ pub const AllSections = struct {
.idx_groupname2group = idx_groupname2group, .idx_groupname2group = idx_groupname2group,
.idx_uid2user = idx_uid2user, .idx_uid2user = idx_uid2user,
.idx_name2user = idx_name2user, .idx_name2user = idx_name2user,
.header = header, .header = header.asBytes(),
}; };
} }
pub fn iov(self: *const AllSections) error{OutOfMemory}![]os.iovec_const {
const sections = &[_][]const u8{
self.header,
self.bdz_gid,
self.bdz_groupname,
self.bdz_uid,
self.bdz_username,
mem.sliceAsBytes(self.idx_gid2group),
mem.sliceAsBytes(self.idx_groupname2group),
mem.sliceAsBytes(self.idx_uid2user),
mem.sliceAsBytes(self.idx_name2user),
mem.sliceAsBytes(self.shell_sections.index.constSlice()),
mem.sliceAsBytes(self.shell_sections.blob.constSlice()),
self.groups.blob,
self.users.blob,
self.groupmembers.blob,
self.additional_gids.blob,
};
var result = try ArrayList(os.iovec_const).initCapacity(
self.allocator,
sections.len * 2,
);
errdefer result.deinit();
for (sections) |section| {
result.appendAssumeCapacity(os.iovec_const{
.iov_base = section.ptr,
.iov_len = section.len,
});
const padding = pad.until(usize, section_length_bits, section.len);
if (padding != 0)
result.appendAssumeCapacity(.{
.iov_base = zeroes,
.iov_len = padding,
});
}
return result.toOwnedSlice();
}
pub fn deinit(self: *AllSections) void { pub fn deinit(self: *AllSections) void {
self.allocator.free(self.bdz_gid); self.allocator.free(self.bdz_gid);
self.allocator.free(self.bdz_groupname); self.allocator.free(self.bdz_groupname);
@ -689,6 +733,9 @@ test "test groups, group members and users" {
try testing.expectEqualStrings(user.home, got.home()); try testing.expectEqualStrings(user.home, got.home());
try testing.expectEqualStrings(user.shell, got.shell(sections.shell_reader)); try testing.expectEqualStrings(user.shell, got.shell(sections.shell_reader));
} }
var iovec = try sections.iov();
allocator.free(iovec);
} }
test "userGids" { test "userGids" {
@ -738,7 +785,7 @@ test "pack gids" {
} }
fn testUser(name: []const u8) User { fn testUser(name: []const u8) User {
var result = std.mem.zeroes(User); var result = mem.zeroes(User);
result.name = name; result.name = name;
return result; return result;
} }