add CGroup
This commit is contained in:
parent
a655d8a88a
commit
5968d8494e
6
lib/CGroup.zig
Normal file
6
lib/CGroup.zig
Normal file
@ -0,0 +1,6 @@
|
||||
const CGroup = @This();
|
||||
|
||||
gid: u32,
|
||||
name: [:0]const u8,
|
||||
// https://github.com/ziglang/zig/issues/7517
|
||||
members: [:null]const ?[*:0]const u8,
|
@ -86,7 +86,7 @@ pub fn init(
|
||||
members.len = 0;
|
||||
|
||||
for (groupmembers) |member_name| {
|
||||
if (name2user.get(member_name.?)) |user_idx| {
|
||||
if (name2user.get(member_name)) |user_idx| {
|
||||
members.len += 1;
|
||||
members[members.len - 1] = user_idx;
|
||||
try user2groups[user_idx].append(allocator, @intCast(u32, i));
|
||||
@ -203,16 +203,16 @@ pub fn testCorpus(allocator: Allocator) !Corpus {
|
||||
.shell = "/usr/sbin/nologin",
|
||||
} };
|
||||
|
||||
var members0 = &[_:null]?[*:0]const u8{"root"};
|
||||
var members1 = &[_:null]?[*:0]const u8{"vidmantas"};
|
||||
var members2 = &[_:null]?[*:0]const u8{ "svc-bar", "vidmantas" };
|
||||
var members3 = &[_:null]?[*:0]const u8{ "svc-bar", "Name" ** 8, "vidmantas", "root" };
|
||||
var members0 = &[_][]const u8{"root"};
|
||||
var members1 = &[_][]const u8{"vidmantas"};
|
||||
var members2 = &[_][]const u8{ "svc-bar", "vidmantas" };
|
||||
var members3 = &[_][]const u8{ "svc-bar", "Name" ** 8, "vidmantas", "root" };
|
||||
|
||||
const groups = [_]Group{
|
||||
Group{ .gid = 0, .name = "root", .members = members0 },
|
||||
Group{ .gid = 128, .name = "vidmantas", .members = members1 },
|
||||
Group{ .gid = 9999, .name = "all", .members = members3 },
|
||||
Group{ .gid = 100000, .name = "service-account", .members = members2 },
|
||||
try Group.init(allocator, 0, "root", members0),
|
||||
try Group.init(allocator, 128, "vidmantas", members1),
|
||||
try Group.init(allocator, 9999, "all", members3),
|
||||
try Group.init(allocator, 100000, "service-account", members2),
|
||||
};
|
||||
|
||||
return try Corpus.init(allocator, users[0..], groups[0..]);
|
||||
|
35
lib/DB.zig
35
lib/DB.zig
@ -15,6 +15,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 Group = @import("Group.zig");
|
||||
const PackedGroup = @import("PackedGroup.zig");
|
||||
const GroupStored = PackedGroup.GroupStored;
|
||||
@ -219,10 +220,12 @@ pub fn fromBytes(buf: []align(8) const u8) InvalidHeader!DB {
|
||||
}
|
||||
|
||||
const GroupMemberNames = struct {
|
||||
_buf: []u8,
|
||||
arr: [:null]const ?[*:0]const u8,
|
||||
|
||||
pub fn deinit(self: *GroupMemberNames, allocator: Allocator) void {
|
||||
allocator.free(self.arr[0]);
|
||||
if (self._buf.len == 0) return;
|
||||
allocator.free(self._buf);
|
||||
allocator.free(self.arr);
|
||||
}
|
||||
};
|
||||
@ -236,22 +239,26 @@ fn groupMemberNames(
|
||||
) error{OutOfMemory}!GroupMemberNames {
|
||||
const v = compress.uvarintMust(self.groupmembers[offset..]);
|
||||
const total_members_len = v.value;
|
||||
offset += v.bytes_read;
|
||||
var vit = compress.VarintSliceIteratorMust(self.groupmembers[offset..]);
|
||||
const offset2 = offset + v.bytes_read;
|
||||
var vit = compress.VarintSliceIteratorMust(self.groupmembers[offset2..]);
|
||||
const num_members = vit.remaining;
|
||||
if (num_members == 0) return null;
|
||||
if (num_members == 0)
|
||||
return GroupMemberNames{
|
||||
._buf = &[0]u8{},
|
||||
.arr = &[1:null]?[*:0]const u8{null},
|
||||
};
|
||||
|
||||
// TODO (zig 0.10+) make result type sentinel-aware and stop
|
||||
// the terminating-null-pointer-dancing.
|
||||
var result = try allocator.alloc(?[:0]const u8, num_members + 1);
|
||||
errdefer allocator.free(result);
|
||||
result.len = num_members + 1;
|
||||
result[num_members] = null;
|
||||
result.len = num_members;
|
||||
var arr = try allocator.alloc(?[*:0]const u8, num_members + 1);
|
||||
errdefer allocator.free(arr);
|
||||
arr.len = num_members + 1;
|
||||
arr[num_members] = null;
|
||||
arr.len = num_members;
|
||||
|
||||
var buf = try allocator.alloc(u8, total_members_len + num_members);
|
||||
errdefer allocator.free(buf);
|
||||
var it = compress.DeltaCompressionIterator(&vit);
|
||||
var it = compress.DeltaDecompressionIterator(&vit);
|
||||
var i: usize = 0;
|
||||
while (it.nextMust()) |member_offset| : (i += 1) {
|
||||
const entry = PackedUser.fromBytes(self.users[member_offset..]);
|
||||
@ -260,9 +267,9 @@ fn groupMemberNames(
|
||||
buf.len += name.len + 1;
|
||||
mem.copy(u8, buf[old_len..], name);
|
||||
buf[buf.len - 1] = 0;
|
||||
result[i] = buf[old_len..buf.len :0];
|
||||
arr[i] = buf[old_len..buf.len :0];
|
||||
}
|
||||
return GroupMemberNames{ .arr = result };
|
||||
return GroupMemberNames{ ._buf = buf, .arr = arr };
|
||||
}
|
||||
|
||||
// getgrtnam returns a Group entry by name. The Group must be
|
||||
@ -271,7 +278,7 @@ fn getgrnam(
|
||||
self: *const DB,
|
||||
allocator: Allocator,
|
||||
name: []const u8,
|
||||
) error{OutOfMemory}!?Group {
|
||||
) error{OutOfMemory}!?CGroup {
|
||||
const idx = bdz.search(self.bdz_groupname, name);
|
||||
const offset = self.idx_groupname2group[idx];
|
||||
const group = PackedGroup.fromBytes(self.groups[offset..]).group;
|
||||
@ -283,7 +290,7 @@ fn getgrnam(
|
||||
const namez = try allocator.dupeZ(u8, name);
|
||||
errdefer allocator.free(namez);
|
||||
|
||||
return Group{
|
||||
return CGroup{
|
||||
.name = namez,
|
||||
.gid = group.gid(),
|
||||
.members = members.arr,
|
||||
|
@ -2,67 +2,56 @@ const std = @import("std");
|
||||
|
||||
const mem = std.mem;
|
||||
const Allocator = mem.Allocator;
|
||||
|
||||
const Group = @This();
|
||||
|
||||
gid: u32,
|
||||
name: [:0]const u8,
|
||||
// should be [:null]const ?[:0]const u8, but it crashes the compiler. See
|
||||
// https://github.com/ziglang/zig/issues/7517.
|
||||
// members[members.len] is always null for cloned groups. Once the bug
|
||||
// in the compiler is fixed, we should update the return type here.
|
||||
members: [:null]const ?[*:0]const u8,
|
||||
name: []const u8,
|
||||
members: []align(1) const []const u8,
|
||||
|
||||
// storage of name + members
|
||||
// storage of name, members and members strings. for no particular reason.
|
||||
// Everything (name, members, member strings) could be allocated separately
|
||||
// (one extreme) and only once (another extreme). For some reason I chose the
|
||||
// right extreme, but it doesn't have to be this way.
|
||||
_buf: []const u8,
|
||||
|
||||
pub fn new(
|
||||
pub fn init(
|
||||
allocator: Allocator,
|
||||
gid: u32,
|
||||
name: []const u8,
|
||||
members: []const []const u8,
|
||||
members: []align(1) const []const u8,
|
||||
) error{OutOfMemory}!Group {
|
||||
const buf_len = blk: {
|
||||
const buf_len = @sizeOf([]const u8) * members.len + name.len + blk: {
|
||||
var sum: usize = 0;
|
||||
for (members) |member| sum += member.len;
|
||||
std.debug.print("\nsum: {d}\n", .{sum});
|
||||
break :blk @intCast(u32, sum);
|
||||
};
|
||||
_ = buf_len;
|
||||
_ = allocator;
|
||||
_ = gid;
|
||||
_ = name;
|
||||
_ = members;
|
||||
return error.OutOfMemory;
|
||||
}
|
||||
|
||||
pub fn clone(self: *const Group, allocator: Allocator) error{OutOfMemory}!Group {
|
||||
var members = try allocator.allocSentinel(?[*:0]const u8, self.members.len, null);
|
||||
errdefer allocator.free(members);
|
||||
|
||||
var buf = try allocator.alloc(u8, self._buf.len);
|
||||
var buf = try allocator.alloc(u8, buf_len);
|
||||
errdefer allocator.free(buf);
|
||||
mem.copy(u8, buf, self._buf);
|
||||
|
||||
const our_begin = @ptrToInt(members.ptr);
|
||||
const their_begin = @ptrToInt(self.members.ptr);
|
||||
for (self.members) |*name_ptr, i| {
|
||||
const offset = @ptrToInt(name_ptr) - their_begin;
|
||||
members[i] = @intToPtr([*:0]const u8, our_begin + offset);
|
||||
var ptr_end = @sizeOf([]const u8) * members.len;
|
||||
var members_ptr = mem.bytesAsSlice([]const u8, buf[0..ptr_end]);
|
||||
var start: usize = name.len;
|
||||
for (members) |member, i| {
|
||||
mem.copy(u8, buf[start..], member);
|
||||
members_ptr[i] = buf[start .. start + member.len];
|
||||
start += member.len;
|
||||
}
|
||||
|
||||
mem.copy(u8, buf[start..], name);
|
||||
return Group{
|
||||
.gid = self.gid,
|
||||
.name = buf[0..self.name.len],
|
||||
.members = members[0.. :null],
|
||||
.gid = gid,
|
||||
.name = buf[start .. start + name.len],
|
||||
.members = members_ptr,
|
||||
._buf = buf,
|
||||
};
|
||||
}
|
||||
|
||||
// This could be made more efficient, but clone() is never in the hot path.
|
||||
pub fn clone(self: *const Group, allocator: Allocator) error{OutOfMemory}!Group {
|
||||
return init(allocator, self.gid, self.name, self.members);
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Group, allocator: Allocator) void {
|
||||
allocator.free(self.name);
|
||||
if (self.members[0]) |firstmember|
|
||||
allocator.free(firstmember);
|
||||
allocator.free(self.members);
|
||||
allocator.free(self._buf);
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
@ -73,11 +62,7 @@ test "Group.clone" {
|
||||
var member1 = mem.sliceTo(try testing.allocator.dupeZ(u8, "member1"), 0);
|
||||
defer testing.allocator.free(member1);
|
||||
|
||||
var group = Group{
|
||||
.gid = 1,
|
||||
.name = "foo",
|
||||
.members = &[_:null]?[*:0]const u8{ member1, "member2" },
|
||||
};
|
||||
var group = try init(testing.allocator, 1, "foo", &[_][]const u8{ member1, "member2" });
|
||||
|
||||
var cloned = try group.clone(testing.allocator);
|
||||
defer cloned.deinit(testing.allocator);
|
||||
@ -87,5 +72,5 @@ test "Group.clone" {
|
||||
member1[0] = 'x';
|
||||
try testing.expectEqual(cloned.gid, 1);
|
||||
try testing.expectEqualSlices(u8, cloned.name, "foo");
|
||||
//try testing.expectEqualSlices(u8, @as([*:0]const u8, cloned.members[0].?), "member1");
|
||||
try testing.expectEqualSlices(u8, cloned.members[0], "member1");
|
||||
}
|
||||
|
@ -166,6 +166,12 @@ const deltaDecompressionIterator = struct {
|
||||
pub fn remaining(self: *const deltaDecompressionIterator) usize {
|
||||
return self.vit.remaining;
|
||||
}
|
||||
|
||||
pub fn nextMust(self: *deltaDecompressionIterator) ?u64 {
|
||||
return self.next() catch |err| switch (err) {
|
||||
error.Overflow => unreachable,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn DeltaDecompressionIterator(vit: *varintSliceIterator) deltaDecompressionIterator {
|
||||
|
Loading…
Reference in New Issue
Block a user