diff --git a/.gitignore b/.gitignore index 93c1b5f..e901168 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -/zig-cache +/.zig-cache /zig-out diff --git a/build.zig b/build.zig index db50e95..26f870f 100644 --- a/build.zig +++ b/build.zig @@ -6,19 +6,19 @@ pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); _ = b.addModule("journalz", .{ - .root_source_file = .{ .path = "src/root.zig" }, + .root_source_file = b.path("src/root.zig"), .target = target, .optimize = optimize, }); - const lib_unit_tests = b.addTest(.{ - .root_source_file = .{ .path = "src/root.zig" }, + const unit_tests = b.addTest(.{ + .root_source_file = b.path("src/root.zig"), .target = target, .optimize = optimize, }); - const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests); + const run_unit_tests = b.addRunArtifact(unit_tests); const test_step = b.step("test", "Run unit tests"); - test_step.dependOn(&run_lib_unit_tests.step); + test_step.dependOn(&run_unit_tests.step); } diff --git a/build.zig.zon b/build.zig.zon index 2c55665..07751cd 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -5,6 +5,8 @@ .dependencies = .{}, .paths = .{ - "", + "build.zig", + "build.zig.zon", + "src", }, } diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..f92845d --- /dev/null +++ b/flake.lock @@ -0,0 +1,60 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1726560853, + "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1727122398, + "narHash": "sha256-o8VBeCWHBxGd4kVMceIayf5GApqTavJbTa44Xcg5Rrk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "30439d93eb8b19861ccbe3e581abf97bdc91b093", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..70a4f22 --- /dev/null +++ b/flake.nix @@ -0,0 +1,34 @@ +{ + inputs = { + nixpkgs = { + url = "nixpkgs/nixos-unstable"; + }; + flake-utils = { + url = "github:numtide/flake-utils"; + }; + }; + + outputs = { + nixpkgs, + flake-utils, + ... + }: + flake-utils.lib.eachDefaultSystem ( + system: let + pkgs = import nixpkgs { + inherit system; + }; + in { + devShells = { + default = pkgs.mkShell { + nativeBuildInputs = [ + pkgs.zig_0_13 + ]; + shellHook = '' + export name=journalz + ''; + }; + }; + } + ); +} diff --git a/src/cmsghdr.zig b/src/cmsghdr.zig index 1c09569..5b33f9b 100644 --- a/src/cmsghdr.zig +++ b/src/cmsghdr.zig @@ -43,5 +43,5 @@ pub fn cmsghdr(comptime T: type) type { } test { - std.testing.refAllDecls(cmsghdr([3]std.os.fd_t)); + std.testing.refAllDecls(cmsghdr([3]std.os.linux.fd_t)); } diff --git a/src/root.zig b/src/root.zig index 96e6a46..8e0ad59 100644 --- a/src/root.zig +++ b/src/root.zig @@ -35,7 +35,7 @@ pub const Priority = enum(u3) { DEBUG = 7, }; -const JOURNAL_SOCKET: []const u8 = "/run/systemd/journal/socket"; +const JOURNAL_SOCKET: [:0]const u8 = "/run/systemd/journal/socket"; const SCM_RIGHTS = 1; @@ -54,55 +54,74 @@ pub const Logger = struct { const Self = @This(); identifier: ?[]const u8, - socket: std.os.socket_t, - path: std.os.sockaddr.un = undefined, + socket: std.os.linux.socket_t, + path: std.os.linux.sockaddr.un = undefined, pub fn init(identifier: ?[]const u8) !Logger { var logger = Logger{ .identifier = identifier, - .socket = try std.os.socket(std.os.AF.UNIX, std.os.SOCK.DGRAM | std.os.SOCK.CLOEXEC, 0), + .socket = socket: { + const rc = std.os.linux.socket( + std.os.linux.AF.UNIX, + std.os.linux.SOCK.DGRAM | std.os.linux.SOCK.CLOEXEC, + 0, + ); + switch (std.posix.errno(rc)) { + .SUCCESS => break :socket @intCast(rc), + else => return error.Failed, + } + }, }; - errdefer std.os.close(logger.socket); - logger.path.family = std.os.AF.UNIX; - @memset(logger.path.path[0..logger.path.path.len], 0); + std.debug.assert(logger.path.path.len > JOURNAL_SOCKET.len); + + errdefer _ = std.os.linux.close(logger.socket); + + logger.path.family = std.os.linux.AF.UNIX; @memcpy(logger.path.path[0..JOURNAL_SOCKET.len], JOURNAL_SOCKET); + logger.path.path[JOURNAL_SOCKET.len] = 0; return logger; } pub fn deinit(self: Self) void { - std.os.close(self.socket); + _ = std.os.linux.close(self.socket); } const Message = struct { logger: Logger, priority: Priority, - memfd: std.os.fd_t, + memfd: std.os.linux.fd_t, - fn _writeString(self: Message, str: []const u8) !void { - const len = try std.os.write(self.memfd, str); - if (len != str.len) return error.ShortWrite; + fn writeBytes(self: Message, str: []const u8) !void { + const rc = std.os.linux.write(self.memfd, str.ptr, str.len); + switch (std.posix.errno(rc)) { + .SUCCESS => { + if (rc != str.len) return error.ShortWrite; + }, + else => return error.Failed, + } } - fn _writeU64(self: Message, native: u64) !void { + fn writeU64(self: Message, native: u64) !void { const le = std.mem.nativeToLittle(u64, native); const msg = std.mem.asBytes(&le); - try self._writeString(msg); + try self.writeBytes(msg); } pub fn string(self: Message, key: []const u8, value: []const u8) !void { - try self._writeString(key); - try self._writeString("\n"); - try self._writeU64(value.len); - try self._writeString(value); - try self._writeString("\n"); + try self.writeBytes(key); + try self.writeBytes("\n"); + try self.writeU64(value.len); + try self.writeBytes(value); + try self.writeBytes("\n"); } pub fn int(self: Message, key: []const u8, value: anytype) !void { - if (@typeInfo(@TypeOf(value)) != .Int) @compileError("type " ++ @typeName(@TypeOf(value)) ++ " is not an integer type"); + if (@typeInfo(@TypeOf(value)) != .Int) + @compileError("type " ++ @typeName(@TypeOf(value)) ++ " is not an integer type"); - var buf: [32]u8 = undefined; + var buf: [64]u8 = undefined; var fbs = std.io.fixedBufferStream(&buf); const writer = fbs.writer(); try std.fmt.formatInt(value, 10, .lower, .{}, writer); @@ -124,21 +143,27 @@ pub const Logger = struct { } pub fn send(self: *const Message) !void { - _ = try std.os.fcntl( - self.memfd, - F_ADD_SEALS, - F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_EXEC, - ); + { + const rc = std.os.linux.fcntl( + self.memfd, + F_ADD_SEALS, + F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_EXEC, + ); + switch (std.posix.errno(rc)) { + .SUCCESS => {}, + else => return error.Failed, + } + } - var cmsg = cmsghdr.cmsghdr(std.os.fd_t).init( + var cmsg = cmsghdr.cmsghdr(std.os.linux.fd_t).init( .{ - .level = std.os.SOL.SOCKET, + .level = std.os.linux.SOL.SOCKET, .type = SCM_RIGHTS, .data = self.memfd, }, ); - var msghdr = std.os.msghdr_const{ + var msghdr = std.os.linux.msghdr_const{ .name = @ptrCast(&self.logger.path), .namelen = @sizeOf(@TypeOf(self.logger.path)), .iov = undefined, @@ -148,27 +173,38 @@ pub const Logger = struct { .flags = 0, }; - const result = try std.os.sendmsg( - self.logger.socket, - &msghdr, - 0, - ); + { + const rc = std.os.linux.sendmsg( + self.logger.socket, + &msghdr, + 0, + ); - std.debug.assert(result == 0); + switch (std.posix.errno(rc)) { + .SUCCESS => {}, + else => return error.Failed, + } + } - std.os.close(self.memfd); + _ = std.os.linux.close(self.memfd); } pub fn cancel(self: Message) void { - std.os.close(self.memfd); + _ = std.os.linux.close(self.memfd); } }; fn message(self: Logger, priority: Priority) !Message { - const memfd = try std.os.memfd_create( - "zig", - std.os.MFD.CLOEXEC | std.os.MFD.ALLOW_SEALING | MFD_NOEXEC_SEAL, - ); + const memfd: std.os.linux.fd_t = memfd: { + const rc = std.os.linux.memfd_create( + "zig", + std.os.linux.MFD.CLOEXEC | std.os.linux.MFD.ALLOW_SEALING | MFD_NOEXEC_SEAL, + ); + switch (std.posix.errno(rc)) { + .SUCCESS => break :memfd @intCast(rc), + else => return error.Failed, + } + }; const msg = Message{ .logger = self,