diff options
Diffstat (limited to 'src/pkg_event.c')
-rw-r--r-- | src/pkg_event.c | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/src/pkg_event.c b/src/pkg_event.c new file mode 100644 index 0000000..2eda1ee --- /dev/null +++ b/src/pkg_event.c @@ -0,0 +1,313 @@ +/* + * starter + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Seungtaek Chung <seungtaek.chung@samsung.com>, Mi-Ju Lee <miju52.lee@samsung.com>, Xi Zhichan <zhichan.xi@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <ail.h> +#include <errno.h> +#include <Elementary.h> +#include <Ecore.h> +#include <Ecore_File.h> +#include <stdio.h> +#include <sys/inotify.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <stdbool.h> +#include <unistd.h> +#include <vconf.h> + +#include "pkg_event.h" +#include "util.h" + + +#define CONF_FILE "/usr/share/install-info/desktop.conf" +#define BUFSZE 1024 + + +extern int errno; +struct inotify_path +{ + int wd; + char *path; +}; + +struct desktop_notifier s_desktop_notifier = { + .number = 0, + .ifd = 0, + .handler = NULL, +}; + + + +struct inotify_path paths[CONF_PATH_NUMBER]; + + +static Eina_Bool +directory_notify(void* data, Ecore_Fd_Handler* fd_handler) +{ + char *buf; + ssize_t read_size, len, i = 0; + int fd; + + fd = ecore_main_fd_handler_fd_get(fd_handler); + _D("There are some modification, ifd [%d]", fd); + if(fd < 0) { + _E("Failed to get fd"); + return ECORE_CALLBACK_CANCEL; + } + + if (ioctl(fd, FIONREAD, &read_size) < 0) { + _E("Failed to get q size"); + return ECORE_CALLBACK_CANCEL; + } + + if (read_size <= 0) { + _E("Buffer is not ready!!!"); + return ECORE_CALLBACK_RENEW; + } + + buf = malloc(read_size); + if (!buf) { + _E("Failed to allocate heap for event handling"); + return ECORE_CALLBACK_RENEW; + } + + memset(buf, 0, read_size); + + len = read(fd, buf, read_size); + if (len < 0) { + free(buf); + // Stop monitoring about this invalid file descriptor + return ECORE_CALLBACK_CANCEL; + } + buf[read_size - 1] = '\0'; + + while (i < len) { + struct inotify_event* event = (struct inotify_event*) &buf[i]; + char *str_potksed = "potksed."; + char *package = NULL; + ssize_t idx; + int nev_name; + + // 1. check the extension of a file + nev_name = strlen(event->name) - 1; + for (idx = 0; nev_name >= 0 && str_potksed[idx]; idx++) { + if (event->name[nev_name] != str_potksed[idx]) { + break; + } + nev_name --; + } + + if (str_potksed[idx] != '\0' || nev_name < 0) { + _SECURE_D("This is not a desktop file : %s", event->name); + i += sizeof(struct inotify_event) + event->len; + continue; + } + + package = strdup(event->name); + break_if(NULL == package); + + package[nev_name + 1] = '\0'; + _SECURE_D("Package : %s", package); + + // add & update + if (event->mask & IN_CLOSE_WRITE || event->mask & IN_MOVED_TO) { // for moving + ail_appinfo_h ai = NULL; + ail_error_e ret; + + ret = ail_get_appinfo(package, &ai); + if (AIL_ERROR_OK == ret || AIL_ERROR_NO_DATA == ret) { + if (ai) ail_destroy_appinfo(ai); + + if (AIL_ERROR_NO_DATA == ret) { + if (ail_desktop_add(package) < 0) { + _SECURE_D("Failed to add a new package (%s)", event->name); + } + } else if (AIL_ERROR_OK == ret) { + if (ail_desktop_update(package) < 0) { + _SECURE_D("Failed to add a new package (%s)", event->name); + } + } + } else { + _E("Failed to get appinfo"); + } + } else if (event->mask & IN_DELETE) { // for deleting + if (ail_desktop_remove(package) < 0) + _SECURE_D("Failed to remove a package (%s)", event->name); + } else { + _D("this event is not dealt with inotify"); + } + + free(package); + + i += sizeof(struct inotify_event) + event->len; + } + + free(buf); + return ECORE_CALLBACK_RENEW; +} + + + +static inline char *_ltrim(char *str) +{ + retv_if(NULL == str, NULL); + while (*str && (*str == ' ' || *str == '\t' || *str == '\n')) str ++; + return str; +} + + + +static inline int _rtrim(char *str) +{ + int len; + + retv_if(NULL == str, 0); + + len = strlen(str); + while (--len >= 0 && (str[len] == ' ' || str[len] == '\n' || str[len] == '\t')) { + str[len] = '\0'; + } + + return len; +} + + + +static int _retrieve_conf_path(struct inotify_path* paths) +{ + char *line = NULL; + FILE *fp; + size_t size = 0; + ssize_t read; + int i = 0; + + fp = fopen(CONF_FILE, "r"); + if (NULL == fp) { + _E(CONF_FILE); + return -1; + } + + while ((read = getline(&line, &size, fp)) != -1 && i < CONF_PATH_NUMBER - 1) { + char *begin; + + if (size <= 0) break; + + begin = _ltrim(line); + _rtrim(line); + + if (*begin == '#' || *begin == '\0') continue; + + paths[i].path = strdup(begin); + i++; + } + + if (line) free(line); + paths[i].path = NULL; + fclose(fp); + + return i; +} + + + +static void _unretrieve_conf_path(struct inotify_path* paths, int number) +{ + register int i; + + for (i = 0; i < number; i ++) { + if (paths[i].path) { + free(paths[i].path); + paths[i].path = NULL; + } + } +} + + + +void pkg_event_init() +{ + int wd = 0; + int i; + + s_desktop_notifier.ifd = inotify_init(); + if (s_desktop_notifier.ifd == -1) { + _E("inotify_init error: %s", strerror(errno)); + return; + } + + s_desktop_notifier.number = _retrieve_conf_path(paths); + + for (i = 0; i < CONF_PATH_NUMBER && paths[i].path; i++) + { + _D("Configuration file for desktop file monitoring [%s] is added", paths[i].path); + if (access(paths[i].path, R_OK) != 0) + { + ecore_file_mkpath(paths[i].path); + if (chmod(paths[i].path, 0777) == -1) { + _E("cannot chmod %s", paths[i].path); + } + } + + wd = inotify_add_watch(s_desktop_notifier.ifd, paths[i].path, IN_CLOSE_WRITE | IN_MOVED_TO | IN_DELETE); + if (wd == -1) { + _E("inotify_add_watch error: %s", strerror(errno)); + close(s_desktop_notifier.ifd); + return; + } + + paths[i].wd = wd; + } + + s_desktop_notifier.handler = ecore_main_fd_handler_add(s_desktop_notifier.ifd, ECORE_FD_READ, directory_notify, NULL, NULL, NULL); + if (!s_desktop_notifier.handler) { + // TODO: Handles me.. EXCEPTION!! + _E("cannot add handler for inotify"); + } +} + + + +void pkg_event_fini(void) +{ + register int i; + + if (s_desktop_notifier.handler) { + ecore_main_fd_handler_del(s_desktop_notifier.handler); + } + + for (i = 0; i < CONF_PATH_NUMBER; i ++) { + if (paths[i].wd) { + if (inotify_rm_watch(s_desktop_notifier.ifd, paths[i].wd) < 0) { + _E("Error: %s", strerror(errno)); + } + paths[i].wd = 0; + } + } + + _unretrieve_conf_path(paths, s_desktop_notifier.number); + + if (s_desktop_notifier.ifd) { + close(s_desktop_notifier.ifd); + s_desktop_notifier.ifd = 0; + } +} + + +// End of a file |