Обычный режим работы

This commit is contained in:
Alexander Zhirov 2025-09-20 23:13:30 +03:00
parent aa214dcf96
commit 62be8600c6
Signed by: alexander
GPG key ID: C8D8BE544A27C511
4 changed files with 308 additions and 636 deletions

123
c/main.c Normal file
View file

@ -0,0 +1,123 @@
// gcc -O2 -Wall -Wextra -o main main.c
#define _GNU_SOURCE
#include <sys/fanotify.h> // <-- прототипы fanotify_*
#include <sys/epoll.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <limits.h> // PATH_MAX
#ifndef AT_FDCWD
# include <fcntl.h>
#endif
/* Настройки из твоего D-кода */
#define INIT_FLAGS (FAN_CLASS_PRE_CONTENT | FAN_CLOEXEC | FAN_NONBLOCK)
#define EVENT_FLAGS (O_RDONLY | O_LARGEFILE | O_CLOEXEC)
#define BASE_FLAGS (FAN_MARK_ADD)
#define PERM_MASK (FAN_OPEN_PERM | FAN_ACCESS_PERM | FAN_OPEN_EXEC_PERM | FAN_OPEN | FAN_CLOSE_WRITE)
#define BUF_SZ (64 * 1024)
/* Простой лог */
static void log_line(const char *s) {
struct iovec v[2];
static const char nl = '\n';
v[0].iov_base = (void*)s; v[0].iov_len = strlen(s);
v[1].iov_base = (void*)&nl; v[1].iov_len = 1;
writev(STDERR_FILENO, v, 2);
}
static ssize_t fd_path(int fd, char *buf, size_t cap) {
char linkpath[64];
int m = snprintf(linkpath, sizeof(linkpath), "/proc/self/fd/%d", fd);
if (m <= 0 || (size_t)m >= sizeof(linkpath)) return -1;
ssize_t r = readlink(linkpath, buf, cap - 1);
if (r >= 0) buf[r] = '\0';
return r;
}
int main(void) {
int fan = fanotify_init(INIT_FLAGS, EVENT_FLAGS);
if (fan == -1) { perror("fanotify_init"); return 1; }
/* метим /tmp и /home как файловые системы */
if (fanotify_mark(fan, BASE_FLAGS | FAN_MARK_FILESYSTEM, PERM_MASK, AT_FDCWD, "/tmp") == -1) {
perror("fanotify_mark(/tmp)"); return 1;
}
if (fanotify_mark(fan, BASE_FLAGS | FAN_MARK_FILESYSTEM, PERM_MASK, AT_FDCWD, "/home") == -1) {
perror("fanotify_mark(/home)"); return 1;
}
int ep = epoll_create1(EPOLL_CLOEXEC);
if (ep == -1) { perror("epoll_create1"); return 1; }
struct epoll_event ev = { .events = EPOLLIN | EPOLLONESHOT };
ev.data.u64 = 1; /* тег */
if (epoll_ctl(ep, EPOLL_CTL_ADD, fan, &ev) == -1) { perror("epoll_ctl ADD"); return 1; }
char *buf = malloc(BUF_SZ);
if (!buf) { perror("malloc"); return 1; }
log_line("fanomon: started (watching /tmp and /home)");
for (;;) {
struct epoll_event out;
int n = epoll_wait(ep, &out, 1, -1);
if (n == -1) { if (errno == EINTR) continue; perror("epoll_wait"); break; }
if ((out.events & EPOLLIN) && out.data.u64 == 1) {
for (;;) {
ssize_t len = read(fan, buf, BUF_SZ);
if (len == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) break;
if (len <= 0) break;
struct fanotify_event_metadata *meta;
for (meta = (struct fanotify_event_metadata*)buf;
FAN_EVENT_OK(meta, len);
meta = FAN_EVENT_NEXT(meta, len)) {
if (meta->vers != FANOTIFY_METADATA_VERSION) { log_line("metadata version mismatch"); continue; }
if (meta->mask & FAN_Q_OVERFLOW) { log_line("queue overflow"); continue; }
/* Быстро отвечаем на PERM-события */
if (meta->mask & (FAN_OPEN_PERM | FAN_ACCESS_PERM | FAN_OPEN_EXEC_PERM)) {
struct fanotify_response resp = { .fd = meta->fd, .response = FAN_ALLOW };
if (write(fan, &resp, sizeof(resp)) == -1) perror("fanotify_response");
}
/* Лёгкий лог пути (после ответа) */
if (meta->fd >= 0) {
char path[PATH_MAX];
if (fd_path(meta->fd, path, sizeof(path)) >= 0) {
char line[PATH_MAX + 16];
const char *tag =
(meta->mask & FAN_OPEN) ? "OPEN " :
(meta->mask & FAN_CLOSE_WRITE) ? "CLOSEW" :
(meta->mask & FAN_ACCESS_PERM) ? "APERM " :
(meta->mask & FAN_OPEN_PERM) ? "OPERM " :
(meta->mask & FAN_OPEN_EXEC_PERM) ? "XPERM " : "EVENT ";
snprintf(line, sizeof(line), "%s %s", tag, path);
log_line(line);
}
close(meta->fd);
}
}
}
/* Реарм ONE_SHOT */
ev.events = EPOLLIN | EPOLLONESHOT;
ev.data.u64 = 1;
if (epoll_ctl(ep, EPOLL_CTL_MOD, fan, &ev) == -1) { perror("epoll_ctl MOD"); break; }
}
}
free(buf);
close(ep);
close(fan);
return 0;
}