setpw/endpw* now iterate

This commit is contained in:
Motiejus Jakštys 2022-07-14 18:39:30 +03:00
parent 43015f4d1d
commit 8db43a537b

View File

@ -194,8 +194,13 @@ 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 state = getStateErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL; global_init.call();
return getgrgid_r(state, gid, gr, buffer, buflen, errnop); if (global_state) |*state| {
return getgrgid_r(state, gid, gr, buffer, buflen, errnop);
} else {
errnop.* = @enumToInt(os.E.AGAIN);
return c.NSS_STATUS_UNAVAIL;
}
} }
fn getgrgid_r( fn getgrgid_r(
@ -233,8 +238,13 @@ 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 state = getStateErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL; global_init.call();
return getgrnam_r(state, name, group, buffer, buflen, errnop); if (global_state) |*state| {
return getgrnam_r(state, name, group, buffer, buflen, errnop);
} else {
errnop.* = @enumToInt(os.E.AGAIN);
return c.NSS_STATUS_UNAVAIL;
}
} }
fn getgrnam_r( fn getgrnam_r(
@ -265,8 +275,10 @@ fn getgrnam_r(
export fn _nss_turbo_setpwent(_: c_int) c.enum_nss_status { export fn _nss_turbo_setpwent(_: c_int) c.enum_nss_status {
global_init.call(); global_init.call();
var state = global_state orelse return c.NSS_STATUS_UNAVAIL; if (global_state) |*state|
return setpwent(&state); return setpwent(state)
else
return c.NSS_STATUS_UNAVAIL;
} }
fn setpwent(state: *State) c.enum_nss_status { fn setpwent(state: *State) c.enum_nss_status {
@ -279,20 +291,18 @@ fn setpwent(state: *State) c.enum_nss_status {
db.header.num_users, db.header.num_users,
db.shellReader(), db.shellReader(),
); );
std.debug.print("state.getpwent_iterator: {*}\n", .{
&state.getpwent_iterator.?,
});
return c.NSS_STATUS_SUCCESS; return c.NSS_STATUS_SUCCESS;
} }
export fn _nss_turbo_endpwent() c.enum_nss_status { export fn _nss_turbo_endpwent() c.enum_nss_status {
global_init.call(); global_init.call();
var state = global_state orelse return c.NSS_STATUS_UNAVAIL; if (global_state) |*state|
return endpwent(&state); return endpwent(state)
else
return c.NSS_STATUS_UNAVAIL;
} }
fn endpwent(state: *State) c.enum_nss_status { fn endpwent(state: *State) c.enum_nss_status {
std.debug.print("endpwent\n", .{});
state.getpwent_iterator_mu.lock(); state.getpwent_iterator_mu.lock();
state.getpwent_iterator = null; state.getpwent_iterator = null;
state.getpwent_iterator_mu.unlock(); state.getpwent_iterator_mu.unlock();
@ -300,8 +310,11 @@ fn endpwent(state: *State) c.enum_nss_status {
} }
export fn _nss_turbo_setgrent(_: c_int) c.enum_nss_status { export fn _nss_turbo_setgrent(_: c_int) c.enum_nss_status {
var state = getState() orelse return c.NSS_STATUS_UNAVAIL; global_init.call();
return setgrent(&state); if (global_state) |*state|
return setgrent(state)
else
return c.NSS_STATUS_UNAVAIL;
} }
fn setgrent(state: *State) c.enum_nss_status { fn setgrent(state: *State) c.enum_nss_status {
@ -315,8 +328,11 @@ fn setgrent(state: *State) c.enum_nss_status {
} }
export fn _nss_turbo_endgrent() c.enum_nss_status { export fn _nss_turbo_endgrent() c.enum_nss_status {
var state = getState() orelse return c.NSS_STATUS_UNAVAIL; global_init.call();
return endgrent(&state); if (global_state) |*state|
return endgrent(state)
else
return c.NSS_STATUS_UNAVAIL;
} }
fn endgrent(state: *State) c.enum_nss_status { fn endgrent(state: *State) c.enum_nss_status {
@ -332,8 +348,13 @@ export fn _nss_turbo_getgrent_r(
buflen: usize, buflen: usize,
errnop: *c_int, errnop: *c_int,
) c.enum_nss_status { ) c.enum_nss_status {
var state = getStateErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL; global_init.call();
return getgrent_r(state, result, buffer, buflen, errnop); if (global_state) |*state| {
return getgrent_r(state, result, buffer, buflen, errnop);
} else {
errnop.* = @enumToInt(os.E.AGAIN);
return c.NSS_STATUS_UNAVAIL;
}
} }
fn getgrent_r( fn getgrent_r(
@ -346,30 +367,30 @@ fn getgrent_r(
state.getgrent_iterator_mu.lock(); state.getgrent_iterator_mu.lock();
defer state.getgrent_iterator_mu.unlock(); defer state.getgrent_iterator_mu.unlock();
var it = state.getgrent_iterator orelse { if (state.getgrent_iterator) |*it| {
const group = it.next() orelse {
errnop.* = 0;
return c.NSS_STATUS_NOTFOUND;
};
const cgroup1 = if (state.omit_members)
DB.packCGroupNoMembers(&group, buffer[0..buflen])
else
state.file.db.packCGroup(&group, buffer[0..buflen]);
if (cgroup1) |cgroup| {
result.* = cgroup;
return c.NSS_STATUS_SUCCESS;
} else |err| switch (err) {
error.BufferTooSmall => {
errnop.* = @enumToInt(os.E.RANGE);
return c.NSS_STATUS_TRYAGAIN;
},
}
} else {
// logic from _nss_systemd_getgrent_r // logic from _nss_systemd_getgrent_r
errnop.* = @enumToInt(os.E.HOSTDOWN); errnop.* = @enumToInt(os.E.HOSTDOWN);
return c.NSS_STATUS_UNAVAIL; return c.NSS_STATUS_UNAVAIL;
};
const group = it.next() orelse {
errnop.* = 0;
return c.NSS_STATUS_NOTFOUND;
};
const cgroup1 = if (state.omit_members)
DB.packCGroupNoMembers(&group, buffer[0..buflen])
else
state.file.db.packCGroup(&group, buffer[0..buflen]);
if (cgroup1) |cgroup| {
result.* = cgroup;
return c.NSS_STATUS_SUCCESS;
} else |err| switch (err) {
error.BufferTooSmall => {
errnop.* = @enumToInt(os.E.RANGE);
return c.NSS_STATUS_TRYAGAIN;
},
} }
} }
@ -379,8 +400,13 @@ export fn _nss_turbo_getpwent_r(
buflen: usize, buflen: usize,
errnop: *c_int, errnop: *c_int,
) c.enum_nss_status { ) c.enum_nss_status {
var state = getStateErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL; global_init.call();
return getpwent_r(state, result, buffer, buflen, errnop); if (global_state) |*state| {
return getpwent_r(state, result, buffer, buflen, errnop);
} else {
errnop.* = @enumToInt(os.E.AGAIN);
return c.NSS_STATUS_UNAVAIL;
}
} }
fn getpwent_r( fn getpwent_r(
@ -393,30 +419,27 @@ fn getpwent_r(
state.getpwent_iterator_mu.lock(); state.getpwent_iterator_mu.lock();
defer state.getpwent_iterator_mu.unlock(); defer state.getpwent_iterator_mu.unlock();
std.debug.print("starting getpwent_r\n", .{}); if (state.getpwent_iterator) |*it| {
var it = state.getpwent_iterator orelse { const user = it.next() orelse {
errnop.* = 0;
return c.NSS_STATUS_NOTFOUND;
};
const buf = buffer[0..buflen];
const cuser = state.file.db.writeUser(user, buf) catch |err| switch (err) {
error.BufferTooSmall => {
errnop.* = @enumToInt(os.E.RANGE);
return c.NSS_STATUS_TRYAGAIN;
},
};
result.* = cuser;
return c.NSS_STATUS_SUCCESS;
} else {
// logic from _nss_systemd_getgrent_r // logic from _nss_systemd_getgrent_r
std.debug.print("no iterator, bailing\n", .{});
errnop.* = @enumToInt(os.E.HOSTDOWN); errnop.* = @enumToInt(os.E.HOSTDOWN);
return c.NSS_STATUS_UNAVAIL; return c.NSS_STATUS_UNAVAIL;
}; }
const user = it.next() orelse {
std.debug.print("end of iteration, returning 0\n", .{});
errnop.* = 0;
return c.NSS_STATUS_NOTFOUND;
};
const buf = buffer[0..buflen];
const cuser = state.file.db.writeUser(user, buf) catch |err| switch (err) {
error.BufferTooSmall => {
errnop.* = @enumToInt(os.E.RANGE);
return c.NSS_STATUS_TRYAGAIN;
},
};
result.* = cuser;
return c.NSS_STATUS_SUCCESS;
} }
export fn _nss_turbo_initgroups_dyn( export fn _nss_turbo_initgroups_dyn(
@ -428,8 +451,13 @@ export fn _nss_turbo_initgroups_dyn(
limit: c_long, limit: c_long,
errnop: *c_int, errnop: *c_int,
) c.enum_nss_status { ) c.enum_nss_status {
const state = getStateErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL; global_init.call();
return initgroups_dyn(state, user_name, gid, start, size, groupsp, limit, errnop); if (global_state) |*state| {
return initgroups_dyn(state, user_name, gid, start, size, groupsp, limit, errnop);
} else {
errnop.* = @enumToInt(os.E.AGAIN);
return c.NSS_STATUS_UNAVAIL;
}
} }
fn initgroups_dyn( fn initgroups_dyn(
@ -488,27 +516,16 @@ fn initgroups_dyn(
return if (added > 0) c.NSS_STATUS_SUCCESS else c.NSS_STATUS_NOTFOUND; return if (added > 0) c.NSS_STATUS_SUCCESS else c.NSS_STATUS_NOTFOUND;
} }
fn getState() ?State { fn getDBErrno(errnop: *c_int) ?*const DB {
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; return &state.file.db;
} else { } else {
errnop.* = @enumToInt(os.E.AGAIN); errnop.* = @enumToInt(os.E.AGAIN);
return null; return null;
} }
} }
fn getDBErrno(errnop: *c_int) ?*const DB {
if (getStateErrno(errnop)) |state| {
return &state.file.db;
} else return null;
}
const testing = std.testing; const testing = std.testing;
test "libnss getpwuid_r and getpwnam_r" { test "libnss getpwuid_r and getpwnam_r" {