2 * Copyright © 2015-2017 Samsung Electronics co., Ltd. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
26 #include <sys/types.h>
36 #include <linux/input.h>
37 #include <sys/inotify.h>
39 #include <pepper-inotify-internal.h>
42 _inotify_event_post(pepper_inotify_watch_t *watch, pepper_inotify_event_type_t type, const char *name, pepper_bool_t is_dir)
44 pepper_inotify_event_t ev;
46 PEPPER_CHECK(watch->inotify->callback.cb, return, "Current inotify has no callback");
48 ev.inotify = watch->inotify;
50 ev.name = (char *)name;
52 ev.path = watch->path;
54 watch->inotify->callback.cb(type, &ev, watch->inotify->callback.data);
58 _inotify_event_process(struct inotify_event *ev, pepper_inotify_watch_t *watch)
62 if (ev->mask & IN_CREATE) {
63 _inotify_event_post(watch, PEPPER_INOTIFY_EVENT_TYPE_CREATE,
64 ev->name, (ev->mask & IN_ISDIR) ? PEPPER_TRUE : PEPPER_FALSE);
66 else if (ev->mask & IN_DELETE) {
67 _inotify_event_post(watch, PEPPER_INOTIFY_EVENT_TYPE_REMOVE,
68 ev->name, (ev->mask & IN_ISDIR) ? PEPPER_TRUE : PEPPER_FALSE);
70 else if (ev->mask & IN_MODIFY) {
71 _inotify_event_post(watch, PEPPER_INOTIFY_EVENT_TYPE_MODIFY,
72 ev->name, (ev->mask & IN_ISDIR) ? PEPPER_TRUE : PEPPER_FALSE);
77 _inotify_fd_read(int fd, uint32_t mask, void *data)
81 struct inotify_event ev[32];
82 pepper_inotify_watch_t *watch_data = data;
84 PEPPER_CHECK(!(mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)),
86 "[%s] With the given fd, there is an error or it's been hung-up.\n",
89 if (!(mask & WL_EVENT_READABLE))
92 nread = read(fd, &ev, sizeof(ev));
93 PEPPER_CHECK(nread >= 0, return 0,
94 "Failed on reading given fd. (error msg : %m, fd:%d)\n", fd);
96 for (i = 0 ; i < (nread / sizeof(ev[0])); i++) {
97 if (ev[i].wd == watch_data->wd)
98 _inotify_event_process(&ev[i], watch_data);
105 pepper_inotify_event_name_get(pepper_inotify_event_t *ev)
107 PEPPER_CHECK(ev, return NULL,
108 "Invalid inotify event\n");
114 pepper_inotify_event_path_get(pepper_inotify_event_t *ev)
116 PEPPER_CHECK(ev, return NULL,
117 "Invalid inotify event\n");
122 PEPPER_API pepper_bool_t
123 pepper_inotify_event_is_directory(pepper_inotify_event_t *ev)
125 PEPPER_CHECK(ev, return PEPPER_FALSE,
126 "Invalid inotify event\n");
131 PEPPER_API pepper_bool_t
132 pepper_inotify_add(pepper_inotify_t *inotify, const char *path)
134 pepper_inotify_watch_t *watch_data;
136 PEPPER_CHECK(inotify, return PEPPER_FALSE, "Invalid pepper_inotify_t object\n");
137 PEPPER_CHECK(path, return PEPPER_FALSE, "Invalid path\n");
139 watch_data = (pepper_inotify_watch_t *)calloc(1, sizeof(pepper_inotify_watch_t));
140 PEPPER_CHECK(watch_data, return PEPPER_FALSE,
141 "Failed to allocate pepper_inotify_watch_t\n");
143 watch_data->inotify = inotify;
145 watch_data->wd = inotify_add_watch(inotify->fd, path,
146 IN_MODIFY | IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO | IN_MOVE_SELF);
147 PEPPER_CHECK(watch_data->wd >= 0, goto failed,
148 "Failed to add watch for %s (error msg:%m)\n", path);
150 strncpy(watch_data->path, path, MAX_PATH_LEN - 1);
152 watch_data->event_source = wl_event_loop_add_fd(inotify->event_loop, inotify->fd,
153 WL_EVENT_READABLE, _inotify_fd_read, watch_data);
154 PEPPER_CHECK(watch_data->event_source, goto failed,
155 "Failed to add fd as an event source.\n");
157 pepper_list_insert(&inotify->watched_list, &watch_data->link);
162 if (watch_data->event_source)
163 wl_event_source_remove(watch_data->event_source);
165 inotify_rm_watch(inotify->fd, watch_data->wd);
172 pepper_inotify_del(pepper_inotify_t *inotify, const char *path)
174 pepper_inotify_watch_t *watch_data, *watch_data_tmp;
176 PEPPER_CHECK(inotify, return, "Invalid pepper_inotify_t object\n");
177 PEPPER_CHECK(path, return, "Invalid path\n");
179 if (!pepper_list_empty(&inotify->watched_list))
181 pepper_list_for_each_safe(watch_data, watch_data_tmp, &inotify->watched_list, link)
183 if (!strncmp(watch_data->path, path, MAX_PATH_LEN - 1))
186 inotify_rm_watch(inotify->fd, watch_data->wd);
187 if (watch_data->event_source)
188 wl_event_source_remove(watch_data->event_source);
189 pepper_list_remove(&watch_data->link);
197 PEPPER_API pepper_inotify_t *
198 pepper_inotify_create(pepper_compositor_t *compositor, pepper_inotify_event_cb_t cb, void *data)
200 pepper_inotify_t *inotify;
202 PEPPER_CHECK(compositor, return NULL, "Invalid compositor object\n");
204 inotify = (pepper_inotify_t *)calloc(1, sizeof(pepper_inotify_t));
205 PEPPER_CHECK(inotify, return NULL, "Failed to allocate pepper_inotify_t\n");
207 inotify->display = pepper_compositor_get_display(compositor);
208 PEPPER_CHECK(inotify->display, goto failed, "Invaild wl_display\n");
210 inotify->event_loop = wl_display_get_event_loop(inotify->display);
211 PEPPER_CHECK(inotify->event_loop, goto failed, "Invaild wl_event_loop\n");
213 inotify->fd = inotify_init();
214 PEPPER_CHECK(inotify->fd >= 0, goto failed, "Failed to init inotify. fd: %d\n", inotify->fd);
216 inotify->callback.cb = cb;
217 inotify->callback.data = data;
219 pepper_list_init(&inotify->watched_list);
233 pepper_inotify_destroy(pepper_inotify_t *inotify)
235 pepper_inotify_watch_t *watch_data, *watch_data_tmp;
237 PEPPER_CHECK(inotify, return, "Invalid pepper_inotify_t object\n");
239 if (!pepper_list_empty(&inotify->watched_list))
241 pepper_list_for_each_safe(watch_data, watch_data_tmp, &inotify->watched_list, link)
244 inotify_rm_watch(inotify->fd, watch_data->wd);
245 if (watch_data->event_source)
246 wl_event_source_remove(watch_data->event_source);
248 pepper_list_remove(&watch_data->link);
252 pepper_list_remove(&inotify->watched_list);