rewrite initgroups_dyn
This commit is contained in:
parent
4aee66fb11
commit
7960cf25c9
|
@ -481,46 +481,43 @@ fn initgroups_dyn(
|
|||
// TODO: use db.userGids()
|
||||
const offset = user.additional_gids_offset;
|
||||
var vit = compress.varintSliceIteratorMust(db.additional_gids[offset..]);
|
||||
const remaining = vit.remaining;
|
||||
|
||||
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];
|
||||
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;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
// the implementation below is ported from glibc's db-initgroups.c
|
||||
// even though we know the size of the groups upfront, I found it too difficult
|
||||
// to preallocate and juggle size, start and limit while keeping glibc happy.
|
||||
var any: bool = false;
|
||||
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);
|
||||
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 {
|
||||
|
|
Loading…
Reference in New Issue