Something went wrong. Try again.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127const std = @import("std");const process = std.process;const posix = std.posix;const linux = std.os.linux;const meta = std.meta;const mem = std.mem;const Io = std.Io;const Config = @import("Config.zig");
const Cli = struct { config_path: []const u8 = "/etc/persistd.json",
const Args = enum { @"--config", @"-c", };
pub fn parse(args: process.Args) !Cli { var self = Cli{};
var iter = args.iterate(); _ = iter.next(); while (iter.next()) |arg| { if (meta.stringToEnum(Args, arg)) |parsed_arg| { switch (parsed_arg) { .@"--config", .@"-c" => { if (iter.next()) |config_path| { self.config_path = config_path; } else { std.debug.print("--config requires argument\n", .{}); return error.MissingArg; } }, } } else { std.debug.print("Unkown argument {s}\n", .{arg}); return error.UnkownArg; } }
return self; }};
pub fn main(init: process.Init) !void { const alloc = init.gpa; const io = init.io;
const cli = try Cli.parse(init.minimal.args);
const config, const arena = Config.load(io, alloc, cli.config_path) catch |err| { std.debug.print("Failed to load config {s}\n", .{cli.config_path}); return err; }; defer arena.deinit();
try apply(io, alloc, &config);
var set = posix.sigemptyset(); posix.sigaddset(&set, .HUP); posix.sigprocmask(posix.SIG.BLOCK, &set, null);
const sfd = try posix.signalfd(-1, &set, linux.SFD.CLOEXEC); defer _ = linux.close(sfd);
while (true) { var info: linux.signalfd_siginfo = undefined; if (try posix.read(sfd, mem.asBytes(&info)) != @sizeOf(linux.signalfd_siginfo)) continue; if (info.signo == @backingInt(posix.SIG.HUP)) { try apply(io, alloc, &config); } }}
fn apply(io: Io, alloc: mem.Allocator, config: *const Config) !void { for (config.mounts) |mount| { for (mount.files) |file| { const target = try mem.concatWithSentinel(alloc, u8, &.{ mount.target, file.path[0 .. file.path.len - 1] }, 0); defer alloc.free(target);
Io.Dir.cwd().access(io, target, .{}) catch |err| if (err == error.FileNotFound) { try Io.Dir.cwd().createDirPath(io, target); } else { return err; };
switch (file.method) { .bind => try bindMount(target, file.path), } }
for (mount.directories) |directory| { const target = try mem.concatWithSentinel(alloc, u8, &.{ mount.target, directory.path[0..directory.path.len] }, 0); defer alloc.free(target);
Io.Dir.cwd().access(io, target, .{}) catch |err| if (err == error.FileNotFound) { try Io.Dir.cwd().createDirPath(io, target); } else { return err; };
switch (directory.method) { .bind => try bindMount(target, directory.path), } } }}
pub fn bindMount(source: [*:0]const u8, target: [*:0]const u8) !void { const result = linux.mount( source, target, null, linux.MS.BIND, 0, );
const err = posix.errno(result); if (err != .SUCCESS) { std.debug.print( "mount({s}, {s}) failed: {s}\n", .{ source, target, @tagName(err) }, ); return error.MountFailed; }}