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);
|
var name2offset = StringHashMap(u32).init(allocator);
|
||||||
errdefer name2offset.deinit();
|
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);
|
var scratch = try allocator.alloc(u32, 256);
|
||||||
defer allocator.free(scratch);
|
defer allocator.free(scratch);
|
||||||
for (corpus.users) |user| {
|
for (corpus.users) |user| {
|
||||||
const usergroups_maybe = corpus.username2groups.get(user.name);
|
if (corpus.username2groups.get(user.name)) |usergroups| {
|
||||||
if (usergroups_maybe == null)
|
|
||||||
continue;
|
|
||||||
const usergroups = usergroups_maybe.?;
|
|
||||||
|
|
||||||
try name2offset.putNoClobber(user.name, try math.cast(u32, blob.items.len));
|
try name2offset.putNoClobber(user.name, try math.cast(u32, blob.items.len));
|
||||||
scratch = try allocator.realloc(scratch, usergroups.len);
|
scratch = try allocator.realloc(scratch, usergroups.len);
|
||||||
scratch.len = 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);
|
try compress.appendUvarint(&blob, usergroups.len);
|
||||||
for (scratch) |gid|
|
for (scratch) |gid|
|
||||||
try compress.appendUvarint(&blob, gid);
|
try compress.appendUvarint(&blob, gid);
|
||||||
|
} else {
|
||||||
|
try name2offset.putNoClobber(user.name, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return UserGids{
|
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(
|
pub fn usersSection(
|
||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
corpus: *const Corpus,
|
corpus: *const Corpus,
|
||||||
gids: *const UserGids,
|
gids: *const UserGids,
|
||||||
shells: *const ShellSections,
|
shells: *const ShellSections,
|
||||||
) usersSectionErr![]const u8 {
|
) error{ OutOfMemory, Overflow }![]const u8 {
|
||||||
// as of writing each user takes 15 bytes + strings + padding, padded to
|
// 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);
|
var buf = try ArrayList(u8).initCapacity(allocator, 24 * corpus.users.len);
|
||||||
_ = gids;
|
for (corpus.users) |user| {
|
||||||
_ = shells;
|
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();
|
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 assert = std.debug.assert;
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
|
const math = std.math;
|
||||||
const Allocator = mem.Allocator;
|
const Allocator = mem.Allocator;
|
||||||
const ArrayList = std.ArrayList;
|
const ArrayList = std.ArrayList;
|
||||||
|
|
||||||
@ -196,6 +197,7 @@ fn packedUser(immutable: bool) type {
|
|||||||
pub fn packTo(
|
pub fn packTo(
|
||||||
arr: *ArrayList(u8),
|
arr: *ArrayList(u8),
|
||||||
user: User,
|
user: User,
|
||||||
|
additional_gids_offset: u29,
|
||||||
idxFn: shell2idxProto,
|
idxFn: shell2idxProto,
|
||||||
) packErr!void {
|
) packErr!void {
|
||||||
// function arguments are consts. We need to mutate the underlying
|
// function arguments are consts. We need to mutate the underlying
|
||||||
@ -213,7 +215,7 @@ fn packedUser(immutable: bool) type {
|
|||||||
const inner = Inner{
|
const inner = Inner{
|
||||||
.uid = user.uid,
|
.uid = user.uid,
|
||||||
.gid = user.gid,
|
.gid = user.gid,
|
||||||
.additional_gids_offset = std.math.maxInt(u29),
|
.additional_gids_offset = additional_gids_offset,
|
||||||
.shell_here = idxFn(user.shell) == null,
|
.shell_here = idxFn(user.shell) == null,
|
||||||
.shell_len_or_idx = idxFn(user.shell) orelse shell_len,
|
.shell_len_or_idx = idxFn(user.shell) orelse shell_len,
|
||||||
.home_len = home_len,
|
.home_len = home_len,
|
||||||
@ -241,10 +243,10 @@ fn packedUser(immutable: bool) type {
|
|||||||
pub fn maxSize() usize {
|
pub fn maxSize() usize {
|
||||||
comptime {
|
comptime {
|
||||||
const unpadded = InnerSize +
|
const unpadded = InnerSize +
|
||||||
std.math.maxInt(u6) + 1 + // home
|
math.maxInt(u6) + 1 + // home
|
||||||
std.math.maxInt(u5) + 1 + // name
|
math.maxInt(u5) + 1 + // name
|
||||||
std.math.maxInt(u6) + 1 + // shell
|
math.maxInt(u6) + 1 + // shell
|
||||||
std.math.maxInt(u8); // gecos
|
math.maxInt(u8); // gecos
|
||||||
return pad.roundUp(u64, alignmentBits, unpadded);
|
return pad.roundUp(u64, alignmentBits, unpadded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -346,7 +348,7 @@ test "construct PackedUser section" {
|
|||||||
.shell = "/usr/bin/nologin",
|
.shell = "/usr/bin/nologin",
|
||||||
}, User{
|
}, User{
|
||||||
.uid = 0,
|
.uid = 0,
|
||||||
.gid = std.math.maxInt(u32),
|
.gid = math.maxInt(u32),
|
||||||
.name = "Name" ** 8,
|
.name = "Name" ** 8,
|
||||||
.gecos = "Gecos" ** 51,
|
.gecos = "Gecos" ** 51,
|
||||||
.home = "Home" ** 16,
|
.home = "Home" ** 16,
|
||||||
@ -360,7 +362,7 @@ test "construct PackedUser section" {
|
|||||||
.shell = "/",
|
.shell = "/",
|
||||||
} };
|
} };
|
||||||
for (users) |user|
|
for (users) |user|
|
||||||
try PackedUserConst.packTo(&buf, user, testShellIndex);
|
try PackedUserConst.packTo(&buf, user, math.maxInt(u29), testShellIndex);
|
||||||
|
|
||||||
var i: u29 = 0;
|
var i: u29 = 0;
|
||||||
var it1 = PackedUserConst.iterator(buf.items, testShell);
|
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].uid, user.uid());
|
||||||
try testing.expectEqual(users[i].gid, user.gid());
|
try testing.expectEqual(users[i].gid, user.gid());
|
||||||
try testing.expectEqual(
|
try testing.expectEqual(
|
||||||
@as(u29, std.math.maxInt(u29)),
|
@as(u29, math.maxInt(u29)),
|
||||||
user.additionalGidsOffset(),
|
user.additionalGidsOffset(),
|
||||||
);
|
);
|
||||||
try testing.expectEqualStrings(users[i].name, user.name());
|
try testing.expectEqualStrings(users[i].name, user.name());
|
||||||
@ -405,14 +407,14 @@ test "PackedUser.maxSize()" {
|
|||||||
defer buf.deinit();
|
defer buf.deinit();
|
||||||
|
|
||||||
const largeUser = User{
|
const largeUser = User{
|
||||||
.uid = std.math.maxInt(u32),
|
.uid = math.maxInt(u32),
|
||||||
.gid = std.math.maxInt(u32),
|
.gid = math.maxInt(u32),
|
||||||
.name = "Name" ** 8, // 32
|
.name = "Name" ** 8, // 32
|
||||||
.gecos = "Gecos" ** 51, // 255
|
.gecos = "Gecos" ** 51, // 255
|
||||||
.home = "Home" ** 16, // 64
|
.home = "Home" ** 16, // 64
|
||||||
.shell = "She.LllL" ** 8, // 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);
|
try testing.expectEqual(PackedUserConst.maxSize(), buf.items.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user