2022-02-18 17:34:50 +02:00
|
|
|
const std = @import("std");
|
2022-02-18 20:29:45 +02:00
|
|
|
|
|
|
|
const Allocator = std.mem.Allocator;
|
2022-02-18 17:34:50 +02:00
|
|
|
|
2022-02-18 17:38:22 +02:00
|
|
|
pub const PackedUserSize = @sizeOf(PackedUser);
|
|
|
|
pub const PackedUser = packed struct {
|
2022-02-18 17:34:50 +02:00
|
|
|
uid: u32,
|
|
|
|
gid: u32,
|
|
|
|
additional_gids_offset: u29,
|
|
|
|
shell_here: u1,
|
2022-02-18 20:36:32 +02:00
|
|
|
shell_len_or_idx: u6,
|
2022-02-18 17:34:50 +02:00
|
|
|
homedir_len: u6,
|
|
|
|
username_is_a_suffix: u1,
|
|
|
|
username_offset_or_len: u5,
|
|
|
|
gecos_len: u8,
|
|
|
|
};
|
|
|
|
|
2022-02-18 20:29:45 +02:00
|
|
|
pub const User = struct {
|
|
|
|
uid: u32,
|
|
|
|
gid: u32,
|
|
|
|
name: []const u8,
|
|
|
|
gecos: []const u8,
|
|
|
|
home: []const u8,
|
|
|
|
shell: []const u8,
|
|
|
|
};
|
|
|
|
|
|
|
|
// UserWriter accepts a naive User struct and returns a PackedUser
|
|
|
|
pub const UserWriter = struct {
|
2022-02-18 20:35:42 +02:00
|
|
|
|
|
|
|
// shellIndexFnType is a signature for a function that accepts a shell
|
|
|
|
// string and returns it's index in the global shell section. Passing a
|
|
|
|
// function makes tests easier, and removes the Shell dependency of this
|
|
|
|
// module.
|
|
|
|
const shellIndexFnType = fn ([]const u8) ?u10;
|
2022-02-18 20:29:45 +02:00
|
|
|
allocator: Allocator,
|
2022-02-18 20:35:42 +02:00
|
|
|
shellIndexFn: shellIndexFnType,
|
2022-02-18 20:29:45 +02:00
|
|
|
|
2022-02-18 20:35:42 +02:00
|
|
|
pub fn init(allocator: Allocator, shellIndexFn: shellIndexFnType) UserWriter {
|
2022-02-18 20:29:45 +02:00
|
|
|
return UserWriter{
|
|
|
|
.allocator = allocator,
|
2022-02-18 20:35:42 +02:00
|
|
|
.shellIndexFn = shellIndexFn,
|
2022-02-18 20:29:45 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-02-18 20:35:42 +02:00
|
|
|
pub fn fromUser(self: *UserWriter, user: User) !PackedUser {
|
2022-02-18 20:29:45 +02:00
|
|
|
var shell_here: u1 = undefined;
|
2022-02-18 20:36:32 +02:00
|
|
|
var shell_len_or_idx: u6 = undefined;
|
2022-02-18 20:35:42 +02:00
|
|
|
if (self.shellIndexFn(user.shell)) |idx| {
|
2022-02-18 20:29:45 +02:00
|
|
|
shell_here = false;
|
2022-02-18 20:36:32 +02:00
|
|
|
shell_len_or_idx = idx;
|
2022-02-18 20:29:45 +02:00
|
|
|
} else {
|
|
|
|
shell_here = true;
|
2022-02-18 20:36:32 +02:00
|
|
|
shell_len_or_idx = user.shell.len;
|
2022-02-18 20:29:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
var puser = PackedUser{
|
|
|
|
.uid = user.uid,
|
|
|
|
.gid = user.gid,
|
|
|
|
.additional_gids_offset = 0, // second pass
|
|
|
|
.shell_here = shell_here,
|
2022-02-18 20:36:32 +02:00
|
|
|
.shell_len_or_idx = shell_len_or_idx,
|
2022-02-18 20:29:45 +02:00
|
|
|
.homedir_len = undefined,
|
|
|
|
.username_is_a_suffix = undefined,
|
|
|
|
.username_offset_or_len = undefined,
|
|
|
|
.gecos_len = undefined,
|
|
|
|
};
|
|
|
|
|
|
|
|
return puser;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-02-18 17:34:50 +02:00
|
|
|
const testing = std.testing;
|
|
|
|
|
|
|
|
test "PackedUser is byte-aligned" {
|
2022-02-18 17:38:22 +02:00
|
|
|
try testing.expectEqual(0, @rem(@bitSizeOf(PackedUser), 8));
|
2022-02-18 17:34:50 +02:00
|
|
|
}
|