refactor libnss.zig

This commit is contained in:
Motiejus Jakštys 2022-07-07 21:20:54 +03:00
parent 98db4ce0b2
commit df14c1fc67
2 changed files with 111 additions and 68 deletions

View File

@ -280,7 +280,7 @@ pub fn fromBytes(buf: []align(8) const u8) InvalidHeader!DB {
} }
// dumps PackedGroup to []u8 and returns a CGroup. // 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..]; const members_slice = self.groupmembers[group.members_offset..];
var vit = compress.VarintSliceIteratorMust(members_slice); var vit = compress.VarintSliceIteratorMust(members_slice);
const num_members = vit.remaining; const num_members = vit.remaining;

View File

@ -108,20 +108,21 @@ export fn _nss_turbo_getpwuid_r(
buflen: usize, buflen: usize,
errnop: *c_int, errnop: *c_int,
) c.enum_nss_status { ) c.enum_nss_status {
const db = getDb(errnop) orelse return c.NSS_STATUS_UNAVAIL; const db = getDBErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL;
if (db.getpwuid(uid, buffer[0..buflen])) |maybe_cuser| {
if (maybe_cuser) |cuser| { var cuser = db.getpwuid(uid, buffer[0..buflen]) catch |err| switch (err) {
passwd.* = cuser;
return c.NSS_STATUS_SUCCESS;
} else {
errnop.* = @enumToInt(os.E.NOENT);
return c.NSS_STATUS_NOTFOUND;
}
} else |err| switch (err) {
error.BufferTooSmall => { error.BufferTooSmall => {
errnop.* = @enumToInt(os.E.RANGE); errnop.* = @enumToInt(os.E.RANGE);
return c.NSS_STATUS_TRYAGAIN; 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, buflen: usize,
errnop: *c_int, errnop: *c_int,
) c.enum_nss_status { ) 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); const nameSlice = mem.sliceTo(name, 0);
if (db.getpwnam(nameSlice, buffer[0..buflen])) |maybe_cuser| {
if (maybe_cuser) |cuser| { var buf = buffer[0..buflen];
passwd.* = cuser; const cuser = db.getpwnam(nameSlice, buf) catch |err| switch (err) {
return c.NSS_STATUS_SUCCESS;
} else {
errnop.* = @enumToInt(os.E.NOENT);
return c.NSS_STATUS_NOTFOUND;
}
} else |err| switch (err) {
error.BufferTooSmall => { error.BufferTooSmall => {
errnop.* = @enumToInt(os.E.RANGE); errnop.* = @enumToInt(os.E.RANGE);
return c.NSS_STATUS_TRYAGAIN; 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, buflen: usize,
errnop: *c_int, errnop: *c_int,
) c.enum_nss_status { ) c.enum_nss_status {
const db = getDb(errnop) orelse return c.NSS_STATUS_UNAVAIL; const db = getDBErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL;
if (db.getgrgid(gid, buffer[0..buflen])) |maybe_cgroup| { var cgroup = db.getgrgid(gid, buffer[0..buflen]) catch |err| switch (err) {
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 => { error.BufferTooSmall => {
errnop.* = @enumToInt(os.E.RANGE); errnop.* = @enumToInt(os.E.RANGE);
return c.NSS_STATUS_TRYAGAIN; 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, buflen: usize,
errnop: *c_int, errnop: *c_int,
) c.enum_nss_status { ) 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); const nameSlice = mem.sliceTo(name, 0);
if (db.getgrnam(nameSlice, buffer[0..buflen])) |maybe_cgroup| { var buf = buffer[0..buflen];
if (maybe_cgroup) |cgroup| { var cgroup = db.getgrnam(nameSlice, buf) catch |err| switch (err) {
group.* = cgroup;
return c.NSS_STATUS_SUCCESS;
} else {
errnop.* = @enumToInt(os.E.NOENT);
return c.NSS_STATUS_NOTFOUND;
}
} else |err| switch (err) {
error.BufferTooSmall => { error.BufferTooSmall => {
errnop.* = @enumToInt(os.E.RANGE); errnop.* = @enumToInt(os.E.RANGE);
return c.NSS_STATUS_TRYAGAIN; 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 { export fn _nss_turbo_setpwent(_: c_int) void {
global_init.call(); global_init.call();
if (global_state) |*state| { var state = global_state orelse return;
state.getpwent_iterator_mu.lock();
defer state.getpwent_iterator_mu.unlock();
state.getpwent_iterator = PackedUser.iterator( state.getpwent_iterator_mu.lock();
state.file.db.users, defer state.getpwent_iterator_mu.unlock();
ShellReader{
.index = state.file.db.shell_index, state.getpwent_iterator = PackedUser.iterator(
.blob = state.file.db.shell_blob, state.file.db.users,
}, ShellReader{
); .index = state.file.db.shell_index,
} .blob = state.file.db.shell_blob,
},
);
} }
export fn _nss_turbo_endpwent() void { export fn _nss_turbo_endpwent() void {
@ -225,36 +229,75 @@ export fn _nss_turbo_endpwent() void {
} }
export fn _nss_turbo_setgrent(_: c_int) void { export fn _nss_turbo_setgrent(_: c_int) void {
global_init.call(); var state = getState() orelse return;
if (global_state) |*state| { state.getgrent_iterator_mu.lock();
state.getgrent_iterator_mu.lock(); defer state.getgrent_iterator_mu.unlock();
defer state.getgrent_iterator_mu.unlock(); state.getgrent_iterator = PackedGroup.iterator(
state.file.db.groups,
state.getgrent_iterator = PackedGroup.iterator( );
state.file.db.groups,
);
}
} }
export fn _nss_turbo_endgrent() void { export fn _nss_turbo_endgrent() void {
global_init.call(); var state = getState() orelse return;
if (global_state) |*state| { state.getgrent_iterator_mu.lock();
state.getgrent_iterator_mu.lock(); defer state.getgrent_iterator_mu.unlock();
defer state.getgrent_iterator_mu.unlock(); state.getgrent_iterator = null;
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(); global_init.call();
if (global_state) |state| { if (global_state) |state| {
return state.file.db; return state;
} else { } else {
errnop.* = @enumToInt(os.E.AGAIN); errnop.* = @enumToInt(os.E.AGAIN);
return null; return null;
} }
} }
fn getDBErrno(errnop: *c_int) ?DB {
if (getStateErrno(errnop)) |state| {
return state.file.db;
} else return null;
}
const testing = std.testing; const testing = std.testing;
test "getpwuid_r and getpwnam_r" { test "getpwuid_r and getpwnam_r" {