fanotify:是否可以通过同一进程监视整个文件系统并在被监视的文件系统中写入少量日志/config



如果我试图通过相同的进程将某些内容记录到文件中,我的系统就会挂起。

实际上,我想用fanotify监视整个文件系统("/"(,还想在"/tmp"中记录任何错误,但这会导致系统挂起。

请找到以下代码:

#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/fanotify.h>
#include <unistd.h>
#include <string.h>
static void
handle_events(int fd)
{
const struct fanotify_event_metadata *metadata;
struct fanotify_event_metadata buf[200];
ssize_t len;
char path[PATH_MAX];
ssize_t path_len;
char procfd_path[PATH_MAX];
struct fanotify_response response;
//Loop while events can be read from fanotify file descriptor 
for (;;) 
{
//Read some events
len = read(fd, (void *) &buf, sizeof(buf));
if (len == -1 && errno != EAGAIN) 
{
system("echo 'Read error' >> /tmp/fanotify.txt");
exit(EXIT_FAILURE);
}
//Check if end of available data reached
if (len <= 0)
break;
//Point to the first event in the buffer
metadata = buf;
//Loop over all events in the buffer
while (FAN_EVENT_OK(metadata, len)) 
{
//Check that run-time and compile-time structures match
if (metadata->vers != FANOTIFY_METADATA_VERSION) 
{
system("echo 'Mismatch of fanotify metadata version' >> /tmp/fanotify.txt");
exit(EXIT_FAILURE);
}
/* metadata->fd contains either FAN_NOFD, indicating a
queue overflow, or a file descriptor (a nonnegative
integer). Here, we simply ignore queue overflow. */
if (metadata->fd >= 0) 
{
//Handle open permission event
if (metadata->mask & FAN_OPEN_PERM) 
{
//Allow file to be opened
response.fd = metadata->fd;
response.response = FAN_ALLOW;
write(fd, &response,sizeof(struct fanotify_response));
system("echo 'FAN_OPEN_PERM:' >> /tmp/fanotify.txt");
}
//Handle closing of writable file event
if (metadata->mask & FAN_CLOSE_WRITE)
{
system("echo 'FAN_CLOSE_WRITE:' >> /tmp/fanotify.txt");
}

//Retrieve and print pathname of the accessed file 
snprintf(procfd_path, sizeof(procfd_path),
"/proc/self/fd/%d", metadata->fd);
path_len = readlink(procfd_path, path,
sizeof(path) - 1);
if (path_len == -1) 
{
system("echo 'readlink error' >> /tmp/fanotify.txt");
exit(EXIT_FAILURE);
}
path[path_len] = '';
close(metadata->fd);
char szLog[256] = {''};
snprintf(szLog, sizeof(szLog), "echo 'File %s' >> /tmp/fanotify.txt", path);
system(szLog);  
//Close the file descriptor of the event
}
//Advance to next event
metadata = FAN_EVENT_NEXT(metadata, len);
}
}
}

以下是我调用handle_events的主要函数

int
main(int argc, char *argv[])
{
char buf;
int fd, poll_num;
nfds_t nfds;
struct pollfd fds[2];
char szMountCommand[1024] = {''};
uint64_t uiMask = FAN_OPEN_PERM | FAN_CLOSE_WRITE | FAN_EVENT_ON_CHILD;
//Check mount point is supplied
if (argc != 2) {
fprintf(stderr, "Usage: %s MOUNTn", argv[0]);
exit(EXIT_FAILURE);
}
system("echo 'Press enter key to terminate' >> /tmp/fanotify.txt");
//Create the file descriptor for accessing the fanotify API
fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
O_RDONLY | O_LARGEFILE);
if (fd == -1) {
system("echo 'fanotify_init failed.' >> /tmp/fanotify.txt");
exit(EXIT_FAILURE);
}
/* Mark the mount for:
- permission events before opening files
- notification events after closing a write-enabled
file descriptor */
snprintf(szMountCommand, sizeof(szMountCommand), "mount --bind %s %s", argv[1], argv[1]);
system(szMountCommand); 
if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT, uiMask, 0, argv[1]) == -1)
{
system("echo 'fanotify_mark failed.' >> /tmp/fanotify.txt");
exit(EXIT_FAILURE);
}
system("echo 'Monitoring:' >> /tmp/fanotify.txt");
//Prepare for polling
nfds = 2;
//Console input
fds[0].fd = STDIN_FILENO;
fds[0].events = POLLIN;
//Fanotify input
fds[1].fd = fd;
fds[1].events = POLLIN;
//This is the loop to wait for incoming events
system("echo 'Listening for events:' >> /tmp/fanotify.txt");
while (1) {
poll_num = poll(fds, nfds, -1);
if (poll_num == -1) {
if (errno == EINTR)     //Interrupted by a signal
continue;           // Restart poll()
system("echo 'poll failed.' >> /tmp/fanotify.txt");
exit(EXIT_FAILURE);
}
if (poll_num > 0) {
if (fds[0].revents & POLLIN) {
//Console input is available: empty stdin and quit
while (read(STDIN_FILENO, &buf, 1) > 0 && buf != 'n')
continue;
break;
}
if (fds[1].revents & POLLIN) {
//Fanotify events are available
handle_events(fd);
}
}
}
system("echo 'Listening for events stopped.' >> /tmp/fanotify.txt");
exit(EXIT_SUCCESS);
}

这是一个无限循环!

假设您收到一个通知(由于某些外部更改(,并希望将其写入同一文件系统。因此,它将生成另一个通知(由于日志记录(。您要编写新通知。这将导致另一个通知。所以这是一个无休止的循环。

您可以使用另一个挂载的文件系统进行日志记录,或者只监视特定的路径。

最新更新