biome: 1.9.2 -> 1.9.3
[NixPkgs.git] / pkgs / by-name / fs / fsnotifier / fsnotifier.patch
blob3fd591635ac48a7c179be06ab8a1577235144416
1 diff --git a/fsnotifier.h b/fsnotifier.h
2 index e7b2a42456bc..9dfb61d8d5d0 100644
3 --- a/fsnotifier.h
4 +++ b/fsnotifier.h
5 @@ -61,7 +61,7 @@ bool init_inotify(void);
6 void set_inotify_callback(void (*callback)(const char *, uint32_t));
7 int get_inotify_fd(void);
8 int watch(const char* root, array* mounts);
9 -void unwatch(int id);
10 +void unwatch(int id, char* path, unsigned int path_len);
11 bool process_inotify_input(void);
12 void close_inotify(void);
14 diff --git a/inotify.c b/inotify.c
15 index a42846379476..0a33eded78bf 100644
16 --- a/inotify.c
17 +++ b/inotify.c
18 @@ -22,6 +22,8 @@ typedef struct watch_node_str {
19 struct watch_node_str* parent;
20 array* kids;
21 unsigned int path_len;
22 + struct watch_node_str* prev;
23 + struct watch_node_str* next;
24 char path[];
25 } watch_node;
27 @@ -102,7 +104,7 @@ int get_inotify_fd(void) {
29 #define EVENT_MASK (IN_MODIFY | IN_ATTRIB | IN_CREATE | IN_DELETE | IN_MOVE | IN_DELETE_SELF | IN_MOVE_SELF)
31 -static int add_watch(unsigned int path_len, watch_node* parent) {
32 +static int add_watch(unsigned int path_len, watch_node* parent, watch_node** out) {
33 int wd = inotify_add_watch(inotify_fd, path_buf, EVENT_MASK);
34 if (wd < 0) {
35 if (errno == EACCES || errno == ENOENT) {
36 @@ -123,36 +125,39 @@ static int add_watch(unsigned int path_len, watch_node* parent) {
37 userlog(LOG_INFO, "watching %s: %d", path_buf, wd);
40 - watch_node* node = table_get(watches, wd);
41 - if (node != NULL) {
42 - if (node->wd != wd) {
43 - userlog(LOG_ERR, "table error: corruption at %d:%s / %d:%s / %d", wd, path_buf, node->wd, node->path, watch_count);
44 - return ERR_ABORT;
45 - }
46 - else if (strcmp(node->path, path_buf) != 0) {
47 - char buf1[PATH_MAX], buf2[PATH_MAX];
48 - const char* normalized1 = realpath(node->path, buf1);
49 - const char* normalized2 = realpath(path_buf, buf2);
50 - if (normalized1 == NULL || normalized2 == NULL || strcmp(normalized1, normalized2) != 0) {
51 - userlog(LOG_ERR, "table error: collision at %d (new %s, existing %s)", wd, path_buf, node->path);
52 - return ERR_ABORT;
53 - }
54 - else {
55 - userlog(LOG_INFO, "intersection at %d: (new %s, existing %s, real %s)", wd, path_buf, node->path, normalized1);
56 - return ERR_IGNORE;
57 - }
58 - }
60 - return wd;
61 - }
63 - node = malloc(sizeof(watch_node) + path_len + 1);
64 + watch_node* existing = table_get(watches, wd);
65 + if (existing != NULL) {
66 + for (;;) {
67 + if (existing->wd != wd) {
68 + userlog(LOG_ERR, "table error: corruption at %d:%s / %d:%s / %d", wd, path_buf, existing->wd, existing->path, watch_count);
69 + return ERR_ABORT;
70 + }
71 + if (existing->path_len == path_len && strncmp(existing->path, path_buf, path_len) == 0) {
72 + return wd;
73 + }
74 + char buf1[PATH_MAX], buf2[PATH_MAX];
75 + const char* normalized1 = realpath(existing->path, buf1);
76 + const char* normalized2 = realpath(path_buf, buf2);
77 + if (normalized1 != NULL && normalized2 != NULL && strcmp(normalized1, normalized2) == 0) {
78 + userlog(LOG_INFO, "intersection at %d: (new %s, existing %s, real %s)", wd, path_buf, existing->path, normalized1);
79 + return ERR_IGNORE;
80 + }
81 + if (existing->next == NULL) {
82 + break;
83 + }
84 + existing = existing->next;
85 + }
86 + }
88 + watch_node* node = malloc(sizeof(watch_node) + path_len + 1);
89 CHECK_NULL(node, ERR_ABORT)
90 memcpy(node->path, path_buf, path_len + 1);
91 node->path_len = path_len;
92 node->wd = wd;
93 node->parent = parent;
94 node->kids = NULL;
95 + node->prev = existing;
96 + node->next = NULL;
98 if (parent != NULL) {
99 if (parent->kids == NULL) {
100 @@ -162,11 +167,15 @@ static int add_watch(unsigned int path_len, watch_node* parent) {
101 CHECK_NULL(array_push(parent->kids, node), ERR_ABORT)
104 - if (table_put(watches, wd, node) == NULL) {
105 + if (existing != NULL) {
106 + existing->next = node;
108 + else if (table_put(watches, wd, node) == NULL) {
109 userlog(LOG_ERR, "table error: unable to put (%d:%s)", wd, path_buf);
110 return ERR_ABORT;
113 + *out = node;
114 return wd;
117 @@ -177,22 +186,27 @@ static void watch_limit_reached(void) {
121 -static void rm_watch(int wd, bool update_parent) {
122 - watch_node* node = table_get(watches, wd);
123 - if (node == NULL) {
124 - return;
125 +static void rm_watch(watch_node* node, bool update_parent) {
126 + if (node->prev != NULL) {
127 + node->prev->next = node->next;
128 + node->next->prev = node->prev;
131 - userlog(LOG_INFO, "unwatching %s: %d (%p)", node->path, node->wd, node);
133 - if (inotify_rm_watch(inotify_fd, node->wd) < 0) {
134 - userlog(LOG_INFO, "inotify_rm_watch(%d:%s): %s", node->wd, node->path, strerror(errno));
135 + else if (node->next != NULL) {
136 + table_put(watches, node->wd, node->next);
137 + node->next->prev = NULL;
139 + else {
140 + userlog(LOG_INFO, "unwatching %s: %d (%p)", node->path, node->wd, node);
141 + if (inotify_rm_watch(inotify_fd, node->wd) < 0) {
142 + userlog(LOG_INFO, "inotify_rm_watch(%d:%s): %s", node->wd, node->path, strerror(errno));
144 + table_put(watches, node->wd, NULL);
147 for (int i = 0; i < array_size(node->kids); i++) {
148 watch_node* kid = array_get(node->kids, i);
149 if (kid != NULL) {
150 - rm_watch(kid->wd, false);
151 + rm_watch(kid, false);
155 @@ -207,7 +221,6 @@ static void rm_watch(int wd, bool update_parent) {
157 array_delete(node->kids);
158 free(node);
159 - table_put(watches, wd, NULL);
163 @@ -234,7 +247,9 @@ static int walk_tree(unsigned int path_len, watch_node* parent, bool recursive,
167 - int id = add_watch(path_len, parent);
169 + watch_node* node;
170 + int id = add_watch(path_len, parent, &node);
172 if (dir == NULL) {
173 return id;
174 @@ -271,7 +286,7 @@ static int walk_tree(unsigned int path_len, watch_node* parent, bool recursive,
176 int subdir_id = walk_tree(path_len + 1 + name_len, table_get(watches, id), recursive, mounts);
177 if (subdir_id < 0 && subdir_id != ERR_IGNORE) {
178 - rm_watch(id, true);
179 + rm_watch(node, true);
180 id = subdir_id;
181 break;
183 @@ -323,47 +338,49 @@ int watch(const char* root, array* mounts) {
187 -void unwatch(int id) {
188 - rm_watch(id, true);
189 +void unwatch(int wd, char* path, unsigned int path_len) {
190 + for (watch_node* node = table_get(watches, wd); node != NULL; node = node->next) {
191 + if (node->path_len == path_len && strncmp(node->path, path, path_len) == 0) {
192 + rm_watch(node, true);
193 + return;
199 static bool process_inotify_event(struct inotify_event* event) {
200 - watch_node* node = table_get(watches, event->wd);
201 - if (node == NULL) {
202 - return true;
205 - bool is_dir = (event->mask & IN_ISDIR) == IN_ISDIR;
206 - userlog(LOG_INFO, "inotify: wd=%d mask=%d dir=%d name=%s", event->wd, event->mask & (~IN_ISDIR), is_dir, node->path);
208 - unsigned int path_len = node->path_len;
209 - memcpy(path_buf, node->path, path_len + 1);
210 - if (event->len > 0) {
211 - path_buf[path_len] = '/';
212 - unsigned int name_len = strlen(event->name);
213 - memcpy(path_buf + path_len + 1, event->name, name_len + 1);
214 - path_len += name_len + 1;
216 + for (watch_node* node = table_get(watches, event->wd); node != NULL; node = node->next) {
217 + bool is_dir = (event->mask & IN_ISDIR) == IN_ISDIR;
218 + userlog(LOG_INFO, "inotify: wd=%d mask=%d dir=%d name=%s", event->wd, event->mask & (~IN_ISDIR), is_dir, node->path);
220 + unsigned int path_len = node->path_len;
221 + memcpy(path_buf, node->path, path_len + 1);
222 + if (event->len > 0) {
223 + path_buf[path_len] = '/';
224 + unsigned int name_len = strlen(event->name);
225 + memcpy(path_buf + path_len + 1, event->name, name_len + 1);
226 + path_len += name_len + 1;
229 - if (callback != NULL) {
230 - (*callback)(path_buf, event->mask);
232 + if (callback != NULL) {
233 + (*callback)(path_buf, event->mask);
236 - if (is_dir && event->mask & (IN_CREATE | IN_MOVED_TO)) {
237 - int result = walk_tree(path_len, node, true, NULL);
238 - if (result < 0 && result != ERR_IGNORE && result != ERR_CONTINUE) {
239 - return false;
240 + if (is_dir && event->mask & (IN_CREATE | IN_MOVED_TO)) {
241 + int result = walk_tree(path_len, node, true, NULL);
242 + if (result < 0 && result != ERR_IGNORE && result != ERR_CONTINUE) {
243 + return false;
248 - if (is_dir && event->mask & (IN_DELETE | IN_MOVED_FROM)) {
249 - for (int i = 0; i < array_size(node->kids); i++) {
250 - watch_node* kid = array_get(node->kids, i);
251 - if (kid != NULL && strncmp(path_buf, kid->path, kid->path_len) == 0) {
252 - rm_watch(kid->wd, false);
253 - array_put(node->kids, i, NULL);
254 - break;
255 + if (is_dir && event->mask & (IN_DELETE | IN_MOVED_FROM)) {
256 + for (int i = 0; i < array_size(node->kids); i++) {
257 + watch_node* kid = array_get(node->kids, i);
258 + if (kid != NULL && strncmp(path_buf, kid->path, kid->path_len) == 0) {
259 + rm_watch(kid, false);
260 + array_put(node->kids, i, NULL);
261 + break;
266 diff --git a/main.c b/main.c
267 index b6b2e6fdb5b0..32cc8efe7856 100644
268 --- a/main.c
269 +++ b/main.c
270 @@ -246,7 +246,7 @@ static void unregister_roots(void) {
271 watch_root* root;
272 while ((root = array_pop(roots)) != NULL) {
273 userlog(LOG_INFO, "unregistering root: %s", root->path);
274 - unwatch(root->id);
275 + unwatch(root->id, root->path, strlen(root->path));
276 free(root->path);
277 free(root);
279 @@ -422,7 +422,7 @@ static void check_root_removal(const char* path) {
280 for (int i = 0; i < array_size(roots); i++) {
281 watch_root* root = array_get(roots, i);
282 if (root->id >= 0 && strcmp(path, UNFLATTEN(root->path)) == 0) {
283 - unwatch(root->id);
284 + unwatch(root->id, root->path, strlen(root->path));
285 root->id = -1;
286 userlog(LOG_INFO, "root deleted: %s\n", root->path);
287 report_event("DELETE", path);