diff --git a/src/DB.zig b/src/DB.zig index 9ab8702..82b445b 100644 --- a/src/DB.zig +++ b/src/DB.zig @@ -350,7 +350,7 @@ fn pushStr(str: []const u8, buf: []u8, offset: *usize) [*]const u8 { return @ptrCast([*]const u8, &buf[start]); } -fn getUser(self: *const DB, user: PackedUser, buf: []u8) error{OutOfMemory}!CUser { +fn getUser(self: *const DB, user: PackedUser, buf: []u8) error{BufferTooSmall}!CUser { const shell_reader = ShellReader{ .index = self.shell_index, .blob = self.shell_blob, @@ -365,7 +365,7 @@ fn getUser(self: *const DB, user: PackedUser, buf: []u8) error{OutOfMemory}!CUse gecos.len + 1 + home.len + 1 + shell.len + 1; - if (strlen > buf.len) return error.OutOfMemory; + if (strlen > buf.len) return error.BufferTooSmall; var offset: usize = 0; const pw_name = pushStr(name, buf, &offset); @@ -384,7 +384,7 @@ fn getUser(self: *const DB, user: PackedUser, buf: []u8) error{OutOfMemory}!CUse } // get a CUser entry by name. -pub fn getpwnam(self: *const DB, name: []const u8, buf: []u8) error{OutOfMemory}!?CUser { +pub fn getpwnam(self: *const DB, name: []const u8, buf: []u8) error{BufferTooSmall}!?CUser { const idx = bdz.search(self.bdz_username, name); // bdz may return a hash that's bigger than the number of users if (idx >= self.header.num_users) return null; @@ -396,7 +396,7 @@ pub fn getpwnam(self: *const DB, name: []const u8, buf: []u8) error{OutOfMemory} } // get a CUser entry by uid. -pub fn getpwuid(self: *const DB, uid: u32, buf: []u8) error{OutOfMemory}!?CUser { +pub fn getpwuid(self: *const DB, uid: u32, buf: []u8) error{BufferTooSmall}!?CUser { const idx = bdz.search_u32(self.bdz_uid, uid); if (idx >= self.header.num_users) return null; const offset = self.idx_uid2user[idx]; @@ -759,7 +759,7 @@ test "getpwnam/getpwuid" { const long = try db.getpwnam("Name" ** 8, buf); try testing.expectEqualStrings(long.?.pw_name[0..33], "Name" ** 8 ++ "\x00"); buf.len -= 1; - try testing.expectError(error.OutOfMemory, db.getpwnam("Name" ** 8, buf)); + try testing.expectError(error.BufferTooSmall, db.getpwnam("Name" ** 8, buf)); } test "additionalGids" { diff --git a/src/libnss.zig b/src/libnss.zig index ed9a609..922c38e 100644 --- a/src/libnss.zig +++ b/src/libnss.zig @@ -19,10 +19,10 @@ const c = @cImport({ }); const ENV_DB = "TURBONSS_DB"; -const ENV_VERBOSE = "TURBONSS__VERBOSE"; +const ENV_VERBOSE = "TURBONSS_VERBOSE"; const ENV_OMIT_MEMBERS = "TURBONSS_OMIT_MEMBERS"; -export const turbonss_default_path: [:0]const u8 = "/etc/turbonss/db.turbo"; +export var turbonss_db_path: [:0]const u8 = "/etc/turbonss/db.turbo"; pub var log_level: std.log.Level = .err; @@ -47,7 +47,7 @@ fn init() void { else .err; - const fname = os.getenvZ(ENV_DB) orelse turbonss_default_path[0..]; + const fname = os.getenvZ(ENV_DB) orelse turbonss_db_path[0..]; log.debug("opening {s}", .{fname}); const env_omit_members = os.getenvZ(ENV_OMIT_MEMBERS) orelse "auto"; @@ -75,34 +75,38 @@ fn shouldOmitMembers(envvar: []const u8, argv: [][*:0]u8) bool { export fn _nss_turbo_getpwuid_r( uid: c_uint, - res: *CUser, + pwd: *CUser, buf: [*]u8, - len: usize, + buflen: usize, errnop: *c_int, ) c.enum_nss_status { - global_init.call(); + const db = get_db(errnop) orelse return c.NSS_STATUS_UNAVAIL; - if (global_state.file == null) { - errnop.* = @enumToInt(os.E.AGAIN); - return c.NSS_STATUS_UNAVAIL; - } - - const db = global_state.file.?.db; - - const cuser = db.getpwuid(uid, buf[0..len]) catch |err| switch (err) { - error.OutOfMemory => { + if (db.getpwuid(uid, buf[0..buflen])) |maybe_cuser| { + if (maybe_cuser) |cuser| { + pwd.* = 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; }, - }; - - if (cuser == null) { - errnop.* = @enumToInt(os.E.NOENT); - return c.NSS_STATUS_NOTFOUND; } - res.* = cuser.?; +} - return c.NSS_STATUS_SUCCESS; +fn get_db(errnop: *c_int) ?DB { + global_init.call(); + + if (global_state.file) |file| { + return file.db; + } else { + errnop.* = @enumToInt(os.E.AGAIN); + return null; + } } const testing = std.testing;