fanotify:是否可以通过相同的过程监视整个文件系统并在监视的文件系统中写入少量日志/配置?

问题描述 投票:0回答:1

如果我尝试通过同一过程将某些内容记录到文件中,我的系统将被挂起。

实际上,我想用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);
    }

如果我尝试通过同一过程将某些内容记录到文件中,则系统将被挂起。实际上,我想用fanotify监视整个文件系统(“ /”),并且还想记录错误,以防万一在“ / tmp”中出现错误,但是......>

linux fanotify
1个回答
0
投票

这是一个无限循环!

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

© www.soinside.com 2019 - 2024. All rights reserved.