From: Daniel Wagner <daniel.wag...@bmw-carit.de> --- include/storage.h | 8 +++ src/config.c | 122 +----------------------------------------- src/connman.h | 5 ++ src/main.c | 2 + src/storage.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 172 insertions(+), 120 deletions(-)
diff --git a/include/storage.h b/include/storage.h index 4c23a14..4582390 100644 --- a/include/storage.h +++ b/include/storage.h @@ -28,9 +28,17 @@ extern "C" { #endif +struct inotify_event; + +typedef void (* storage_notify_cb) (struct inotify_event *event, + const char *ident); + gchar **connman_storage_get_services(); GKeyFile *connman_storage_load_service(const char *service_id); +int connman_storage_notify_register(storage_notify_cb callback); +void connman_storage_notify_unregister(storage_notify_cb callback); + #ifdef __cplusplus } #endif diff --git a/src/config.c b/src/config.c index 16fed8d..d70af8f 100644 --- a/src/config.c +++ b/src/config.c @@ -66,10 +66,6 @@ struct connman_config { static GHashTable *config_table = NULL; static GSList *protected_services = NULL; -static int inotify_wd = -1; - -static GIOChannel *inotify_channel = NULL; -static uint inotify_watch = 0; static connman_bool_t cleanup = FALSE; #define INTERNAL_CONFIG_PREFIX "__internal" @@ -613,120 +609,6 @@ static void config_notify_handler(struct inotify_event *event, g_hash_table_remove(config_table, ident); } -static gboolean inotify_data(GIOChannel *channel, GIOCondition cond, - gpointer user_data) -{ - char buffer[256]; - char *next_event; - gsize bytes_read; - GIOStatus status; - - if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) { - inotify_watch = 0; - return FALSE; - } - - status = g_io_channel_read_chars(channel, buffer, - sizeof(buffer) -1, &bytes_read, NULL); - - switch (status) { - case G_IO_STATUS_NORMAL: - break; - case G_IO_STATUS_AGAIN: - return TRUE; - default: - connman_error("Reading from inotify channel failed"); - inotify_watch = 0; - return FALSE; - } - - next_event = buffer; - - while (bytes_read > 0) { - struct inotify_event *event; - gchar *ident; - gsize len; - - event = (struct inotify_event *) next_event; - if (event->len) - ident = next_event + sizeof(struct inotify_event); - else - ident = NULL; - - len = sizeof(struct inotify_event) + event->len; - - /* check if inotify_event block fit */ - if (len > bytes_read) - break; - - next_event += len; - bytes_read -= len; - - config_notify_handler(event, ident); - } - - return TRUE; -} - -static int create_watch(void) -{ - int fd; - - fd = inotify_init(); - if (fd < 0) - return -EIO; - - inotify_wd = inotify_add_watch(fd, STORAGEDIR, - IN_MODIFY | IN_CREATE | IN_DELETE); - if (inotify_wd < 0) { - connman_error("Creation of STORAGEDIR watch failed"); - close(fd); - return -EIO; - } - - inotify_channel = g_io_channel_unix_new(fd); - if (inotify_channel == NULL) { - connman_error("Creation of inotify channel failed"); - inotify_rm_watch(fd, inotify_wd); - inotify_wd = 0; - - close(fd); - return -EIO; - } - - g_io_channel_set_close_on_unref(inotify_channel, TRUE); - g_io_channel_set_encoding(inotify_channel, NULL, NULL); - g_io_channel_set_buffered(inotify_channel, FALSE); - - inotify_watch = g_io_add_watch(inotify_channel, - G_IO_IN | G_IO_HUP | G_IO_NVAL | G_IO_ERR, - inotify_data, NULL); - - return 0; -} - -static void remove_watch(void) -{ - int fd; - - if (inotify_channel == NULL) - return; - - if (inotify_watch > 0) { - g_source_remove(inotify_watch); - inotify_watch = 0; - } - - fd = g_io_channel_unix_get_fd(inotify_channel); - - if (inotify_wd >= 0) { - inotify_rm_watch(fd, inotify_wd); - inotify_wd = 0; - } - - g_io_channel_unref(inotify_channel); -} - int __connman_config_init(void) { DBG(""); @@ -734,7 +616,7 @@ int __connman_config_init(void) config_table = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, unregister_config); - create_watch(); + connman_storage_notify_register(config_notify_handler); return read_configs(); } @@ -745,7 +627,7 @@ void __connman_config_cleanup(void) cleanup = TRUE; - remove_watch(); + connman_storage_notify_unregister(config_notify_handler); g_hash_table_destroy(config_table); config_table = NULL; diff --git a/src/connman.h b/src/connman.h index 764422c..7ccea97 100644 --- a/src/connman.h +++ b/src/connman.h @@ -208,6 +208,8 @@ int __connman_resolvfile_append(const char *interface, const char *domain, const int __connman_resolvfile_remove(const char *interface, const char *domain, const char *server); int __connman_resolver_redo_servers(const char *interface); +#include <connman/storage.h> + void __connman_storage_migrate(void); GKeyFile *__connman_storage_open_global(void); GKeyFile *__connman_storage_load_global(void); @@ -223,6 +225,9 @@ void __connman_storage_save_provider(GKeyFile *keyfile, const char *identifier); char **__connman_storage_get_providers(void); gboolean __connman_storage_remove_service(const char *service_id); +int __connman_storage_init(void); +void __connman_storage_cleanup(void); + int __connman_detect_init(void); void __connman_detect_cleanup(void); diff --git a/src/main.c b/src/main.c index d14cee6..225afd5 100644 --- a/src/main.c +++ b/src/main.c @@ -545,6 +545,7 @@ int main(int argc, char *argv[]) config_init(option_config); __connman_storage_migrate(); + __connman_storage_init(); __connman_technology_init(); __connman_notifier_init(); __connman_service_init(); @@ -624,6 +625,7 @@ int main(int argc, char *argv[]) __connman_ipconfig_cleanup(); __connman_notifier_cleanup(); __connman_technology_cleanup(); + __connman_storage_cleanup(); __connman_dbus_cleanup(); diff --git a/src/storage.c b/src/storage.c index 8c06ffe..9c86575 100644 --- a/src/storage.c +++ b/src/storage.c @@ -27,6 +27,7 @@ #include <unistd.h> #include <sys/stat.h> #include <dirent.h> +#include <sys/inotify.h> #include <connman/storage.h> @@ -38,6 +39,13 @@ #define MODE (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | \ S_IXGRP | S_IROTH | S_IXOTH) +static int inotify_wd = -1; + +static GIOChannel *inotify_channel = NULL; +static uint inotify_watch = 0; + +static GSList *notify_list; + static GKeyFile *storage_load(const char *pathname) { GKeyFile *keyfile = NULL; @@ -610,3 +618,150 @@ void __connman_storage_migrate(void) done: g_free(pathname); } + +static gboolean inotify_data(GIOChannel *channel, GIOCondition cond, + gpointer user_data) +{ + char buffer[256]; + char *next_event; + gsize bytes_read; + GIOStatus status; + GSList *list; + + if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) { + inotify_watch = 0; + return FALSE; + } + + status = g_io_channel_read_chars(channel, buffer, + sizeof(buffer) -1, &bytes_read, NULL); + + switch (status) { + case G_IO_STATUS_NORMAL: + break; + case G_IO_STATUS_AGAIN: + return TRUE; + default: + connman_error("Reading from inotify channel failed"); + inotify_watch = 0; + return FALSE; + } + + next_event = buffer; + + while (bytes_read > 0) { + struct inotify_event *event; + gchar *ident; + gsize len; + + event = (struct inotify_event *) next_event; + if (event->len) + ident = next_event + sizeof(struct inotify_event); + else + ident = NULL; + + len = sizeof(struct inotify_event) + event->len; + + /* check if inotify_event block fit */ + if (len > bytes_read) + break; + + next_event += len; + bytes_read -= len; + + + for (list = notify_list; list != NULL; list = list->next) { + storage_notify_cb callback = list->data; + + (*callback)(event, ident); + } + } + + return TRUE; +} + +static int create_watch(void) +{ + int fd; + + fd = inotify_init(); + if (fd < 0) + return -EIO; + + inotify_wd = inotify_add_watch(fd, STORAGEDIR, + IN_MODIFY | IN_CREATE | IN_DELETE); + if (inotify_wd < 0) { + connman_error("Creation of STORAGEDIR watch failed"); + close(fd); + return -EIO; + } + + inotify_channel = g_io_channel_unix_new(fd); + if (inotify_channel == NULL) { + connman_error("Creation of inotify channel failed"); + inotify_rm_watch(fd, inotify_wd); + inotify_wd = 0; + + close(fd); + return -EIO; + } + + g_io_channel_set_close_on_unref(inotify_channel, TRUE); + g_io_channel_set_encoding(inotify_channel, NULL, NULL); + g_io_channel_set_buffered(inotify_channel, FALSE); + + inotify_watch = g_io_add_watch(inotify_channel, + G_IO_IN | G_IO_HUP | G_IO_NVAL | G_IO_ERR, + inotify_data, NULL); + + return 0; +} + +static void remove_watch(void) +{ + int fd; + + if (inotify_channel == NULL) + return; + + if (inotify_watch > 0) { + g_source_remove(inotify_watch); + inotify_watch = 0; + } + + fd = g_io_channel_unix_get_fd(inotify_channel); + + if (inotify_wd >= 0) { + inotify_rm_watch(fd, inotify_wd); + inotify_wd = 0; + } + + g_io_channel_unref(inotify_channel); +} + +int connman_storage_notify_register(storage_notify_cb callback) +{ + notify_list = g_slist_prepend(notify_list, callback); + + return 0; +} + +void connman_storage_notify_unregister(storage_notify_cb callback) +{ + notify_list = g_slist_remove(notify_list, callback); +} + +int __connman_storage_init(void) +{ + create_watch(); + + return 0; +} + +void __connman_storage_cleanup(void) +{ + remove_watch(); + + g_slist_free(notify_list); + notify_list = NULL; +} -- 1.7.11.4 _______________________________________________ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman