lunabot/src/journal/journal.zig

117 lines
2.9 KiB
Zig

const std = @import("std");
const os = std.os;
const c = @cImport({
@cInclude("stdio.h");
@cInclude("stdlib.h");
@cInclude("sys/stat.h");
@cInclude("string.h");
@cInclude("time.h");
});
const warn = std.debug.warn;
const allocator = std.heap.c_allocator;
fn alloc_str(size: c_ulong) [*c]u8 {
return @ptrCast([*c]u8, @alignCast(@alignOf(u8), c.malloc(c_ulong(size))));
}
fn free_str(ptr: [*c]u8) void {
c.free(@ptrCast(?*c_void, ptr));
}
export fn journal_open(topic_opt: [*c]u8) os.fd_t {
const topic_len = c.strlen(topic_opt);
const topic: []u8 = topic_opt[0..topic_len];
const journal_dir = std.fs.path.resolve(allocator, [_][]const u8{
std.os.getenvC(c"HOME").?,
".lunabot",
}) catch |err| {
warn("failed to resolve paths: {}\n", err);
return -1;
};
warn("journal_dir = {}\n", journal_dir);
std.fs.makeDir(journal_dir) catch |err| {
if (err != error.PathAlreadyExists) {
warn("failed to create journal dir {}: {}\n", journal_dir, err);
return -1;
}
};
const journal_path = std.fmt.allocPrint(allocator, "{}/{}", journal_dir, topic) catch |err| {
warn("failed to allocprint journal path: {}\n", err);
return -1;
};
defer allocator.free(journal_path);
warn("journal_path = {}\n", journal_path);
const fd = std.os.open(
journal_path,
std.os.O_WRONLY | std.os.O_CREAT | std.os.O_APPEND,
0o755,
) catch |err| {
warn("failed to open {}: {}\n", journal_path, err);
return -1;
};
return fd;
}
export fn journal_write(journal: os.fd_t, message: [*c]u8) void {
const msglen = c.strlen(message);
std.os.write(journal, message[0..msglen]) catch |err| {
std.debug.warn("Error while writing to file: {}\n", err);
return;
};
}
export fn journal_close(journal: os.fd_t) void {
std.os.close(journal);
}
export fn journal_write_topic(
journal: os.fd_t,
topic_opt: [*c]u8,
message_opt: [*c]u8,
) void {
var topic = topic_opt[0..c.strlen(topic_opt)];
var message = message_opt[0..c.strlen(message_opt)];
var tstamp_cstr: [*c]u8 = alloc_str(128);
var rawtime: c.time_t = undefined;
_ = c.time(&rawtime);
var cur_time: [*c]const c.struct_tm = c.gmtime(&rawtime);
_ = c.strftime(tstamp_cstr, usize(128), c"%c", cur_time);
var tstamp = tstamp_cstr[0..c.strlen(tstamp_cstr)];
std.debug.warn("tstamp: {}\ntopic: {}\nmsg: {}\n", tstamp, topic, message);
// catch unreachable is intended.
var fmt_msg = std.fmt.allocPrint(
allocator,
"[{}] [{}]: {}\n",
tstamp,
topic,
message,
) catch |err| {
warn("Failed to make formatted message: {}\n", err);
return;
};
var fmt_msg_cstr = std.cstr.addNullByte(
allocator,
fmt_msg,
) catch unreachable;
free_str(tstamp_cstr);
journal_write(journal, fmt_msg_cstr.ptr);
}