working on iterator
This commit is contained in:
parent
54ec710f10
commit
f2434e3d3c
|
@ -1,19 +1,19 @@
|
|||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
// rounds up a u12 to the nearest factor of 4 and returns the difference
|
||||
// (padding)
|
||||
pub fn roundUpPadding(comptime T: type, comptime nbits: u8, n: T) T {
|
||||
return roundUp(T, nbits, n) - n;
|
||||
}
|
||||
|
||||
// rounds up a u12 to the nearest factor of 4.
|
||||
// rounds up an int to the nearest factor of nbits.
|
||||
pub fn roundUp(comptime T: type, comptime nbits: u8, n: T) T {
|
||||
comptime assert(nbits < @bitSizeOf(T));
|
||||
const factor = comptime (1 << nbits) - 1;
|
||||
return ((n + factor) & ~@as(T, factor));
|
||||
}
|
||||
|
||||
// rounds up an integer to the nearest factor of nbits and returns the
|
||||
// difference (padding)
|
||||
pub fn roundUpPadding(comptime T: type, comptime nbits: u8, n: T) T {
|
||||
return roundUp(T, nbits, n) - n;
|
||||
}
|
||||
|
||||
const testing = std.testing;
|
||||
|
||||
test "padding" {
|
||||
|
|
|
@ -25,7 +25,7 @@ pub const ShellReader = struct {
|
|||
}
|
||||
|
||||
// get returns a shell at the given index.
|
||||
pub fn get(self: *const ShellReader, idx: u10) []const u8 {
|
||||
pub fn get(self: *const ShellReader, idx: u6) []const u8 {
|
||||
const shellIndex = self.sectionIndex[idx];
|
||||
const start = shellIndex.offset << 2;
|
||||
const end = start + shellIndex.len + 1;
|
||||
|
|
88
src/user.zig
88
src/user.zig
|
@ -17,6 +17,21 @@ pub const PackedUser = packed struct {
|
|||
name_is_a_suffix: bool,
|
||||
name_len: u5,
|
||||
gecos_len: u8,
|
||||
wip_padding: u8, // https://github.com/ziglang/zig/pull/10941
|
||||
|
||||
// blobSize returns the length of the blob storing string values.
|
||||
pub fn blobLength(self: *const PackedUser) usize {
|
||||
var result: usize = self.home_len;
|
||||
if (!self.name_is_a_suffix) {
|
||||
result += self.name_len;
|
||||
}
|
||||
result += self.gecos_len;
|
||||
if (self.shell_here) {
|
||||
result += self.shell_len_or_idx;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
const PackedUserAlignmentBits = 3;
|
||||
|
||||
|
@ -71,6 +86,7 @@ pub const UserWriter = struct {
|
|||
.name_is_a_suffix = std.mem.endsWith(u8, user.home, user.name),
|
||||
.name_len = name_len,
|
||||
.gecos_len = gecos_len,
|
||||
.wip_padding = 0,
|
||||
};
|
||||
|
||||
try self.appendTo.appendSlice(std.mem.asBytes(&puser));
|
||||
|
@ -92,37 +108,52 @@ pub const UserWriter = struct {
|
|||
};
|
||||
|
||||
pub const UserReader = struct {
|
||||
const shellIndexProto = fn (u10) []const u8;
|
||||
const shellIndexProto = fn (u6) []const u8;
|
||||
|
||||
blob: []u8,
|
||||
shellIndex: shellIndexProto,
|
||||
blob: []const u8,
|
||||
|
||||
pub const PackedUserEntry = struct {
|
||||
const PackedEntry = struct {
|
||||
packed_user: *PackedUser,
|
||||
blob: []const u8,
|
||||
};
|
||||
|
||||
pub fn init(shellIndex: shellIndexProto, blob: []const u8) UserReader {
|
||||
pub fn init(blob: []u8, shellIndex: shellIndexProto) UserReader {
|
||||
return UserReader{
|
||||
.shellIndex = shellIndex,
|
||||
.blob = blob,
|
||||
.shellIndex = shellIndex,
|
||||
};
|
||||
}
|
||||
|
||||
pub const PackedUserIterator = struct {
|
||||
ur: *const UserReader,
|
||||
index: u32 = 0,
|
||||
pub const PackedIterator = struct {
|
||||
ur: *UserReader,
|
||||
index: usize = 0,
|
||||
|
||||
pub fn next(it: *PackedUserIterator) ?PackedUserEntry {
|
||||
pub fn next(it: *PackedIterator) ?PackedEntry {
|
||||
if (it.index == it.ur.blob.len) return null;
|
||||
assert(it.index < it.blob.len);
|
||||
assert(it.index < it.ur.blob.len);
|
||||
|
||||
const start = it.index;
|
||||
const end = it.index + it.index + @sizeOf(PackedUser);
|
||||
var pu = std.mem.bytesAsValue(it.ur.blob[start..end]);
|
||||
_ = pu;
|
||||
const endUser = it.index + PackedUserSize;
|
||||
var packedUser = std.mem.bytesAsValue(
|
||||
PackedUser,
|
||||
it.ur.blob[it.index..endUser][0..PackedUserSize],
|
||||
);
|
||||
|
||||
const startBlob = endUser + 1;
|
||||
const endBlob = startBlob + packedUser.blobLength();
|
||||
|
||||
it.index = pad.roundUp(usize, PackedUserAlignmentBits, endBlob + 1);
|
||||
|
||||
return PackedEntry{
|
||||
.packed_user = packedUser,
|
||||
.blob = it.ur.blob[startBlob..endBlob],
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn packedIterator(self: *UserReader) PackedIterator {
|
||||
return .{ .ur = self };
|
||||
}
|
||||
};
|
||||
|
||||
const testing = std.testing;
|
||||
|
@ -140,27 +171,46 @@ fn testShellIndex(shell: []const u8) ?u6 {
|
|||
return null;
|
||||
}
|
||||
|
||||
fn testShell(index: u6) []const u8 {
|
||||
return switch (index) {
|
||||
0 => "/bin/bash",
|
||||
1 => "/bin/zsh",
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
test "construct PackedUser blob" {
|
||||
var buf = ArrayList(u8).init(testing.allocator);
|
||||
defer buf.deinit();
|
||||
|
||||
var writer = UserWriter.init(&buf, testShellIndex);
|
||||
const user1 = User{
|
||||
const users = [_]User{
|
||||
User{
|
||||
.uid = 1000,
|
||||
.gid = 1000,
|
||||
.name = "vidmantas",
|
||||
.gecos = "Vidmantas Kaminskas",
|
||||
.home = "/home/vidmantas",
|
||||
.shell = "/bin/bash",
|
||||
};
|
||||
const user2 = User{
|
||||
},
|
||||
User{
|
||||
.uid = 1001,
|
||||
.gid = 1001,
|
||||
.name = "svc-foo",
|
||||
.gecos = "Service Account",
|
||||
.home = "/home/service1",
|
||||
.shell = "/usr/bin/nologin",
|
||||
},
|
||||
};
|
||||
try writer.appendUser(user1);
|
||||
try writer.appendUser(user2);
|
||||
for (users) |user| {
|
||||
try writer.appendUser(user);
|
||||
}
|
||||
|
||||
var rd = UserReader.init(buf.items, testShell);
|
||||
var it = rd.packedIterator();
|
||||
var i: u32 = 0;
|
||||
while (it.next()) |entry| : (i += 1) {
|
||||
try testing.expectEqual(users[i].uid, entry.packed_user.uid);
|
||||
try testing.expectEqual(users[i].gid, entry.packed_user.gid);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue