rewrite initgroups_dyn
This commit is contained in:
parent
4aee66fb11
commit
7960cf25c9
@ -481,46 +481,43 @@ fn initgroups_dyn(
|
|||||||
// TODO: use db.userGids()
|
// TODO: use db.userGids()
|
||||||
const offset = user.additional_gids_offset;
|
const offset = user.additional_gids_offset;
|
||||||
var vit = compress.varintSliceIteratorMust(db.additional_gids[offset..]);
|
var vit = compress.varintSliceIteratorMust(db.additional_gids[offset..]);
|
||||||
const remaining = vit.remaining;
|
|
||||||
|
|
||||||
var gids = compress.deltaDecompressionIterator(&vit);
|
var gids = compress.deltaDecompressionIterator(&vit);
|
||||||
if (size.* < remaining) {
|
|
||||||
const oldsize = @intCast(usize, size.*);
|
|
||||||
const newsize = if (limit <= 0)
|
|
||||||
oldsize + gids.remaining()
|
|
||||||
else
|
|
||||||
math.min(@intCast(usize, limit), oldsize + gids.remaining());
|
|
||||||
|
|
||||||
var buf = groupsp.*[0..oldsize];
|
// the implementation below is ported from glibc's db-initgroups.c
|
||||||
const new_groups = state.initgroups_dyn_allocator.realloc(buf, newsize);
|
// even though we know the size of the groups upfront, I found it too difficult
|
||||||
if (new_groups) |newgroups| {
|
// to preallocate and juggle size, start and limit while keeping glibc happy.
|
||||||
groupsp.* = newgroups.ptr;
|
var any: bool = false;
|
||||||
size.* = @intCast(c_long, newsize);
|
|
||||||
} else |err| switch (err) {
|
|
||||||
error.OutOfMemory => {
|
|
||||||
errnop.* = @enumToInt(os.E.NOMEM);
|
|
||||||
return c.NSS_STATUS_TRYAGAIN;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// I was not able to understand the expected behavior of limit. In glibc
|
|
||||||
// compat-initgroups.c limit is used to malloc the buffer. Something like
|
|
||||||
// this is all over the place:
|
|
||||||
// if (limit > 0 && *size == limit) /* We reached the maximum. */
|
|
||||||
// return;
|
|
||||||
// Our implementation will thus limit the number of *added* entries.
|
|
||||||
|
|
||||||
var added: usize = 0;
|
|
||||||
while (gids.nextMust()) |gid| {
|
while (gids.nextMust()) |gid| {
|
||||||
if (limit > 0 and added == limit) break;
|
if (start.* == size.*) {
|
||||||
|
if (limit > 0 and size.* == limit)
|
||||||
|
return c.NSS_STATUS_SUCCESS;
|
||||||
|
|
||||||
added += 1;
|
const oldsize = @intCast(usize, size.*);
|
||||||
|
const newsize: usize = if (limit <= 0)
|
||||||
|
2 * oldsize
|
||||||
|
else
|
||||||
|
math.min(@intCast(usize, limit), 2 * oldsize);
|
||||||
|
|
||||||
|
var buf = groupsp.*[0..oldsize];
|
||||||
|
const new_groups = state.initgroups_dyn_allocator.realloc(buf, newsize);
|
||||||
|
|
||||||
|
if (new_groups) |newgroups| {
|
||||||
|
groupsp.* = newgroups.ptr;
|
||||||
|
size.* = @intCast(c_long, newsize);
|
||||||
|
} else |err| switch (err) {
|
||||||
|
error.OutOfMemory => {
|
||||||
|
errnop.* = @enumToInt(os.E.NOMEM);
|
||||||
|
return c.NSS_STATUS_TRYAGAIN;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
any = true;
|
||||||
groupsp.*[@intCast(usize, start.*)] = @intCast(u32, gid);
|
groupsp.*[@intCast(usize, start.*)] = @intCast(u32, gid);
|
||||||
start.* += 1;
|
start.* += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (added > 0) c.NSS_STATUS_SUCCESS else c.NSS_STATUS_NOTFOUND;
|
return if (any) c.NSS_STATUS_SUCCESS else c.NSS_STATUS_NOTFOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getDBErrno(errnop: *c_int) ?*const DB {
|
fn getDBErrno(errnop: *c_int) ?*const DB {
|
||||||
|
Loading…
Reference in New Issue
Block a user