add strlen for PackedUser strings

This commit is contained in:
Motiejus Jakštys 2022-04-08 20:05:30 +03:00 committed by Motiejus Jakštys
parent c343bf64fb
commit 41ed32994f
2 changed files with 53 additions and 15 deletions

View File

@ -5,6 +5,7 @@ const math = std.math;
const Allocator = mem.Allocator;
const ArrayList = std.ArrayList;
const StringHashMap = std.StringHashMap;
const fieldInfo = std.meta.fieldInfo;
const pad = @import("padding.zig");
const validate = @import("validate.zig");
@ -129,9 +130,7 @@ pub fn iterator(section: []const u8, shell_reader: shellImport.ShellReader) Iter
return Iterator{ .section = section, .shell_reader = shell_reader };
}
// packTo packs the User record and copies it to the given byte slice.
// The slice must have at least maxRecordSize() bytes available. The
// slice is passed as a pointer, so it can be mutated.
// packTo packs the User record and copies it to the given arraylist.
pub fn packTo(
arr: *ArrayList(u8),
user: User,
@ -141,10 +140,11 @@ pub fn packTo(
std.debug.assert(arr.items.len & 7 == 0);
// function arguments are consts. We need to mutate the underlying
// slice, so passing it via pointer instead.
const home_len = try validate.downCast(u6, user.home.len - 1);
const name_len = try validate.downCast(u5, user.name.len - 1);
const shell_len = try validate.downCast(u8, user.shell.len - 1);
const gecos_len = try validate.downCast(u8, user.gecos.len);
//const home_len = try validate.downCast(u6, user.home.len - 1);
const home_len = try validate.downCast(fieldInfo(Inner, .home_len).field_type, user.home.len - 1);
const name_len = try validate.downCast(fieldInfo(Inner, .name_len).field_type, user.name.len - 1);
const shell_len = try validate.downCast(fieldInfo(Inner, .shell_len_or_idx).field_type, user.shell.len - 1);
const gecos_len = try validate.downCast(fieldInfo(Inner, .gecos_len).field_type, user.gecos.len);
try validate.utf8(user.home);
try validate.utf8(user.name);
@ -211,6 +211,11 @@ pub fn shell(self: PackedUser, shell_reader: shellImport.ShellReader) []const u8
return shell_reader.get(self.inner.shell_len_or_idx);
}
pub const max_str_len = math.maxInt(fieldInfo(Inner, .shell_len_or_idx).field_type) + 1 +
math.maxInt(fieldInfo(Inner, .home_len).field_type) + 1 +
math.maxInt(fieldInfo(Inner, .name_len).field_type) + 1 +
math.maxInt(fieldInfo(Inner, .gecos_len).field_type);
const testing = std.testing;
test "PackedUser internal and external alignment" {
@ -232,6 +237,33 @@ const test_shell_reader = shellImport.ShellReader{
.index = &[_]u16{ 0, 9, 17 },
};
const max_user = User{
.uid = 0,
.gid = math.maxInt(u32),
.name = "Name" ** 8,
.gecos = "realname" ** 255 ++ "realnam",
.home = "Home" ** 16,
.shell = "She.LllL" ** 32,
};
test "max_user and max_str_len are consistent" {
const total_len = max_user.name.len +
max_user.gecos.len +
max_user.home.len +
max_user.shell.len;
try testing.expectEqual(total_len, max_str_len);
}
test "pack max_user" {
var arr = ArrayList(u8).init(testing.allocator);
defer arr.deinit();
var idx_noop = StringHashMap(u8).init(testing.allocator);
defer idx_noop.deinit();
try packTo(&arr, max_user, 0, idx_noop);
}
test "construct PackedUser section" {
var buf = ArrayList(u8).init(testing.allocator);
defer buf.deinit();
@ -250,14 +282,7 @@ test "construct PackedUser section" {
.gecos = "Service Account",
.home = "/home/service1",
.shell = "/usr/bin/nologin",
}, User{
.uid = 0,
.gid = math.maxInt(u32),
.name = "Name" ** 8,
.gecos = "Gecos" ** 51,
.home = "Home" ** 16,
.shell = "She.LllL" ** 32,
}, User{
}, max_user, User{
.uid = 1002,
.gid = 1002,
.name = "svc-bar",

View File

@ -1,6 +1,8 @@
const std = @import("std");
const mem = std.mem;
const Allocator = mem.Allocator;
const ArrayList = std.ArrayList;
const maxInt = std.math.maxInt;
const User = @This();
@ -48,6 +50,17 @@ pub fn deinit(self: *User, allocator: Allocator) void {
self.* = undefined;
}
pub fn fromReader(allocator: Allocator, reader: anytype) ![]User {
var users = ArrayList(User).init(allocator);
var scratch = ArrayList(u8).init(allocator);
defer scratch.deinit();
while (true) {
const line = reader.readUntilDelimiterArrayList(&scratch, '\n', maxInt(usize));
_ = line;
}
_ = users;
}
const testing = std.testing;
test "User.clone" {