2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "helper-inotify.h"
20 #include "stc-manager-util.h"
30 static GHashTable *g_inotify_hash;
32 static gboolean __inotify_data(GIOChannel *channel, GIOCondition cond,
35 stc_inotify_s *inotify = user_data;
36 char buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
41 if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
46 status = g_io_channel_read_chars(channel, buffer,
47 sizeof(buffer), &bytes_read, NULL);
50 case G_IO_STATUS_NORMAL:
52 case G_IO_STATUS_AGAIN:
55 STC_LOGE("Reading from inotify channel failed");
62 while (bytes_read > 0) {
63 struct inotify_event *event;
66 inotify_event_cb callback = inotify->cb;
68 event = (struct inotify_event *) next_event;
70 ident = next_event + sizeof(struct inotify_event);
74 len = sizeof(struct inotify_event) + event->len;
81 (*callback)(event, ident);
87 static void __remove_watch(stc_inotify_s *inotify)
91 if (!inotify->channel)
94 if (inotify->watch > 0)
95 g_source_remove(inotify->watch);
97 fd = g_io_channel_unix_get_fd(inotify->channel);
100 inotify_rm_watch(fd, inotify->wd);
102 g_io_channel_unref(inotify->channel);
105 static int __create_watch(const char *path, stc_inotify_s *inotify)
109 STC_LOGD("Add directory watch for [%s]", path);
115 inotify->wd = inotify_add_watch(fd, path,
116 IN_MODIFY | IN_CREATE | IN_DELETE |
117 IN_MOVED_TO | IN_MOVED_FROM);
118 if (inotify->wd < 0) {
119 STC_LOGE("Creation of [%s] watch failed", path);
124 inotify->channel = g_io_channel_unix_new(fd);
125 if (!inotify->channel) {
126 STC_LOGE("Creation of inotify channel failed");
127 inotify_rm_watch(fd, inotify->wd);
134 g_io_channel_set_close_on_unref(inotify->channel, TRUE);
135 g_io_channel_set_encoding(inotify->channel, NULL, NULL);
136 g_io_channel_set_buffered(inotify->channel, FALSE);
138 inotify->watch = g_io_add_watch(inotify->channel,
139 G_IO_IN | G_IO_HUP | G_IO_NVAL | G_IO_ERR,
140 __inotify_data, inotify);
145 static void __inotify_destroy(gpointer user_data)
147 stc_inotify_s *inotify = user_data;
149 __remove_watch(inotify);
153 int inotify_register(const char *path, inotify_event_cb callback)
156 stc_inotify_s *inotify;
161 inotify = g_hash_table_lookup(g_inotify_hash, path);
165 inotify = g_try_new0(stc_inotify_s, 1);
171 err = __create_watch(path, inotify);
177 g_hash_table_replace(g_inotify_hash, g_strdup(path), inotify);
180 inotify->cb = callback;
185 void inotify_deregister(const char *path)
187 stc_inotify_s *inotify;
189 inotify = g_hash_table_lookup(g_inotify_hash, path);
193 g_hash_table_remove(g_inotify_hash, path);
196 int inotify_initialize(void)
198 g_inotify_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
199 g_free, __inotify_destroy);
203 void inotify_deinitialize(void)
205 g_hash_table_destroy(g_inotify_hash);