summaryrefslogtreecommitdiff
path: root/src/fs_event/fs_event_inotify.c
blob: 757d393cacd1414740606698fd5ddccefd058462 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#define AL_LOG_SECTION "fs_event"
#include <al/log.h>

#include "../util/error.h"
#include "../socket/socket.h"

#include "fs_event.h"

#define EVENT_MAX_SIZE (sizeof(struct inotify_event) + NAME_MAX + 1)

static void event_callback(struct ev_loop *loop, ev_io *w, s32 revents)
{
    (void)loop;
    struct nn_fs_event *fs = (struct nn_fs_event *)w->data;
    (void)revents;
    struct inotify_event *event = al_malloc(EVENT_MAX_SIZE);
    ssize_t ret = nn_read(fs->fd, event, EVENT_MAX_SIZE);
    al_assert(ret > 0);
    if (!(event->mask & fs->mask)) {
        al_assert(event->mask & IN_IGNORED);
        return;
    }
    al_assert(event->wd == fs->wd);
    fs->callback(fs->userdata, event);
    al_free(event);
}

void nn_fs_event_init(struct nn_fs_event *fs, str *path, u32 mask,
    void (*callback)(void *, struct inotify_event *), void *userdata)
{
    fs->fd = inotify_init();
    nn_fd_set_blocking(fs->fd, true);
    fs->path = al_str_to_c_str(path);
    fs->mask = mask;
    fs->callback = callback;
    fs->userdata = userdata;
    fs->event.data = fs;
    ev_io_init_n(&fs->event, event_callback, fs->fd, EV_READ);
}

bool nn_fs_event_start(struct nn_fs_event *fs, struct nn_event_loop *loop)
{
    fs->loop = loop;
    fs->wd = inotify_add_watch(fs->fd, fs->path, fs->mask);
    if (fs->wd == -1) {
        log_error("inotify_add_watch(%s) failed (%s).", fs->path, nn_strerror(errno));
        return false;
    }
    ev_io_start(fs->loop->ev, &fs->event);
    return true;
}

void nn_fs_event_stop(struct nn_fs_event *fs)
{
    inotify_rm_watch(fs->fd, fs->wd);
    ev_io_stop(fs->loop->ev, &fs->event);
}

void nn_fs_event_free(struct nn_fs_event *fs)
{
    close(fs->fd);
    al_free(fs->path);
}