Skip to content

Instantly share code, notes, and snippets.

@furandon-pig
Created December 24, 2021 12:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save furandon-pig/c6c7c94548d7134b6f224cfdb8e5c5b0 to your computer and use it in GitHub Desktop.
Save furandon-pig/c6c7c94548d7134b6f224cfdb8e5c5b0 to your computer and use it in GitHub Desktop.
NetBSDのfilemon機能を利用してファイル書き込みイベントをハンドリングするサンプルです。
/*
* NetBSD filemonのファイル書き込みの監視サンプル。
*
* $ gcc -Wall -Werror -g -o nbsd_filemon_watch_write_event nbsd_filemon_watch_write_event.c
*/
#include <dev/filemon/filemon.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
extern char *optarg;
extern int optind;
int main(int argc, char *argv[])
{
int ch;
char *w_cmd = NULL; // open(RDWR)
while ((ch = getopt(argc, argv, "w:")) != -1) {
switch (ch) {
case 'w': w_cmd = optarg; break;
case '?':
default:
break;
}
}
argc -= optind;
argv += optind;
#if DEBUG
if (w_cmd) printf("W: open(RDWR) %s\n", w_cmd);
#endif
pid_t pid;
int filemon_fd, temp_fd;
int status;
char temp_path[] = "/tmp/filemonXXXXXXXX";
FILE *fp = NULL;
char buf[BUFSIZ];
int read_line = 0;
int count = 0;
int is_done = 0;
filemon_fd = open("/dev/filemon", O_RDWR);
temp_fd = mkstemp(temp_path);
// give filemon the temp file to use
ioctl(filemon_fd, FILEMON_SET_FD, &temp_fd);
// children do not need these one they exec
fcntl(filemon_fd, F_SETFD, FD_CLOEXEC);
fcntl(temp_fd, F_SETFD, FD_CLOEXEC);
pid = fork();
switch(pid) {
case -1:
fprintf(stderr, "cannot fork");
break;
case 0:
printf("filemon: %s\n", temp_path);
pid = getpid();
// tell filemon to monitor this process
ioctl(filemon_fd, FILEMON_SET_PID, &pid);
execvp(argv[0], argv);
_exit(1);
break;
default:
lseek(temp_fd, SEEK_SET, 0);
is_done = 1;
while (is_done) {
fp = fopen(temp_path, "r");
if (fp) {
count = 0;
while (fgets(buf, BUFSIZ-1, fp)) {
if (count++ < read_line) {
continue;
}
if (buf[0] == 'W') {
// "W 521 cal.txt" => "cal.txt"
char *path = strchr(buf, ' ');
path = strchr(++path, ' ');
++path;
switch(fork()) {
case -1:
fprintf(stderr, "cannot fork");
break;
case 0:
if (w_cmd) {
char *script[] = { w_cmd, path, NULL };
execvp(script[0], script);
}
default:
wait(&status);
}
}
if (buf[0] == '#') {
is_done = 0;
break;
}
}
read_line += count - read_line;
fclose(fp);
usleep(700000);
}
}
wait(&status);
close(filemon_fd);
close(temp_fd);
break;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment