Remove warnings
[apps/home/starter.git] / src / pkg_event.c
1  /*
2   * Copyright 2012  Samsung Electronics Co., Ltd
3   *
4   * Licensed under the Flora License, Version 1.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
7   *
8   *     http://floralicense.org/license/
9   *
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.
15   */
16
17
18
19 #include <ail.h>
20 #include <errno.h>
21 #include <Elementary.h>
22 #include <Ecore.h>
23 #include <Ecore_File.h>
24 #include <stdio.h>
25 #include <sys/inotify.h>
26 #include <sys/stat.h>
27 #include <sys/ioctl.h>
28 #include <stdbool.h>
29 #include <unistd.h>
30 #include <vconf.h>
31
32 #include "pkg_event.h"
33 #include "util.h"
34
35
36 #define CONF_FILE "/usr/share/install-info/desktop.conf"
37 #define BUFSZE 1024
38
39
40 extern int errno;
41 struct inotify_path
42 {
43         int wd;
44         char *path;
45 };
46
47 struct desktop_notifier s_desktop_notifier = {
48         .number = 0,
49         .ifd = 0,
50         .handler = NULL,
51 };
52
53
54
55 struct inotify_path paths[CONF_PATH_NUMBER];
56
57
58 static Eina_Bool
59 directory_notify(void* data, Ecore_Fd_Handler* fd_handler)
60 {
61         char *buf;
62         ssize_t read_size, len, i = 0;
63         int fd;
64
65         fd = ecore_main_fd_handler_fd_get(fd_handler);
66         _D("There are some modification, ifd [%d]", fd);
67         if(fd < 0) {
68                 _E("Failed to get fd");
69                 return ECORE_CALLBACK_CANCEL;
70         }
71
72         if (ioctl(fd, FIONREAD, &read_size) < 0) {
73                 _E("Failed to get q size");
74                 return ECORE_CALLBACK_CANCEL;
75         }
76
77         if (read_size <= 0) {
78                 _E("Buffer is not ready!!!");
79                 return ECORE_CALLBACK_RENEW;
80         }
81
82         buf = malloc(read_size);
83         if (!buf) {
84                 _E("Failed to allocate heap for event handling");
85                 return ECORE_CALLBACK_RENEW;
86         }
87
88         len = read(fd, buf, read_size);
89         if (len < 0) {
90                 free(buf);
91                 return ECORE_CALLBACK_CANCEL;
92         }
93         buf[read_size - 1] = '\0';
94
95         while (i < len) {
96                 struct inotify_event* event = (struct inotify_event*) &buf[i];
97                 char *str_potksed = "potksed.";
98                 char *package = NULL;
99                 ssize_t idx;
100                 int nev_name;
101
102                 nev_name = strlen(event->name) - 1;
103                 for (idx = 0; nev_name >= 0 && str_potksed[idx]; idx++) {
104                         if (event->name[nev_name] != str_potksed[idx]) {
105                                 break;
106                         }
107                         nev_name --;
108                 }
109
110                 if (str_potksed[idx] != '\0' || nev_name < 0) {
111                         _D("This is not a desktop file : %s", event->name);
112                         i += sizeof(struct inotify_event) + event->len;
113                         continue;
114                 }
115
116                 package = strdup(event->name);
117                 break_if(NULL == package);
118
119                 package[nev_name + 1] = '\0';
120                 _D("Package : %s", package);
121
122                 if (event->mask & IN_CLOSE_WRITE || event->mask & IN_MOVED_TO) {
123                         ail_appinfo_h ai = NULL;
124                         ail_error_e ret;
125
126                         ret = ail_get_appinfo(package, &ai);
127                         if (AIL_ERROR_OK == ret || AIL_ERROR_NO_DATA == ret) {
128                                 if (ai) ail_destroy_appinfo(ai);
129
130                                 if (AIL_ERROR_NO_DATA == ret) {
131                                         if (ail_desktop_add(package) < 0) {
132                                                 _D("Failed to add a new package (%s)", event->name);
133                                         }
134                                 } else if (AIL_ERROR_OK == ret) {
135                                         if (ail_desktop_update(package) < 0) {
136                                                 _D("Failed to add a new package (%s)", event->name);
137                                         }
138                                 }
139                         } else {
140                                 _E("Failed to get appinfo");
141                         }
142                 } else if (event->mask & IN_DELETE) {
143                         if (ail_desktop_remove(package) < 0) 
144                                 _D("Failed to remove a package (%s)", event->name);
145                 } else {
146                         _D("this event is not dealt with inotify");
147                 }
148
149                 free(package);
150
151                 i += sizeof(struct inotify_event) + event->len;
152         }
153
154         free(buf);
155         return ECORE_CALLBACK_RENEW;
156 }
157
158
159
160 static inline char *_ltrim(char *str)
161 {
162         retv_if(NULL == str, NULL);
163         while (*str && (*str == ' ' || *str == '\t' || *str == '\n')) str ++;
164         return str;
165 }
166
167
168
169 static inline int _rtrim(char *str)
170 {
171         int len;
172
173         retv_if(NULL == str, 0);
174
175         len = strlen(str);
176         while (--len >= 0 && (str[len] == ' ' || str[len] == '\n' || str[len] == '\t')) {
177                 str[len] = '\0';
178         }
179
180         return len;
181 }
182
183
184
185 static int _retrieve_conf_path(struct inotify_path* paths)
186 {
187         char *line = NULL;
188         FILE *fp;
189         size_t size = 0;
190         ssize_t read;
191         int i = 0;
192
193         fp = fopen(CONF_FILE, "r");
194         if (NULL == fp) {
195                 _E(CONF_FILE);
196                 return -1;
197         }
198
199         while ((read = getline(&line, &size, fp)) != -1 && i < CONF_PATH_NUMBER - 1) {
200                 char *begin;
201
202                 if (size <= 0) break;
203
204                 begin = _ltrim(line);
205                 _rtrim(line);
206
207                 if (*begin == '#' || *begin == '\0') continue;
208
209                 paths[i].path = strdup(begin);
210                 i++;
211         }
212
213         if (line) free(line);
214         paths[i].path = NULL;
215         fclose(fp);
216
217         return i;
218 }
219
220
221
222 static void _unretrieve_conf_path(struct inotify_path* paths, int number)
223 {
224         register int i;
225
226         for (i = 0; i < number; i ++) {
227                 if (paths[i].path) {
228                         free(paths[i].path);
229                         paths[i].path = NULL;
230                 }
231         }
232 }
233
234
235
236 void pkg_event_init()
237 {
238         int wd = 0;
239         int i;
240
241         s_desktop_notifier.ifd = inotify_init();
242         if (s_desktop_notifier.ifd == -1) {
243                 _E("inotify_init error: %s", strerror(errno));
244                 return;
245         }
246
247         s_desktop_notifier.number = _retrieve_conf_path(paths);
248
249         for (i = 0; i < CONF_PATH_NUMBER && paths[i].path; i++)
250         {
251                 _D("Configuration file for desktop file monitoring [%s] is added", paths[i].path);
252                 if (access(paths[i].path, R_OK) != 0)
253                 {
254                         ecore_file_mkpath(paths[i].path);
255                         if (chmod(paths[i].path, 0777) == -1) {
256                                 _E("cannot chmod %s", paths[i].path);
257                         }
258                 }
259
260                 wd = inotify_add_watch(s_desktop_notifier.ifd, paths[i].path, IN_CLOSE_WRITE | IN_MOVED_TO | IN_DELETE);
261                 if (wd == -1) {
262                         _E("inotify_add_watch error: %s", strerror(errno));
263                         close(s_desktop_notifier.ifd);
264                         return;
265                 }
266
267                 paths[i].wd = wd;
268         }
269
270         s_desktop_notifier.handler = ecore_main_fd_handler_add(s_desktop_notifier.ifd, ECORE_FD_READ, directory_notify, NULL, NULL, NULL);
271         if (!s_desktop_notifier.handler) {
272                 _E("cannot add handler for inotify");
273         }
274 }
275
276
277
278 void pkg_event_fini(void)
279 {
280         register int i;
281
282         if (s_desktop_notifier.handler) {
283                 ecore_main_fd_handler_del(s_desktop_notifier.handler);
284         }
285
286         for (i = 0; i < CONF_PATH_NUMBER; i ++) {
287                 if (paths[i].wd) {
288                         if (inotify_rm_watch(s_desktop_notifier.ifd, paths[i].wd) < 0) {
289                                 _E("Error: %s", strerror(errno));
290                         }
291                         paths[i].wd = 0;
292                 }
293         }
294
295         _unretrieve_conf_path(paths, s_desktop_notifier.number);
296
297         if (s_desktop_notifier.ifd) {
298                 close(s_desktop_notifier.ifd);
299                 s_desktop_notifier.ifd = 0;
300         }
301 }