如果我尝试通过同一进程将某些内容登录到文件中,我的系统就会挂起。
实际上,我想用 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] = '\0';
close(metadata->fd);
char szLog[256] = {'\0'};
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] = {'\0'};
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 MOUNT\n", 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);
}