static void config_notify_handler(struct inotify_event *event, const char *ident, gpointer user_data) { char *ext; if (!ident) return; if (!g_str_has_suffix(ident, ".config")) return; ext = g_strrstr(ident, ".config"); if (!ext) return; *ext = '\0'; if (!validate_ident(ident)) { connman_error("Invalid config ident %s", ident); return; } if (event->mask & IN_CREATE) return; if (event->mask & (IN_DELETE | IN_MOVED_FROM)) { g_hash_table_remove(config_table, ident); return; } if (event->mask & (IN_MODIFY | IN_MOVED_TO)) { struct vpn_config *config; char *path = get_dir(); config = g_hash_table_lookup(config_table, ident); if (config) { g_hash_table_remove_all(config->provider_table); load_config(config, path, REMOVE); /* Re-scan the config file for any changes */ g_hash_table_remove_all(config->provider_table); load_config(config, path, ADD); } else { /* * Inotify will send create event followed by modify * event for any config file that is copied to * monitored directory. So in practice we should just * ignore the create event and trust only the modify * one in order to avoid create/remove/create loop */ config = create_config(ident); if (config) load_config(config, path, ADD); } g_free(path); } }
static int read_configs(void) { GDir *dir; char *path = get_dir(); DBG("path %s", path); dir = g_dir_open(path, 0, NULL); if (dir) { const gchar *file; while ((file = g_dir_read_name(dir))) { GString *str; gchar *ident; if (!g_str_has_suffix(file, ".config")) continue; ident = g_strrstr(file, ".config"); if (!ident) continue; str = g_string_new_len(file, ident - file); if (!str) continue; ident = g_string_free(str, FALSE); if (validate_ident(ident)) { struct vpn_config *config; config = create_config(ident); if (config) load_config(config, path, ADD); } else { connman_error("Invalid config ident %s", ident); } g_free(ident); } g_dir_close(dir); } g_free(path); return 0; }