tests for passwd_all

This commit is contained in:
Motiejus Jakštys 2022-07-11 14:14:21 +03:00
parent f0777b9e94
commit 9a7447eaa1
4 changed files with 94 additions and 45 deletions

View File

@ -81,7 +81,7 @@ additional_gids_offset: u64,
pub const Entry = struct { pub const Entry = struct {
user: PackedUser, user: PackedUser,
next: ?[]const u8, end: usize,
}; };
pub fn fromBytes(bytes: []const u8) Entry { pub fn fromBytes(bytes: []const u8) Entry {
@ -93,37 +93,40 @@ pub fn fromBytes(bytes: []const u8) Entry {
}; };
const end_blob = end_strings + gids_offset.bytes_read; const end_blob = end_strings + gids_offset.bytes_read;
const nextStart = pad.roundUp(usize, alignment_bits, end_blob);
var next: ?[]const u8 = null;
if (nextStart < bytes.len)
next = bytes[nextStart..];
return Entry{ return Entry{
.user = PackedUser{ .user = PackedUser{
.inner = inner, .inner = inner,
.bytes = bytes[start_blob..end_blob], .bytes = bytes[start_blob..end_blob],
.additional_gids_offset = gids_offset.value, .additional_gids_offset = gids_offset.value,
}, },
.next = next, .end = pad.roundUp(usize, alignment_bits, end_blob),
}; };
} }
pub const Iterator = struct { pub const Iterator = struct {
section: ?[]const u8, section: []const u8,
nextStart: usize = 0,
shell_reader: ShellReader, shell_reader: ShellReader,
idx: u32 = 0,
total: u32,
pub fn next(it: *Iterator) ?PackedUser { pub fn next(it: *Iterator) ?PackedUser {
if (it.section) |section| { if (it.idx == it.total)
const entry = PackedUser.fromBytes(section);
it.section = entry.next;
return entry.user;
}
return null; return null;
const entry = PackedUser.fromBytes(it.section[it.nextStart..]);
it.nextStart += entry.end;
it.idx += 1;
return entry.user;
} }
}; };
pub fn iterator(section: []const u8, shell_reader: ShellReader) Iterator { pub fn iterator(section: []const u8, total: u32, shell_reader: ShellReader) Iterator {
return Iterator{ .section = section, .shell_reader = shell_reader }; return Iterator{
.section = section,
.total = total,
.shell_reader = shell_reader,
};
} }
// packTo packs the User record and copies it to the given arraylist. // packTo packs the User record and copies it to the given arraylist.
@ -289,7 +292,7 @@ test "construct PackedUser section" {
} }
var i: u29 = 0; var i: u29 = 0;
var it1 = PackedUser.iterator(buf.items, test_shell_reader); var it1 = PackedUser.iterator(buf.items, users.len, test_shell_reader);
while (it1.next()) |user| : (i += 1) { while (it1.next()) |user| : (i += 1) {
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());

View File

@ -92,7 +92,7 @@ fn strlen(self: *const User) usize {
const line_fmt = "{s}:x:{d}:{d}:{s}:{s}:{s}\n"; const line_fmt = "{s}:x:{d}:{d}:{s}:{s}:{s}\n";
const max_line_len = fmt.count(line_fmt, .{ pub const max_line_len = fmt.count(line_fmt, .{
max_user.name, max_user.name,
max_user.uid, max_user.uid,
max_user.gid, max_user.gid,
@ -136,7 +136,7 @@ pub fn fromReader(allocator: Allocator, err: *ErrCtx, reader: anytype) ![]User {
users.deinit(); users.deinit();
} }
var buf: [max_line_len + 1]u8 = undefined; var buf: [max_line_len]u8 = undefined;
while (try reader.readUntilDelimiterOrEof(buf[0..], '\n')) |line| { while (try reader.readUntilDelimiterOrEof(buf[0..], '\n')) |line| {
var user = try fromLine(allocator, err, line); var user = try fromLine(allocator, err, line);
try users.append(user); try users.append(user);

View File

@ -267,7 +267,11 @@ fn setpwent(state: *State) void {
defer state.getpwent_iterator_mu.unlock(); defer state.getpwent_iterator_mu.unlock();
const db = state.file.db; const db = state.file.db;
state.getpwent_iterator = PackedUser.iterator(db.users, db.shellReader()); state.getpwent_iterator = PackedUser.iterator(
db.users,
db.header.num_users,
db.shellReader(),
);
} }
export fn _nss_turbo_endpwent() void { export fn _nss_turbo_endpwent() void {

View File

@ -9,6 +9,7 @@ const flags = @import("flags.zig");
const DB = @import("DB.zig"); const DB = @import("DB.zig");
const File = @import("File.zig"); const File = @import("File.zig");
const PackedUser = @import("PackedUser.zig"); const PackedUser = @import("PackedUser.zig");
const User = @import("User.zig");
const Mode = enum { group, passwd }; const Mode = enum { group, passwd };
@ -97,13 +98,10 @@ fn execute(
} }
fn passwd(stdout: anytype, db: *const DB, keys: []const [*:0]const u8) u8 { fn passwd(stdout: anytype, db: *const DB, keys: []const [*:0]const u8) u8 {
var some_notfound = false;
if (keys.len == 0) if (keys.len == 0)
return passwd_all(stdout, db); return passwd_all(stdout, db);
var some_notfound = false;
const shell_reader = db.shellReader(); const shell_reader = db.shellReader();
for (keys) |key| { for (keys) |key| {
const keyZ = mem.span(key); const keyZ = mem.span(key);
const maybe_packed_user = if (fmt.parseUnsigned(u32, keyZ, 10)) |uid| const maybe_packed_user = if (fmt.parseUnsigned(u32, keyZ, 10)) |uid|
@ -124,7 +122,7 @@ fn passwd(stdout: anytype, db: *const DB, keys: []const [*:0]const u8) u8 {
} }
fn passwd_all(stdout: anytype, db: *const DB) u8 { fn passwd_all(stdout: anytype, db: *const DB) u8 {
var it = PackedUser.iterator(db.users, db.shellReader()); var it = PackedUser.iterator(db.users, db.header.num_users, db.shellReader());
while (it.next()) |packed_user| { while (it.next()) |packed_user| {
const line = packed_user.toUser(db.shellReader()).toLine(); const line = packed_user.toUser(db.shellReader()).toLine();
stdout.writeAll(line.constSlice()) catch return 3; stdout.writeAll(line.constSlice()) catch return 3;
@ -132,9 +130,23 @@ fn passwd_all(stdout: anytype, db: *const DB) u8 {
return 0; return 0;
} }
fn group(stdout: anytype, db: *const DB, keys: []const [*:0]const u8) u8 {
if (keys.len == 0)
return group_all(stdout, db);
var some_notfound = false;
return if (some_notfound) 2 else 0;
}
fn group_all(stdout: anytype, db: *const DB) u8 {
_ = stdout;
_ = db;
return 0;
}
const testing = std.testing; const testing = std.testing;
test "passwd and passwd_all" { test "passwd" {
var tf = try File.TestDB.init(testing.allocator); var tf = try File.TestDB.init(testing.allocator);
defer tf.deinit(); defer tf.deinit();
var stdout = ArrayList(u8).init(testing.allocator); var stdout = ArrayList(u8).init(testing.allocator);
@ -142,6 +154,7 @@ test "passwd and passwd_all" {
var stderr = ArrayList(u8).init(testing.allocator); var stderr = ArrayList(u8).init(testing.allocator);
defer stderr.deinit(); defer stderr.deinit();
{
const args = &[_][*:0]const u8{ const args = &[_][*:0]const u8{
"--db", "--db",
tf.path, tf.path,
@ -160,11 +173,40 @@ test "passwd and passwd_all" {
var offset: usize = want_root.len + want_vidmantas.len; var offset: usize = want_root.len + want_vidmantas.len;
try testing.expectEqualStrings(stdout.items[want_root.len..offset], want_vidmantas); try testing.expectEqualStrings(stdout.items[want_root.len..offset], want_vidmantas);
try testing.expectEqualStrings(stdout.items[offset..], want_root); try testing.expectEqualStrings(stdout.items[offset..], want_root);
}
} }
fn group(stdout: anytype, db: *const DB, keys: []const [*:0]const u8) u8 { test "passwd_all" {
_ = db; var tf = try File.TestDB.init(testing.allocator);
_ = stdout; defer tf.deinit();
_ = keys; var stdout = ArrayList(u8).init(testing.allocator);
return 0; defer stdout.deinit();
var stderr = ArrayList(u8).init(testing.allocator);
defer stderr.deinit();
const args = &[_][*:0]const u8{
"--db",
tf.path,
"passwd",
};
var buf: [User.max_line_len]u8 = undefined;
const got = execute(stdout.writer(), stderr.writer(), args);
try testing.expectEqual(got, 0);
const want_names = &[_][]const u8{
"Name" ** 8,
"nobody",
"root",
"svc-bar",
"vidmantas",
};
var i: usize = 0;
const reader = io.fixedBufferStream(stdout.items).reader();
while (try reader.readUntilDelimiterOrEof(buf[0..], '\n')) |line| {
var name = mem.split(u8, line, ":");
try testing.expectEqualStrings(want_names[i], name.next().?);
i += 1;
}
} }