Group.fromReader
This commit is contained in:
parent
e238db9b60
commit
31b5bb2d72
@ -1,8 +1,11 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const os = std.os;
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
|
const fmt = std.fmt;
|
||||||
const meta = std.meta;
|
const meta = std.meta;
|
||||||
|
const maxInt = std.math.maxInt;
|
||||||
const Allocator = mem.Allocator;
|
const Allocator = mem.Allocator;
|
||||||
|
const ArrayList = std.ArrayList;
|
||||||
const Group = @This();
|
const Group = @This();
|
||||||
|
|
||||||
gid: u32,
|
gid: u32,
|
||||||
@ -55,6 +58,45 @@ pub fn deinit(self: *Group, allocator: Allocator) void {
|
|||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const FromReaderError = error{ InvalidRecord, OutOfMemory } || os.ReadError;
|
||||||
|
|
||||||
|
pub fn fromReader(allocator: Allocator, reader: anytype) FromReaderError![]Group {
|
||||||
|
var groups = ArrayList(Group).init(allocator);
|
||||||
|
var member_ptrs = ArrayList([]const u8).init(allocator);
|
||||||
|
defer member_ptrs.deinit();
|
||||||
|
var line = ArrayList(u8).init(allocator);
|
||||||
|
defer line.deinit();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
// TODO: catch and interpret different errors
|
||||||
|
const max = std.math.maxInt(u32);
|
||||||
|
reader.readUntilDelimiterArrayList(&line, '\n', max) catch |err| switch (err) {
|
||||||
|
error.EndOfStream => break,
|
||||||
|
error.StreamTooLong => unreachable,
|
||||||
|
else => |e| return e,
|
||||||
|
};
|
||||||
|
|
||||||
|
var it = mem.split(u8, line.items, ":");
|
||||||
|
const name = it.next() orelse return error.InvalidRecord;
|
||||||
|
_ = it.next() orelse return error.InvalidRecord; // password
|
||||||
|
const gids = it.next() orelse return error.InvalidRecord;
|
||||||
|
const members_commas = it.next() orelse return error.InvalidRecord;
|
||||||
|
// the line must be exhaustive.
|
||||||
|
if (it.next() != null) return error.InvalidRecord;
|
||||||
|
|
||||||
|
const gid = fmt.parseInt(u32, gids, 10) catch return error.InvalidRecord;
|
||||||
|
|
||||||
|
var members_it = mem.split(u8, members_commas, ",");
|
||||||
|
while (members_it.next()) |member|
|
||||||
|
try member_ptrs.append(member);
|
||||||
|
|
||||||
|
try groups.append(try init(allocator, gid, name, member_ptrs.items));
|
||||||
|
member_ptrs.shrinkRetainingCapacity(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return groups.toOwnedSlice();
|
||||||
|
}
|
||||||
|
|
||||||
// suggested buffer size in bytes if all strings were zero-terminated
|
// suggested buffer size in bytes if all strings were zero-terminated
|
||||||
// (for CGroup).
|
// (for CGroup).
|
||||||
pub fn strlenZ(self: *const Group) usize {
|
pub fn strlenZ(self: *const Group) usize {
|
||||||
|
@ -43,15 +43,14 @@ pub fn clone(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const line_fmt = "{s}:x:{d}:{d}:{s}:{s}:{s}\n";
|
|
||||||
|
|
||||||
// fromLine accepts a line of /etc/passwd (with or without the EOL) and makes a
|
// fromLine accepts a line of /etc/passwd (with or without the EOL) and makes a
|
||||||
// User.
|
// User.
|
||||||
fn fromLine(allocator: Allocator, line: []const u8) error{ InvalidRecord, OutOfMemory }!User {
|
fn fromLine(allocator: Allocator, line: []const u8) error{ InvalidRecord, OutOfMemory }!User {
|
||||||
var it = mem.split(u8, line, ":");
|
var it = mem.split(u8, line, ":");
|
||||||
|
const name = it.next() orelse return error.InvalidRecord;
|
||||||
|
_ = it.next() orelse return error.InvalidRecord; // password
|
||||||
const uids = it.next() orelse return error.InvalidRecord;
|
const uids = it.next() orelse return error.InvalidRecord;
|
||||||
const gids = it.next() orelse return error.InvalidRecord;
|
const gids = it.next() orelse return error.InvalidRecord;
|
||||||
const name = it.next() orelse return error.InvalidRecord;
|
|
||||||
const gecos = it.next() orelse return error.InvalidRecord;
|
const gecos = it.next() orelse return error.InvalidRecord;
|
||||||
const home = it.next() orelse return error.InvalidRecord;
|
const home = it.next() orelse return error.InvalidRecord;
|
||||||
const shell = it.next() orelse return error.InvalidRecord;
|
const shell = it.next() orelse return error.InvalidRecord;
|
||||||
@ -84,6 +83,8 @@ fn strlen(self: *const User) usize {
|
|||||||
self.shell.len;
|
self.shell.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const line_fmt = "{s}:x:{d}:{d}:{s}:{s}:{s}\n";
|
||||||
|
|
||||||
const max_line_len = fmt.count(line_fmt, .{
|
const max_line_len = fmt.count(line_fmt, .{
|
||||||
max_user.name,
|
max_user.name,
|
||||||
max_user.uid,
|
max_user.uid,
|
||||||
@ -120,7 +121,7 @@ pub fn deinit(self: *User, allocator: Allocator) void {
|
|||||||
|
|
||||||
pub fn fromReader(allocator: Allocator, reader: anytype) ![]User {
|
pub fn fromReader(allocator: Allocator, reader: anytype) ![]User {
|
||||||
var users = ArrayList(User).init(allocator);
|
var users = ArrayList(User).init(allocator);
|
||||||
var buf: [max_line_len]u8 = undefined;
|
var buf: [max_line_len + 1]u8 = undefined;
|
||||||
// TODO: catch and interpret error
|
// TODO: catch and interpret error
|
||||||
while (try reader.readUntilDelimiterOrEof(buf[0..], '\n')) |line| {
|
while (try reader.readUntilDelimiterOrEof(buf[0..], '\n')) |line| {
|
||||||
const user = try fromLine(allocator, line);
|
const user = try fromLine(allocator, line);
|
||||||
|
@ -9,6 +9,7 @@ const GeneralPurposeAllocator = std.heap.GeneralPurposeAllocator;
|
|||||||
|
|
||||||
const flags = @import("../flags.zig");
|
const flags = @import("../flags.zig");
|
||||||
const User = @import("../User.zig");
|
const User = @import("../User.zig");
|
||||||
|
const Group = @import("../Group.zig");
|
||||||
|
|
||||||
const usage =
|
const usage =
|
||||||
\\usage: turbonss-unix2db [options]
|
\\usage: turbonss-unix2db [options]
|
||||||
@ -66,8 +67,10 @@ fn execute(
|
|||||||
defer groupFile.close();
|
defer groupFile.close();
|
||||||
|
|
||||||
var users = try User.fromReader(allocator, passwdFile.reader());
|
var users = try User.fromReader(allocator, passwdFile.reader());
|
||||||
|
var groups = try Group.fromReader(allocator, groupFile.reader());
|
||||||
|
|
||||||
try stderr.print("read {d} users\n", .{users.len});
|
try stderr.print("read {d} users\n", .{users.len});
|
||||||
|
try stderr.print("read {d} groups\n", .{groups.len});
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user