factor / factor

Factor programming language

Home Page:https://factorcode.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

add efficient support for tail -f on kqueue, epoll, windows...etc if supported

erg opened this issue · comments

really naive attempt at tail -f fails because readln returns EOF

"resource:README.md" utf8 [
    [
        readln dup print nl
    ] loop
] with-file-reader

File monitors would probably get the job done, but there's a more efficine way sometimes.

linux: https://github.com/coreutils/coreutils/blob/master/src/tail.c#L1235

chatgpt actually got it right--try this on macos

// clang follow.c && ./a.out README.md
// echo a >> README.md

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <unistd.h>
#include <errno.h>

#define BUF_SIZE 1024

int main(int argc, char *argv[]) {
    int fd, kq, nev;
    struct kevent change;
    struct kevent event;
    char buf[BUF_SIZE];
    int len;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    // Open file
    fd = open(argv[1], O_RDONLY);
    if (fd == -1) {
        perror("Failed to open file");
        exit(EXIT_FAILURE);
    }

    // Create kqueue
    kq = kqueue();
    if (kq == -1) {
        perror("kqueue failed");
        exit(EXIT_FAILURE);
    }

    // Initialize kevent structure
    EV_SET(&change, fd, EVFILT_VNODE,
           EV_ADD | EV_ENABLE | EV_CLEAR,
           NOTE_WRITE | NOTE_EXTEND, 0, 0);

    // Move to the end of the file
    if (lseek(fd, 0, SEEK_END) == -1) {
        perror("lseek failed");
        exit(EXIT_FAILURE);
    }

    // Event loop
    while (1) {
        nev = kevent(kq, &change, 1, &event, 1, NULL);
        if (nev == -1) {
            perror("kevent failed");
            exit(EXIT_FAILURE);
        } else if (nev > 0) {
            if (event.fflags & NOTE_WRITE || event.fflags & NOTE_EXTEND) {
                while ((len = read(fd, buf, BUF_SIZE)) > 0) {
                    write(STDOUT_FILENO, buf, len);
                }
                if (len == -1) {
                    perror("read failed");
                    exit(EXIT_FAILURE);
                }
            }
        }
    }

    // Close file and kqueue
    close(fd);
    close(kq);

    return 0;
}