| @@ -1,4 +1,5 @@ |
| 1 | 1 | | /* Copyright 2017 Max Voit, Bert Muennich |
| 2 | + | * Copyright 2022 nsxiv contributors |
| 2 | 3 | | * |
| 3 | 4 | | * This file is a part of nsxiv. |
| 4 | 5 | | * |
| @@ -20,16 +21,14 @@ |
| 20 | 21 | | |
| 21 | 22 | | #if HAVE_INOTIFY |
| 22 | 23 | | |
| 24 | + | #include <assert.h> |
| 23 | 25 | | #include <errno.h> |
| 24 | 26 | | #include <stdlib.h> |
| 25 | 27 | | #include <string.h> |
| 26 | 28 | | #include <sys/inotify.h> |
| 27 | 29 | | #include <unistd.h> |
| 28 | 30 | | |
| 29 | | − | static union { |
| 30 | | − | char d[4096]; /* aligned buffer */ |
| 31 | | − | struct inotify_event e; |
| 32 | | − | } buf; |
| 31 | + | static struct { char *buf; size_t len; } scratch; |
| 33 | 32 | | |
| 34 | 33 | | void arl_init(arl_t *arl) |
| 35 | 34 | | { |
| @@ -43,7 +42,7 @@ CLEANUP void arl_cleanup(arl_t *arl) |
| 43 | 42 | | { |
| 44 | 43 | | if (arl->fd != -1) |
| 45 | 44 | | close(arl->fd); |
| 46 | | − | free(arl->filename); |
| 45 | + | free(scratch.buf); |
| 47 | 46 | | } |
| 48 | 47 | | |
| 49 | 48 | | static void rm_watch(int fd, int *wd) |
| @@ -61,26 +60,32 @@ static void add_watch(int fd, int *wd, const char *path, uint32_t mask) |
| 61 | 60 | | error(0, errno, "inotify: %s", path); |
| 62 | 61 | | } |
| 63 | 62 | | |
| 64 | | − | void arl_setup(arl_t *arl, const char *filepath) |
| 63 | + | static char *arl_scratch_push(const char *filepath, size_t len) |
| 65 | 64 | | { |
| 66 | | − | char *base = strrchr(filepath, '/'); |
| 65 | + | if (scratch.len < len + 1) { |
| 66 | + | scratch.len = len + 1; |
| 67 | + | scratch.buf = erealloc(scratch.buf, scratch.len); |
| 68 | + | } |
| 69 | + | scratch.buf[len] = '\0'; |
| 70 | + | return memcpy(scratch.buf, filepath, len); |
| 71 | + | } |
| 72 | + | |
| 73 | + | void arl_add(arl_t *arl, const char *filepath) |
| 74 | + | { |
| 75 | + | char *base, *dir; |
| 67 | 76 | | |
| 68 | 77 | | if (arl->fd == -1) |
| 69 | 78 | | return; |
| 70 | 79 | | |
| 71 | 80 | | rm_watch(arl->fd, &arl->wd_dir); |
| 72 | 81 | | rm_watch(arl->fd, &arl->wd_file); |
| 73 | | − | |
| 74 | 82 | | add_watch(arl->fd, &arl->wd_file, filepath, IN_CLOSE_WRITE | IN_DELETE_SELF); |
| 75 | 83 | | |
| 76 | | − | free(arl->filename); |
| 77 | | − | arl->filename = estrdup(filepath); |
| 78 | | − | |
| 79 | | − | if (base != NULL) { |
| 80 | | − | arl->filename[++base - filepath] = '\0'; |
| 81 | | − | add_watch(arl->fd, &arl->wd_dir, arl->filename, IN_CREATE | IN_MOVED_TO); |
| 82 | | − | strcpy(arl->filename, base); /* NOLINT: basename will always be shorter than fullpath */ |
| 83 | | − | } |
| 84 | + | base = strrchr(filepath, '/'); |
| 85 | + | assert(base != NULL); /* filepath must be result of `realpath(3)` */ |
| 86 | + | dir = arl_scratch_push(filepath, base - filepath); |
| 87 | + | add_watch(arl->fd, &arl->wd_dir, dir, IN_CREATE | IN_MOVED_TO); |
| 88 | + | arl->filename = arl_scratch_push(base + 1, strlen(base + 1)); |
| 84 | 89 | | } |
| 85 | 90 | | |
| 86 | 91 | | bool arl_handle(arl_t *arl) |
| @@ -88,6 +93,8 @@ bool arl_handle(arl_t *arl) |
| 88 | 93 | | bool reload = false; |
| 89 | 94 | | char *ptr; |
| 90 | 95 | | const struct inotify_event *e; |
| 96 | + | /* inotify_event aligned buffer */ |
| 97 | + | static union { char d[4096]; struct inotify_event e; } buf; |
| 91 | 98 | | |
| 92 | 99 | | while (true) { |
| 93 | 100 | | ssize_t len = read(arl->fd, buf.d, sizeof(buf.d)); |
| @@ -124,7 +131,7 @@ void arl_cleanup(arl_t *arl) |
| 124 | 131 | | (void) arl; |
| 125 | 132 | | } |
| 126 | 133 | | |
| 127 | | − | void arl_setup(arl_t *arl, const char *filepath) |
| 134 | + | void arl_add(arl_t *arl, const char *filepath) |
| 128 | 135 | | { |
| 129 | 136 | | (void) arl; |
| 130 | 137 | | (void) filepath; |