diff --git a/src/DB.zig b/src/DB.zig index 54e130f..d632101 100644 --- a/src/DB.zig +++ b/src/DB.zig @@ -321,7 +321,7 @@ fn getGroup(self: *const DB, group: PackedGroup, buf: []u8) error{BufferTooSmall } // get a CGroup entry by name. -fn getgrnam(self: *const DB, name: []const u8, buf: []u8) error{BufferTooSmall}!?CGroup { +pub fn getgrnam(self: *const DB, name: []const u8, buf: []u8) error{BufferTooSmall}!?CGroup { const idx = bdz.search(self.bdz_groupname, name); if (idx >= self.header.num_groups) return null; const offset = self.idx_groupname2group[idx]; @@ -332,7 +332,7 @@ fn getgrnam(self: *const DB, name: []const u8, buf: []u8) error{BufferTooSmall}! } // get a CGroup entry by it's gid. -fn getgrgid(self: *const DB, gid: u32, buf: []u8) error{BufferTooSmall}!?CGroup { +pub fn getgrgid(self: *const DB, gid: u32, buf: []u8) error{BufferTooSmall}!?CGroup { const idx = bdz.search_u32(self.bdz_gid, gid); if (idx >= self.header.num_groups) return null; const offset = self.idx_gid2group[idx]; @@ -344,8 +344,8 @@ fn getgrgid(self: *const DB, gid: u32, buf: []u8) error{BufferTooSmall}!?CGroup fn pushStr(str: []const u8, buf: []u8, offset: *usize) [*:0]const u8 { const start = offset.*; - mem.copy(u8, buf[offset.*..], str); - buf[offset.* + str.len] = 0; + mem.copy(u8, buf[start..], str); + buf[start + str.len] = 0; offset.* += str.len + 1; return @ptrCast([*:0]const u8, &buf[start]); } diff --git a/src/libnss.zig b/src/libnss.zig index 7d4cd87..e560fdf 100644 --- a/src/libnss.zig +++ b/src/libnss.zig @@ -95,13 +95,6 @@ fn init() void { }; } -fn shouldOmitMembers(envvar: []const u8, argv: [][*:0]u8) bool { - if (mem.eql(u8, envvar, "1")) return true; - if (mem.eql(u8, envvar, "0")) return false; - if (argv.len == 0) return false; - return mem.eql(u8, mem.sliceTo(argv[0], 0), "id"); -} - export fn _nss_turbo_getpwuid_r( uid: c_uint, passwd: *CUser, @@ -151,6 +144,55 @@ export fn _nss_turbo_getpwnam_r( } } +export fn _nss_turbo_getgrgid_r( + gid: c_uint, + gr: *CGroup, + buffer: [*]u8, + buflen: usize, + errnop: *c_int, +) c.enum_nss_status { + const db = getDb(errnop) orelse return c.NSS_STATUS_UNAVAIL; + if (db.getgrgid(gid, buffer[0..buflen])) |maybe_cgroup| { + if (maybe_cgroup) |cgroup| { + gr.* = cgroup; + 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_getgrnam_r( + name: [*:0]const u8, + group: *CGroup, + buffer: [*]u8, + buflen: usize, + errnop: *c_int, +) c.enum_nss_status { + const db = getDb(errnop) orelse return c.NSS_STATUS_UNAVAIL; + const nameSlice = mem.sliceTo(name, 0); + if (db.getgrnam(nameSlice, buffer[0..buflen])) |maybe_cgroup| { + if (maybe_cgroup) |cgroup| { + group.* = cgroup; + 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; + }, + } +} + fn getDb(errnop: *c_int) ?DB { global_init.call(); if (global_state.file) |file| { @@ -214,3 +256,29 @@ fn testVidmantas(u: CUser) !void { try testing.expectEqualStrings("Vidmantas Kaminskas", mem.sliceTo(u.pw_gecos, 0)); try testing.expectEqualStrings("/bin/bash", mem.sliceTo(u.pw_shell, 0)); } + +test "getgrgid_r and getgrnam_r" { + var tf = try File.TestDB.init(testing.allocator); + defer tf.deinit(); + const turbonss_db_path_old = turbonss_db_path; + turbonss_db_path = tf.path; + defer { + turbonss_db_path = turbonss_db_path_old; + } + + var buffer: [1024]u8 = undefined; + var errno: c_int = 0; + var group: CGroup = undefined; + try testing.expectEqual( + c.NSS_STATUS_SUCCESS, + _nss_turbo_getgrgid_r(128, &group, &buffer, buffer.len, &errno), + ); + try testing.expectEqual(@as(c_int, 0), errno); + try testVidmantasGroup(group); +} + +fn testVidmantasGroup(g: CGroup) !void { + try testing.expectEqual(@as(u32, 128), g.gid); + const members = g.members; + try testing.expect(members[0] != null); +}