libnss: pass state explicitly
This commit is contained in:
parent
f327fb24ba
commit
78ac541e49
10
src/File.zig
10
src/File.zig
@ -39,9 +39,10 @@ pub fn close(self: *File) void {
|
||||
const testing = std.testing;
|
||||
|
||||
pub const TestDB = struct {
|
||||
allocator: Allocator,
|
||||
file: File,
|
||||
dir: testing.TmpDir,
|
||||
path: [:0]const u8,
|
||||
allocator: Allocator,
|
||||
|
||||
pub fn init(allocator: Allocator) !TestDB {
|
||||
var errc = ErrCtx{};
|
||||
@ -65,9 +66,9 @@ pub const TestDB = struct {
|
||||
break :blk real_path;
|
||||
};
|
||||
|
||||
const full_path = try fs.path.join(allocator, &[_][]const u8{
|
||||
const full_path = try fs.path.joinZ(allocator, &[_][]const u8{
|
||||
base_path,
|
||||
"db.turbo\x00",
|
||||
"db.turbo",
|
||||
});
|
||||
allocator.free(base_path);
|
||||
|
||||
@ -78,8 +79,9 @@ pub const TestDB = struct {
|
||||
_ = try os.writev(fd, db.iov().constSlice());
|
||||
|
||||
return TestDB{
|
||||
.file = try open(full_path),
|
||||
.dir = tmp,
|
||||
.path = full_path[0 .. full_path.len - 1 :0],
|
||||
.path = full_path,
|
||||
.allocator = allocator,
|
||||
};
|
||||
}
|
||||
|
141
src/libnss.zig
141
src/libnss.zig
@ -115,7 +115,17 @@ export fn _nss_turbo_getpwuid_r(
|
||||
errnop: *c_int,
|
||||
) c.enum_nss_status {
|
||||
const db = getDBErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL;
|
||||
return getpwuid_r(&db, uid, passwd, buffer, buflen, errnop);
|
||||
}
|
||||
|
||||
fn getpwuid_r(
|
||||
db: *const DB,
|
||||
uid: c_uint,
|
||||
passwd: *CUser,
|
||||
buffer: [*]u8,
|
||||
buflen: usize,
|
||||
errnop: *c_int,
|
||||
) c.enum_nss_status {
|
||||
var cuser = db.getpwuid(uid, buffer[0..buflen]) catch |err| switch (err) {
|
||||
error.BufferTooSmall => {
|
||||
errnop.* = @enumToInt(os.E.RANGE);
|
||||
@ -140,6 +150,17 @@ export fn _nss_turbo_getpwnam_r(
|
||||
errnop: *c_int,
|
||||
) c.enum_nss_status {
|
||||
const db = getDBErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL;
|
||||
return getpwnam_r(&db, name, passwd, buffer, buflen, errnop);
|
||||
}
|
||||
|
||||
fn getpwnam_r(
|
||||
db: *const DB,
|
||||
name: [*:0]const u8,
|
||||
passwd: *CUser,
|
||||
buffer: [*]u8,
|
||||
buflen: usize,
|
||||
errnop: *c_int,
|
||||
) c.enum_nss_status {
|
||||
const nameSlice = mem.sliceTo(name, 0);
|
||||
|
||||
var buf = buffer[0..buflen];
|
||||
@ -167,6 +188,17 @@ export fn _nss_turbo_getgrgid_r(
|
||||
errnop: *c_int,
|
||||
) c.enum_nss_status {
|
||||
const state = getStateErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL;
|
||||
return getgrgid_r(&state, gid, gr, buffer, buflen, errnop);
|
||||
}
|
||||
|
||||
fn getgrgid_r(
|
||||
state: *const State,
|
||||
gid: c_uint,
|
||||
gr: *CGroup,
|
||||
buffer: [*]u8,
|
||||
buflen: usize,
|
||||
errnop: *c_int,
|
||||
) c.enum_nss_status {
|
||||
const db = state.file.db;
|
||||
const omit_members = state.omit_members;
|
||||
|
||||
@ -195,9 +227,19 @@ export fn _nss_turbo_getgrnam_r(
|
||||
errnop: *c_int,
|
||||
) c.enum_nss_status {
|
||||
const state = getStateErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL;
|
||||
return getgrnam_r(&state, name, group, buffer, buflen, errnop);
|
||||
}
|
||||
|
||||
fn getgrnam_r(
|
||||
state: *const State,
|
||||
name: [*:0]const u8,
|
||||
group: *CGroup,
|
||||
buffer: [*]u8,
|
||||
buflen: usize,
|
||||
errnop: *c_int,
|
||||
) c.enum_nss_status {
|
||||
const db = state.file.db;
|
||||
const omit_members = state.omit_members;
|
||||
|
||||
const nameSlice = mem.sliceTo(name, 0);
|
||||
var buf = buffer[0..buflen];
|
||||
var cgroup = db.getgrnam(nameSlice, buf, omit_members) catch |err| switch (err) {
|
||||
@ -206,12 +248,10 @@ export fn _nss_turbo_getgrnam_r(
|
||||
return c.NSS_STATUS_TRYAGAIN;
|
||||
},
|
||||
};
|
||||
|
||||
const got_cgroup = cgroup orelse {
|
||||
errnop.* = @enumToInt(os.E.NOENT);
|
||||
return c.NSS_STATUS_NOTFOUND;
|
||||
};
|
||||
|
||||
group.* = got_cgroup;
|
||||
return c.NSS_STATUS_SUCCESS;
|
||||
}
|
||||
@ -219,7 +259,10 @@ export fn _nss_turbo_getgrnam_r(
|
||||
export fn _nss_turbo_setpwent(_: c_int) void {
|
||||
global_init.call();
|
||||
var state = global_state orelse return;
|
||||
setpwent(&state);
|
||||
}
|
||||
|
||||
fn setpwent(state: *State) void {
|
||||
state.getpwent_iterator_mu.lock();
|
||||
defer state.getpwent_iterator_mu.unlock();
|
||||
|
||||
@ -235,7 +278,10 @@ export fn _nss_turbo_setpwent(_: c_int) void {
|
||||
export fn _nss_turbo_endpwent() void {
|
||||
global_init.call();
|
||||
var state = global_state orelse return;
|
||||
endpwent(&state);
|
||||
}
|
||||
|
||||
fn endpwent(state: *State) void {
|
||||
state.getpwent_iterator_mu.lock();
|
||||
state.getpwent_iterator = null;
|
||||
state.getpwent_iterator_mu.unlock();
|
||||
@ -243,6 +289,10 @@ export fn _nss_turbo_endpwent() void {
|
||||
|
||||
export fn _nss_turbo_setgrent(_: c_int) void {
|
||||
var state = getState() orelse return;
|
||||
setgrent(&state);
|
||||
}
|
||||
|
||||
fn setgrent(state: *State) void {
|
||||
state.getgrent_iterator_mu.lock();
|
||||
defer state.getgrent_iterator_mu.unlock();
|
||||
state.getgrent_iterator = PackedGroup.iterator(
|
||||
@ -252,7 +302,10 @@ export fn _nss_turbo_setgrent(_: c_int) void {
|
||||
|
||||
export fn _nss_turbo_endgrent() void {
|
||||
var state = getState() orelse return;
|
||||
endgrent(&state);
|
||||
}
|
||||
|
||||
fn endgrent(state: *State) void {
|
||||
state.getgrent_iterator_mu.lock();
|
||||
state.getgrent_iterator = null;
|
||||
state.getgrent_iterator_mu.unlock();
|
||||
@ -265,7 +318,16 @@ export fn _nss_turbo_getgrent_r(
|
||||
errnop: *c_int,
|
||||
) c.enum_nss_status {
|
||||
var state = getStateErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL;
|
||||
return getgrent_r(&state, result, buffer, buflen, errnop);
|
||||
}
|
||||
|
||||
fn getgrent_r(
|
||||
state: *State,
|
||||
result: *CGroup,
|
||||
buffer: [*]u8,
|
||||
buflen: usize,
|
||||
errnop: *c_int,
|
||||
) c.enum_nss_status {
|
||||
state.getgrent_iterator_mu.lock();
|
||||
defer state.getgrent_iterator_mu.unlock();
|
||||
|
||||
@ -303,7 +365,16 @@ export fn _nss_turbo_getpwent_r(
|
||||
errnop: *c_int,
|
||||
) c.enum_nss_status {
|
||||
var state = getStateErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL;
|
||||
return getpwent_r(&state, result, buffer, buflen, errnop);
|
||||
}
|
||||
|
||||
fn getpwent_r(
|
||||
state: *State,
|
||||
result: *CUser,
|
||||
buffer: [*]u8,
|
||||
buflen: usize,
|
||||
errnop: *c_int,
|
||||
) c.enum_nss_status {
|
||||
state.getpwent_iterator_mu.lock();
|
||||
defer state.getpwent_iterator_mu.unlock();
|
||||
|
||||
@ -332,7 +403,7 @@ export fn _nss_turbo_getpwent_r(
|
||||
|
||||
export fn _nss_turbo_initgroups_dyn(
|
||||
user_name: [*:0]const u8,
|
||||
_: u32,
|
||||
gid: u32,
|
||||
start: *c_long,
|
||||
size: *c_long,
|
||||
groupsp: *[*]u32,
|
||||
@ -340,8 +411,20 @@ export fn _nss_turbo_initgroups_dyn(
|
||||
errnop: *c_int,
|
||||
) c.enum_nss_status {
|
||||
const state = getStateErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL;
|
||||
const db = state.file.db;
|
||||
return initgroups_dyn(&state, user_name, gid, start, size, groupsp, limit, errnop);
|
||||
}
|
||||
|
||||
fn initgroups_dyn(
|
||||
state: *const State,
|
||||
user_name: [*:0]const u8,
|
||||
_: u32,
|
||||
start: *c_long,
|
||||
size: *c_long,
|
||||
groupsp: *[*]u32,
|
||||
limit: c_long,
|
||||
errnop: *c_int,
|
||||
) c.enum_nss_status {
|
||||
const db = state.file.db;
|
||||
const user = db.getUser(mem.sliceTo(user_name, 0)) orelse {
|
||||
errnop.* = @enumToInt(os.E.NOENT);
|
||||
return c.NSS_STATUS_NOTFOUND;
|
||||
@ -413,19 +496,19 @@ const testing = std.testing;
|
||||
test "getpwuid_r and getpwnam_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;
|
||||
}
|
||||
const state = State{
|
||||
.file = tf.file,
|
||||
.omit_members = false,
|
||||
.initgroups_dyn_allocator = testing.failing_allocator,
|
||||
};
|
||||
|
||||
var buffer: [1024]u8 = undefined;
|
||||
var buf: [1024]u8 = undefined;
|
||||
var errno: c_int = 0;
|
||||
|
||||
var passwd: CUser = undefined;
|
||||
try testing.expectEqual(
|
||||
c.NSS_STATUS_SUCCESS,
|
||||
_nss_turbo_getpwuid_r(128, &passwd, &buffer, buffer.len, &errno),
|
||||
getpwuid_r(&state.file.db, 128, &passwd, &buf, buf.len, &errno),
|
||||
);
|
||||
try testing.expectEqual(@as(c_int, 0), errno);
|
||||
try testVidmantas(passwd);
|
||||
@ -433,7 +516,7 @@ test "getpwuid_r and getpwnam_r" {
|
||||
passwd = undefined;
|
||||
try testing.expectEqual(
|
||||
c.NSS_STATUS_SUCCESS,
|
||||
_nss_turbo_getpwnam_r("vidmantas", &passwd, &buffer, buffer.len, &errno),
|
||||
getpwnam_r(&state.file.db, "vidmantas", &passwd, &buf, buf.len, &errno),
|
||||
);
|
||||
try testing.expectEqual(@as(c_int, 0), errno);
|
||||
try testVidmantas(passwd);
|
||||
@ -441,7 +524,7 @@ test "getpwuid_r and getpwnam_r" {
|
||||
passwd = undefined;
|
||||
try testing.expectEqual(
|
||||
c.NSS_STATUS_NOTFOUND,
|
||||
_nss_turbo_getpwnam_r("does not exist", &passwd, &buffer, buffer.len, &errno),
|
||||
getpwnam_r(&state.file.db, "does not exist", &passwd, &buf, buf.len, &errno),
|
||||
);
|
||||
try testing.expectEqual(@enumToInt(os.E.NOENT), @intCast(u16, errno));
|
||||
|
||||
@ -449,7 +532,7 @@ test "getpwuid_r and getpwnam_r" {
|
||||
var small_buffer: [1]u8 = undefined;
|
||||
try testing.expectEqual(
|
||||
c.NSS_STATUS_TRYAGAIN,
|
||||
_nss_turbo_getpwuid_r(0, &passwd, &small_buffer, small_buffer.len, &errno),
|
||||
getpwuid_r(&state.file.db, 0, &passwd, &small_buffer, small_buffer.len, &errno),
|
||||
);
|
||||
try testing.expectEqual(@enumToInt(os.E.RANGE), @intCast(u16, errno));
|
||||
}
|
||||
@ -471,12 +554,12 @@ test "getgrgid_r and getgrnam_r" {
|
||||
turbonss_db_path = turbonss_db_path_old;
|
||||
}
|
||||
|
||||
var buffer: [1024]u8 = undefined;
|
||||
var buf: [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),
|
||||
_nss_turbo_getgrgid_r(128, &group, &buf, buf.len, &errno),
|
||||
);
|
||||
try testing.expectEqual(@as(c_int, 0), errno);
|
||||
try testVidmantasGroup(group);
|
||||
@ -484,7 +567,7 @@ test "getgrgid_r and getgrnam_r" {
|
||||
group = undefined;
|
||||
try testing.expectEqual(
|
||||
c.NSS_STATUS_SUCCESS,
|
||||
_nss_turbo_getgrnam_r("vidmantas", &group, &buffer, buffer.len, &errno),
|
||||
_nss_turbo_getgrnam_r("vidmantas", &group, &buf, buf.len, &errno),
|
||||
);
|
||||
try testing.expectEqual(@as(c_int, 0), errno);
|
||||
try testVidmantasGroup(group);
|
||||
@ -492,21 +575,21 @@ test "getgrgid_r and getgrnam_r" {
|
||||
group = undefined;
|
||||
try testing.expectEqual(
|
||||
c.NSS_STATUS_NOTFOUND,
|
||||
_nss_turbo_getgrnam_r("does not exist", &group, &buffer, buffer.len, &errno),
|
||||
_nss_turbo_getgrnam_r("does not exist", &group, &buf, buf.len, &errno),
|
||||
);
|
||||
try testing.expectEqual(@enumToInt(os.E.NOENT), @intCast(u16, errno));
|
||||
}
|
||||
|
||||
test "initgroups_dyn" {
|
||||
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;
|
||||
}
|
||||
const allocator = testing.allocator;
|
||||
global_state.?.initgroups_dyn_allocator = allocator;
|
||||
|
||||
var tf = try File.TestDB.init(allocator);
|
||||
defer tf.deinit();
|
||||
var state = State{
|
||||
.file = tf.file,
|
||||
.omit_members = false,
|
||||
.initgroups_dyn_allocator = allocator,
|
||||
};
|
||||
|
||||
var size: c_long = 3; // size of the gids array is this
|
||||
var groups = try allocator.alloc(u32, @intCast(usize, size)); // buffer too small
|
||||
@ -515,7 +598,8 @@ test "initgroups_dyn" {
|
||||
groups[0] = 42; // canary
|
||||
var start: c_long = 1; // canary is there
|
||||
|
||||
const status = _nss_turbo_initgroups_dyn(
|
||||
const status = initgroups_dyn(
|
||||
&state,
|
||||
"vidmantas",
|
||||
0, // gid, ignored
|
||||
&start,
|
||||
@ -528,6 +612,7 @@ test "initgroups_dyn" {
|
||||
try testing.expectEqual(@as(c_int, 42), errno);
|
||||
try testing.expectEqual(@as(u32, 42), groups[0]);
|
||||
try testing.expectEqual(@as(u32, 128), groups[1]);
|
||||
try testing.expectEqual(@as(u32, 9999), groups[2]);
|
||||
}
|
||||
|
||||
fn testVidmantasGroup(g: CGroup) !void {
|
||||
|
Loading…
Reference in New Issue
Block a user