From 339fae531e71fffcd04a080f9a65e00374d6e75c Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Sun, 17 Mar 2024 10:37:16 +0200 Subject: [PATCH] initial commit --- .gitignore | 2 + build.zig | 48 +++++++++++++++++++ compile_flags.txt | 13 +++++ src/main.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 181 insertions(+) create mode 100644 .gitignore create mode 100644 build.zig create mode 100644 compile_flags.txt create mode 100644 src/main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c26d4af --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +zig-out +zig-cache diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..9135a39 --- /dev/null +++ b/build.zig @@ -0,0 +1,48 @@ +const std = @import("std"); + +fn linkPkgConfigOutput(b: *std.build.Builder, obj: *std.build.LibExeObjStep, pkg_config_args: []const []const u8) !void { + var argv = std.ArrayList([]const u8).init(b.allocator); + try argv.append("pkg-config"); + try argv.appendSlice(pkg_config_args); + + const result = try std.ChildProcess.exec(.{ + .allocator = b.allocator, + .argv = argv.items + }); + var cflags = std.ArrayList([]const u8).init(b.allocator); + defer cflags.deinit(); + + const stdout_trimmed = std.mem.trim(u8, result.stdout, " \n"); + var cflags_iter = std.mem.splitScalar(u8, stdout_trimmed, ' '); + while (cflags_iter.next()) |cflag| { + if (std.mem.startsWith(u8, cflag, "-l")) { + obj.linkSystemLibrary(cflag[2..]); + } else if (std.mem.startsWith(u8, cflag, "-I")) { + obj.addIncludePath(.{ .path = cflag[2..] }); + } + } +} + +pub fn build(b: *std.build.Builder) !void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const exe = b.addExecutable(.{ + .name = "rolexhound", + .target = target, + .optimize = optimize, + .root_source_file = .{ .path = "src/main.c" } + }); + exe.linkLibC(); + try linkPkgConfigOutput(b, exe, &.{ "--cflags", "--libs", "libnotify" }); + + b.installArtifact(exe); + + const run_exe = b.addRunArtifact(exe); + if (b.args) |args| { + run_exe.addArgs(args); + } + + const run_step = b.step("run", "Launch program"); + run_step.dependOn(&run_exe.step); +} diff --git a/compile_flags.txt b/compile_flags.txt new file mode 100644 index 0000000..c388288 --- /dev/null +++ b/compile_flags.txt @@ -0,0 +1,13 @@ +-I/usr/include/gdk-pixbuf-2.0 +-I/usr/include/glib-2.0 +-I/usr/lib/glib-2.0/include +-I/usr/include/blkid +-I/usr/include/libmount +-I/usr/include/sysprof-6 +-pthread +-I/usr/include/libpng16 +-lnotify +-lgdk_pixbuf-2.0 +-lgio-2.0 +-lgobject-2.0 +-lglib-2.0 diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..6099784 --- /dev/null +++ b/src/main.c @@ -0,0 +1,118 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CLI_ERR_OK 0 +#define CLI_ERR_TOO_FEW_ARGS 1 +#define CLI_ERR_INOTIFY_INIT 2 +#define CLI_ERR_INOTIFY_ADD_WATCH 3 +#define CLI_ERR_READ 4 +#define CLI_ERR_LIBNOTIFY 5 + +struct daemon_state { + bool running; + int inotify_fd; + int inotify_wd; +}; +static struct daemon_state g_state = { + .running = true +}; + +void daemon_deinit(struct daemon_state *state) { + inotify_rm_watch(g_state.inotify_fd, g_state.inotify_wd); + notify_uninit(); +} + +void signal_handler(int signal) { + g_state.running = false; + printf("Stoping daemon\n"); + daemon_deinit(&g_state); + exit(0); +} + +int main(int argc, char **argv) { + if (argc < 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return CLI_ERR_TOO_FEW_ARGS; + } + + char *path = argv[1]; + char *base_path = strrchr(path, '/'); + if (base_path == NULL) { + base_path = path; + } else { + base_path += 1; + } + + if (!notify_init("rolexhound")) { + perror("notify_init"); + return CLI_ERR_LIBNOTIFY; + } + + int inotify_fd = inotify_init(); + if (inotify_fd == -1) { + perror("inotify_init"); + return CLI_ERR_INOTIFY_INIT; + } + + int inotify_wd = inotify_add_watch(inotify_fd, path, IN_CREATE | IN_DELETE | IN_ACCESS | IN_CLOSE_WRITE | IN_MODIFY | IN_MOVE_SELF); + if (inotify_fd == -1) { + perror("inotify_add_watch"); + return CLI_ERR_INOTIFY_ADD_WATCH; + } + + signal(SIGABRT, signal_handler); + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + + uint8_t buffer[4096]; + while (g_state.running) { + printf("Waiting for inotify event.\n"); + + int read_length = read(inotify_fd, buffer, sizeof(buffer)); + if (read_length == -1) { + perror("read"); + return CLI_ERR_READ; + } + + int buffer_used = 0; + while (buffer_used < read_length) { + struct inotify_event *event = (struct inotify_event*)&buffer[buffer_used]; + + if (event->mask & IN_CREATE) { + printf("- File created\n"); + } + if (event->mask & IN_DELETE) { + printf("- File deleted\n"); + } + if (event->mask & IN_ACCESS) { + printf("- File accessed\n"); + } + if (event->mask & IN_CLOSE_WRITE) { + printf("- File close & write\n"); + } + if (event->mask & IN_MODIFY) { + printf("- File modified\n"); + } + if (event->mask & IN_MOVE_SELF) { + printf("- File moved self\n"); + } + + buffer_used += sizeof(struct inotify_event) + event->len; + + NotifyNotification *notification = notify_notification_new(base_path, "file event", "dialog-information"); + notify_notification_show(notification, NULL); + g_object_unref(G_OBJECT(notification)); + } + } + + daemon_deinit(&g_state); + + return CLI_ERR_OK; +}