From a2893a366e8604279edca04d10b355d663e12a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Motiejus=20Jak=C5=A1tys?= Date: Wed, 6 Jul 2022 16:29:21 +0300 Subject: [PATCH] getpwnam_r and getpwuid_r --- src/PackedUser.zig | 4 ---- src/libnss.zig | 51 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/PackedUser.zig b/src/PackedUser.zig index 315bbbb..5d3aa18 100644 --- a/src/PackedUser.zig +++ b/src/PackedUser.zig @@ -84,10 +84,6 @@ pub const Entry = struct { next: ?[]const u8, }; -// TODO(motiejus) provide a way to return an entry without decoding the -// additional_gids_offset: -// - will not return the 'next' slice. -// - cannot throw an Overflow error. pub fn fromBytes(bytes: []const u8) Entry { const inner = mem.bytesAsValue(Inner, bytes[0..@sizeOf(Inner)]); const start_blob = @sizeOf(Inner); diff --git a/src/libnss.zig b/src/libnss.zig index 4617860..aed5195 100644 --- a/src/libnss.zig +++ b/src/libnss.zig @@ -22,7 +22,7 @@ const ENV_DB = "TURBONSS_DB"; const ENV_LOGLEVEL = "TURBONSS_LOGLEVEL"; const ENV_OMIT_MEMBERS = "TURBONSS_OMIT_MEMBERS"; -export var turbonss_db_path: [:0]const u8 = "/etc/turbonss/db.turbo"; +var turbonss_db_path: [:0]const u8 = "/etc/turbonss/db.turbo"; pub var log_level: std.log.Level = .err; @@ -104,16 +104,40 @@ fn shouldOmitMembers(envvar: []const u8, argv: [][*:0]u8) bool { export fn _nss_turbo_getpwuid_r( uid: c_uint, - pwd: *CUser, - buf: [*]u8, + passwd: *CUser, + buffer: [*]u8, buflen: usize, errnop: *c_int, ) c.enum_nss_status { const db = get_db(errnop) orelse return c.NSS_STATUS_UNAVAIL; - - if (db.getpwuid(uid, buf[0..buflen])) |maybe_cuser| { + if (db.getpwuid(uid, buffer[0..buflen])) |maybe_cuser| { if (maybe_cuser) |cuser| { - pwd.* = cuser; + passwd.* = cuser; + return c.NSS_STATUS_SUCCESS; + } else { + errnop.* = @enumToInt(os.E.NOENT); + return c.NSS_STATUS_NOTFOUND; + } + } else |err| switch (err) { + error.BufferTooSmall => { + errnop.* = @enumToInt(os.E.RANGE); + return c.NSS_STATUS_TRYAGAIN; + }, + } +} + +export fn _nss_turbo_getpwnam_r( + name: [*:0]u8, + passwd: *CUser, + buffer: [*]u8, + buflen: usize, + errnop: *c_int, +) c.enum_nss_status { + const db = get_db(errnop) orelse return c.NSS_STATUS_UNAVAIL; + const nameSlice = mem.sliceTo(name, 0); + if (db.getpwnam(nameSlice, buffer[0..buflen])) |maybe_cuser| { + if (maybe_cuser) |cuser| { + passwd.* = cuser; return c.NSS_STATUS_SUCCESS; } else { errnop.* = @enumToInt(os.E.NOENT); @@ -141,7 +165,20 @@ fn get_db(errnop: *c_int) ?DB { const testing = std.testing; test "nss_turbo_getpwuid_r" { + const allocator = testing.allocator; + var errc = ErrCtx{}; - var tf = try File.TestDB.init(testing.allocator, &errc); + var tf = try File.TestDB.init(allocator, &errc); defer tf.deinit(); + std.debug.print("tf.path: {s}\n", .{tf.path}); + turbonss_db_path = tf.path; + + var passwd: CUser = undefined; + var buffer: [1024]u8 = undefined; + var errno: c_int = 0; + + const status = _nss_turbo_getpwuid_r(0, &passwd, &buffer, buffer.len, &errno); + if (true) return error.SkipZigTest; + try testing.expectEqual(@as(c_int, 0), errno); + try testing.expectEqual(c.NSS_STATUS_SUCCESS, status); }