Add CGroupPtr
This commit is contained in:
parent
3c507ffe08
commit
d4ba5a9a58
@ -1,7 +0,0 @@
|
||||
const CGroup = @This();
|
||||
|
||||
gid: u32,
|
||||
name: [:0]const u8,
|
||||
// Should be a sentinel-terminated array.
|
||||
// https://github.com/ziglang/zig/issues/7517
|
||||
members: []align(1) const ?[*:0]const u8,
|
@ -46,12 +46,12 @@ pub fn init(
|
||||
var getgr_bufsize: usize = 0;
|
||||
for (groupsConst) |*group, i| {
|
||||
groups_arr[i] = try group.clone(allocator);
|
||||
getgr_bufsize = math.max(getgr_bufsize, groups_arr[i].strlenZ());
|
||||
getgr_bufsize = math.max(getgr_bufsize, group.strlenZ());
|
||||
}
|
||||
var getpw_bufsize: usize = 0;
|
||||
for (usersConst) |*user, i| {
|
||||
users_arr[i] = try user.clone(allocator);
|
||||
getpw_bufsize = math.max(getpw_bufsize, users_arr[i].strlenZ());
|
||||
getpw_bufsize = math.max(getpw_bufsize, user.strlenZ());
|
||||
}
|
||||
|
||||
sort.sort(User, users_arr, {}, cmpUser);
|
||||
|
46
lib/DB.zig
46
lib/DB.zig
@ -16,7 +16,7 @@ const pad = @import("padding.zig");
|
||||
const compress = @import("compress.zig");
|
||||
const PackedUser = @import("PackedUser.zig");
|
||||
const User = @import("User.zig");
|
||||
const CGroup = @import("CGroup.zig");
|
||||
const CGroup = @import("cgroup.zig").CGroup;
|
||||
const Group = @import("Group.zig");
|
||||
const PackedGroup = @import("PackedGroup.zig");
|
||||
const GroupStored = PackedGroup.GroupStored;
|
||||
@ -267,13 +267,8 @@ fn getGroup(
|
||||
};
|
||||
}
|
||||
|
||||
// getgrtnam returns a Group entry by name. The Group must be
|
||||
// deinit'ed by caller.
|
||||
fn getgrnam(
|
||||
self: *const DB,
|
||||
name: []const u8,
|
||||
buf: *[]u8,
|
||||
) error{OutOfMemory}!?CGroup {
|
||||
// get a CGroup entry by name.
|
||||
fn getgrnam(self: *const DB, name: []const u8, buf: *[]u8) error{OutOfMemory}!?CGroup {
|
||||
const idx = bdz.search(self.bdz_groupname, name);
|
||||
const offset = self.idx_groupname2group[idx];
|
||||
const group = PackedGroup.fromBytes(self.groups[offset << 3 ..]).group;
|
||||
@ -591,26 +586,43 @@ test "read/write via iovec" {
|
||||
}
|
||||
|
||||
test "high-level API" {
|
||||
const allocator = testing.allocator;
|
||||
var corpus = try Corpus.testCorpus(allocator);
|
||||
var corpus = try Corpus.testCorpus(testing.allocator);
|
||||
defer corpus.deinit();
|
||||
var db = try DB.fromCorpus(testing.allocator, &corpus);
|
||||
defer db.deinit(testing.allocator);
|
||||
var buf = try testing.allocator.alloc(u8, db.header.getgr_bufsize);
|
||||
defer testing.allocator.free(buf);
|
||||
|
||||
var db = try DB.fromCorpus(allocator, &corpus);
|
||||
defer db.deinit(allocator);
|
||||
|
||||
// TODO: should accept a buffer instead of an allocator instead.
|
||||
var buf = try allocator.alloc(u8, db.header.getgr_bufsize);
|
||||
defer allocator.free(buf);
|
||||
const all = try db.getgrnam("all", &buf);
|
||||
try testing.expect(all != null);
|
||||
try testing.expectEqual(all.?.gid, 9999);
|
||||
try testing.expectEqualStrings(all.?.name, "all");
|
||||
try testing.expectEqualStrings(mem.sliceTo(all.?.name, 0), "all");
|
||||
const members = all.?.members;
|
||||
try testing.expectEqualStrings(mem.sliceTo(members[0].?, 0), "Name" ** 8);
|
||||
try testing.expectEqualStrings(mem.sliceTo(members[1].?, 0), "root");
|
||||
try testing.expectEqualStrings(mem.sliceTo(members[2].?, 0), "svc-bar");
|
||||
try testing.expectEqualStrings(mem.sliceTo(members[3].?, 0), "vidmantas");
|
||||
try testing.expectEqual(members[4], null);
|
||||
|
||||
const cgroup = all.?.ptr();
|
||||
try testing.expectEqual(cgroup.gid, all.?.gid);
|
||||
try testing.expectEqual(cgroup.name[0], 'a');
|
||||
try testing.expectEqual(cgroup.name[1], 'l');
|
||||
try testing.expectEqual(cgroup.name[2], 'l');
|
||||
try testing.expectEqual(cgroup.name[3], 0);
|
||||
}
|
||||
|
||||
test "getgr_bufsize" {
|
||||
var corpus = try Corpus.testCorpus(testing.allocator);
|
||||
defer corpus.deinit();
|
||||
var db = try DB.fromCorpus(testing.allocator, &corpus);
|
||||
defer db.deinit(testing.allocator);
|
||||
var buf = try testing.allocator.alloc(u8, db.header.getgr_bufsize);
|
||||
defer testing.allocator.free(buf);
|
||||
|
||||
_ = try db.getgrnam("all", &buf);
|
||||
buf.len -= 1;
|
||||
try testing.expectError(error.OutOfMemory, db.getgrnam("all", &buf));
|
||||
}
|
||||
|
||||
test "additionalGids" {
|
||||
|
@ -1,6 +1,8 @@
|
||||
const std = @import("std");
|
||||
const ptr_size = @import("cgroup.zig").ptr_size;
|
||||
|
||||
const mem = std.mem;
|
||||
const meta = std.meta;
|
||||
const Allocator = mem.Allocator;
|
||||
const Group = @This();
|
||||
|
||||
@ -56,9 +58,12 @@ pub fn deinit(self: *Group, allocator: Allocator) void {
|
||||
|
||||
// buffer size in bytes if all strings were zero-terminated.
|
||||
pub fn strlenZ(self: *const Group) usize {
|
||||
return self._buf.len +
|
||||
self.members.len + // each membername sentinel
|
||||
1; // name sentinel
|
||||
var count: usize = 0;
|
||||
for (self.members) |member|
|
||||
count += member.len + 1;
|
||||
count += ptr_size * (self.members.len + 1);
|
||||
count += self.name.len + 1;
|
||||
return count;
|
||||
}
|
||||
|
||||
const testing = std.testing;
|
||||
|
32
lib/cgroup.zig
Normal file
32
lib/cgroup.zig
Normal file
@ -0,0 +1,32 @@
|
||||
const meta = @import("std").meta;
|
||||
|
||||
// All string fields are 0-terminated, but that's not part of the type.
|
||||
// members field is null-terminated, but that's also not part of the type.
|
||||
// Making it part of the type crashes zig compiler in pre-0.10.
|
||||
// https://github.com/ziglang/zig/issues/7517
|
||||
|
||||
pub const CGroup = struct {
|
||||
gid: u32,
|
||||
// should be [*:0]const u8
|
||||
name: []const u8,
|
||||
// Should be [*:null]align(1) const ?[*:0]const u8
|
||||
members: []align(1) const ?[*:0]const u8,
|
||||
|
||||
pub fn ptr(self: *const CGroup) CGroupPtr {
|
||||
return CGroupPtr{
|
||||
.gid = self.gid,
|
||||
.name = self.name.ptr,
|
||||
.members = @intToPtr([*]const u8, @ptrToInt(self.members.ptr)),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// size of the pointer to a single member.
|
||||
pub const ptr_size = @sizeOf(meta.Child(meta.fieldInfo(CGroup, .members).field_type));
|
||||
|
||||
// a workaround of not having sentinel-terminated `name` and `members`.
|
||||
pub const CGroupPtr = extern struct {
|
||||
gid: u32,
|
||||
name: [*]const u8,
|
||||
members: [*]const u8,
|
||||
};
|
@ -2,6 +2,7 @@ const std = @import("std");
|
||||
const mem = std.mem;
|
||||
const math = std.math;
|
||||
const native_endian = @import("builtin").target.cpu.arch.endian();
|
||||
const ptr_size = @import("cgroup.zig").ptr_size;
|
||||
|
||||
const max_shells = @import("shell.zig").max_shells;
|
||||
const magic = [4]u8{ 0xf0, 0x9f, 0xa4, 0xb7 };
|
||||
@ -33,7 +34,7 @@ pub const Header = packed struct {
|
||||
magic: [4]u8 = magic,
|
||||
version: u8 = version,
|
||||
endian: Endian = Endian.native(),
|
||||
ptr_size: u4 = @sizeOf(?[*:0]const u8),
|
||||
ptr_size: u4 = ptr_size,
|
||||
nblocks_shell_blob: u8,
|
||||
num_shells: u8,
|
||||
num_groups: u32,
|
||||
@ -65,7 +66,7 @@ pub const Header = packed struct {
|
||||
// when ptr size is larger than on the host that constructed it the DB,
|
||||
// getgr_bufsize/getpw_bufsize may return insufficient values, causing
|
||||
// OutOfMemory for getgr* and getpw* calls.
|
||||
if (self.ptr_size < @sizeOf(?[*:0]const u8))
|
||||
if (self.ptr_size < ptr_size)
|
||||
return error.InvalidPointerSize;
|
||||
|
||||
return self;
|
||||
|
Loading…
Reference in New Issue
Block a user