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;
|
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.
|
// dumps PackedGroup to []u8 and returns a CGroup.
|
||||||
pub fn packCGroup(self: *const DB, group: PackedGroup, buf: []u8) error{BufferTooSmall}!CGroup {
|
pub fn packCGroup(self: *const DB, group: PackedGroup, buf: []u8) error{BufferTooSmall}!CGroup {
|
||||||
const members_slice = self.groupmembers[group.members_offset..];
|
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.
|
// 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);
|
const idx = bdz.search(self.bdz_groupname, name);
|
||||||
if (idx >= self.header.num_groups) return null;
|
if (idx >= self.header.num_groups) return null;
|
||||||
const offset = self.idx_groupname2group[idx];
|
const offset = self.idx_groupname2group[idx];
|
||||||
const nbits = PackedGroup.alignment_bits;
|
const nbits = PackedGroup.alignment_bits;
|
||||||
const group = PackedGroup.fromBytes(self.groups[offset << nbits ..]).group;
|
const group = PackedGroup.fromBytes(self.groups[offset << nbits ..]).group;
|
||||||
if (!mem.eql(u8, name, group.name())) return null;
|
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.
|
// 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);
|
const idx = bdz.search_u32(self.bdz_gid, gid);
|
||||||
if (idx >= self.header.num_groups) return null;
|
if (idx >= self.header.num_groups) return null;
|
||||||
const offset = self.idx_gid2group[idx];
|
const offset = self.idx_gid2group[idx];
|
||||||
const nbits = PackedGroup.alignment_bits;
|
const nbits = PackedGroup.alignment_bits;
|
||||||
const group = PackedGroup.fromBytes(self.groups[offset << nbits ..]).group;
|
const group = PackedGroup.fromBytes(self.groups[offset << nbits ..]).group;
|
||||||
if (gid != group.gid()) return null;
|
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 {
|
fn pushStr(str: []const u8, buf: []u8, offset: *usize) [*:0]const u8 {
|
||||||
@ -708,8 +746,8 @@ test "getgrnam/getgrgid" {
|
|||||||
defer testing.allocator.free(buf);
|
defer testing.allocator.free(buf);
|
||||||
|
|
||||||
{
|
{
|
||||||
try testing.expectEqual(try db.getgrnam("doesnotexist", buf), null);
|
try testing.expectEqual(try db.getgrnam("doesnotexist", buf, false), null);
|
||||||
const all = (try db.getgrnam("all", buf)).?;
|
const all = (try db.getgrnam("all", buf, false)).?;
|
||||||
try testing.expectEqual(all.gid, 9999);
|
try testing.expectEqual(all.gid, 9999);
|
||||||
try testing.expectEqualStrings(all.name[0..4], "all\x00");
|
try testing.expectEqualStrings(all.name[0..4], "all\x00");
|
||||||
const members = all.members;
|
const members = all.members;
|
||||||
@ -721,16 +759,23 @@ test "getgrnam/getgrgid" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
try testing.expectEqual(try db.getgrgid(42, buf), null);
|
const all = (try db.getgrnam("all", buf, true)).?;
|
||||||
const all = (try db.getgrgid(9999, buf)).?;
|
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.expectEqual(all.gid, 9999);
|
||||||
try testing.expectEqualStrings(all.name[0..3], "all");
|
try testing.expectEqualStrings(all.name[0..3], "all");
|
||||||
}
|
}
|
||||||
try testing.expectEqualStrings("", errc.unwrap().constSlice());
|
try testing.expectEqualStrings("", errc.unwrap().constSlice());
|
||||||
|
|
||||||
_ = try db.getgrnam("all", buf);
|
_ = try db.getgrnam("all", buf, false);
|
||||||
buf.len -= 1;
|
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" {
|
test "getpwnam/getpwuid" {
|
||||||
|
@ -160,8 +160,12 @@ 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 db = getDBErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL;
|
const state = getStateErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL;
|
||||||
var cgroup = db.getgrgid(gid, buffer[0..buflen]) catch |err| switch (err) {
|
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 => {
|
error.BufferTooSmall => {
|
||||||
errnop.* = @enumToInt(os.E.RANGE);
|
errnop.* = @enumToInt(os.E.RANGE);
|
||||||
return c.NSS_STATUS_TRYAGAIN;
|
return c.NSS_STATUS_TRYAGAIN;
|
||||||
@ -184,10 +188,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 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);
|
const nameSlice = mem.sliceTo(name, 0);
|
||||||
var buf = buffer[0..buflen];
|
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 => {
|
error.BufferTooSmall => {
|
||||||
errnop.* = @enumToInt(os.E.RANGE);
|
errnop.* = @enumToInt(os.E.RANGE);
|
||||||
return c.NSS_STATUS_TRYAGAIN;
|
return c.NSS_STATUS_TRYAGAIN;
|
||||||
@ -267,16 +274,20 @@ export fn _nss_turbo_getgrent_r(
|
|||||||
return c.NSS_STATUS_NOTFOUND;
|
return c.NSS_STATUS_NOTFOUND;
|
||||||
};
|
};
|
||||||
|
|
||||||
const buf = buffer[0..buflen];
|
const cgroup1 = if (state.omit_members)
|
||||||
const cgroup = state.file.db.packCGroup(group, buf) catch |err| switch (err) {
|
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 => {
|
error.BufferTooSmall => {
|
||||||
errnop.* = @enumToInt(os.E.RANGE);
|
errnop.* = @enumToInt(os.E.RANGE);
|
||||||
return c.NSS_STATUS_TRYAGAIN;
|
return c.NSS_STATUS_TRYAGAIN;
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
||||||
result.* = cgroup;
|
|
||||||
return c.NSS_STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn _nss_turbo_getpwent_r(
|
export fn _nss_turbo_getpwent_r(
|
||||||
|
Loading…
Reference in New Issue
Block a user