wip writing of users
This commit is contained in:
parent
e3fd1c833c
commit
a6349cd114
@ -232,14 +232,13 @@ pub fn userGids(allocator: Allocator, corpus: *const Corpus) userGidsErr!UserGid
|
||||
var name2offset = StringHashMap(u32).init(allocator);
|
||||
errdefer name2offset.deinit();
|
||||
|
||||
// zero'th entry is empty, so groupless users can refer to it.
|
||||
try compress.appendUvarint(&blob, 0);
|
||||
|
||||
var scratch = try allocator.alloc(u32, 256);
|
||||
defer allocator.free(scratch);
|
||||
for (corpus.users) |user| {
|
||||
const usergroups_maybe = corpus.username2groups.get(user.name);
|
||||
if (usergroups_maybe == null)
|
||||
continue;
|
||||
const usergroups = usergroups_maybe.?;
|
||||
|
||||
if (corpus.username2groups.get(user.name)) |usergroups| {
|
||||
try name2offset.putNoClobber(user.name, try math.cast(u32, blob.items.len));
|
||||
scratch = try allocator.realloc(scratch, usergroups.len);
|
||||
scratch.len = usergroups.len;
|
||||
@ -251,6 +250,9 @@ pub fn userGids(allocator: Allocator, corpus: *const Corpus) userGidsErr!UserGid
|
||||
try compress.appendUvarint(&blob, usergroups.len);
|
||||
for (scratch) |gid|
|
||||
try compress.appendUvarint(&blob, gid);
|
||||
} else {
|
||||
try name2offset.putNoClobber(user.name, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return UserGids{
|
||||
@ -259,18 +261,25 @@ pub fn userGids(allocator: Allocator, corpus: *const Corpus) userGidsErr!UserGid
|
||||
};
|
||||
}
|
||||
|
||||
pub const usersSectionErr = Allocator.Error || error{Overflow};
|
||||
pub fn usersSection(
|
||||
allocator: Allocator,
|
||||
corpus: *const Corpus,
|
||||
gids: *const UserGids,
|
||||
shells: *const ShellSections,
|
||||
) usersSectionErr![]const u8 {
|
||||
) error{ OutOfMemory, Overflow }![]const u8 {
|
||||
// as of writing each user takes 15 bytes + strings + padding, padded to
|
||||
// 8 bytes. 24 is a very optimistic lower bound.
|
||||
// 8 bytes. 24 is an optimistic lower bound for an average record size.
|
||||
var buf = try ArrayList(u8).initCapacity(allocator, 24 * corpus.users.len);
|
||||
_ = gids;
|
||||
_ = shells;
|
||||
for (corpus.users) |user| {
|
||||
const offset = gids.name2offset.get(user.name).?;
|
||||
std.debug.assert(offset & 7 == 0);
|
||||
try userImport.PackedUserConst.packTo(
|
||||
&buf,
|
||||
user,
|
||||
@truncate(u29, @shrExact(offset, 3)),
|
||||
shells.indices.get,
|
||||
);
|
||||
}
|
||||
return buf.toOwnedSlice();
|
||||
}
|
||||
|
||||
|
24
src/user.zig
24
src/user.zig
@ -6,6 +6,7 @@ const InvalidRecord = validate.InvalidRecord;
|
||||
|
||||
const assert = std.debug.assert;
|
||||
const mem = std.mem;
|
||||
const math = std.math;
|
||||
const Allocator = mem.Allocator;
|
||||
const ArrayList = std.ArrayList;
|
||||
|
||||
@ -196,6 +197,7 @@ fn packedUser(immutable: bool) type {
|
||||
pub fn packTo(
|
||||
arr: *ArrayList(u8),
|
||||
user: User,
|
||||
additional_gids_offset: u29,
|
||||
idxFn: shell2idxProto,
|
||||
) packErr!void {
|
||||
// function arguments are consts. We need to mutate the underlying
|
||||
@ -213,7 +215,7 @@ fn packedUser(immutable: bool) type {
|
||||
const inner = Inner{
|
||||
.uid = user.uid,
|
||||
.gid = user.gid,
|
||||
.additional_gids_offset = std.math.maxInt(u29),
|
||||
.additional_gids_offset = additional_gids_offset,
|
||||
.shell_here = idxFn(user.shell) == null,
|
||||
.shell_len_or_idx = idxFn(user.shell) orelse shell_len,
|
||||
.home_len = home_len,
|
||||
@ -241,10 +243,10 @@ fn packedUser(immutable: bool) type {
|
||||
pub fn maxSize() usize {
|
||||
comptime {
|
||||
const unpadded = InnerSize +
|
||||
std.math.maxInt(u6) + 1 + // home
|
||||
std.math.maxInt(u5) + 1 + // name
|
||||
std.math.maxInt(u6) + 1 + // shell
|
||||
std.math.maxInt(u8); // gecos
|
||||
math.maxInt(u6) + 1 + // home
|
||||
math.maxInt(u5) + 1 + // name
|
||||
math.maxInt(u6) + 1 + // shell
|
||||
math.maxInt(u8); // gecos
|
||||
return pad.roundUp(u64, alignmentBits, unpadded);
|
||||
}
|
||||
}
|
||||
@ -346,7 +348,7 @@ test "construct PackedUser section" {
|
||||
.shell = "/usr/bin/nologin",
|
||||
}, User{
|
||||
.uid = 0,
|
||||
.gid = std.math.maxInt(u32),
|
||||
.gid = math.maxInt(u32),
|
||||
.name = "Name" ** 8,
|
||||
.gecos = "Gecos" ** 51,
|
||||
.home = "Home" ** 16,
|
||||
@ -360,7 +362,7 @@ test "construct PackedUser section" {
|
||||
.shell = "/",
|
||||
} };
|
||||
for (users) |user|
|
||||
try PackedUserConst.packTo(&buf, user, testShellIndex);
|
||||
try PackedUserConst.packTo(&buf, user, math.maxInt(u29), testShellIndex);
|
||||
|
||||
var i: u29 = 0;
|
||||
var it1 = PackedUserConst.iterator(buf.items, testShell);
|
||||
@ -368,7 +370,7 @@ test "construct PackedUser section" {
|
||||
try testing.expectEqual(users[i].uid, user.uid());
|
||||
try testing.expectEqual(users[i].gid, user.gid());
|
||||
try testing.expectEqual(
|
||||
@as(u29, std.math.maxInt(u29)),
|
||||
@as(u29, math.maxInt(u29)),
|
||||
user.additionalGidsOffset(),
|
||||
);
|
||||
try testing.expectEqualStrings(users[i].name, user.name());
|
||||
@ -405,14 +407,14 @@ test "PackedUser.maxSize()" {
|
||||
defer buf.deinit();
|
||||
|
||||
const largeUser = User{
|
||||
.uid = std.math.maxInt(u32),
|
||||
.gid = std.math.maxInt(u32),
|
||||
.uid = math.maxInt(u32),
|
||||
.gid = math.maxInt(u32),
|
||||
.name = "Name" ** 8, // 32
|
||||
.gecos = "Gecos" ** 51, // 255
|
||||
.home = "Home" ** 16, // 64
|
||||
.shell = "She.LllL" ** 8, // 64
|
||||
};
|
||||
try PackedUserConst.packTo(&buf, largeUser, testShellIndex);
|
||||
try PackedUserConst.packTo(&buf, largeUser, math.maxInt(u29), testShellIndex);
|
||||
try testing.expectEqual(PackedUserConst.maxSize(), buf.items.len);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user