From df14c1fc675dd38b5d2c453b86d8e21e661304ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Motiejus=20Jak=C5=A1tys?= Date: Thu, 7 Jul 2022 21:20:54 +0300 Subject: [PATCH] refactor libnss.zig --- src/DB.zig | 2 +- src/libnss.zig | 177 ++++++++++++++++++++++++++++++------------------- 2 files changed, 111 insertions(+), 68 deletions(-) diff --git a/src/DB.zig b/src/DB.zig index a939eec..5c10b66 100644 --- a/src/DB.zig +++ b/src/DB.zig @@ -280,7 +280,7 @@ pub fn fromBytes(buf: []align(8) const u8) InvalidHeader!DB { } // dumps PackedGroup to []u8 and returns a CGroup. -fn getGroup(self: *const DB, group: PackedGroup, buf: []u8) error{BufferTooSmall}!CGroup { +pub fn getGroup(self: *const DB, group: PackedGroup, buf: []u8) error{BufferTooSmall}!CGroup { const members_slice = self.groupmembers[group.members_offset..]; var vit = compress.VarintSliceIteratorMust(members_slice); const num_members = vit.remaining; diff --git a/src/libnss.zig b/src/libnss.zig index dcd2552..a9737ec 100644 --- a/src/libnss.zig +++ b/src/libnss.zig @@ -108,20 +108,21 @@ export fn _nss_turbo_getpwuid_r( buflen: usize, errnop: *c_int, ) c.enum_nss_status { - const db = getDb(errnop) orelse return c.NSS_STATUS_UNAVAIL; - if (db.getpwuid(uid, buffer[0..buflen])) |maybe_cuser| { - if (maybe_cuser) |cuser| { - passwd.* = cuser; - return c.NSS_STATUS_SUCCESS; - } else { - errnop.* = @enumToInt(os.E.NOENT); - return c.NSS_STATUS_NOTFOUND; - } - } else |err| switch (err) { + const db = getDBErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL; + + var cuser = db.getpwuid(uid, buffer[0..buflen]) catch |err| switch (err) { error.BufferTooSmall => { errnop.* = @enumToInt(os.E.RANGE); return c.NSS_STATUS_TRYAGAIN; }, + }; + + if (cuser) |got| { + passwd.* = got; + return c.NSS_STATUS_SUCCESS; + } else { + errnop.* = @enumToInt(os.E.NOENT); + return c.NSS_STATUS_NOTFOUND; } } @@ -132,21 +133,23 @@ export fn _nss_turbo_getpwnam_r( buflen: usize, errnop: *c_int, ) c.enum_nss_status { - const db = getDb(errnop) orelse return c.NSS_STATUS_UNAVAIL; + const db = getDBErrno(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); - return c.NSS_STATUS_NOTFOUND; - } - } else |err| switch (err) { + + var buf = buffer[0..buflen]; + const cuser = db.getpwnam(nameSlice, buf) catch |err| switch (err) { error.BufferTooSmall => { errnop.* = @enumToInt(os.E.RANGE); return c.NSS_STATUS_TRYAGAIN; }, + }; + + if (cuser) |got| { + passwd.* = got; + return c.NSS_STATUS_SUCCESS; + } else { + errnop.* = @enumToInt(os.E.NOENT); + return c.NSS_STATUS_NOTFOUND; } } @@ -157,20 +160,20 @@ export fn _nss_turbo_getgrgid_r( 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) { + const db = getDBErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL; + var cgroup = db.getgrgid(gid, buffer[0..buflen]) catch |err| switch (err) { error.BufferTooSmall => { errnop.* = @enumToInt(os.E.RANGE); return c.NSS_STATUS_TRYAGAIN; }, + }; + + if (cgroup) |got| { + gr.* = got; + return c.NSS_STATUS_SUCCESS; + } else { + errnop.* = @enumToInt(os.E.NOENT); + return c.NSS_STATUS_NOTFOUND; } } @@ -181,38 +184,39 @@ export fn _nss_turbo_getgrnam_r( buflen: usize, errnop: *c_int, ) c.enum_nss_status { - const db = getDb(errnop) orelse return c.NSS_STATUS_UNAVAIL; + const db = getDBErrno(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) { + var buf = buffer[0..buflen]; + var cgroup = db.getgrnam(nameSlice, buf) catch |err| switch (err) { error.BufferTooSmall => { errnop.* = @enumToInt(os.E.RANGE); return c.NSS_STATUS_TRYAGAIN; }, + }; + + if (cgroup) |got| { + group.* = got; + return c.NSS_STATUS_SUCCESS; + } else { + errnop.* = @enumToInt(os.E.NOENT); + return c.NSS_STATUS_NOTFOUND; } } export fn _nss_turbo_setpwent(_: c_int) void { global_init.call(); - if (global_state) |*state| { - state.getpwent_iterator_mu.lock(); - defer state.getpwent_iterator_mu.unlock(); + var state = global_state orelse return; - state.getpwent_iterator = PackedUser.iterator( - state.file.db.users, - ShellReader{ - .index = state.file.db.shell_index, - .blob = state.file.db.shell_blob, - }, - ); - } + state.getpwent_iterator_mu.lock(); + defer state.getpwent_iterator_mu.unlock(); + + state.getpwent_iterator = PackedUser.iterator( + state.file.db.users, + ShellReader{ + .index = state.file.db.shell_index, + .blob = state.file.db.shell_blob, + }, + ); } export fn _nss_turbo_endpwent() void { @@ -225,36 +229,75 @@ export fn _nss_turbo_endpwent() void { } export fn _nss_turbo_setgrent(_: c_int) void { - global_init.call(); - if (global_state) |*state| { - state.getgrent_iterator_mu.lock(); - defer state.getgrent_iterator_mu.unlock(); - - state.getgrent_iterator = PackedGroup.iterator( - state.file.db.groups, - ); - } + var state = getState() orelse return; + state.getgrent_iterator_mu.lock(); + defer state.getgrent_iterator_mu.unlock(); + state.getgrent_iterator = PackedGroup.iterator( + state.file.db.groups, + ); } export fn _nss_turbo_endgrent() void { - global_init.call(); - if (global_state) |*state| { - state.getgrent_iterator_mu.lock(); - defer state.getgrent_iterator_mu.unlock(); - state.getgrent_iterator = null; + var state = getState() orelse return; + state.getgrent_iterator_mu.lock(); + defer state.getgrent_iterator_mu.unlock(); + state.getgrent_iterator = null; +} + +export fn _nss_turbo_getgrent_r( + result: *CGroup, + buffer: [*]u8, + buflen: usize, + errnop: *c_int, +) c.enum_nss_status { + var state = getStateErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL; + + state.getgrent_iterator_mu.lock(); + defer state.getgrent_iterator_mu.unlock(); + + var it = state.getgrent_iterator orelse { + // logic from _nss_systemd_getgrent_r + errnop.* = @enumToInt(os.E.HOSTDOWN); + return c.NSS_STATUS_UNAVAIL; + }; + + var group = it.next() orelse { + errnop.* = @enumToInt(os.E.NOENT); + return c.NSS_STATUS_NOTFOUND; + }; + + if (state.file.db.getGroup(group, buffer[0..buflen])) |cgroup| { + result.* = cgroup; + return c.NSS_STATUS_SUCCESS; + } else |err| switch (err) { + error.BufferTooSmall => { + errnop.* = @enumToInt(os.E.RANGE); + return c.NSS_STATUS_TRYAGAIN; + }, } } -fn getDb(errnop: *c_int) ?DB { +fn getState() ?State { + global_init.call(); + return global_state; +} + +fn getStateErrno(errnop: *c_int) ?State { global_init.call(); if (global_state) |state| { - return state.file.db; + return state; } else { errnop.* = @enumToInt(os.E.AGAIN); return null; } } +fn getDBErrno(errnop: *c_int) ?DB { + if (getStateErrno(errnop)) |state| { + return state.file.db; + } else return null; +} + const testing = std.testing; test "getpwuid_r and getpwnam_r" {