use omit_members sometimes
This commit is contained in:
parent
434f9e1571
commit
5fa4a71ddf
65
src/DB.zig
65
src/DB.zig
@ -279,6 +279,28 @@ pub fn fromBytes(buf: []align(8) const u8) InvalidHeader!DB {
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn packCGroupNoMembers(group: PackedGroup, buf: []u8) error{BufferTooSmall}!CGroup {
|
||||
// first word in buf will be a pointer to null. that probably can be
|
||||
// simplified by writing (0)**word_size to the buffer, but let's pretend
|
||||
// type safety for a moment.
|
||||
const name_start = @sizeOf(?[*:0]const u8);
|
||||
if (name_start > buf.len) return error.BufferTooSmall;
|
||||
var member_ptrs = mem.bytesAsSlice(?[*:0]const u8, buf[0..name_start]);
|
||||
member_ptrs[0] = null;
|
||||
|
||||
// write name
|
||||
const name = group.name();
|
||||
if (name_start + name.len + 1 > buf.len) return error.BufferTooSmall;
|
||||
mem.copy(u8, buf[name_start..], name);
|
||||
buf[name_start + name.len] = 0;
|
||||
|
||||
return CGroup{
|
||||
.gid = group.gid(),
|
||||
.name = buf[name_start .. name_start + name.len :0].ptr,
|
||||
.members = member_ptrs.ptr,
|
||||
};
|
||||
}
|
||||
|
||||
// dumps PackedGroup to []u8 and returns a CGroup.
|
||||
pub fn packCGroup(self: *const DB, group: PackedGroup, buf: []u8) error{BufferTooSmall}!CGroup {
|
||||
const members_slice = self.groupmembers[group.members_offset..];
|
||||
@ -321,25 +343,41 @@ pub fn packCGroup(self: *const DB, group: PackedGroup, buf: []u8) error{BufferTo
|
||||
}
|
||||
|
||||
// get a CGroup entry by name.
|
||||
pub fn getgrnam(self: *const DB, name: []const u8, buf: []u8) error{BufferTooSmall}!?CGroup {
|
||||
pub fn getgrnam(
|
||||
self: *const DB,
|
||||
name: []const u8,
|
||||
buf: []u8,
|
||||
omit_members: bool,
|
||||
) error{BufferTooSmall}!?CGroup {
|
||||
const idx = bdz.search(self.bdz_groupname, name);
|
||||
if (idx >= self.header.num_groups) return null;
|
||||
const offset = self.idx_groupname2group[idx];
|
||||
const nbits = PackedGroup.alignment_bits;
|
||||
const group = PackedGroup.fromBytes(self.groups[offset << nbits ..]).group;
|
||||
if (!mem.eql(u8, name, group.name())) return null;
|
||||
return try self.packCGroup(group, buf);
|
||||
return if (omit_members)
|
||||
try packCGroupNoMembers(group, buf)
|
||||
else
|
||||
try self.packCGroup(group, buf);
|
||||
}
|
||||
|
||||
// get a CGroup entry by it's gid.
|
||||
pub fn getgrgid(self: *const DB, gid: u32, buf: []u8) error{BufferTooSmall}!?CGroup {
|
||||
pub fn getgrgid(
|
||||
self: *const DB,
|
||||
gid: u32,
|
||||
buf: []u8,
|
||||
omit_members: bool,
|
||||
) error{BufferTooSmall}!?CGroup {
|
||||
const idx = bdz.search_u32(self.bdz_gid, gid);
|
||||
if (idx >= self.header.num_groups) return null;
|
||||
const offset = self.idx_gid2group[idx];
|
||||
const nbits = PackedGroup.alignment_bits;
|
||||
const group = PackedGroup.fromBytes(self.groups[offset << nbits ..]).group;
|
||||
if (gid != group.gid()) return null;
|
||||
return try self.packCGroup(group, buf);
|
||||
return if (omit_members)
|
||||
try packCGroupNoMembers(group, buf)
|
||||
else
|
||||
try self.packCGroup(group, buf);
|
||||
}
|
||||
|
||||
fn pushStr(str: []const u8, buf: []u8, offset: *usize) [*:0]const u8 {
|
||||
@ -708,8 +746,8 @@ test "getgrnam/getgrgid" {
|
||||
defer testing.allocator.free(buf);
|
||||
|
||||
{
|
||||
try testing.expectEqual(try db.getgrnam("doesnotexist", buf), null);
|
||||
const all = (try db.getgrnam("all", buf)).?;
|
||||
try testing.expectEqual(try db.getgrnam("doesnotexist", buf, false), null);
|
||||
const all = (try db.getgrnam("all", buf, false)).?;
|
||||
try testing.expectEqual(all.gid, 9999);
|
||||
try testing.expectEqualStrings(all.name[0..4], "all\x00");
|
||||
const members = all.members;
|
||||
@ -721,16 +759,23 @@ test "getgrnam/getgrgid" {
|
||||
}
|
||||
|
||||
{
|
||||
try testing.expectEqual(try db.getgrgid(42, buf), null);
|
||||
const all = (try db.getgrgid(9999, buf)).?;
|
||||
const all = (try db.getgrnam("all", buf, true)).?;
|
||||
try testing.expectEqual(all.gid, 9999);
|
||||
try testing.expectEqualStrings(all.name[0..4], "all\x00");
|
||||
try testing.expectEqual(all.members[0], null);
|
||||
}
|
||||
|
||||
{
|
||||
try testing.expectEqual(try db.getgrgid(42, buf, false), null);
|
||||
const all = (try db.getgrgid(9999, buf, false)).?;
|
||||
try testing.expectEqual(all.gid, 9999);
|
||||
try testing.expectEqualStrings(all.name[0..3], "all");
|
||||
}
|
||||
try testing.expectEqualStrings("", errc.unwrap().constSlice());
|
||||
|
||||
_ = try db.getgrnam("all", buf);
|
||||
_ = try db.getgrnam("all", buf, false);
|
||||
buf.len -= 1;
|
||||
try testing.expectError(error.BufferTooSmall, db.getgrnam("all", buf));
|
||||
try testing.expectError(error.BufferTooSmall, db.getgrnam("all", buf, false));
|
||||
}
|
||||
|
||||
test "getpwnam/getpwuid" {
|
||||
|
@ -160,8 +160,12 @@ export fn _nss_turbo_getgrgid_r(
|
||||
buflen: usize,
|
||||
errnop: *c_int,
|
||||
) c.enum_nss_status {
|
||||
const db = getDBErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL;
|
||||
var cgroup = db.getgrgid(gid, buffer[0..buflen]) catch |err| switch (err) {
|
||||
const state = getStateErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL;
|
||||
const db = state.file.db;
|
||||
const omit_members = state.omit_members;
|
||||
|
||||
var buf = buffer[0..buflen];
|
||||
var cgroup = db.getgrgid(gid, buf, omit_members) catch |err| switch (err) {
|
||||
error.BufferTooSmall => {
|
||||
errnop.* = @enumToInt(os.E.RANGE);
|
||||
return c.NSS_STATUS_TRYAGAIN;
|
||||
@ -184,10 +188,13 @@ export fn _nss_turbo_getgrnam_r(
|
||||
buflen: usize,
|
||||
errnop: *c_int,
|
||||
) c.enum_nss_status {
|
||||
const db = getDBErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL;
|
||||
const state = getStateErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL;
|
||||
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) catch |err| switch (err) {
|
||||
var cgroup = db.getgrnam(nameSlice, buf, omit_members) catch |err| switch (err) {
|
||||
error.BufferTooSmall => {
|
||||
errnop.* = @enumToInt(os.E.RANGE);
|
||||
return c.NSS_STATUS_TRYAGAIN;
|
||||
@ -267,16 +274,20 @@ export fn _nss_turbo_getgrent_r(
|
||||
return c.NSS_STATUS_NOTFOUND;
|
||||
};
|
||||
|
||||
const buf = buffer[0..buflen];
|
||||
const cgroup = state.file.db.packCGroup(group, buf) catch |err| switch (err) {
|
||||
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;
|
||||
},
|
||||
};
|
||||
|
||||
result.* = cgroup;
|
||||
return c.NSS_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
export fn _nss_turbo_getpwent_r(
|
||||
|
Loading…
Reference in New Issue
Block a user