1
Fork 0
turbonss/src/unix2db/main.zig

116 lines
3.4 KiB
Zig
Raw Normal View History

2022-05-25 09:42:42 +03:00
const std = @import("std");
2022-06-05 23:56:45 +03:00
const fs = std.fs;
const io = std.io;
const mem = std.mem;
const os = std.os;
const ArrayList = std.ArrayList;
const Allocator = std.mem.Allocator;
const GeneralPurposeAllocator = std.heap.GeneralPurposeAllocator;
2022-05-25 09:42:42 +03:00
const flags = @import("../flags.zig");
2022-06-05 23:56:45 +03:00
const User = @import("../User.zig");
2022-06-07 05:32:21 +03:00
const Group = @import("../Group.zig");
2022-06-07 05:59:00 +03:00
const Corpus = @import("../Corpus.zig");
const DB = @import("../DB.zig");
2022-06-05 23:56:45 +03:00
const usage =
\\usage: turbonss-unix2db [options]
\\
\\ -h Print this help message and exit
\\ --passwd Path to passwd file (default: ./passwd)
\\ --group Path to group file (default: ./group)
\\
;
pub fn main() !void {
// This line is here because of https://github.com/ziglang/zig/issues/7807
const argv: []const [*:0]const u8 = os.argv;
const gpa = GeneralPurposeAllocator(.{});
const return_code = execute(gpa, argv[1..]) catch |err| {
try io.getStdErr().writeAll("uncaught error: {s}\n", @intToError(err));
os.exit(1);
};
os.exit(return_code);
}
fn execute(
allocator: Allocator,
stderr: anytype,
argv: []const [*:0]const u8,
) !u8 {
const result = flags.parse(argv, &[_]flags.Flag{
.{ .name = "-h", .kind = .boolean },
.{ .name = "--passwd", .kind = .arg },
.{ .name = "--group", .kind = .arg },
2022-06-07 05:59:00 +03:00
.{ .name = "--output", .kind = .arg },
2022-06-05 23:56:45 +03:00
}) catch {
try stderr.writeAll(usage);
return 1;
};
2022-05-25 09:42:42 +03:00
2022-06-05 23:56:45 +03:00
if (result.boolFlag("-h")) {
try io.getStdOut().writeAll(usage);
return 0;
}
if (result.args.len != 0) {
try stderr.print("ERROR: unknown option '{s}'\n", .{result.args[0]});
try stderr.writeAll(usage);
return 1;
}
2022-06-07 05:59:00 +03:00
const passwdFname = result.argFlag("--passwd") orelse "./passwd";
const groupFname = result.argFlag("--group") orelse "./group";
const outFile = result.argFlag("--output") orelse "./db.turbo";
2022-06-05 23:56:45 +03:00
2022-06-07 05:59:00 +03:00
var passwdFile = try fs.cwd().openFile(passwdFname, .{ .mode = .read_only });
2022-06-05 23:56:45 +03:00
defer passwdFile.close();
2022-06-07 05:59:00 +03:00
var groupFile = try fs.cwd().openFile(groupFname, .{ .mode = .read_only });
2022-06-05 23:56:45 +03:00
defer groupFile.close();
var users = try User.fromReader(allocator, passwdFile.reader());
2022-06-07 05:59:00 +03:00
defer for (users) |*user| user.deinit(allocator);
2022-06-07 05:32:21 +03:00
var groups = try Group.fromReader(allocator, groupFile.reader());
2022-06-07 05:59:00 +03:00
defer for (groups) |*group| group.deinit(allocator);
2022-06-05 23:56:45 +03:00
2022-06-07 05:59:00 +03:00
var corpus = try Corpus.init(allocator, users, groups);
defer corpus.deinit();
var db = try DB.fromCorpus(allocator, &corpus);
defer db.deinit(allocator);
const fd = try os.open(outFile, os.O.WRONLY | os.O.TRUNC, 0644);
errdefer os.close(fd);
const len = try os.writev(fd, db.iov().constSlice());
try os.fsync(fd);
os.close(fd);
try stderr.print("total {d} bytes. groups={d} users={d}\n", .{
len,
users.len,
groups.len,
});
2022-06-05 23:56:45 +03:00
return 0;
}
2022-05-25 09:42:42 +03:00
const testing = std.testing;
2022-06-05 23:56:45 +03:00
test "invalid argument" {
const allocator = testing.allocator;
const args = &[_][*:0]const u8{"--invalid-argument"};
var stderr = ArrayList(u8).init(allocator);
defer stderr.deinit();
const exit_code = try execute(allocator, stderr.writer(), args[0..]);
try testing.expectEqual(@as(u8, 1), exit_code);
2022-06-07 05:59:00 +03:00
try testing.expect(mem.startsWith(
u8,
stderr.items,
"ERROR: unknown option '--invalid-argument'",
));
2022-05-25 09:42:42 +03:00
}
2022-06-07 05:59:00 +03:00
test "smoke test" {}