feat: add simple inotify prototype

This commit is contained in:
2024-08-02 19:11:12 +02:00
parent 94a4ac27c5
commit 6c3ad9ffa5
10 changed files with 212 additions and 60 deletions

67
src/cli.c Normal file
View File

@ -0,0 +1,67 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include "cli.h"
struct cli_options new_options() {
struct cli_options result;
result.file.has_value = false;
result.verbosity = 1;
result.help = false;
result.version = false;
return result;
}
void free_options(struct cli_options v) {
if(v.file.has_value)
free(v.file.value);
}
// <max
const char* optstring = "f:v:hV";
const char* help_msg =
"Usage: %s [-v level] [-h] [-V]\n"
"\n"
SCI_DESCRIPTION "\n"
"\n"
"THIS PROGRAM IS STILL JUST A PROTOTYPE, AND NOT\n"
"ACTUALLY USEFUL YET\n"
"\n"
"OPTIONS:\n"
" -f file set file\n"
" -v level Set verbosity level [0-3]\n"
" -h Show this message and exit\n"
" -V Show version and exit\n"
;
// <max
void print_help(FILE * out, char* prog_name) {
fprintf(out, help_msg, prog_name);
}
struct cli_options parse(int argc, char** argv) {
struct cli_options options = new_options();
int opt;
while((opt = getopt(argc, argv, optstring)) != -1) {
switch(opt) {
case 'f':
options.file.value = strdup(optarg);
options.file.has_value = true;
break;
case 'v':
options.verbosity = atoi(optarg);
break;
case 'V':
options.version = true;
break;
case 'h':
options.help = true;
break;
default:
print_help(stderr, argv[0]);
exit(EXIT_FAILURE);
}
}
return options;
}

View File

@ -1,64 +1,37 @@
#include <stdio.h>
#include "cli.h"
#include "notify.h"
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <getopt.h>
struct cli_options {
int verbosity;
bool help;
bool version;
};
struct cli_options new_options() {
struct cli_options result;
result.verbosity = 0;
result.help = false;
return result;
}
// <max
char* help_msg =
"Usage: %s [-v level] [-h] [-V]\n"
"\n"
SCI_NAME " is a simple contiuous integration system.\n"
"\n"
"OPTIONS:\n"
" -v level Set verbosity level [0-3]\n"
" -h Show this message and exit\n"
" -V Show version and exit\n"
;
// <max
void print_help(FILE * out, char* prog_name) {
fprintf(out, help_msg, prog_name);
void on_notify_event(struct inotify_event* const e) {
fprintf(stdout, "got an event:\n");
fprintf(stdout, " wd: %d\n", e->wd);
fprintf(stdout, " mask: %d\n", e->mask);
fprintf(stdout, " cookie: %d\n", e->cookie);
fprintf(stdout, " len: %d\n", e->len);
fprintf(stdout, " name: %s\n", e->name);
}
int main(int argc, char** argv) {
struct cli_options options = new_options();
int opt;
while((opt = getopt(argc, argv, "v:hV")) != -1) {
switch(opt) {
case 'v':
options.verbosity = atoi(optarg);
break;
case 'V':
options.version = true;
break;
case 'h':
options.help = true;
break;
default: // '?'
print_help(stderr, argv[0]);
exit(EXIT_FAILURE);
}
}
if(options.help) {
struct cli_options args = parse(argc, argv);
if(args.help) {
print_help(stdout, argv[0]);
exit(EXIT_SUCCESS);
}
if(options.version) {
if(args.version) {
fprintf(stdout, SCI_VERSION "\n");
exit(EXIT_SUCCESS);
}
if(args.file.has_value) {
if(access(args.file.value, F_OK) != 0) {
fprintf(stderr, "no such file or directory %s\n", args.file.value);
exit(EXIT_FAILURE);
}
listen_for_changes(args.file.value, &on_notify_event);
}
free_options(args);
}

23
src/notify.c Normal file
View File

@ -0,0 +1,23 @@
#include "notify.h"
#include "util.h"
#define EV_SIZE sizeof(struct inotify_event)
#define BUF_LEN EV_SIZE * 32
void listen_for_changes(const char* filename, notify_callback callback) {
int fd = inotify_init();
ASSERT_SYSCALL_SUCCESS(fd);
inotify_add_watch(fd, filename, IN_ATTRIB);
fprintf(stdout, "listening for changes in file: %s\n", filename);
char buffer[BUF_LEN];
int r = read(fd, buffer, BUF_LEN);
assert(r != -1);
for(int i = 0; i < r; ) {
struct inotify_event* e = (struct inotify_event*)&buffer[i];
callback(e);
i += EV_SIZE + e->len;
}
ASSERT_SYSCALL_SUCCESS(close(fd)); // TODO: have a hashmap of threads (see readme)
}