wip getpwnam
This commit is contained in:
parent
9e80d6676b
commit
4469d174ea
91
lib/DB.zig
91
lib/DB.zig
@ -14,12 +14,13 @@ const ArenaAllocator = std.heap.ArenaAllocator;
|
||||
const Corpus = @import("Corpus.zig");
|
||||
const pad = @import("padding.zig");
|
||||
const compress = @import("compress.zig");
|
||||
const PackedUser = @import("PackedUser.zig");
|
||||
const User = @import("User.zig");
|
||||
const Group = @import("Group.zig");
|
||||
const CGroup = Group.CGroup;
|
||||
const PackedGroup = @import("PackedGroup.zig");
|
||||
const GroupStored = PackedGroup.GroupStored;
|
||||
const User = @import("User.zig");
|
||||
const CUser = User.CUser;
|
||||
const PackedUser = @import("PackedUser.zig");
|
||||
const ShellSections = @import("shell.zig").ShellWriter.ShellSections;
|
||||
const ShellReader = @import("shell.zig").ShellReader;
|
||||
const ShellWriter = @import("shell.zig").ShellWriter;
|
||||
@ -123,6 +124,8 @@ pub fn fromCorpus(
|
||||
.getpw_bufsize = corpus.getpw_bufsize,
|
||||
};
|
||||
|
||||
std.debug.print("fromCorpus shell.index: {any}\n", .{shell.index.constSlice()});
|
||||
|
||||
return DB{
|
||||
.header = header,
|
||||
.bdz_gid = bdz_gid,
|
||||
@ -169,6 +172,8 @@ pub fn iov(self: *const DB) BoundedArray(os.iovec_const, DB_fields.len * 2) {
|
||||
*const Header => mem.asBytes(value),
|
||||
else => mem.sliceAsBytes(value),
|
||||
};
|
||||
if (mem.eql(u8, field.name, "shell_index"))
|
||||
std.debug.print("shell_index original: {any}\n", .{value});
|
||||
result.appendAssumeCapacity(os.iovec_const{
|
||||
.iov_base = bytes.ptr,
|
||||
.iov_len = bytes.len,
|
||||
@ -219,15 +224,13 @@ pub fn fromBytes(buf: []align(8) const u8) InvalidHeader!DB {
|
||||
offset += lengths[i];
|
||||
}
|
||||
|
||||
std.debug.print("GOT shell_index: {any}\n", .{result.shell_index});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// dumps PackedGroup to []u8 and returns a CGroup.
|
||||
fn getGroup(
|
||||
self: *const DB,
|
||||
group: PackedGroup,
|
||||
buf: *[]u8,
|
||||
) error{OutOfMemory}!CGroup {
|
||||
fn getGroup(self: *const DB, group: PackedGroup, buf: *[]u8) error{OutOfMemory}!CGroup {
|
||||
const members_slice = self.groupmembers[group.members_offset..];
|
||||
var vit = compress.VarintSliceIteratorMust(members_slice);
|
||||
const num_members = vit.remaining;
|
||||
@ -271,7 +274,8 @@ fn getGroup(
|
||||
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;
|
||||
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.getGroup(group, buf);
|
||||
}
|
||||
@ -280,16 +284,69 @@ fn getgrnam(self: *const DB, name: []const u8, buf: *[]u8) error{OutOfMemory}!?C
|
||||
fn getgrgid(self: *const DB, gid: u32, buf: *[]u8) error{OutOfMemory}!?CGroup {
|
||||
const idx = bdz.search_u32(self.bdz_gid, gid);
|
||||
const offset = self.idx_gid2group[idx];
|
||||
const group = PackedGroup.fromBytes(self.groups[offset << 3 ..]).group;
|
||||
const nbits = PackedGroup.alignment_bits;
|
||||
const group = PackedGroup.fromBytes(self.groups[offset << nbits ..]).group;
|
||||
if (gid != group.gid()) return null;
|
||||
return try self.getGroup(group, buf);
|
||||
}
|
||||
|
||||
fn pushStr(str: []const u8, buf: *[]u8, offset: *usize) [*]const u8 {
|
||||
const start = offset.*;
|
||||
mem.copy(u8, buf.*[offset.*..], str);
|
||||
buf.*[offset.* + str.len] = 0;
|
||||
offset.* += str.len + 1;
|
||||
return @ptrCast([*]const u8, &buf.*[start]);
|
||||
}
|
||||
|
||||
fn getUser(self: *const DB, user: PackedUser, buf: *[]u8) error{OutOfMemory}!CUser {
|
||||
const shell_reader = ShellReader{
|
||||
.index = self.shell_index,
|
||||
.blob = self.shell_blob,
|
||||
};
|
||||
const name = user.name();
|
||||
const gecos = user.gecos();
|
||||
const home = user.home();
|
||||
const shell = user.shell(shell_reader);
|
||||
|
||||
const strlen =
|
||||
name.len + 1 +
|
||||
gecos.len + 1 +
|
||||
home.len + 1 +
|
||||
shell.len + 1;
|
||||
if (strlen > buf.len) return error.OutOfMemory;
|
||||
|
||||
var offset: usize = 0;
|
||||
const pw_name = pushStr(name, buf, &offset);
|
||||
const pw_gecos = pushStr(gecos, buf, &offset);
|
||||
const pw_dir = pushStr(home, buf, &offset);
|
||||
const pw_shell = pushStr(shell, buf, &offset);
|
||||
|
||||
return CUser{
|
||||
.pw_name = pw_name,
|
||||
.pw_uid = user.uid(),
|
||||
.pw_gid = user.gid(),
|
||||
.pw_gecos = pw_gecos,
|
||||
.pw_dir = pw_dir,
|
||||
.pw_shell = pw_shell,
|
||||
};
|
||||
}
|
||||
|
||||
// get a CUser entry by name.
|
||||
fn getpwnam(self: *const DB, name: []const u8, buf: *[]u8) error{OutOfMemory}!?CUser {
|
||||
const idx = bdz.search(self.bdz_username, name);
|
||||
const offset = self.idx_name2user[idx];
|
||||
const nbits = PackedUser.alignment_bits;
|
||||
const user = PackedUser.fromBytes(self.users[offset << nbits ..]).user;
|
||||
if (!mem.eql(u8, name, user.name())) return null;
|
||||
return try self.getUser(user, buf);
|
||||
}
|
||||
|
||||
fn shellSections(
|
||||
allocator: Allocator,
|
||||
corpus: *const Corpus,
|
||||
) error{OutOfMemory}!ShellSections {
|
||||
var popcon = ShellWriter.init(allocator);
|
||||
errdefer popcon.deinit();
|
||||
for (corpus.users.items(.shell)) |shell|
|
||||
try popcon.put(shell);
|
||||
return popcon.toOwnedSections(max_shells);
|
||||
@ -609,6 +666,22 @@ test "getgr_bufsize" {
|
||||
try testing.expectError(error.OutOfMemory, db.getgrnam("all", &buf));
|
||||
}
|
||||
|
||||
test "getpwnam" {
|
||||
var arena = ArenaAllocator.init(testing.allocator);
|
||||
defer arena.deinit();
|
||||
var corpus = try Corpus.testCorpus(arena.allocator());
|
||||
var db = try DB.fromCorpus(arena.allocator(), &corpus);
|
||||
std.debug.print("db.shell.index: {any}\n", .{db.shell_index});
|
||||
var buf = try arena.allocator().alloc(u8, db.header.getpw_bufsize);
|
||||
|
||||
const vidmantas = (try db.getpwnam("vidmantas", &buf)).?;
|
||||
try testing.expectEqual(vidmantas.pw_uid, 128);
|
||||
try testing.expectEqual(vidmantas.pw_gid, 128);
|
||||
try testing.expectEqualStrings(vidmantas.pw_name[0..9], "vidmantas");
|
||||
try testing.expectEqualStrings(vidmantas.pw_gecos[0..10], "Vidmantas Kaminskas");
|
||||
try testing.expectEqualStrings(vidmantas.pw_dir[0..10], "/home/vidmantas");
|
||||
}
|
||||
|
||||
test "additionalGids" {
|
||||
const allocator = testing.allocator;
|
||||
var corpus = try Corpus.testCorpus(allocator);
|
||||
|
@ -209,7 +209,8 @@ pub fn shell(self: PackedUser, shell_reader: shellImport.ShellReader) []const u8
|
||||
return shell_reader.get(self.inner.shell_len_or_idx);
|
||||
}
|
||||
|
||||
pub const max_str_len = math.maxInt(fieldInfo(Inner, .shell_len_or_idx).field_type) + 1 +
|
||||
pub const max_str_len =
|
||||
math.maxInt(fieldInfo(Inner, .shell_len_or_idx).field_type) + 1 +
|
||||
math.maxInt(fieldInfo(Inner, .home_len).field_type) + 1 +
|
||||
math.maxInt(fieldInfo(Inner, .name_len).field_type) + 1 +
|
||||
math.maxInt(fieldInfo(Inner, .gecos_len).field_type);
|
||||
|
12
lib/User.zig
12
lib/User.zig
@ -6,6 +6,8 @@ const Allocator = mem.Allocator;
|
||||
const ArrayList = std.ArrayList;
|
||||
const BoundedArray = std.BoundedArray;
|
||||
|
||||
const pw_passwd = "x\x00";
|
||||
|
||||
const User = @This();
|
||||
const PackedUser = @import("PackedUser.zig");
|
||||
const validate = @import("validate.zig");
|
||||
@ -126,6 +128,16 @@ pub fn fromReader(allocator: Allocator, reader: anytype) ![]User {
|
||||
_ = users;
|
||||
}
|
||||
|
||||
pub const CUser = extern struct {
|
||||
pw_name: [*]const u8,
|
||||
pw_passwd: [*]const u8 = pw_passwd,
|
||||
pw_uid: u32,
|
||||
pw_gid: u32,
|
||||
pw_gecos: [*]const u8,
|
||||
pw_dir: [*]const u8,
|
||||
pw_shell: [*]const u8,
|
||||
};
|
||||
|
||||
const testing = std.testing;
|
||||
|
||||
pub const max_user = User{
|
||||
|
@ -22,6 +22,8 @@ pub const ShellReader = struct {
|
||||
|
||||
// get returns a shell at the given index.
|
||||
pub fn get(self: *const ShellReader, idx: u8) []const u8 {
|
||||
std.debug.print("\nrequested shell at index {d}; ", .{idx});
|
||||
std.debug.print("start:{d} end:{d}\n", .{ self.index[idx], self.index[idx + 1] });
|
||||
return self.blob[self.index[idx]..self.index[idx + 1]];
|
||||
}
|
||||
};
|
||||
@ -73,6 +75,7 @@ pub const ShellWriter = struct {
|
||||
self.index.set(idx8, offset);
|
||||
}
|
||||
self.index.appendAssumeCapacity(@intCast(u8, self.blob.len));
|
||||
std.debug.print("\nGEN shell_index: {any}\n", .{self.index.constSlice()});
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -141,9 +144,7 @@ pub const ShellWriter = struct {
|
||||
}
|
||||
|
||||
const total = std.math.min(deque.count(), limit);
|
||||
var topShells = BoundedArray([]const u8, max_shells).init(total) catch |err| switch (err) {
|
||||
error.Overflow => unreachable,
|
||||
};
|
||||
var topShells = BoundedArray([]const u8, max_shells).init(total) catch unreachable;
|
||||
|
||||
var i: u32 = 0;
|
||||
while (i < total) : (i += 1)
|
||||
|
Loading…
Reference in New Issue
Block a user