const std = @import("std"); 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; const flags = @import("../flags.zig"); const User = @import("../User.zig"); const Group = @import("../Group.zig"); const Corpus = @import("../Corpus.zig"); const DB = @import("../DB.zig"); 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 }, .{ .name = "--output", .kind = .arg }, }) catch { try stderr.writeAll(usage); return 1; }; 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; } const passwdFname = result.argFlag("--passwd") orelse "./passwd"; const groupFname = result.argFlag("--group") orelse "./group"; const outFile = result.argFlag("--output") orelse "./db.turbo"; var passwdFile = try fs.cwd().openFile(passwdFname, .{ .mode = .read_only }); defer passwdFile.close(); var groupFile = try fs.cwd().openFile(groupFname, .{ .mode = .read_only }); defer groupFile.close(); var users = try User.fromReader(allocator, passwdFile.reader()); defer for (users) |*user| user.deinit(allocator); var groups = try Group.fromReader(allocator, groupFile.reader()); defer for (groups) |*group| group.deinit(allocator); 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, }); return 0; } const testing = std.testing; 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); try testing.expect(mem.startsWith( u8, stderr.items, "ERROR: unknown option '--invalid-argument'", )); } test "smoke test" {}