diff --git a/debian/control b/debian/control index 181252f..bdcd0a7 100644 --- a/debian/control +++ b/debian/control @@ -186,6 +186,7 @@ Package: libkysdk-conf2-tools Architecture: any Section: utils Depends: libkysdk-conf2 (= ${binary:Version}), + python3-tk, ${misc:Depends}, ${shlibs:Depends} Multi-Arch: same diff --git a/debian/libkysdk-conf2-tools.install b/debian/libkysdk-conf2-tools.install index 575a426..815c788 100644 --- a/debian/libkysdk-conf2-tools.install +++ b/debian/libkysdk-conf2-tools.install @@ -1,3 +1,4 @@ usr/bin/kconf2 usr/bin -usr/bin/kconf2-editor usr/bin -src/conf2/tools/gschema_xml2yaml.py usr/bin \ No newline at end of file +src/conf2/tools/kconf2-editor usr/bin +src/conf2/tools/health-check usr/bin +src/conf2/tools/gschema_xml2yaml usr/bin diff --git a/debian/libkysdk-conf2.install b/debian/libkysdk-conf2.install index 7eb9672..5e97b1d 100644 --- a/debian/libkysdk-conf2.install +++ b/debian/libkysdk-conf2.install @@ -3,10 +3,23 @@ src/conf2/service/conf2Utils.py usr/bin src/conf2/service/conf2-server.py usr/bin src/conf2/service/kysdk-conf2.conf etc/dbus-1/system.d src/conf2/service/kysdk-conf2.service lib/systemd/system +src/conf2/service/conf2-session-server.py usr/bin +src/conf2/service/kysdk-conf2.desktop etc/xdg/autostart/ +src/conf2/configs/conf2.yaml etc/kylin-config/ + +# dbus control src/conf2/service/com.kylin.kysdk.conf2.limit etc/dbus-1/conf src/conf2/service/com.kylin.kysdk.conf2.limit usr/share/dbus-1/conf src/conf2/service/com.kylin.kysdk.conf2.limit.verify etc/dbus-1/conf src/conf2/service/com.kylin.kysdk.conf2.limit.verify usr/share/dbus-1/conf -src/conf2/service/conf2-session-server.py usr/bin -src/conf2/service/kysdk-conf2.desktop etc/xdg/autostart/ -src/conf2/configs/conf2.yaml etc/kylin-config/ + +# sync-config +bin/sync-config-system usr/bin +src/conf2/sync-config/com.kylin.kysdk.SyncConfig.conf etc/dbus-1/system.d +src/conf2/sync-config/com.kylin.kysdk.SyncConfig.service lib/systemd/system +bin/sync-config-session usr/bin +src/conf2/sync-config/com.kylin.kysdk.SyncConfig.desktop etc/xdg/autostart/ + +# update-db +src/conf2/service/conf2-update.py usr/bin +src/conf2/service/conf2-update-db.service lib/systemd/system diff --git a/development-files/kysdk-config.pc b/development-files/kysdk-config.pc index b377d54..73236b7 100644 --- a/development-files/kysdk-config.pc +++ b/development-files/kysdk-config.pc @@ -1,8 +1,8 @@ -base_version=2.4.0 +base_version=2.5.0 Name: libkysdk-config Description: kysdk base layer config component Requires: kysdk-utils Version: 2.5.0 Cflags: -I/usr/include/kysdk/kysdk-base/ -Libs: -lkyconf \ No newline at end of file +Libs: -lkyconf diff --git a/src/conf2/CMakeLists.txt b/src/conf2/CMakeLists.txt index 37403db..dea32cd 100644 --- a/src/conf2/CMakeLists.txt +++ b/src/conf2/CMakeLists.txt @@ -1,16 +1,19 @@ find_package(PkgConfig REQUIRED) -pkg_check_modules(GLIB REQUIRED glib-2.0 gio-2.0 gtk+-3.0) -pkg_check_modules(GTK REQUIRED gtk+-3.0) +pkg_check_modules(GLIB REQUIRED glib-2.0 gio-2.0) +# pkg_check_modules(GTK REQUIRED gtk+-3.0) include_directories(${GLIB_INCLUDE_DIRS} ) +include_directories(api) + add_subdirectory(api) +add_subdirectory(sync-config) add_executable(kconf2 tools/kconf2-tool.c ) target_link_libraries(kconf2 kyconf2) -add_executable(kconf2-editor tools/kconf2-editor.c ) -target_link_libraries(kconf2-editor kyconf2 ${GTK_LIBRARIES}) +# add_executable(kconf2-editor tools/kconf2-editor.c ) +# target_link_libraries(kconf2-editor kyconf2 ${GTK_LIBRARIES}) add_executable(kyconf2-test test/kyconf2-test.c) target_link_libraries(kyconf2-test kyconf2) @@ -18,8 +21,8 @@ target_link_libraries(kyconf2-test kyconf2) install(TARGETS kconf2 DESTINATION /usr/bin) -install(TARGETS kconf2-editor - DESTINATION /usr/bin) +# install(TARGETS kconf2-editor +# DESTINATION /usr/bin) install(TARGETS kyconf2-test DESTINATION /usr/bin) diff --git a/src/conf2/api/ksettingsschema.c b/src/conf2/api/ksettingsschema.c index 659a477..8810d31 100644 --- a/src/conf2/api/ksettingsschema.c +++ b/src/conf2/api/ksettingsschema.c @@ -282,7 +282,9 @@ static KSettingsSchema *_get_schema(const char *id, const char *version) int rc = sqlite3_open(db_file, &db); if (rc != SQLITE_OK) { - if (0 == strcmp(db_file, "/root/.config/kylin-config/user.db")) + if ((0 == strcmp(db_file, "/root/.config/kylin-config/user.db")) || + (0 == strcmp(db_file, "/home/lightdm/.config/kylin-config/user.db")) || + (0 == strcmp(db_file, "/home/messagebus/.config/kylin-config/user.db"))) { syslog(LOG_INFO, "[kysdk-conf2] %s -> :open %s failed! %s try to open /etc/kylin-config/user.db.\n", __func__, db_file, sqlite3_errmsg(db)); rc = sqlite3_open("/etc/kylin-config/user.db", &db); @@ -378,6 +380,30 @@ out: return schema; } +static char *_get_db_file_path(char *buffer, size_t size) +{ + uid_t uid = getuid(); // 获取当前进程的用户ID + char user_name[128] = {0}; + struct passwd *pw = getpwuid(uid); // 获取用户ID对应的用户信息结构体 + if (NULL == pw) + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> :Get user name failed! use root config\n", __func__); + return NULL; + } + else + { + strcpy(user_name, pw->pw_name); + endpwent(); + } + + char db_file[PATH_MAX]; + if (0 == strcmp(user_name, "root")) + snprintf(buffer, size, "/root/.config/kylin-config/user.db"); + else + snprintf(buffer, size, "/home/%s/.config/kylin-config/user.db", user_name); + return buffer; +} + static void _get_schemas() { char ***apps = NULL, ***versions = NULL, ***configures = NULL; @@ -387,7 +413,7 @@ static void _get_schemas() struct passwd *pw = getpwuid(uid); // 获取用户ID对应的用户信息结构体 if (NULL == pw) { - syslog(LOG_INFO, "[kysdk-conf2] %s -> :Get user name failed! use root config\n", __func__); + syslog(LOG_DEBUG, "[kysdk-conf2] %s -> :Get user name failed! use root config\n", __func__); strcpy(user_name, "root"); } else @@ -401,7 +427,7 @@ static void _get_schemas() sprintf(db_file, "/root/.config/kylin-config/user.db"); else sprintf(db_file, "/home/%s/.config/kylin-config/user.db", user_name); - // syslog(LOG_INFO, "[kysdk-conf2] %s -> :open %s \n", __func__, db_file); + // syslog(LOG_DEBUG, "[kysdk-conf2] %s -> :open %s \n", __func__, db_file); // 读取数据库数据 sqlite3 *db = NULL; @@ -411,9 +437,12 @@ static void _get_schemas() int rc = sqlite3_open(db_file, &db); if (rc != SQLITE_OK) { - if (0 == strcmp(db_file, "/root/.config/kylin-config/user.db")) + // 华为云项目中,systemd屏蔽用户目录;lighdm没有用户目录 所以读取etc下的数据 + if ((0 == strcmp(db_file, "/root/.config/kylin-config/user.db")) || + (0 == strcmp(db_file, "/home/lightdm/.config/kylin-config/user.db")) || + (0 == strcmp(db_file, "/home/messagebus/.config/kylin-config/user.db"))) { - syslog(LOG_INFO, "[kysdk-conf2] %s -> :open %s failed! %s try to open /etc/kylin-config/user.db.\n", __func__, db_file, sqlite3_errmsg(db)); + syslog(LOG_INFO, "[kysdk-conf2] %s -> :open %s failed : %s! try to open /etc/kylin-config/user.db.\n", __func__, db_file, sqlite3_errmsg(db)); rc = sqlite3_open("/etc/kylin-config/user.db", &db); if (rc != SQLITE_OK) { @@ -422,9 +451,12 @@ static void _get_schemas() } } else + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> :open %s failed : %s\n", __func__, db_file, sqlite3_errmsg(db)); return; + } } - + char sql[100]; rc = sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &err_msg); if (rc != SQLITE_OK) @@ -468,7 +500,7 @@ static void _get_schemas() } sqlite3_close(db); - if (!apps || !versions || ! configures) + if (!apps || !versions || !configures) return; // 顶层hash, 元素为appData:hash(versionData:hash(s:KSettingsSchema)) @@ -476,7 +508,7 @@ static void _get_schemas() schemas_table = g_hash_table_new_full(data_hash, data_equal, app_data_destroy, (GDestroyNotify)g_hash_table_destroy); if (NULL == schemas_table) { - syslog(LOG_INFO, "[kysdk-conf2] %s -> :Creat hash Table failed\n", __func__); + syslog(LOG_DEBUG, "[kysdk-conf2] %s -> :Creat hash Table failed\n", __func__); goto out; } @@ -496,7 +528,7 @@ static void _get_schemas() { AppData *app_data = NULL; VersionData *version_data = NULL; - syslog(LOG_INFO, "[kysdk-conf2] %s -> Read a new version id %s, old id is %d\n", __func__, configures[i][1], version_id); + syslog(LOG_DEBUG, "[kysdk-conf2] %s -> Read a new version id %s, old id is %d\n", __func__, configures[i][1], version_id); version_id = atoi(configures[i][1]); version_data = calloc(1, sizeof *version_data); @@ -506,7 +538,7 @@ static void _get_schemas() // 版本id对应的应用id改变 if (app_id != atoi(VER_COLUMN[1])) { - syslog(LOG_INFO, "[kysdk-conf2] %s -> Read a new app id %s, old id is %d\n", __func__, VER_COLUMN[1], app_id); + syslog(LOG_DEBUG, "[kysdk-conf2] %s -> Read a new app id %s, old id is %d\n", __func__, VER_COLUMN[1], app_id); app_id = atoi(VER_COLUMN[1]); app_data = calloc(1, sizeof *app_data); @@ -519,7 +551,7 @@ static void _get_schemas() version = g_hash_table_new_full(data_hash, data_equal, version_data_destroy, (GDestroyNotify)g_hash_table_destroy); if (NULL == version) { - syslog(LOG_INFO, "[kysdk-conf2] %s -> :Creat hash2 Table failed\n", __func__); + syslog(LOG_DEBUG, "[kysdk-conf2] %s -> :Creat hash2 Table failed\n", __func__); app_data_destroy(app_data); version_data_destroy(version_data); goto out; @@ -537,19 +569,19 @@ static void _get_schemas() g_hash_table_insert(version, version_data, schemas); if (NULL == schemas) { - syslog(LOG_INFO, "[kysdk-conf2] %s -> :Creat schemas hash Table failed\n", __func__); + syslog(LOG_DEBUG, "[kysdk-conf2] %s -> :Creat schemas hash Table failed\n", __func__); version_data_destroy(version_data); goto out; } } else version_data_destroy(version_data); - syslog(LOG_INFO, "[kysdk-conf2] %s -> Read %s configure wiht version number %s\n", __func__, APP_COLUMN[1], VER_COLUMN[2]); + syslog(LOG_DEBUG, "[kysdk-conf2] %s -> Read %s configure wiht version number %s\n", __func__, APP_COLUMN[1], VER_COLUMN[2]); schema = g_hash_table_lookup(schemas, APP_COLUMN[1]); if (NULL == schema) { - syslog(LOG_INFO, "[kysdk-conf2] %s -> Creat node %s\n", __func__, APP_COLUMN[1]); + syslog(LOG_DEBUG, "[kysdk-conf2] %s -> Creat node %s\n", __func__, APP_COLUMN[1]); schema = calloc(1, sizeof *schema); if (NULL == schema) goto out; @@ -560,7 +592,7 @@ static void _get_schemas() } else { - syslog(LOG_INFO, "[kysdk-conf2] %s -> Clear node %s\n", __func__, APP_COLUMN[1]); + syslog(LOG_DEBUG, "[kysdk-conf2] %s -> Clear node %s\n", __func__, APP_COLUMN[1]); if (schema->values) { g_hash_table_destroy(schema->values); @@ -604,7 +636,7 @@ static void _get_schemas() } sprintf(parent_name, "%s%s", APP_COLUMN[1], tmp); } - syslog(LOG_INFO, "[kysdk-conf2] %s -> %s's parent name %s\n", __func__, node_name, parent_name); + syslog(LOG_DEBUG, "[kysdk-conf2] %s -> %s's parent name %s\n", __func__, node_name, parent_name); // 给父组件增加子组件名 KSettingsSchema *parent_schema = g_hash_table_lookup(schemas, parent_name); @@ -624,7 +656,7 @@ static void _get_schemas() schema = g_hash_table_lookup(schemas, schema_name); if (NULL == schema) { - syslog(LOG_INFO, "[kysdk-conf2] %s -> Creat node %s\n", __func__, schema_name); + syslog(LOG_DEBUG, "[kysdk-conf2] %s -> Creat node %s\n", __func__, schema_name); schema = calloc(1, sizeof *schema); if (NULL == schema) { @@ -646,7 +678,7 @@ static void _get_schemas() } else { - syslog(LOG_INFO, "[kysdk-conf2] %s -> Clear node %s\n", __func__, APP_COLUMN[1]); + syslog(LOG_DEBUG, "[kysdk-conf2] %s -> Clear node %s\n", __func__, APP_COLUMN[1]); if (schema->values) { g_hash_table_destroy(schema->values); @@ -673,7 +705,7 @@ static void _get_schemas() } else if (0 == strcmp(node_type, "key")) { - syslog(LOG_INFO, "[kysdk-conf2] %s -> Read %s configure %s wiht version number %s\n", __func__, schema->id, node_name, schema->version); + syslog(LOG_DEBUG, "[kysdk-conf2] %s -> Read %s configure %s wiht version number %s\n", __func__, schema->id, node_name, schema->version); // hash表 s:hash(s:s) if (NULL == schema->values) schema->values = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_hash_table_destroy); @@ -769,22 +801,24 @@ KSettingsSchema *kdk_conf2_schema_table_lookup(const char *id, const char *versi GHashTableIter iter; g_hash_table_iter_init(&iter, schemas_table); - while (g_hash_table_iter_next(&iter, (gpointer*)(&app_data), (gpointer*)(&version_hash))) + while (g_hash_table_iter_next(&iter, (gpointer*)&app_data, (gpointer*)&version_hash)) { - syslog(LOG_INFO, "[kysdk-conf2] %s -> find %s\n", __func__, app_data->name); + syslog(LOG_DEBUG, "[kysdk-conf2] %s -> find %s\n", __func__, app_data->name); if (0 == strcmp(app_data->name, list[0])) { + syslog(LOG_DEBUG, "[kysdk-conf2] %s -> find app :%s\n", __func__, app_data->name); VersionData *version_data = NULL; GHashTable *schemas = NULL; version = version ? version : app_data->default_version; GHashTableIter iter_version; g_hash_table_iter_init(&iter_version, version_hash); - while (g_hash_table_iter_next(&iter_version, (gpointer*)(&version_data), (gpointer*)(&schemas))) + while (g_hash_table_iter_next(&iter_version, (gpointer*)&version_data, (gpointer*)&schemas)) { - syslog(LOG_INFO, "[kysdk-conf2] %s -> find %s '%s configure\n", __func__, app_data->name, version_data->name); + syslog(LOG_DEBUG, "[kysdk-conf2] %s -> find %s '%s configure\n", __func__, app_data->name, version_data->name); if (0 == strcmp(version_data->name, version)) { + syslog(LOG_DEBUG, "[kysdk-conf2] %s -> find version :%s\n", __func__, version_data->name); result = g_hash_table_lookup(schemas, id); break; } @@ -1055,6 +1089,20 @@ void kdk_conf2_schema_update_schemas_table() _get_schemas(); } +void kdk_conf2_schema_key_set_value(GHashTable *key, char *value) +{ + if (g_hash_table_contains(key, "custom_value")) + g_hash_table_replace(key, "custom_value", strdup(value)); + else + g_hash_table_insert(key, "custom_value", strdup(value)); +} + +void kdk_conf2_schema_key_reset(GHashTable *key) +{ + if (g_hash_table_contains(key, "custom_value")) + g_hash_table_remove(key, "custom_value"); +} + // 重新读取某个schema的配置 KSettingsSchema *kdk_conf2_schema_reload(const char *id, const char *version) { @@ -1066,7 +1114,7 @@ KSettingsSchema *kdk_conf2_schema_reload(const char *id, const char *version) GHashTableIter iter; g_hash_table_iter_init(&iter, schemas_table); - while (g_hash_table_iter_next(&iter, (gpointer*)(&app_data), (gpointer*)(&version_hash))) + while (g_hash_table_iter_next(&iter, (gpointer*)&app_data, (gpointer*)&version_hash)) { if (0 == strcmp(app_data->name, list[0])) { @@ -1075,7 +1123,7 @@ KSettingsSchema *kdk_conf2_schema_reload(const char *id, const char *version) GHashTableIter iter_version; g_hash_table_iter_init(&iter_version, version_hash); - while (g_hash_table_iter_next(&iter_version, (gpointer*)(&version_data), (gpointer*)(&schemas))) + while (g_hash_table_iter_next(&iter_version, (gpointer*)&version_data, (gpointer*)&schemas)) { if (0 == strcmp(version_data->name, version)) { diff --git a/src/conf2/api/ksettingsschema.h b/src/conf2/api/ksettingsschema.h index 7370bcc..43d0709 100644 --- a/src/conf2/api/ksettingsschema.h +++ b/src/conf2/api/ksettingsschema.h @@ -96,6 +96,10 @@ extern "C" void kdk_conf2_schema_update_schemas_table(); + void kdk_conf2_schema_key_set_value(GHashTable *key, char *value); + + void kdk_conf2_schema_key_reset(GHashTable *key); + #if __cplusplus } #endif diff --git a/src/conf2/api/libkysettings.c b/src/conf2/api/libkysettings.c index 753e0f1..c939932 100644 --- a/src/conf2/api/libkysettings.c +++ b/src/conf2/api/libkysettings.c @@ -28,7 +28,6 @@ #include #include #include -#include #include "libkysettings.h" #include "ksettingsschema.h" @@ -46,7 +45,6 @@ typedef struct _KSettingsPrivate GMainContext *main_context; KSettingsSchema *schema; GDBusConnection *conn; - GSettings *gsettings; guint sub_id[2]; } KSettingsPrivate; @@ -107,11 +105,6 @@ static void k_settings_finalize(GObject *object) g_dbus_connection_signal_unsubscribe(ksettings->priv->conn, ksettings->priv->sub_id[SIGNAL_CHANGED]); g_dbus_connection_signal_unsubscribe(ksettings->priv->conn, ksettings->priv->sub_id[SIGNAL_RELOAD]); g_object_unref(ksettings->priv->conn); - if (ksettings->priv->gsettings) - { - g_settings_sync(); - g_object_unref(ksettings->priv->gsettings); - } } G_OBJECT_CLASS(k_settings_parent_class)->finalize(object); @@ -164,20 +157,6 @@ static void *_g_main_loop_thread(void *data) return NULL; } -static void _on_gsettings_key_changed(GSettings *setting, const char *key, void *user_data) -{ - GVariant *value = g_settings_get_value(setting, key); - KSettings *ksetting = (KSettings *)user_data; - char *conf2_value = kdk_conf2_get_value(ksetting, key); - if (0 == strcmp(conf2_value, g_variant_print(value, TRUE))) - return; - if (kdk_conf2_set_value(ksetting, key, g_variant_print(value, TRUE))) - { - // g_signal_emit(ksetting, k_settings_signals[SIGNAL_CHANGED], g_quark_from_string(key), key); - } - g_variant_unref(value); -} - /** * @brief _on_key_changed DBus服务中key_changed信号响应函数 * @param connection @@ -206,34 +185,9 @@ static void _on_key_changed(GDBusConnection *connection, ksettings->priv->schema = kdk_conf2_schema_reload(id, version); g_signal_emit(ksettings, k_settings_signals[SIGNAL_CHANGED], g_quark_from_string(key), key); syslog(LOG_INFO, "[kysdk-conf2] %s changed signal\n", key); - if (ksettings->priv->gsettings) - { - const gchar *endptr = NULL; - GError *error = NULL; - GVariant *gsetting_value = g_settings_get_value(ksettings->priv->gsettings, key); - if (NULL != gsetting_value) - { - char *value = kdk_conf2_get_value(ksettings, key); - if (0 != strcmp(value, g_variant_print(gsetting_value, TRUE))) - { - char *type = kdk_conf2_get_type(ksettings, key); - GVariant *variant = g_variant_parse(G_VARIANT_TYPE(type), value, NULL, &endptr, &error); - if (NULL == variant) - { - klog_err("[kysdk-conf2] %s -> %s\n", __func__, error->message); - return; - } - g_settings_set_value(ksettings->priv->gsettings, key, variant); - g_settings_sync(); - g_variant_unref(variant); - } - g_variant_unref(gsetting_value); - } - } } g_free(schema_id); g_free(schema_version); - mutex = 0; } /** @@ -386,6 +340,124 @@ static int _call_method(const char *method, const char *id, const char *version, return response; } +static int _compare_versions(char *version1, char *version2) +{ + if (version1 != NULL && version2 == NULL) + return 1; + else if (version1 == NULL && version2 != NULL) + return -1; + else if (version1 == NULL && version2 == NULL) + return 0; + + int result = 0; + + char v1[64], v2[64]; + memset(v1, 0, 64); + strcpy(v1, version1); + memset(v2, 0, 64); + strcpy(v2, version2); + + char *save_ptr1 = NULL; + char *save_ptr2 = NULL; + char *token1; + char *token2; + token1 = strtok_r(v1, ".-k", &save_ptr1); + token2 = strtok_r(v2, ".-k", &save_ptr2); + + while (1) + { + if (token1 != NULL && token2 != NULL) + { + int num1 = atoi(token1); + int num2 = atoi(token2); + + if (num1 > num2) + { + result = 1; + break; + } + else if (num1 < num2) + { + result = -1; + break; + } + } + else if (token1 == NULL && token2 != NULL) + { + result = -1; + break; + } + else if (token1 != NULL && token2 == NULL) + { + result = 1; + break; + } + else if (token1 == NULL && token2 == NULL) + break; + + token1 = strtok_r(NULL, ".-k", &save_ptr1); + token2 = strtok_r(NULL, ".-k", &save_ptr2); + } + + return result; +} + +static char *_check_version(const char *id, const char *version) +{ + if (version != NULL) + return version; + + AppData *app_data = NULL; + GHashTable *version_hash = NULL; + char app[64]; + int size = 0; + char *p = id; + while (*p != '.' && *p != '\0') + { + size++; + p++; + } + strncpy(app, id, size); + + GHashTableIter iter; + g_hash_table_iter_init(&iter, schemas_table); + while (g_hash_table_iter_next(&iter, (gpointer*)&app_data, (gpointer*)&version_hash)) + { + if (0 == strcmp(app_data->name, app)) + { + VersionData *version_data = NULL; + GHashTable *schemas = NULL; + // TODO: 读取配置文件获取最大最小版本 + char *min_version = "1.2.0.0-0k0.0"; + char *max_version = "2.5.1.0-0k0.0"; + if ((-1 == _compare_versions(min_version, app_data->default_version)) && + (1 == _compare_versions(max_version, app_data->default_version))) + { + return app_data->default_version; + } + + GHashTableIter iter_version; + g_hash_table_iter_init(&iter_version, version_hash); + char *tmp = NULL; + while (g_hash_table_iter_next(&iter_version, (gpointer*)&version_data, (gpointer*)&schemas)) + { + if (0 == strcmp(version_data->name, app_data->default_version)) + { + continue; + } + if ((-1 == _compare_versions(min_version, version_data->name)) && + (1 == _compare_versions(max_version, version_data->name))) + { + // 返回符合要求的版本中,最高的版本 + tmp = _compare_versions(version_data->name, tmp) > 0 ? version_data->name : tmp; + } + } + return tmp; + } + } + return NULL; +} + KSettings *kdk_conf2_new(const char *id, const char *version) { if (NULL == id) @@ -403,6 +475,14 @@ KSettings *kdk_conf2_new(const char *id, const char *version) return NULL; } + // version = _check_version(id, version); + // if (NULL == version) + // { + // syslog(LOG_INFO, "[kysdk-conf2] There is no version number that meets the requirements\n"); + // return NULL; + // } + // syslog(LOG_INFO, "[kysdk-conf2] Use the %s version of the configuration file\n", version); + KSettingsSchema *schema = kdk_conf2_schema_table_lookup(id, version); if (NULL == schema) { @@ -417,88 +497,87 @@ KSettings *kdk_conf2_new(const char *id, const char *version) return NULL; } - const char * const *gsettings_schemas = g_settings_list_schemas(); - if (gsettings_schemas) - { - for (int i = 0; gsettings_schemas[i]; i++) - { - char *p = strstr(gsettings_schemas[i], id); - if (NULL == p) - continue; - int len = strlen(id); - if (*(p + len) == '\0') - { - ksettings->priv->gsettings = g_settings_new(gsettings_schemas[i]); - g_signal_connect(ksettings->priv->gsettings, "changed", G_CALLBACK(_on_gsettings_key_changed), ksettings); - } - } - } - ksettings->priv->schema = schema; - uid_t uid = getuid(); // 获取当前进程的用户ID - char user_name[128] = {0}; - struct passwd *pw = getpwuid(uid); // 获取用户ID对应的用户信息结构体 - if (NULL == pw) + int is_dbus_daemon = 0; + char process_name[256]; + FILE *fp = fopen("/proc/self/comm", "r"); + if (fp != NULL) { - syslog(LOG_INFO, "[kysdk-conf2] %s -> :Get user name failed! use root config\n", __func__); - strcpy(user_name, "root"); - } - else - { - strcpy(user_name, pw->pw_name); - endpwent(); + fgets(process_name, sizeof(process_name), fp); + fclose(fp); + // 去除末尾换行符 + process_name[strcspn(process_name, "\n")] = 0; + if (0 == strcmp(process_name, "dbus-daemon")) + is_dbus_daemon = 1; } - // 创建dbus服务的链接,用于调用接口及接收信号 - GError *error = NULL; - if (0 == strcmp(user_name, "root")) - ksettings->priv->conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); - else - ksettings->priv->conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error); - if (error != NULL) + if (!is_dbus_daemon) { - syslog(LOG_INFO, "[kysdk-conf2] Connection Error: %s\n", error->message); - g_object_unref(ksettings); - ksettings = NULL; - g_error_free(error); - return NULL; - } + uid_t uid = getuid(); // 获取当前进程的用户ID + char user_name[128] = {0}; + struct passwd *pw = getpwuid(uid); // 获取用户ID对应的用户信息结构体 + if (NULL == pw) + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> :Get user name failed! use root config\n", __func__); + strcpy(user_name, "root"); + } + else + { + strcpy(user_name, pw->pw_name); + endpwent(); + } - // 监听key_changed信号 - ksettings->priv->sub_id[0] = g_dbus_connection_signal_subscribe(ksettings->priv->conn, - "com.kylin.kysdk.conf2", // 消息来源 (NULL 表示任意) - "com.kylin.kysdk.conf2", // 接口名称 - "key_changed", // 信号名称 - "/com/kylin/kysdk/conf2", // 对象路径 (NULL 表示任意) - NULL, - G_DBUS_SIGNAL_FLAGS_NONE, - _on_key_changed, - ksettings, - NULL); - // 监听重载信号 - ksettings->priv->sub_id[1] = g_dbus_connection_signal_subscribe(ksettings->priv->conn, - "com.kylin.kysdk.conf2", // 消息来源 (NULL 表示任意) - "com.kylin.kysdk.conf2", // 接口名称 - "updated", // 信号名称 - "/com/kylin/kysdk/conf2", // 对象路径 (NULL 表示任意) - NULL, - G_DBUS_SIGNAL_FLAGS_NONE, - _on_updated, - ksettings, - NULL); + // 创建dbus服务的链接,用于调用接口及接收信号 + GError *error = NULL; + if (0 == strcmp(user_name, "root")) + ksettings->priv->conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + else + ksettings->priv->conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error); + if (error != NULL) + { + syslog(LOG_INFO, "[kysdk-conf2] Connection Error: %s\n", error->message); + g_object_unref(ksettings); + ksettings = NULL; + g_error_free(error); + return NULL; + } - // 创建glib的事件处理循环,单独起线程。 - // 如果循环已经启动,增加dbus_signal_loop的引用计数 - if (NULL == dbus_signal_loop) - { - dbus_signal_loop = g_main_loop_new(NULL, FALSE); - pthread_t thread; - pthread_create(&thread, NULL, _g_main_loop_thread, NULL); + // 监听key_changed信号 + ksettings->priv->sub_id[0] = g_dbus_connection_signal_subscribe(ksettings->priv->conn, + "com.kylin.kysdk.conf2", // 消息来源 (NULL 表示任意) + "com.kylin.kysdk.conf2", // 接口名称 + "key_changed", // 信号名称 + "/com/kylin/kysdk/conf2", // 对象路径 (NULL 表示任意) + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + _on_key_changed, + ksettings, + NULL); + // 监听重载信号 + ksettings->priv->sub_id[1] = g_dbus_connection_signal_subscribe(ksettings->priv->conn, + "com.kylin.kysdk.conf2", // 消息来源 (NULL 表示任意) + "com.kylin.kysdk.conf2", // 接口名称 + "updated", // 信号名称 + "/com/kylin/kysdk/conf2", // 对象路径 (NULL 表示任意) + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + _on_updated, + ksettings, + NULL); + + // 创建glib的事件处理循环,单独起线程。 + // 如果循环已经启动,增加dbus_signal_loop的引用计数 + if (NULL == dbus_signal_loop) + { + dbus_signal_loop = g_main_loop_new(NULL, FALSE); + pthread_t thread; + pthread_create(&thread, NULL, _g_main_loop_thread, NULL); + } + else + g_main_loop_ref(dbus_signal_loop); + ref_count++; } - else - g_main_loop_ref(dbus_signal_loop); - ref_count++; return ksettings; } @@ -509,12 +588,30 @@ void kdk_conf2_ksettings_destroy(KSettings *ksettings) g_object_unref(ksettings); - // 减少dbus_signal_loop的引用计数 - // 如果归零则停止事件循环 - g_main_loop_unref(dbus_signal_loop); + int is_dbus_daemon = 0; + char process_name[256]; + FILE *fp = fopen("/proc/self/comm", "r"); + if (fp != NULL) + { + fgets(process_name, sizeof(process_name), fp); + fclose(fp); + // 去除末尾换行符 + process_name[strcspn(process_name, "\n")] = 0; + if (0 == strcmp(process_name, "dbus-daemon")) + is_dbus_daemon = 1; + } + + if (!is_dbus_daemon) + { + // 减少dbus_signal_loop的引用计数 + // 如果归零则停止事件循环 + g_main_loop_unref(dbus_signal_loop); + } if (0 == (--ref_count)) { - g_main_loop_quit(dbus_signal_loop); + g_hash_table_destroy(schemas_table); + schemas_table = NULL; + // g_main_loop_quit(dbus_signal_loop); dbus_signal_loop = NULL; } } @@ -620,16 +717,22 @@ int kdk_conf2_set_value(KSettings *ksettings, const char *key, const char *value char *id = kdk_conf2_schema_get_id(ksettings->priv->schema); char *version = kdk_conf2_schema_get_version(ksettings->priv->schema); if (NULL == curr_value || 0 != strcmp(curr_value, value)) + { result = _call_method("set", id, version, key, value); + if (result) + { + key_hash = kdk_conf2_schema_get_key(ksettings->priv->schema, key); + kdk_conf2_schema_key_set_value(key_hash, value); + } + } else result = TRUE; g_free(id); g_free(version); g_free(curr_value); - syslog(LOG_INFO, "[kysdk-conf2] %s -> Set value finished. Return %s\n", __func__, result ? "true" : "false"); return result; } @@ -1130,10 +1233,15 @@ void kdk_conf2_reset(KSettings *ksettings, const char *key) syslog(LOG_INFO, "[kysdk-conf2] %s -> :reset %s value\n", __func__, key); char *id = kdk_conf2_schema_get_id(ksettings->priv->schema); char *version = kdk_conf2_schema_get_version(ksettings->priv->schema); - _call_method("reset", - id, - version, - key, NULL); + int result = _call_method("reset", + id, + version, + key, NULL); + if (result) + { + GHashTable *key_hash = kdk_conf2_schema_get_key(ksettings->priv->schema, key); + kdk_conf2_schema_key_reset(key_hash); + } g_free(id); g_free(version); } @@ -1217,6 +1325,11 @@ char **kdk_conf2_list_schemas(const char *app, const char *version) tmp = tmp->next; } + if (0 == ref_count) + { + g_hash_table_destroy(schemas_table); + schemas_table = NULL; + } return result; } diff --git a/src/conf2/api/libkysettings.h b/src/conf2/api/libkysettings.h index f46bf50..ac6fe1c 100644 --- a/src/conf2/api/libkysettings.h +++ b/src/conf2/api/libkysettings.h @@ -29,172 +29,546 @@ extern "C" typedef struct _KSettings KSettings; typedef void (*KCallBack) (void); - // typedef void (*KCallBack) (KSettings *ksettings, - // const char *key, - // void *user_data); + /** + * @brief 创建指定id,指定version的配置句柄 + * + * @param id 配置id,从应用名开始到目标组的路径,每个组名以"."分割 + * @param version 配置版本号 + * @return KSettings* 配置组的句柄,每个句柄存储一个组的所有配置数据 + */ KSettings * kdk_conf2_new (const char *id, const char *version); + /** + * @brief 销毁配置句柄 + * + * @param ksettings 配置句柄 + */ void kdk_conf2_ksettings_destroy (KSettings *ksettings); + /** + * @brief 获取句柄的配置id + * + * @param ksettings 配置句柄 + * @return char* 配置id,失败返回NULL。返回值需要释放 + */ char * kdk_conf2_get_id (KSettings *ksettings); + /** + * @brief 获取句柄的配置版本 + * + * @param ksettings 配置句柄 + * @return char* 配置版本,失败返回NULL。返回值需要释放 + */ char * kdk_conf2_get_version (KSettings *ksettings); + /** + * @brief 获取配置句柄的子组配置句柄 + * + * @param ksettings 配置句柄 + * @param name 子组名 + * @return KSettings* 子组句柄 + */ KSettings * kdk_conf2_get_child (KSettings *ksettings, const char *name); + /** + * @brief 列举配置组的所有子组 + * + * @param ksettings 配置句柄 + * @return char** 子组列表,失败返回NULL。返回值需要释放 + */ char ** kdk_conf2_list_children (KSettings *ksettings); + /** + * @brief 列举配置组的所有键 + * + * @param ksettings 配置句柄 + * @return char** 键名列表,失败返回NULL。返回值需要释放 + */ char ** kdk_conf2_list_keys (KSettings *ksettings); + /** + * @brief 获取配置项的取值范围 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return char* 取值范围,如果是数字类型返回字符串"[min,max]",如果是枚举返回字符串"{nick : value}" + */ char * kdk_conf2_get_range (KSettings *ksettings, const char *key); + /** + * @brief 检查要设置的值是否在键的取值范围内 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @param value 要设置的值 + * @return int 可视作bool类型,0表示否,1表示是 + */ int kdk_conf2_range_check (KSettings *ksettings, const char *key, const char *value); + /** + * @brief 设置键的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @param value 要设置的值 + * @return int 可视作bool类型,0表示失败,1表示成功 + */ int kdk_conf2_set_value (KSettings *ksettings, const char *key, const char *value); + /** + * @brief 获取键的值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return char* 符合glib类型标签的数据字符串,失败返回NULL。返回值需要释放 + */ char * kdk_conf2_get_value (KSettings *ksettings, const char *key); + /** + * @brief 获取键的默认值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return char* 符合glib类型标签的数据字符串,失败返回NULL。返回值需要释放 + */ char * kdk_conf2_get_default_value (KSettings *ksettings, const char *key); + /** + * @brief 设置bool类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @param value 键值,bool类型,即0或1 + * @return int 可视作bool类型,0表示失败,1表示成功 + */ int kdk_conf2_set_boolean (KSettings *ksettings, const char *key, int value); + /** + * @brief 获取bool类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return int 0表示FALSE,1表示TRUE + */ int kdk_conf2_get_boolean (KSettings *ksettings, const char *key); - + /** + * @brief 获取bool类型的键默认值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return int 0表示FALSE,1表示TRUE + */ int kdk_conf2_get_default_boolean (KSettings *ksettings, const char *key); + /** + * @brief 设置double类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @param value 键值 + * @return int 可视作bool类型,0表示失败,1表示成功 + */ int kdk_conf2_set_double (KSettings *ksettings, const char *key, double value); + /** + * @brief 获取double类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return double 配置值 + */ double kdk_conf2_get_double (KSettings *ksettings, const char *key); + /** + * @brief 获取double类型的键默认值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return double 配置值 + */ double kdk_conf2_get_default_double (KSettings *ksettings, const char *key); + /** + * @brief 设置枚举类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @param value 要设置的值 + * @return int 可视作bool类型,0表示失败,1表示成功 + */ int kdk_conf2_set_enum (KSettings *ksettings, const char *key, int value); + /** + * @brief 获取枚举类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return int 枚举值 + */ int kdk_conf2_get_enum (KSettings *ksettings, const char *key); + /** + * @brief 获取枚举类型的键默认值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return int 枚举值 + */ int kdk_conf2_get_default_enum (KSettings *ksettings, const char *key); + /** + * @brief 设置int类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @param value 要设置的键值 + * @return int 可视作bool类型,0表示失败,1表示成功 + */ int kdk_conf2_set_int (KSettings *ksettings, const char *key, int value); + /** + * @brief 获取int类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return int 键值 + */ int kdk_conf2_get_int (KSettings *ksettings, const char *key); + /** + * @brief 获取int类型的键默认值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return int 键值 + */ int kdk_conf2_get_default_int (KSettings *ksettings, const char *key); + /** + * @brief 设置int64类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @param value 要设置的键值 + * @return int 可视作bool类型,0表示失败,1表示成功 + */ int kdk_conf2_set_int64 (KSettings *ksettings, const char *key, long value); + /** + * @brief 获取int64类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return long 键值 + */ long kdk_conf2_get_int64 (KSettings *ksettings, const char *key); + /** + * @brief 获取int64类型的键默认值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return long 键值 + */ long kdk_conf2_get_default_int64 (KSettings *ksettings, const char *key); + /** + * @brief 设置uint类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @param value 要设置的键值 + * @return int 可视作bool类型,0表示失败,1表示成功 + */ int kdk_conf2_set_uint (KSettings *ksettings, const char *key, unsigned int value); + /** + * @brief 获取uint类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return unsigned int 键值 + */ unsigned int kdk_conf2_get_uint (KSettings *ksettings, const char *key); + /** + * @brief 获取uint类型的键默认值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return unsigned int 键值 + */ unsigned int kdk_conf2_get_default_uint (KSettings *ksettings, const char *key); + /** + * @brief 设置uint64类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @param value 要设置的键值 + * @return int 可视作bool类型,0表示失败,1表示成功 + */ int kdk_conf2_set_uint64 (KSettings *ksettings, const char *key, unsigned long value); + /** + * @brief 获取uint64类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return unsigned long 键值 + */ unsigned long kdk_conf2_get_uint64 (KSettings *ksettings, const char *key); + /** + * @brief 获取uint64类型的键默认值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return unsigned long 键值 + */ unsigned long kdk_conf2_get_default_uint64 (KSettings *ksettings, const char *key); + /** + * @brief 设置string类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @param value 要设置的键值,符合类型标签的字符串 + * @return int 可视作bool类型,0表示失败,1表示成功 + */ int kdk_conf2_set_string (KSettings *ksettings, const char *key, const char *value); + /** + * @brief 获取string类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return char* 符合类型标签的字符串,失败返回NULL。返回值需要释放 + */ char * kdk_conf2_get_string (KSettings *ksettings, const char *key); + /** + * @brief 获取string类型的键默认值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return char* 符合类型标签的字符串,失败返回NULL。返回值需要释放 + */ char * kdk_conf2_get_default_string (KSettings *ksettings, const char *key); + /** + * @brief 设置字符串列表类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @param value 要设置的键值 + * @return int 可视作bool类型,0表示失败,1表示成功 + */ int kdk_conf2_set_strv (KSettings *ksettings, const char *key, const char * const *value); + /** + * @brief 获取字符串列表类型的键值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return char** 字符串列表,失败返回NULL。返回值需要释放 + */ char ** kdk_conf2_get_strv (KSettings *ksettings, const char *key); + /** + * @brief 获取字符串列表类型的键默认值 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return char** 字符串列表,失败返回NULL。返回值需要释放 + */ char ** kdk_conf2_get_default_strv (KSettings *ksettings, const char *key); + /** + * @brief 获取键的详细描述 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return char* 键的描述,不存在返回NULL。返回值需要释放 + */ char * kdk_conf2_get_descrition (KSettings *ksettings, const char *key); + /** + * @brief 获取键的简要描述 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return char* 键的简述,不存在返回NULL。返回值需要释放 + */ char * kdk_conf2_get_summary (KSettings *ksettings, const char *key); + /** + * @brief 获取键的类型标签字符串 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return char* 键的类型标枪字符串,返回值需要释放 + */ char * kdk_conf2_get_type (KSettings *ksettings, const char *key); + /** + * @brief 将键值复位为默认值 + * + * @param ksettings 配置句柄 + * @param key 键名 + */ void kdk_conf2_reset (KSettings *ksettings, const char *key); + /** + * @brief 检查键值是否可写 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return int 可视作bool类型,0表示否,1表示是 + */ int kdk_conf2_is_writable (KSettings *ksettings, const char *key); + /** + * @brief 检测组内是否存在某个键 + * + * @param ksettings 配置句柄 + * @param key 键名 + * @return int 可视作bool类型,0表示否,1表示是 + */ int kdk_conf2_has_key (KSettings *ksettings, const char *key); + /** + * @brief changed信号的回调原型,注册时强转成KCallBack类型 + * + */ + typedef void (*changed) (KSettings *ksettings, + const char *key, + void *user_data); + /** + * @brief 注册回调函数相应信号,信号的回调函数参数各不相同但连接时都需要强转为KCallBack类型 + * + * @param ksettings 配置句柄 + * @param signal_name 信号名 信号名"changed",如果监听指定键,则写作"changed:key" + * @param handler 回调函数 + * @param user_data 用户数据 + * @return unsigned long 信号连接id + */ unsigned long kdk_conf2_connect_signal (KSettings *ksettings, const char *signal_name, KCallBack handler, void *user_data); - + + /** + * @brief 重新加载配置文件 + * + */ void kdk_conf2_reload (void); + /** + * @brief 列举指定app,指定version的所有id + * + * @param app 应用名 + * @param version 版本号 + * @return char** id列表,失败返回NULL。返回值需要释放 + */ char ** kdk_conf2_list_schemas (const char *app, const char *version); + /** + * @brief 将配置数据以app为单位生成配置文件到指定目录 + * + * @param path 路径 + * @return int 可视作bool类型,0表示失败,1表示成功 + */ int kdk_conf2_save_user_configure (const char *path); + /** + * @brief 以旧id的配置为模板,创建一个新的id + * + * @param old_id 旧的配置id + * @param new_id 新的配置id + * @param version 旧id的版本号,新id将自动创建在这个版本号下 + * @return KSettings* 新id的配置句柄,失败返回NULL + */ KSettings * kdk_conf2_new_extends_id (const char *old_id, const char *new_id, const char *version); - + + /** + * @brief 检查配置id是否存在 + * + * @param id 配置id + * @param version 配置版本 + * @return int 可视作bool类型,0表示否,1表示是 + */ int kdk_conf2_is_schema (const char *id, const char *version); - + /** + * @brief 获取组的简要描述 + * + * @param ksettings 配置句柄 + * @return char* 组的简述,不存在返回NULL。 + */ char * kdk_conf2_get_schema_summary (KSettings *ksettings); + /** + * @brief 获取组的纤细描述 + * + * @param ksettings 配置句柄 + * @return char* 组的描述,不存在返回NULL。 + */ char * kdk_conf2_get_schema_desription (KSettings *ksettings); #if __cplusplus } diff --git a/src/conf2/service/com.kylin.kysdk.conf2.limit b/src/conf2/service/com.kylin.kysdk.conf2.limit index 667ef78..516a40c 100644 --- a/src/conf2/service/com.kylin.kysdk.conf2.limit +++ b/src/conf2/service/com.kylin.kysdk.conf2.limit @@ -5,4 +5,6 @@ key4 = /usr/bin/ukui-settings-daemon key5 = /usr/sbin/lightdm key6 = /usr/bin/ukui-screensaver-dialog key7 = /usr/sbin/ukui-greeter -key8 = /lib/systemd/systemd-logind \ No newline at end of file +key8 = /lib/systemd/systemd-logind +key9 = /usr/bin/sync-config-system +key10 = /usr/bin/sync-config-session diff --git a/src/conf2/service/com.kylin.kysdk.conf2.limit.verify b/src/conf2/service/com.kylin.kysdk.conf2.limit.verify index 18c3a99..5165347 100644 --- a/src/conf2/service/com.kylin.kysdk.conf2.limit.verify +++ b/src/conf2/service/com.kylin.kysdk.conf2.limit.verify @@ -1 +1 @@ -f45558b6a1cb69ceb6e4e58d8b9a47b551db8543 \ No newline at end of file +40a1a38e65f5ae16cbe035b6812e4326741366ac diff --git a/src/conf2/service/conf2-server.py b/src/conf2/service/conf2-server.py index 092e48b..0786730 100644 --- a/src/conf2/service/conf2-server.py +++ b/src/conf2/service/conf2-server.py @@ -43,7 +43,7 @@ class KYSettingsDBusService(dbus.service.Object): self._converter = conf2Utils.Converter(logger) self._watchdog = conf2Utils.FileWatche('/etc/kylin-config/basic', self) - self._reload() + # self._reload() if os.path.exists('/etc/dbus-1/conf/com.kylin.kysdk.conf2.limit'): conf = ConfigParser() @@ -55,43 +55,6 @@ class KYSettingsDBusService(dbus.service.Object): logger.info(f'DBus Class init end') - def isAllowedCaller(self,sender): - if sender is None: - return - pid = self.getSenderPid(sender) - self.checkSenderEnv(pid) - exe_file = '/proc/%u/exe' % pid - real_file = os.readlink(exe_file) - if real_file.startswith('/usr/bin/python'): - cmd_file = '/proc/%u/cmdline' % pid - with open(cmd_file, 'r') as cf: - cmd_line = cf.readline() - cmds = cmd_line.split('\0') - if len(cmds) >= 2: - real_file = cmds[1] - if real_file not in programWhiteList: - raise dbus.exceptions.DBusException('[%s] dbus method control,operation not permitted' % real_file) - - def getSenderPid(self,sender): - system_bus = dbus.SystemBus() - dbus_obj = system_bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus') - inter_obj = dbus.Interface(dbus_obj, dbus_interface='org.freedesktop.DBus') - try: - pid = inter_obj.GetConnectionUnixProcessID(sender) - except dbus.DBusException as e: - raise dbus.exceptions.DBusException('[%s] dbus method control,operation not permitted' % sender) - return pid - - def checkSenderEnv(self, pid): - env_file = '/proc/%u/environ' % pid - with open(env_file, 'r') as ef: - env_lines = ef.readline() - env_details = env_lines.replace('\0', '\n').split('\n') - for env_detail in env_details: - key = env_detail.split('=')[0] - if key in envBlackList: - raise dbus.exceptions.DBusException('[%u] dbus method control,env forbidden' % pid) - # 重载 def _reload(self): if self._converter.update_read_only_db(): @@ -112,7 +75,6 @@ class KYSettingsDBusService(dbus.service.Object): # 设置一个配置的值 @dbus.service.method("com.kylin.kysdk.conf2", in_signature='sssss', out_signature='i', sender_keyword='sender') def set(self, user, id, version, key, value, sender = None): - # self.isAllowedCaller(sender) success = False if user == 'root': success = self._converter.set('/root/.config/kylin-config/user.db', id, version, key, value) @@ -127,7 +89,6 @@ class KYSettingsDBusService(dbus.service.Object): # 恢复单个默认值 @dbus.service.method("com.kylin.kysdk.conf2", in_signature='ssss', out_signature='i', sender_keyword='sender') def reset(self,user, id, version, key, sender = None): - # self.isAllowedCaller(sender) success = False if user == 'root': success = self._converter.reset('/root/.config/kylin-config/user.db', id, version, key) @@ -142,14 +103,12 @@ class KYSettingsDBusService(dbus.service.Object): # 恢复整个id的默认值 @dbus.service.method("com.kylin.kysdk.conf2", in_signature='', out_signature='i', sender_keyword='sender') def reload(self, sender = None): - # self.isAllowedCaller(sender) success = self._reload() self.updated() if success else None return success @dbus.service.method("com.kylin.kysdk.conf2", in_signature='ss', out_signature='b', sender_keyword='sender') def save(self, user, path, sender = None): - # self.isAllowedCaller(sender) success = False if user == 'root': success = self._converter.save('/root/.config/kylin-config/user.db', path) @@ -160,7 +119,6 @@ class KYSettingsDBusService(dbus.service.Object): #复制old_id的配置到new_id的位置,并将新的数据写入到数据库 @dbus.service.method("com.kylin.kysdk.conf2", in_signature='ssss', out_signature='b', sender_keyword='sender') def extends_id(self, old_id:str, new_id:str, version:str, user:str, sender = None): - # self.isAllowedCaller(sender) success = False if user == 'root': success = self._converter.extends_id(old_id, new_id, version, '/root/.config/kylin-config/user.db') diff --git a/src/conf2/service/conf2-update-db.service b/src/conf2/service/conf2-update-db.service new file mode 100644 index 0000000..32a3907 --- /dev/null +++ b/src/conf2/service/conf2-update-db.service @@ -0,0 +1,9 @@ +[Unit] +Description=KYLIN CONF2 UPDATE DB + +[Service] +Type=oneshot +ExecStart=/usr/bin/conf2-update.py + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/src/conf2/service/conf2-update.py b/src/conf2/service/conf2-update.py new file mode 100644 index 0000000..5917ebb --- /dev/null +++ b/src/conf2/service/conf2-update.py @@ -0,0 +1,17 @@ +#!/usr/bin/python3.8 +import os +import logging +import conf2Utils + +os.makedirs('/etc/kylin-config', exist_ok=True) +logging.basicConfig(filename='/etc/kylin-config/systembus.log', + level=logging.DEBUG, + format='%(asctime)s.%(msecs)03d - %(name)s - %(levelname)s - %(message)s', + datefmt='%Y-%m-%d %H:%M:%S') +logger = logging.getLogger() +converter = conf2Utils.Converter(logger) + +logger.info('update db start') +if converter.update_read_only_db(): + converter.update_user_db('/root/.config/kylin-config/user.db') +logger.info('update db end') \ No newline at end of file diff --git a/src/conf2/service/conf2Utils.py b/src/conf2/service/conf2Utils.py index 0d649a4..764a9e9 100644 --- a/src/conf2/service/conf2Utils.py +++ b/src/conf2/service/conf2Utils.py @@ -28,6 +28,7 @@ class Converter: def update_user_db(self, path): if not os.path.exists(self._ro_db): + self.logger.info(f'/etc/kylin-config/user.db not existed') return False existed = self._update_table_structure(path) @@ -37,6 +38,8 @@ class Converter: self._user_dict = self._db2dict(path) else: data = self._db2dict(self._ro_db) + if self._user_dict == {}: + self._user_dict = self._db2dict(path) self._del_discarded_key(self._user_dict, data) self._merge_dict(self._user_dict, data) @@ -186,16 +189,16 @@ class Converter: return False # 用于kconf2-editor保存文件,仅有普通用户权限,root用户没有图形化界面 - def editor_save(self, data, dest_path): + def editor_save(self, apps:list, data, dest_path): try: self.logger.info(f'editor_save begin') #将用户配置写入到复制的只读视图里 self._value_override_default(data) - for key in data: - with open(f'{dest_path}/{key}.yaml', 'w') as yaml_file: - yaml_file.write(yaml.safe_dump({key:data[key]}, allow_unicode = True)) + for app in apps: + with open(f'{dest_path}/{app}.yaml', 'w') as yaml_file: + yaml_file.write(yaml.safe_dump({app:data[app]}, allow_unicode = True)) self.logger.info(f'editor_save end') return True @@ -601,7 +604,21 @@ class Converter: num = int(num, 10) enum_range[element['_nick']] = num range = str(enum_range) - + elif value_type == 'bool': + value_type = 'b' + elif value_type == 'int': + value_type = 'i' + elif value_type == 'int64': + value_type = 'x' + elif value_type == 'uint': + value_type = 'u' + elif value_type == 'uint64': + value_type = 't' + elif value_type == 'double': + value_type = 'd' + elif value_type == 'string': + value_type = 's' + cursor.execute('''INSERT INTO configures (version_id, node_name, node_type, permission, description, summary, parent, value_type, custom_value, default_value, range) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', diff --git a/src/conf2/service/kysdk-conf2.desktop b/src/conf2/service/kysdk-conf2.desktop index 2d8a161..288d4dc 100644 --- a/src/conf2/service/kysdk-conf2.desktop +++ b/src/conf2/service/kysdk-conf2.desktop @@ -3,7 +3,8 @@ Type=Application Exec=/usr/bin/conf2-session-server.py TryExec=/usr/bin/conf2-session-server.py Name=KYSDK-CONF2-SESSION-BUS +X-UKUI-Autostart-Phase=Initialization Icon= Keywords=session;kysdk-conf2-session Comment=This session date you into sdk -NoDisplay=true \ No newline at end of file +NoDisplay=true diff --git a/src/conf2/service/kysdk-conf2.service b/src/conf2/service/kysdk-conf2.service index e66c42a..6268f79 100644 --- a/src/conf2/service/kysdk-conf2.service +++ b/src/conf2/service/kysdk-conf2.service @@ -1,6 +1,6 @@ [Unit] Description=KYLIN CONF2 DBUS -Before=systemd-logind.service +Before=systemd-logind.service com.kylin.kysdk.SyncConfig.service [Service] Type=dbus diff --git a/src/conf2/sync-config/CMakeLists.txt b/src/conf2/sync-config/CMakeLists.txt new file mode 100644 index 0000000..eadeab6 --- /dev/null +++ b/src/conf2/sync-config/CMakeLists.txt @@ -0,0 +1,26 @@ +add_executable(sync-config-system system.c sync-dbus-server.c gdbus/libsyncconfig.c) +target_link_libraries(sync-config-system ${GLIB_LIBRARIES} ${GIO_LIBRARIES} kyconf2 kylog) + +add_executable(sync-config-session session.c sync-dbus-server.c gdbus/libsyncconfig.c) +target_link_libraries(sync-config-session ${GLIB_LIBRARIES} ${GIO_LIBRARIES} kyconf2 kylog) + +# 包含 GNU 安装目录设置 +include(GNUInstallDirs) + +# 设置 CMAKE_INSTALL_LIBDIR 变量 +if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "armv8l") + set(CMAKE_INSTALL_LIBDIR "/usr/lib/arm-linux-gnueabihf/") +elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "mips64") + set(CMAKE_INSTALL_LIBDIR "/usr/lib/mips64el-linux-gnuabi64/") +elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "i686") + set(CMAKE_INSTALL_LIBDIR "/usr/lib/i386-linux-gnu/") +else() + set(CMAKE_INSTALL_LIBDIR "/usr/lib/${CMAKE_HOST_SYSTEM_PROCESSOR}-linux-gnu/") +endif() + +# 安装文件 +install(TARGETS sync-config-session + DESTINATION /usr/bin) + +install(TARGETS sync-config-system + DESTINATION /usr/bin) \ No newline at end of file diff --git a/src/conf2/sync-config/com.kylin.kysdk.SyncConfig.conf b/src/conf2/sync-config/com.kylin.kysdk.SyncConfig.conf new file mode 100644 index 0000000..c8d80ca --- /dev/null +++ b/src/conf2/sync-config/com.kylin.kysdk.SyncConfig.conf @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/conf2/sync-config/com.kylin.kysdk.SyncConfig.desktop b/src/conf2/sync-config/com.kylin.kysdk.SyncConfig.desktop new file mode 100644 index 0000000..a3eddb9 --- /dev/null +++ b/src/conf2/sync-config/com.kylin.kysdk.SyncConfig.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Type=Application +Exec=/usr/bin/sync-config-session +TryExec=/usr/bin/sync-config-session +Name=KYSDK-CONF2-SYNC-CONFIG-BUS +X-UKUI-Autostart-Phase=Initialization +Icon= +Keywords=session; +Comment=This session date you into sdk +NoDisplay=true \ No newline at end of file diff --git a/src/conf2/sync-config/com.kylin.kysdk.SyncConfig.service b/src/conf2/sync-config/com.kylin.kysdk.SyncConfig.service new file mode 100644 index 0000000..8a238ae --- /dev/null +++ b/src/conf2/sync-config/com.kylin.kysdk.SyncConfig.service @@ -0,0 +1,12 @@ +[Unit] +Description=KYLIN CONF2 SYNC DBUS + +[Service] +Type=dbus +Restart=always +RestartSec=1 +BusName=com.kylin.kysdk.SyncConfig +ExecStart=/usr/bin/sync-config-system + +[Install] +WantedBy=multi-user.target diff --git a/src/conf2/sync-config/gdbus/com.kylin.kysdk.SyncConfig.xml b/src/conf2/sync-config/gdbus/com.kylin.kysdk.SyncConfig.xml new file mode 100755 index 0000000..9f2b74b --- /dev/null +++ b/src/conf2/sync-config/gdbus/com.kylin.kysdk.SyncConfig.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/conf2/sync-config/gdbus/libsyncconfig.c b/src/conf2/sync-config/gdbus/libsyncconfig.c new file mode 100644 index 0000000..dca7aa8 --- /dev/null +++ b/src/conf2/sync-config/gdbus/libsyncconfig.c @@ -0,0 +1,1415 @@ +/* + * This file is generated by gdbus-codegen, do not modify it. + * + * The license of this code is the same as for the D-Bus interface description + * it was derived from. Note that it links to GLib, so must comply with the + * LGPL linking clauses. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "libsyncconfig.h" + +#include +#ifdef G_OS_UNIX +# include +#endif + +typedef struct +{ + GDBusArgInfo parent_struct; + gboolean use_gvariant; +} _ExtendedGDBusArgInfo; + +typedef struct +{ + GDBusMethodInfo parent_struct; + const gchar *signal_name; + gboolean pass_fdlist; +} _ExtendedGDBusMethodInfo; + +typedef struct +{ + GDBusSignalInfo parent_struct; + const gchar *signal_name; +} _ExtendedGDBusSignalInfo; + +typedef struct +{ + GDBusPropertyInfo parent_struct; + const gchar *hyphen_name; + guint use_gvariant : 1; + guint emits_changed_signal : 1; +} _ExtendedGDBusPropertyInfo; + +typedef struct +{ + GDBusInterfaceInfo parent_struct; + const gchar *hyphen_name; +} _ExtendedGDBusInterfaceInfo; + +typedef struct +{ + const _ExtendedGDBusPropertyInfo *info; + guint prop_id; + GValue orig_value; /* the value before the change */ +} ChangedProperty; + +static void +_changed_property_free (ChangedProperty *data) +{ + g_value_unset (&data->orig_value); + g_free (data); +} + +static gboolean +_g_strv_equal0 (gchar **a, gchar **b) +{ + gboolean ret = FALSE; + guint n; + if (a == NULL && b == NULL) + { + ret = TRUE; + goto out; + } + if (a == NULL || b == NULL) + goto out; + if (g_strv_length (a) != g_strv_length (b)) + goto out; + for (n = 0; a[n] != NULL; n++) + if (g_strcmp0 (a[n], b[n]) != 0) + goto out; + ret = TRUE; +out: + return ret; +} + +static gboolean +_g_variant_equal0 (GVariant *a, GVariant *b) +{ + gboolean ret = FALSE; + if (a == NULL && b == NULL) + { + ret = TRUE; + goto out; + } + if (a == NULL || b == NULL) + goto out; + ret = g_variant_equal (a, b); +out: + return ret; +} + +G_GNUC_UNUSED static gboolean +_g_value_equal (const GValue *a, const GValue *b) +{ + gboolean ret = FALSE; + g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b)); + switch (G_VALUE_TYPE (a)) + { + case G_TYPE_BOOLEAN: + ret = (g_value_get_boolean (a) == g_value_get_boolean (b)); + break; + case G_TYPE_UCHAR: + ret = (g_value_get_uchar (a) == g_value_get_uchar (b)); + break; + case G_TYPE_INT: + ret = (g_value_get_int (a) == g_value_get_int (b)); + break; + case G_TYPE_UINT: + ret = (g_value_get_uint (a) == g_value_get_uint (b)); + break; + case G_TYPE_INT64: + ret = (g_value_get_int64 (a) == g_value_get_int64 (b)); + break; + case G_TYPE_UINT64: + ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b)); + break; + case G_TYPE_DOUBLE: + { + /* Avoid -Wfloat-equal warnings by doing a direct bit compare */ + gdouble da = g_value_get_double (a); + gdouble db = g_value_get_double (b); + ret = memcmp (&da, &db, sizeof (gdouble)) == 0; + } + break; + case G_TYPE_STRING: + ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0); + break; + case G_TYPE_VARIANT: + ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b)); + break; + default: + if (G_VALUE_TYPE (a) == G_TYPE_STRV) + ret = _g_strv_equal0 (g_value_get_boxed (a), g_value_get_boxed (b)); + else + g_critical ("_g_value_equal() does not handle type %s", g_type_name (G_VALUE_TYPE (a))); + break; + } + return ret; +} + +/* ------------------------------------------------------------------------ + * Code for interface com.kylin.kysdk.SyncConfig + * ------------------------------------------------------------------------ + */ + +/** + * SECTION:SyncConfig + * @title: SyncConfig + * @short_description: Generated C code for the com.kylin.kysdk.SyncConfig D-Bus interface + * + * This section contains code for working with the com.kylin.kysdk.SyncConfig D-Bus interface in C. + */ + +/* ---- Introspection data for com.kylin.kysdk.SyncConfig ---- */ + +static const _ExtendedGDBusArgInfo _sync_config__method_info_register_schema_IN_ARG_Conf2Id = +{ + { + -1, + (gchar *) "Conf2Id", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _sync_config__method_info_register_schema_IN_ARG_SchemaId = +{ + { + -1, + (gchar *) "SchemaId", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _sync_config__method_info_register_schema_IN_ARG_SchemaPath = +{ + { + -1, + (gchar *) "SchemaPath", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _sync_config__method_info_register_schema_IN_ARG_pointers[] = +{ + &_sync_config__method_info_register_schema_IN_ARG_Conf2Id.parent_struct, + &_sync_config__method_info_register_schema_IN_ARG_SchemaId.parent_struct, + &_sync_config__method_info_register_schema_IN_ARG_SchemaPath.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo _sync_config__method_info_register_schema_OUT_ARG_ArgOut = +{ + { + -1, + (gchar *) "ArgOut", + (gchar *) "b", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _sync_config__method_info_register_schema_OUT_ARG_pointers[] = +{ + &_sync_config__method_info_register_schema_OUT_ARG_ArgOut.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _sync_config__method_info_register_schema = +{ + { + -1, + (gchar *) "RegisterSchema", + (GDBusArgInfo **) &_sync_config__method_info_register_schema_IN_ARG_pointers, + (GDBusArgInfo **) &_sync_config__method_info_register_schema_OUT_ARG_pointers, + NULL + }, + "handle-register-schema", + FALSE +}; + +static const _ExtendedGDBusArgInfo _sync_config__method_info_unregister_schema_IN_ARG_SchemaId = +{ + { + -1, + (gchar *) "SchemaId", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const _ExtendedGDBusArgInfo _sync_config__method_info_unregister_schema_IN_ARG_SchemaPath = +{ + { + -1, + (gchar *) "SchemaPath", + (gchar *) "s", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _sync_config__method_info_unregister_schema_IN_ARG_pointers[] = +{ + &_sync_config__method_info_unregister_schema_IN_ARG_SchemaId.parent_struct, + &_sync_config__method_info_unregister_schema_IN_ARG_SchemaPath.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo _sync_config__method_info_unregister_schema_OUT_ARG_ArgOut = +{ + { + -1, + (gchar *) "ArgOut", + (gchar *) "b", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _sync_config__method_info_unregister_schema_OUT_ARG_pointers[] = +{ + &_sync_config__method_info_unregister_schema_OUT_ARG_ArgOut.parent_struct, + NULL +}; + +static const _ExtendedGDBusMethodInfo _sync_config__method_info_unregister_schema = +{ + { + -1, + (gchar *) "UnregisterSchema", + (GDBusArgInfo **) &_sync_config__method_info_unregister_schema_IN_ARG_pointers, + (GDBusArgInfo **) &_sync_config__method_info_unregister_schema_OUT_ARG_pointers, + NULL + }, + "handle-unregister-schema", + FALSE +}; + +static const GDBusMethodInfo * const _sync_config__method_info_pointers[] = +{ + &_sync_config__method_info_register_schema.parent_struct, + &_sync_config__method_info_unregister_schema.parent_struct, + NULL +}; + +static const _ExtendedGDBusArgInfo _sync_config__signal_info_state_ARG_state = +{ + { + -1, + (gchar *) "state", + (gchar *) "i", + NULL + }, + FALSE +}; + +static const GDBusArgInfo * const _sync_config__signal_info_state_ARG_pointers[] = +{ + &_sync_config__signal_info_state_ARG_state.parent_struct, + NULL +}; + +static const _ExtendedGDBusSignalInfo _sync_config__signal_info_state = +{ + { + -1, + (gchar *) "state", + (GDBusArgInfo **) &_sync_config__signal_info_state_ARG_pointers, + NULL + }, + "state" +}; + +static const GDBusSignalInfo * const _sync_config__signal_info_pointers[] = +{ + &_sync_config__signal_info_state.parent_struct, + NULL +}; + +static const _ExtendedGDBusInterfaceInfo _sync_config__interface_info = +{ + { + -1, + (gchar *) "com.kylin.kysdk.SyncConfig", + (GDBusMethodInfo **) &_sync_config__method_info_pointers, + (GDBusSignalInfo **) &_sync_config__signal_info_pointers, + NULL, + NULL + }, + "", +}; + + +/** + * sync_config__interface_info: + * + * Gets a machine-readable description of the com.kylin.kysdk.SyncConfig D-Bus interface. + * + * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free. + */ +GDBusInterfaceInfo * +sync_config__interface_info (void) +{ + return (GDBusInterfaceInfo *) &_sync_config__interface_info.parent_struct; +} + +/** + * sync_config__override_properties: + * @klass: The class structure for a #GObject derived class. + * @property_id_begin: The property id to assign to the first overridden property. + * + * Overrides all #GObject properties in the #SyncConfig interface for a concrete class. + * The properties are overridden in the order they are defined. + * + * Returns: The last property id. + */ +guint +sync_config__override_properties (GObjectClass *klass, guint property_id_begin) +{ + return property_id_begin - 1; +} + + + +/** + * SyncConfig: + * + * Abstract interface type for the D-Bus interface com.kylin.kysdk.SyncConfig. + */ + +/** + * SyncConfigIface: + * @parent_iface: The parent interface. + * @handle_register_schema: Handler for the #SyncConfig::handle-register-schema signal. + * @handle_unregister_schema: Handler for the #SyncConfig::handle-unregister-schema signal. + * @state: Handler for the #SyncConfig::state signal. + * + * Virtual table for the D-Bus interface com.kylin.kysdk.SyncConfig. + */ + +typedef SyncConfigIface SyncConfigInterface; +G_DEFINE_INTERFACE (SyncConfig, sync_config_, G_TYPE_OBJECT) + +static void +sync_config__default_init (SyncConfigIface *iface) +{ + /* GObject signals for incoming D-Bus method calls: */ + /** + * SyncConfig::handle-register-schema: + * @object: A #SyncConfig. + * @invocation: A #GDBusMethodInvocation. + * @arg_Conf2Id: Argument passed by remote caller. + * @arg_SchemaId: Argument passed by remote caller. + * @arg_SchemaPath: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the RegisterSchema() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call sync_config__complete_register_schema() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-register-schema", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (SyncConfigIface, handle_register_schema), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 4, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + + /** + * SyncConfig::handle-unregister-schema: + * @object: A #SyncConfig. + * @invocation: A #GDBusMethodInvocation. + * @arg_SchemaId: Argument passed by remote caller. + * @arg_SchemaPath: Argument passed by remote caller. + * + * Signal emitted when a remote caller is invoking the UnregisterSchema() D-Bus method. + * + * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call sync_config__complete_unregister_schema() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. + * + * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run. + */ + g_signal_new ("handle-unregister-schema", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (SyncConfigIface, handle_unregister_schema), + g_signal_accumulator_true_handled, + NULL, + g_cclosure_marshal_generic, + G_TYPE_BOOLEAN, + 3, + G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_STRING); + + /* GObject signals for received D-Bus signals: */ + /** + * SyncConfig::state: + * @object: A #SyncConfig. + * @arg_state: Argument. + * + * On the client-side, this signal is emitted whenever the D-Bus signal "state" is received. + * + * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal. + */ + g_signal_new ("state", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (SyncConfigIface, state), + NULL, + NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, + 1, G_TYPE_INT); + +} + +/** + * sync_config__emit_state: + * @object: A #SyncConfig. + * @arg_state: Argument to pass with the signal. + * + * Emits the "state" D-Bus signal. + */ +void +sync_config__emit_state ( + SyncConfig *object, + gint arg_state) +{ + g_signal_emit_by_name (object, "state", arg_state); +} + +/** + * sync_config__call_register_schema: + * @proxy: A #SyncConfigProxy. + * @arg_Conf2Id: Argument to pass with the method invocation. + * @arg_SchemaId: Argument to pass with the method invocation. + * @arg_SchemaPath: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the RegisterSchema() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call sync_config__call_register_schema_finish() to get the result of the operation. + * + * See sync_config__call_register_schema_sync() for the synchronous, blocking version of this method. + */ +void +sync_config__call_register_schema ( + SyncConfig *proxy, + const gchar *arg_Conf2Id, + const gchar *arg_SchemaId, + const gchar *arg_SchemaPath, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "RegisterSchema", + g_variant_new ("(sss)", + arg_Conf2Id, + arg_SchemaId, + arg_SchemaPath), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * sync_config__call_register_schema_finish: + * @proxy: A #SyncConfigProxy. + * @out_ArgOut: (out) (optional): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to sync_config__call_register_schema(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with sync_config__call_register_schema(). + * + * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. + */ +gboolean +sync_config__call_register_schema_finish ( + SyncConfig *proxy, + gboolean *out_ArgOut, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(b)", + out_ArgOut); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * sync_config__call_register_schema_sync: + * @proxy: A #SyncConfigProxy. + * @arg_Conf2Id: Argument to pass with the method invocation. + * @arg_SchemaId: Argument to pass with the method invocation. + * @arg_SchemaPath: Argument to pass with the method invocation. + * @out_ArgOut: (out) (optional): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the RegisterSchema() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See sync_config__call_register_schema() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. + */ +gboolean +sync_config__call_register_schema_sync ( + SyncConfig *proxy, + const gchar *arg_Conf2Id, + const gchar *arg_SchemaId, + const gchar *arg_SchemaPath, + gboolean *out_ArgOut, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "RegisterSchema", + g_variant_new ("(sss)", + arg_Conf2Id, + arg_SchemaId, + arg_SchemaPath), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(b)", + out_ArgOut); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * sync_config__call_unregister_schema: + * @proxy: A #SyncConfigProxy. + * @arg_SchemaId: Argument to pass with the method invocation. + * @arg_SchemaPath: Argument to pass with the method invocation. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously invokes the UnregisterSchema() D-Bus method on @proxy. + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call sync_config__call_unregister_schema_finish() to get the result of the operation. + * + * See sync_config__call_unregister_schema_sync() for the synchronous, blocking version of this method. + */ +void +sync_config__call_unregister_schema ( + SyncConfig *proxy, + const gchar *arg_SchemaId, + const gchar *arg_SchemaPath, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "UnregisterSchema", + g_variant_new ("(ss)", + arg_SchemaId, + arg_SchemaPath), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +/** + * sync_config__call_unregister_schema_finish: + * @proxy: A #SyncConfigProxy. + * @out_ArgOut: (out) (optional): Return location for return parameter or %NULL to ignore. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to sync_config__call_unregister_schema(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with sync_config__call_unregister_schema(). + * + * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. + */ +gboolean +sync_config__call_unregister_schema_finish ( + SyncConfig *proxy, + gboolean *out_ArgOut, + GAsyncResult *res, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(b)", + out_ArgOut); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * sync_config__call_unregister_schema_sync: + * @proxy: A #SyncConfigProxy. + * @arg_SchemaId: Argument to pass with the method invocation. + * @arg_SchemaPath: Argument to pass with the method invocation. + * @out_ArgOut: (out) (optional): Return location for return parameter or %NULL to ignore. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously invokes the UnregisterSchema() D-Bus method on @proxy. The calling thread is blocked until a reply is received. + * + * See sync_config__call_unregister_schema() for the asynchronous version of this method. + * + * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set. + */ +gboolean +sync_config__call_unregister_schema_sync ( + SyncConfig *proxy, + const gchar *arg_SchemaId, + const gchar *arg_SchemaPath, + gboolean *out_ArgOut, + GCancellable *cancellable, + GError **error) +{ + GVariant *_ret; + _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "UnregisterSchema", + g_variant_new ("(ss)", + arg_SchemaId, + arg_SchemaPath), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (_ret == NULL) + goto _out; + g_variant_get (_ret, + "(b)", + out_ArgOut); + g_variant_unref (_ret); +_out: + return _ret != NULL; +} + +/** + * sync_config__complete_register_schema: + * @object: A #SyncConfig. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @ArgOut: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the RegisterSchema() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +sync_config__complete_register_schema ( + SyncConfig *object, + GDBusMethodInvocation *invocation, + gboolean ArgOut) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(b)", + ArgOut)); +} + +/** + * sync_config__complete_unregister_schema: + * @object: A #SyncConfig. + * @invocation: (transfer full): A #GDBusMethodInvocation. + * @ArgOut: Parameter to return. + * + * Helper function used in service implementations to finish handling invocations of the UnregisterSchema() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar. + * + * This method will free @invocation, you cannot use it afterwards. + */ +void +sync_config__complete_unregister_schema ( + SyncConfig *object, + GDBusMethodInvocation *invocation, + gboolean ArgOut) +{ + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(b)", + ArgOut)); +} + +/* ------------------------------------------------------------------------ */ + +/** + * SyncConfigProxy: + * + * The #SyncConfigProxy structure contains only private data and should only be accessed using the provided API. + */ + +/** + * SyncConfigProxyClass: + * @parent_class: The parent class. + * + * Class structure for #SyncConfigProxy. + */ + +struct _SyncConfigProxyPrivate +{ + GData *qdata; +}; + +static void sync_config__proxy_iface_init (SyncConfigIface *iface); + +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 +G_DEFINE_TYPE_WITH_CODE (SyncConfigProxy, sync_config__proxy, G_TYPE_DBUS_PROXY, + G_ADD_PRIVATE (SyncConfigProxy) + G_IMPLEMENT_INTERFACE (SYNC_CONFIG_TYPE_, sync_config__proxy_iface_init)) + +#else +G_DEFINE_TYPE_WITH_CODE (SyncConfigProxy, sync_config__proxy, G_TYPE_DBUS_PROXY, + G_IMPLEMENT_INTERFACE (SYNC_CONFIG_TYPE_, sync_config__proxy_iface_init)) + +#endif +static void +sync_config__proxy_finalize (GObject *object) +{ + SyncConfigProxy *proxy = SYNC_CONFIG__PROXY (object); + g_datalist_clear (&proxy->priv->qdata); + G_OBJECT_CLASS (sync_config__proxy_parent_class)->finalize (object); +} + +static void +sync_config__proxy_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec G_GNUC_UNUSED) +{ +} + +static void +sync_config__proxy_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec G_GNUC_UNUSED) +{ +} + +static void +sync_config__proxy_g_signal (GDBusProxy *proxy, + const gchar *sender_name G_GNUC_UNUSED, + const gchar *signal_name, + GVariant *parameters) +{ + _ExtendedGDBusSignalInfo *info; + GVariantIter iter; + GVariant *child; + GValue *paramv; + gsize num_params; + gsize n; + guint signal_id; + info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_sync_config__interface_info.parent_struct, signal_name); + if (info == NULL) + return; + num_params = g_variant_n_children (parameters); + paramv = g_new0 (GValue, num_params + 1); + g_value_init (¶mv[0], SYNC_CONFIG_TYPE_); + g_value_set_object (¶mv[0], proxy); + g_variant_iter_init (&iter, parameters); + n = 1; + while ((child = g_variant_iter_next_value (&iter)) != NULL) + { + _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1]; + if (arg_info->use_gvariant) + { + g_value_init (¶mv[n], G_TYPE_VARIANT); + g_value_set_variant (¶mv[n], child); + n++; + } + else + g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); + g_variant_unref (child); + } + signal_id = g_signal_lookup (info->signal_name, SYNC_CONFIG_TYPE_); + g_signal_emitv (paramv, signal_id, 0, NULL); + for (n = 0; n < num_params + 1; n++) + g_value_unset (¶mv[n]); + g_free (paramv); +} + +static void +sync_config__proxy_g_properties_changed (GDBusProxy *_proxy, + GVariant *changed_properties, + const gchar *const *invalidated_properties) +{ + SyncConfigProxy *proxy = SYNC_CONFIG__PROXY (_proxy); + guint n; + const gchar *key; + GVariantIter *iter; + _ExtendedGDBusPropertyInfo *info; + g_variant_get (changed_properties, "a{sv}", &iter); + while (g_variant_iter_next (iter, "{&sv}", &key, NULL)) + { + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_sync_config__interface_info.parent_struct, key); + g_datalist_remove_data (&proxy->priv->qdata, key); + if (info != NULL) + g_object_notify (G_OBJECT (proxy), info->hyphen_name); + } + g_variant_iter_free (iter); + for (n = 0; invalidated_properties[n] != NULL; n++) + { + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_sync_config__interface_info.parent_struct, invalidated_properties[n]); + g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]); + if (info != NULL) + g_object_notify (G_OBJECT (proxy), info->hyphen_name); + } +} + +static void +sync_config__proxy_init (SyncConfigProxy *proxy) +{ +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 + proxy->priv = sync_config__proxy_get_instance_private (proxy); +#else + proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, SYNC_CONFIG_TYPE__PROXY, SyncConfigProxyPrivate); +#endif + + g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), sync_config__interface_info ()); +} + +static void +sync_config__proxy_class_init (SyncConfigProxyClass *klass) +{ + GObjectClass *gobject_class; + GDBusProxyClass *proxy_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = sync_config__proxy_finalize; + gobject_class->get_property = sync_config__proxy_get_property; + gobject_class->set_property = sync_config__proxy_set_property; + + proxy_class = G_DBUS_PROXY_CLASS (klass); + proxy_class->g_signal = sync_config__proxy_g_signal; + proxy_class->g_properties_changed = sync_config__proxy_g_properties_changed; + +#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 + g_type_class_add_private (klass, sizeof (SyncConfigProxyPrivate)); +#endif +} + +static void +sync_config__proxy_iface_init (SyncConfigIface *iface) +{ +} + +/** + * sync_config__proxy_new: + * @connection: A #GDBusConnection. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied. + * @user_data: User data to pass to @callback. + * + * Asynchronously creates a proxy for the D-Bus interface com.kylin.kysdk.SyncConfig. See g_dbus_proxy_new() for more details. + * + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call sync_config__proxy_new_finish() to get the result of the operation. + * + * See sync_config__proxy_new_sync() for the synchronous, blocking version of this constructor. + */ +void +sync_config__proxy_new ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_async_initable_new_async (SYNC_CONFIG_TYPE__PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "com.kylin.kysdk.SyncConfig", NULL); +} + +/** + * sync_config__proxy_new_finish: + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to sync_config__proxy_new(). + * @error: Return location for error or %NULL + * + * Finishes an operation started with sync_config__proxy_new(). + * + * Returns: (transfer full) (type SyncConfigProxy): The constructed proxy object or %NULL if @error is set. + */ +SyncConfig * +sync_config__proxy_new_finish ( + GAsyncResult *res, + GError **error) +{ + GObject *ret; + GObject *source_object; + source_object = g_async_result_get_source_object (res); + ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); + g_object_unref (source_object); + if (ret != NULL) + return SYNC_CONFIG_ (ret); + else + return NULL; +} + +/** + * sync_config__proxy_new_sync: + * @connection: A #GDBusConnection. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection. + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL + * + * Synchronously creates a proxy for the D-Bus interface com.kylin.kysdk.SyncConfig. See g_dbus_proxy_new_sync() for more details. + * + * The calling thread is blocked until a reply is received. + * + * See sync_config__proxy_new() for the asynchronous version of this constructor. + * + * Returns: (transfer full) (type SyncConfigProxy): The constructed proxy object or %NULL if @error is set. + */ +SyncConfig * +sync_config__proxy_new_sync ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error) +{ + GInitable *ret; + ret = g_initable_new (SYNC_CONFIG_TYPE__PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "com.kylin.kysdk.SyncConfig", NULL); + if (ret != NULL) + return SYNC_CONFIG_ (ret); + else + return NULL; +} + + +/** + * sync_config__proxy_new_for_bus: + * @bus_type: A #GBusType. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: A bus name (well-known or unique). + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied. + * @user_data: User data to pass to @callback. + * + * Like sync_config__proxy_new() but takes a #GBusType instead of a #GDBusConnection. + * + * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()). + * You can then call sync_config__proxy_new_for_bus_finish() to get the result of the operation. + * + * See sync_config__proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor. + */ +void +sync_config__proxy_new_for_bus ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_async_initable_new_async (SYNC_CONFIG_TYPE__PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "com.kylin.kysdk.SyncConfig", NULL); +} + +/** + * sync_config__proxy_new_for_bus_finish: + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to sync_config__proxy_new_for_bus(). + * @error: Return location for error or %NULL + * + * Finishes an operation started with sync_config__proxy_new_for_bus(). + * + * Returns: (transfer full) (type SyncConfigProxy): The constructed proxy object or %NULL if @error is set. + */ +SyncConfig * +sync_config__proxy_new_for_bus_finish ( + GAsyncResult *res, + GError **error) +{ + GObject *ret; + GObject *source_object; + source_object = g_async_result_get_source_object (res); + ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); + g_object_unref (source_object); + if (ret != NULL) + return SYNC_CONFIG_ (ret); + else + return NULL; +} + +/** + * sync_config__proxy_new_for_bus_sync: + * @bus_type: A #GBusType. + * @flags: Flags from the #GDBusProxyFlags enumeration. + * @name: A bus name (well-known or unique). + * @object_path: An object path. + * @cancellable: (nullable): A #GCancellable or %NULL. + * @error: Return location for error or %NULL + * + * Like sync_config__proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection. + * + * The calling thread is blocked until a reply is received. + * + * See sync_config__proxy_new_for_bus() for the asynchronous version of this constructor. + * + * Returns: (transfer full) (type SyncConfigProxy): The constructed proxy object or %NULL if @error is set. + */ +SyncConfig * +sync_config__proxy_new_for_bus_sync ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error) +{ + GInitable *ret; + ret = g_initable_new (SYNC_CONFIG_TYPE__PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "com.kylin.kysdk.SyncConfig", NULL); + if (ret != NULL) + return SYNC_CONFIG_ (ret); + else + return NULL; +} + + +/* ------------------------------------------------------------------------ */ + +/** + * SyncConfigSkeleton: + * + * The #SyncConfigSkeleton structure contains only private data and should only be accessed using the provided API. + */ + +/** + * SyncConfigSkeletonClass: + * @parent_class: The parent class. + * + * Class structure for #SyncConfigSkeleton. + */ + +struct _SyncConfigSkeletonPrivate +{ + GValue *properties; + GList *changed_properties; + GSource *changed_properties_idle_source; + GMainContext *context; + GMutex lock; +}; + +static void +_sync_config__skeleton_handle_method_call ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + SyncConfigSkeleton *skeleton = SYNC_CONFIG__SKELETON (user_data); + _ExtendedGDBusMethodInfo *info; + GVariantIter iter; + GVariant *child; + GValue *paramv; + gsize num_params; + guint num_extra; + gsize n; + guint signal_id; + GValue return_value = G_VALUE_INIT; + info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation); + g_assert (info != NULL); + num_params = g_variant_n_children (parameters); + num_extra = info->pass_fdlist ? 3 : 2; paramv = g_new0 (GValue, num_params + num_extra); + n = 0; + g_value_init (¶mv[n], SYNC_CONFIG_TYPE_); + g_value_set_object (¶mv[n++], skeleton); + g_value_init (¶mv[n], G_TYPE_DBUS_METHOD_INVOCATION); + g_value_set_object (¶mv[n++], invocation); + if (info->pass_fdlist) + { +#ifdef G_OS_UNIX + g_value_init (¶mv[n], G_TYPE_UNIX_FD_LIST); + g_value_set_object (¶mv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation))); +#else + g_assert_not_reached (); +#endif + } + g_variant_iter_init (&iter, parameters); + while ((child = g_variant_iter_next_value (&iter)) != NULL) + { + _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra]; + if (arg_info->use_gvariant) + { + g_value_init (¶mv[n], G_TYPE_VARIANT); + g_value_set_variant (¶mv[n], child); + n++; + } + else + g_dbus_gvariant_to_gvalue (child, ¶mv[n++]); + g_variant_unref (child); + } + signal_id = g_signal_lookup (info->signal_name, SYNC_CONFIG_TYPE_); + g_value_init (&return_value, G_TYPE_BOOLEAN); + g_signal_emitv (paramv, signal_id, 0, &return_value); + if (!g_value_get_boolean (&return_value)) + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name); + g_value_unset (&return_value); + for (n = 0; n < num_params + num_extra; n++) + g_value_unset (¶mv[n]); + g_free (paramv); +} + +static GVariant * +_sync_config__skeleton_handle_get_property ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name G_GNUC_UNUSED, + const gchar *property_name, + GError **error, + gpointer user_data) +{ + SyncConfigSkeleton *skeleton = SYNC_CONFIG__SKELETON (user_data); + GValue value = G_VALUE_INIT; + GParamSpec *pspec; + _ExtendedGDBusPropertyInfo *info; + GVariant *ret; + ret = NULL; + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_sync_config__interface_info.parent_struct, property_name); + g_assert (info != NULL); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); + if (pspec == NULL) + { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); + } + else + { + g_value_init (&value, pspec->value_type); + g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value); + ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature)); + g_value_unset (&value); + } + return ret; +} + +static gboolean +_sync_config__skeleton_handle_set_property ( + GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *object_path G_GNUC_UNUSED, + const gchar *interface_name G_GNUC_UNUSED, + const gchar *property_name, + GVariant *variant, + GError **error, + gpointer user_data) +{ + SyncConfigSkeleton *skeleton = SYNC_CONFIG__SKELETON (user_data); + GValue value = G_VALUE_INIT; + GParamSpec *pspec; + _ExtendedGDBusPropertyInfo *info; + gboolean ret; + ret = FALSE; + info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_sync_config__interface_info.parent_struct, property_name); + g_assert (info != NULL); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name); + if (pspec == NULL) + { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name); + } + else + { + if (info->use_gvariant) + g_value_set_variant (&value, variant); + else + g_dbus_gvariant_to_gvalue (variant, &value); + g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value); + g_value_unset (&value); + ret = TRUE; + } + return ret; +} + +static const GDBusInterfaceVTable _sync_config__skeleton_vtable = +{ + _sync_config__skeleton_handle_method_call, + _sync_config__skeleton_handle_get_property, + _sync_config__skeleton_handle_set_property, + {NULL} +}; + +static GDBusInterfaceInfo * +sync_config__skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) +{ + return sync_config__interface_info (); +} + +static GDBusInterfaceVTable * +sync_config__skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED) +{ + return (GDBusInterfaceVTable *) &_sync_config__skeleton_vtable; +} + +static GVariant * +sync_config__skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton) +{ + SyncConfigSkeleton *skeleton = SYNC_CONFIG__SKELETON (_skeleton); + + GVariantBuilder builder; + guint n; + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + if (_sync_config__interface_info.parent_struct.properties == NULL) + goto out; + for (n = 0; _sync_config__interface_info.parent_struct.properties[n] != NULL; n++) + { + GDBusPropertyInfo *info = _sync_config__interface_info.parent_struct.properties[n]; + if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE) + { + GVariant *value; + value = _sync_config__skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "com.kylin.kysdk.SyncConfig", info->name, NULL, skeleton); + if (value != NULL) + { + g_variant_take_ref (value); + g_variant_builder_add (&builder, "{sv}", info->name, value); + g_variant_unref (value); + } + } + } +out: + return g_variant_builder_end (&builder); +} + +static void +sync_config__skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton) +{ +} + +static void +_sync_config__on_signal_state ( + SyncConfig *object, + gint arg_state) +{ + SyncConfigSkeleton *skeleton = SYNC_CONFIG__SKELETON (object); + + GList *connections, *l; + GVariant *signal_variant; + connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton)); + + signal_variant = g_variant_ref_sink (g_variant_new ("(i)", + arg_state)); + for (l = connections; l != NULL; l = l->next) + { + GDBusConnection *connection = l->data; + g_dbus_connection_emit_signal (connection, + NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "com.kylin.kysdk.SyncConfig", "state", + signal_variant, NULL); + } + g_variant_unref (signal_variant); + g_list_free_full (connections, g_object_unref); +} + +static void sync_config__skeleton_iface_init (SyncConfigIface *iface); +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 +G_DEFINE_TYPE_WITH_CODE (SyncConfigSkeleton, sync_config__skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, + G_ADD_PRIVATE (SyncConfigSkeleton) + G_IMPLEMENT_INTERFACE (SYNC_CONFIG_TYPE_, sync_config__skeleton_iface_init)) + +#else +G_DEFINE_TYPE_WITH_CODE (SyncConfigSkeleton, sync_config__skeleton, G_TYPE_DBUS_INTERFACE_SKELETON, + G_IMPLEMENT_INTERFACE (SYNC_CONFIG_TYPE_, sync_config__skeleton_iface_init)) + +#endif +static void +sync_config__skeleton_finalize (GObject *object) +{ + SyncConfigSkeleton *skeleton = SYNC_CONFIG__SKELETON (object); + g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free); + if (skeleton->priv->changed_properties_idle_source != NULL) + g_source_destroy (skeleton->priv->changed_properties_idle_source); + g_main_context_unref (skeleton->priv->context); + g_mutex_clear (&skeleton->priv->lock); + G_OBJECT_CLASS (sync_config__skeleton_parent_class)->finalize (object); +} + +static void +sync_config__skeleton_init (SyncConfigSkeleton *skeleton) +{ +#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 + skeleton->priv = sync_config__skeleton_get_instance_private (skeleton); +#else + skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, SYNC_CONFIG_TYPE__SKELETON, SyncConfigSkeletonPrivate); +#endif + + g_mutex_init (&skeleton->priv->lock); + skeleton->priv->context = g_main_context_ref_thread_default (); +} + +static void +sync_config__skeleton_class_init (SyncConfigSkeletonClass *klass) +{ + GObjectClass *gobject_class; + GDBusInterfaceSkeletonClass *skeleton_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = sync_config__skeleton_finalize; + + skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass); + skeleton_class->get_info = sync_config__skeleton_dbus_interface_get_info; + skeleton_class->get_properties = sync_config__skeleton_dbus_interface_get_properties; + skeleton_class->flush = sync_config__skeleton_dbus_interface_flush; + skeleton_class->get_vtable = sync_config__skeleton_dbus_interface_get_vtable; + +#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38 + g_type_class_add_private (klass, sizeof (SyncConfigSkeletonPrivate)); +#endif +} + +static void +sync_config__skeleton_iface_init (SyncConfigIface *iface) +{ + iface->state = _sync_config__on_signal_state; +} + +/** + * sync_config__skeleton_new: + * + * Creates a skeleton object for the D-Bus interface com.kylin.kysdk.SyncConfig. + * + * Returns: (transfer full) (type SyncConfigSkeleton): The skeleton object. + */ +SyncConfig * +sync_config__skeleton_new (void) +{ + return SYNC_CONFIG_ (g_object_new (SYNC_CONFIG_TYPE__SKELETON, NULL)); +} + diff --git a/src/conf2/sync-config/gdbus/libsyncconfig.h b/src/conf2/sync-config/gdbus/libsyncconfig.h new file mode 100644 index 0000000..7e0fdab --- /dev/null +++ b/src/conf2/sync-config/gdbus/libsyncconfig.h @@ -0,0 +1,234 @@ +/* + * This file is generated by gdbus-codegen, do not modify it. + * + * The license of this code is the same as for the D-Bus interface description + * it was derived from. Note that it links to GLib, so must comply with the + * LGPL linking clauses. + */ + +#ifndef __LIBSYNCCONFIG_H__ +#define __LIBSYNCCONFIG_H__ + +#include + +G_BEGIN_DECLS + + +/* ------------------------------------------------------------------------ */ +/* Declarations for com.kylin.kysdk.SyncConfig */ + +#define SYNC_CONFIG_TYPE_ (sync_config__get_type ()) +#define SYNC_CONFIG_(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SYNC_CONFIG_TYPE_, SyncConfig)) +#define SYNC_CONFIG_IS_(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SYNC_CONFIG_TYPE_)) +#define SYNC_CONFIG__GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), SYNC_CONFIG_TYPE_, SyncConfigIface)) + +struct _SyncConfig; +typedef struct _SyncConfig SyncConfig; +typedef struct _SyncConfigIface SyncConfigIface; + +struct _SyncConfigIface +{ + GTypeInterface parent_iface; + + + gboolean (*handle_register_schema) ( + SyncConfig *object, + GDBusMethodInvocation *invocation, + const gchar *arg_Conf2Id, + const gchar *arg_SchemaId, + const gchar *arg_SchemaPath); + + gboolean (*handle_unregister_schema) ( + SyncConfig *object, + GDBusMethodInvocation *invocation, + const gchar *arg_SchemaId, + const gchar *arg_SchemaPath); + + void (*state) ( + SyncConfig *object, + gint arg_state); + +}; + +GType sync_config__get_type (void) G_GNUC_CONST; + +GDBusInterfaceInfo *sync_config__interface_info (void); +guint sync_config__override_properties (GObjectClass *klass, guint property_id_begin); + + +/* D-Bus method call completion functions: */ +void sync_config__complete_register_schema ( + SyncConfig *object, + GDBusMethodInvocation *invocation, + gboolean ArgOut); + +void sync_config__complete_unregister_schema ( + SyncConfig *object, + GDBusMethodInvocation *invocation, + gboolean ArgOut); + + + +/* D-Bus signal emissions functions: */ +void sync_config__emit_state ( + SyncConfig *object, + gint arg_state); + + + +/* D-Bus method calls: */ +void sync_config__call_register_schema ( + SyncConfig *proxy, + const gchar *arg_Conf2Id, + const gchar *arg_SchemaId, + const gchar *arg_SchemaPath, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean sync_config__call_register_schema_finish ( + SyncConfig *proxy, + gboolean *out_ArgOut, + GAsyncResult *res, + GError **error); + +gboolean sync_config__call_register_schema_sync ( + SyncConfig *proxy, + const gchar *arg_Conf2Id, + const gchar *arg_SchemaId, + const gchar *arg_SchemaPath, + gboolean *out_ArgOut, + GCancellable *cancellable, + GError **error); + +void sync_config__call_unregister_schema ( + SyncConfig *proxy, + const gchar *arg_SchemaId, + const gchar *arg_SchemaPath, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean sync_config__call_unregister_schema_finish ( + SyncConfig *proxy, + gboolean *out_ArgOut, + GAsyncResult *res, + GError **error); + +gboolean sync_config__call_unregister_schema_sync ( + SyncConfig *proxy, + const gchar *arg_SchemaId, + const gchar *arg_SchemaPath, + gboolean *out_ArgOut, + GCancellable *cancellable, + GError **error); + + + +/* ---- */ + +#define SYNC_CONFIG_TYPE__PROXY (sync_config__proxy_get_type ()) +#define SYNC_CONFIG__PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SYNC_CONFIG_TYPE__PROXY, SyncConfigProxy)) +#define SYNC_CONFIG__PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), SYNC_CONFIG_TYPE__PROXY, SyncConfigProxyClass)) +#define SYNC_CONFIG__PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SYNC_CONFIG_TYPE__PROXY, SyncConfigProxyClass)) +#define SYNC_CONFIG_IS__PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SYNC_CONFIG_TYPE__PROXY)) +#define SYNC_CONFIG_IS__PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SYNC_CONFIG_TYPE__PROXY)) + +typedef struct _SyncConfigProxy SyncConfigProxy; +typedef struct _SyncConfigProxyClass SyncConfigProxyClass; +typedef struct _SyncConfigProxyPrivate SyncConfigProxyPrivate; + +struct _SyncConfigProxy +{ + /*< private >*/ + GDBusProxy parent_instance; + SyncConfigProxyPrivate *priv; +}; + +struct _SyncConfigProxyClass +{ + GDBusProxyClass parent_class; +}; + +GType sync_config__proxy_get_type (void) G_GNUC_CONST; + +#if GLIB_CHECK_VERSION(2, 44, 0) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (SyncConfigProxy, g_object_unref) +#endif + +void sync_config__proxy_new ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +SyncConfig *sync_config__proxy_new_finish ( + GAsyncResult *res, + GError **error); +SyncConfig *sync_config__proxy_new_sync ( + GDBusConnection *connection, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error); + +void sync_config__proxy_new_for_bus ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +SyncConfig *sync_config__proxy_new_for_bus_finish ( + GAsyncResult *res, + GError **error); +SyncConfig *sync_config__proxy_new_for_bus_sync ( + GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *object_path, + GCancellable *cancellable, + GError **error); + + +/* ---- */ + +#define SYNC_CONFIG_TYPE__SKELETON (sync_config__skeleton_get_type ()) +#define SYNC_CONFIG__SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SYNC_CONFIG_TYPE__SKELETON, SyncConfigSkeleton)) +#define SYNC_CONFIG__SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), SYNC_CONFIG_TYPE__SKELETON, SyncConfigSkeletonClass)) +#define SYNC_CONFIG__SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SYNC_CONFIG_TYPE__SKELETON, SyncConfigSkeletonClass)) +#define SYNC_CONFIG_IS__SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SYNC_CONFIG_TYPE__SKELETON)) +#define SYNC_CONFIG_IS__SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SYNC_CONFIG_TYPE__SKELETON)) + +typedef struct _SyncConfigSkeleton SyncConfigSkeleton; +typedef struct _SyncConfigSkeletonClass SyncConfigSkeletonClass; +typedef struct _SyncConfigSkeletonPrivate SyncConfigSkeletonPrivate; + +struct _SyncConfigSkeleton +{ + /*< private >*/ + GDBusInterfaceSkeleton parent_instance; + SyncConfigSkeletonPrivate *priv; +}; + +struct _SyncConfigSkeletonClass +{ + GDBusInterfaceSkeletonClass parent_class; +}; + +GType sync_config__skeleton_get_type (void) G_GNUC_CONST; + +#if GLIB_CHECK_VERSION(2, 44, 0) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (SyncConfigSkeleton, g_object_unref) +#endif + +SyncConfig *sync_config__skeleton_new (void); + + +G_END_DECLS + +#endif /* __LIBSYNCCONFIG_H__ */ diff --git a/src/conf2/sync-config/session.c b/src/conf2/sync-config/session.c new file mode 100644 index 0000000..61b966c --- /dev/null +++ b/src/conf2/sync-config/session.c @@ -0,0 +1,8 @@ +#include "sync-dbus-server.h" + +int main(int argc, char const *argv[]) +{ + monitoring_requires_synchronized_configuration(); + init_gdbus_server(G_BUS_TYPE_SESSION); + return 0; +} \ No newline at end of file diff --git a/src/conf2/sync-config/sync-dbus-server.c b/src/conf2/sync-config/sync-dbus-server.c new file mode 100644 index 0000000..7a39f21 --- /dev/null +++ b/src/conf2/sync-config/sync-dbus-server.c @@ -0,0 +1,464 @@ +#include "sync-dbus-server.h" +#include +#include +#include +#include +#include +#include <../api/libkysettings.h> + +/***************************************dbus服务********************************************/ + +static SyncConfig *skeleton = NULL; + +static gboolean on_handle_register_schema(SyncConfig *skeleton, GDBusMethodInvocation *invocation, + const gchar *arg_Conf2Id, + const gchar *arg_SchemaId, + const gchar *arg_Path, + gpointer user_data) +{ + printf("Regester call %s\n", arg_Conf2Id); + + sync_config__complete_register_schema(skeleton, invocation, TRUE); + return TRUE; +} + +static gboolean on_handle_unregister_schema(SyncConfig *skeleton, GDBusMethodInvocation *invocation, + const gchar *arg_SchemaId, + const gchar *arg_Path, + gpointer user_data) +{ + printf("Unregester call\n"); + sync_config__complete_unregister_schema(skeleton, invocation, TRUE); + return TRUE; +} + +/** + * 连接上bus daemon的回调 + **/ +void on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data) +{ + klog_info("on_bus_acquired has been invoked, name is %s\n", name); + GError *error = NULL; + skeleton = sync_config__skeleton_new(); + // 连接方法同步处理函数 + g_signal_connect(G_OBJECT(skeleton), "handle-register-schema", G_CALLBACK(on_handle_register_schema), NULL); + g_signal_connect(G_OBJECT(skeleton), "handle-unregister-schema", G_CALLBACK(on_handle_unregister_schema), NULL); + // 发布服务到总线 + g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(skeleton), connection, "/com/kylin/kysdk/syncConfig", &error); + if (error != NULL) + { + klog_err("Error: Failed to export object. Reason: %s.\n", error->message); + g_error_free(error); + } +} + +/** + * 成功注册busName的回调 + **/ +void on_bus_name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data) +{ +} + +/** + * busName丢失的回调,一般是server挂了?? + **/ +void on_bus_name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data) +{ +} + +/** + * 测试发送信号函数,调用Hello.h自动生成的方法 + **/ +static gint status_value = 1; +static gboolean emit_test_state_signal(gconstpointer p) +{ + printf("emit_test_status_signal invoked\n"); + if (skeleton != NULL) + { + sync_config__emit_state(skeleton, status_value); + } + status_value++; +} + +gboolean init_gdbus_server(GBusType type) +{ + guint owner_id; + GMainLoop *loop; +#if !GLIB_CHECK_VERSION(2, 35, 0) + g_type_init(); +#endif + owner_id = g_bus_own_name(type, "com.kylin.kysdk.SyncConfig", + G_BUS_NAME_OWNER_FLAGS_NONE, + on_bus_acquired, on_bus_name_acquired, on_bus_name_lost, NULL, NULL); + + // 测试,每3s发一次signal + // g_timeout_add(3000, (GSourceFunc)emit_test_state_signal, NULL); + + // 主线程进入循环 + loop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(loop); + + g_bus_unown_name(owner_id); + + return TRUE; +} + +/***************************************同步配置********************************************/ +#define OUT +#define KPATH_LEN 512 +#define APP_LEN 128 +#define VER_LEN 32 +#define LINE_LEN 4096 + +struct _conf2_gsetting_handle_duple +{ + KSettings *ksetting; + GSettings *gsetting; +}; +// static GPtrArray *handle_array = g_ptr_array_new(); + + +static void _on_gsettings_key_changed(GSettings *gsetting, const char *key, void *user_data) +{ + GVariant *value = g_settings_get_value(gsetting, key); + KSettings *ksetting = (KSettings *)user_data; + char *conf2_value = kdk_conf2_get_value(ksetting, key); + if (0 == strcmp(conf2_value, g_variant_print(value, TRUE))) + return; + int ret = kdk_conf2_set_value(ksetting, key, g_variant_print(value, TRUE)); + if (ret) + { + printf("_on_gsettings_key_changed\n"); + // g_signal_emit(ksetting, k_settings_signals[SIGNAL_CHANGED], g_quark_from_string(key), key); + } + g_variant_unref(value); +} + +static void _on_conf2_key_changed(KSettings *ksetting, const char *key, void *user_data) +{ + GSettings *gsetting = (GSettings*)user_data; + const gchar *endptr = NULL; + GError *error = NULL; + GVariant *gsetting_value = g_settings_get_value(gsetting, key); + if (NULL != gsetting_value) + { + char *value = kdk_conf2_get_value(ksetting, key); + if (0 != strcmp(value, g_variant_print(gsetting_value, TRUE))) + { + char *type = kdk_conf2_get_type(ksetting, key); + GVariant *variant = g_variant_parse(G_VARIANT_TYPE(type), value, NULL, &endptr, &error); + if (NULL == variant) + { + // klog_err("[kysdk-conf2] %s -> %s\n", __func__, error->message); + return; + } + printf("_on_conf2_key_changed\n"); + g_settings_set_value(gsetting, key, variant); + g_settings_sync(); + g_variant_unref(variant); + } + g_variant_unref(gsetting_value); + } +} + +static char *_conf2_id_in_gsetting_schemas(const char *conf2_id, const char **gsetting_schemas) +{ + for(; *gsetting_schemas; gsetting_schemas++) + { + if (g_str_has_suffix(*gsetting_schemas, conf2_id)) + return *gsetting_schemas; + } + return NULL; +} + +/** + * @brief 比较两个版本号的大小 + * + * @param version1 版本号 + * @param version2 版本号 + * @return int version1大于version时返回1, 等于返回0, 小于返回-1 + */ +static int _compare_versions(char *version1, char *version2) +{ + if (version1 != NULL && version2 == NULL) + return 1; + else if (version1 == NULL && version2 != NULL) + return -1; + else if (version1 == NULL && version2 == NULL) + return 0; + + int result = 0; + + char v1[64], v2[64]; + memset(v1, 0, 64); + strcpy(v1, version1); + memset(v2, 0, 64); + strcpy(v2, version2); + + char *save_ptr1 = NULL; + char *save_ptr2 = NULL; + char *token1; + char *token2; + token1 = strtok_r(v1, ".-k", &save_ptr1); + token2 = strtok_r(v2, ".-k", &save_ptr2); + + while (1) + { + if (token1 != NULL && token2 != NULL) + { + int num1 = atoi(token1); + int num2 = atoi(token2); + + if (num1 > num2) + { + result = 1; + break; + } + else if (num1 < num2) + { + result = -1; + break; + } + } + else if (token1 == NULL && token2 != NULL) + { + result = -1; + break; + } + else if (token1 != NULL && token2 == NULL) + { + result = 1; + break; + } + else if (token1 == NULL && token2 == NULL) + break; + + token1 = strtok_r(NULL, ".-k", &save_ptr1); + token2 = strtok_r(NULL, ".-k", &save_ptr2); + } + + return result; +} + +static inline gboolean _copy_str_check(char *dest, char *src, size_t length) +{ + // 去掉前面空格 + g_strchug(src); + /*本行内容应该是 【应用名:】,如果不是以":"结尾,说明文件内容格式错误*/ + char *dot = strchr(src, ':'); + if (NULL != dot) + { + int len = dot - src; + strncpy(dest, src, len < length - 1 ? len : length); + return TRUE; + } + return FALSE; +} + +static gboolean _get_conf2_app(FILE *fp, OUT char *app) +{ + gboolean result = FALSE; + + char line[LINE_LEN], *dot = NULL; + int version_indent = 0; + while (fgets(line, LINE_LEN, fp)) + { + // 无缩进且不是注释,既第一行内容 + dot = strchr("#\t ", line[0]); + if (NULL == dot) + { + result = _copy_str_check(app, line, APP_LEN); + break; + } + } + return result; +} + +static gboolean _get_conf2_version(FILE *fp, OUT char *version) +{ + gboolean result = FALSE; + + char line[LINE_LEN], *dot = NULL; + int version_indent = 0; + while (fgets(line, LINE_LEN, fp)) + { + // 获取版本号的缩进,缩进最短的正文既版本号 + if (0 == version_indent) + { + for (;; version_indent++) + { + // line[version_indent]不是空格 + if (NULL == strchr("\t ", line[version_indent])) + { + // 注释行,缩进计数归零 + if ('#' == line[version_indent]) + version_indent = 0; + else + { + // 这行正文既一个版本号 + if (FALSE == _copy_str_check(version, line, VER_LEN)) + { + printf("111%s\n", line); + return result; + } + } + break; // for循环 + } + } + continue; // while循环 + } + // 检查这一行是不是版本号 + int i = 0; + for (; i < version_indent; i++) + { + // 空格不够 + if (NULL == strchr("\t ", line[i])) + { + // 注释行或空行 + if (NULL != strchr("#\n", line[i])) + break; // for循环 + else + { + // TODO: log 文件缩进格式错误 + printf("222%s\n", line); + return result; + } + } + } + if (i == version_indent) + { + if((line[i] != '#') && (line[i] != ' ') && (line[i] != '\t')) + { + + char tmp[VER_LEN]; + memset(tmp, 0, VER_LEN); + if (FALSE == _copy_str_check(tmp, line, VER_LEN)) + { + // TODO: log 文件格式错误 + printf("333%s\n", line); + return result; + } + if ( -1 == _compare_versions(version, tmp)) + { + strcpy(version, tmp); + } + } + } + } + result = TRUE; + return result; +} + +/* +自解析yaml格式文件,并获取应用名和版本号。 +注意:dbus-daemon会把自己的文件安装到basic目录,且后缀名为yaml,但 +文件内部的格式并不是yaml格式 + */ +static gboolean _get_conf2_app_and_version(const char *file, OUT char *app, OUT char *version) +{ + gboolean result = FALSE; + + memset(app, 0, APP_LEN); + memset(version, 0, VER_LEN); + + FILE *fp = fopen(file, "r"); + if (NULL == fp) + { + // TODO: 文件打开失败 + return result; + } + + result = _get_conf2_app(fp, app); + if (FALSE == result) + { + // TODO: log 文件内容不符合yaml格式 + goto out; + } + result = _get_conf2_version(fp, version); + if (FALSE == result) + { + // TODO: log 文件内容不符合yaml格式 + goto out; + } +out: + fclose(fp); + return result; +} + +static gboolean _connect_signal_sync_config(const char *conf2_id, const char *conf2_version, const char *gsetting_id, const char *gsetting_path) +{ + GSettings *gsetting = NULL; + KSettings *ksetting = NULL; + if ( NULL == gsetting_path) + gsetting = g_settings_new(gsetting_id); + else + gsetting = g_settings_new_with_path(gsetting_id, gsetting_path); + + ksetting = kdk_conf2_new(conf2_id, conf2_version); + + if (!(gsetting && ksetting)) + { + // TODO: log 创建句柄失败 + g_object_unref(gsetting); + kdk_conf2_ksettings_destroy(ksetting); + return FALSE; + } + g_signal_connect(gsetting, "changed", G_CALLBACK(_on_gsettings_key_changed), ksetting); + kdk_conf2_connect_signal(ksetting, "changed", (KCallBack)_on_conf2_key_changed, gsetting); + return TRUE; +} + +int monitoring_requires_synchronized_configuration() +{ + const char * const *gsetting_schemas = g_settings_list_schemas(); + + DIR *dir = NULL; + struct dirent *dire = NULL; + dir = opendir("/etc/kylin-config/basic"); + if (NULL == dir) + { + return -1; + } + + while (NULL != (dire = readdir(dir))) + { + char file_name[KPATH_LEN]; + memset(file_name, 0, KPATH_LEN); + char *dot = strrchr(dire->d_name, '.'); + if (NULL == dot) + { + // log + continue; + } + size_t len = dot - dire->d_name; + strncpy(file_name, dire->d_name, len); + // 文件名与gsetting的id相同,需要同步 + if (g_strv_contains(gsetting_schemas, file_name)) + { + // 获取应用名和版本号 + g_snprintf(file_name, KPATH_LEN, "/etc/kylin-config/basic/%s", dire->d_name); + char app[APP_LEN], version[VER_LEN]; + memset(app, 0, APP_LEN); + memset(version, 0, VER_LEN); + if (FALSE == _get_conf2_app_and_version(file_name, app, version)) + { + // TODO: 记录日志读取文件内应用与app失败 + continue; + } + char **ksetting_schemas = kdk_conf2_list_schemas(app, version); + if (NULL == ksetting_schemas) + { + //TODO: log 获取conf2中app的version版本的id列表失败 + continue; + } + for(char **tmp = ksetting_schemas; *tmp; tmp++) + { + char *gsetting_id = NULL; + if(NULL != (gsetting_id = _conf2_id_in_gsetting_schemas(*tmp, gsetting_schemas))) + _connect_signal_sync_config(*tmp, version, gsetting_id, NULL); + } + g_strfreev(ksetting_schemas); + } + } + closedir(dir); +} \ No newline at end of file diff --git a/src/conf2/sync-config/sync-dbus-server.h b/src/conf2/sync-config/sync-dbus-server.h new file mode 100644 index 0000000..441a762 --- /dev/null +++ b/src/conf2/sync-config/sync-dbus-server.h @@ -0,0 +1,19 @@ +#ifndef SYNC_DBUS_SERVER_H +#define SYNC_DBUS_SERVER_H + +#include "gdbus/libsyncconfig.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + int monitoring_requires_synchronized_configuration(); + + gboolean init_gdbus_server(GBusType type); + +#ifdef __cplusplus +} +#endif + +#endif // SYNC_DBUS_SERVER_H \ No newline at end of file diff --git a/src/conf2/sync-config/system.c b/src/conf2/sync-config/system.c new file mode 100644 index 0000000..af0a68e --- /dev/null +++ b/src/conf2/sync-config/system.c @@ -0,0 +1,8 @@ +#include "sync-dbus-server.h" + +int main(int argc, char const *argv[]) +{ + monitoring_requires_synchronized_configuration(); + init_gdbus_server(G_BUS_TYPE_SYSTEM); + return 0; +} \ No newline at end of file diff --git a/src/conf2/test/kyconf2-test.c b/src/conf2/test/kyconf2-test.c index cc281a4..8066793 100644 --- a/src/conf2/test/kyconf2-test.c +++ b/src/conf2/test/kyconf2-test.c @@ -49,7 +49,7 @@ int main(int argc, char *argv[]) * 只有已连接切读过一次配置时才能接收到该信号 * 接收信号需要开启主程序的消息循环 */ - // kdk_conf2_connect_signal(setting, "changed::int", (KCallBack)on_key_changed, NULL); + // kdk_conf2_connect_signal(setting, "changed::int", on_key_changed, NULL); char *schema_summary = kdk_conf2_get_schema_summary(setting); if (schema_summary) @@ -171,39 +171,39 @@ int main(int argc, char *argv[]) } /**********长整形读写**********/ - long l = kdk_conf2_get_default_int(setting, "long"); + long l = kdk_conf2_get_default_int64(setting, "long"); printf("Long default value is %d\n", l); - l = kdk_conf2_get_int(setting, "long"); + l = kdk_conf2_get_int64(setting, "long"); printf("Long value is %d\n", l); - success = kdk_conf2_set_int(setting, "long", l + 1); + success = kdk_conf2_set_int64(setting, "long", l + 1); if (0 == success) { printf("set long failed\n"); } /**********无符号整形读写**********/ - unsigned int u = kdk_conf2_get_default_int(setting, "uint"); + unsigned int u = kdk_conf2_get_default_uint(setting, "uint"); printf("Uint default value is %d\n", u); - u = kdk_conf2_get_int(setting, "uint"); + u = kdk_conf2_get_uint(setting, "uint"); printf("Uint value is %d\n", u); - success = kdk_conf2_set_int(setting, "uint", u + 1); + success = kdk_conf2_set_uint(setting, "uint", u + 1); if (0 == success) { printf("set uint failed\n"); } /**********无符号长整形读写**********/ - unsigned long t = kdk_conf2_get_default_int(setting, "ulong"); + unsigned long t = kdk_conf2_get_default_uint64(setting, "ulong"); printf("Ulong default value is %d\n", t); - t = kdk_conf2_get_int(setting, "ulong"); + t = kdk_conf2_get_uint64(setting, "ulong"); printf("Ulong value is %d\n", t); - success = kdk_conf2_set_int(setting, "ulong", t + 1); + success = kdk_conf2_set_uint64(setting, "ulong", t + 1); if (0 == success) { printf("set ulong failed\n"); @@ -304,7 +304,7 @@ int main(int argc, char *argv[]) int writable = kdk_conf2_is_writable(setting, "int"); printf("Int is %s\n", writable ? "writable" : "not writable"); - // kdk_conf2_connect_signal(setting, "reload", (KCallBack)on_reload, NULL); + // kdk_conf2_connect_signal(setting, "reload", on_reload, NULL); kdk_conf2_reload(); char **schemas = kdk_conf2_list_schemas("test", NULL); diff --git a/src/conf2/tools/conf2yaml.py b/src/conf2/tools/conf2yaml similarity index 100% rename from src/conf2/tools/conf2yaml.py rename to src/conf2/tools/conf2yaml diff --git a/src/conf2/tools/gschema_xml2yaml.py b/src/conf2/tools/gschema_xml2yaml similarity index 80% rename from src/conf2/tools/gschema_xml2yaml.py rename to src/conf2/tools/gschema_xml2yaml index bb4b2cd..bb8ace5 100755 --- a/src/conf2/tools/gschema_xml2yaml.py +++ b/src/conf2/tools/gschema_xml2yaml @@ -26,6 +26,14 @@ import re import sys import xml.etree.ElementTree as ET import yaml +import argparse + +id_help = "指定一个gschema.xml的一个id,例如org.ukui.control-center。"\ +"工具会将这个id以及其子id(例如org.ukui.control-center.apt.prox)转为yaml格式,并生成yaml文件。" + +version_help = "指定生成yaml文件的配置版本,如果不指定版本则默认版本为2.0.0.0-0k0.0" + +path_help = "指定yaml文件的生成目录,如果不指定生成在${HOME}/yaml目录中" def convert_one_file(data:dict, path:str, file:str): @@ -92,14 +100,24 @@ def convert_one_file(data:dict, path:str, file:str): print(f'{path}/{file} not exists') if __name__ == '__main__': - app = sys.argv[1] + parser = argparse.ArgumentParser(description='这是一个将gschema.xml文件转化为yaml格式的程序, 例如: python3 src/conf2/tools/gschema_xml2yaml.py -i org.ukui.control-center -v 3.2.1.0-0k0.15 -p /home/kylin') + parser.add_argument('--id', '-i', type=str, help=id_help) + parser.add_argument('--version', '-v', type=str, help=version_help) + parser.add_argument('--path', '-p', type=str, help=path_help) + args = parser.parse_args() + + app = args.id + version = '2.0.0-0k0.0' - if 3 == len(sys.argv): - version = sys.argv[2] + if args.version: + version = args.version + path = '/usr/share/glib-2.0/schemas' - if len(sys.argv) > 3: - path = sys.argv[3] + home = os.getenv('HOME') + out_path = f'{home}/yaml' + if args.path: + out_path = args.path organization = app.rsplit('.', 1)[0] @@ -122,8 +140,7 @@ if __name__ == '__main__': yaml_data = yaml.safe_dump(result, allow_unicode = True) # 将YAML数据写入文件 - home = os.getenv('HOME') - file = f"{home}/yaml/{app}.yaml" + file = f"{out_path}/{app}.yaml" if not os.path.exists(os.path.dirname(file)): os.makedirs(os.path.dirname(file), exist_ok=True) diff --git a/src/conf2/tools/health-check b/src/conf2/tools/health-check new file mode 100644 index 0000000..7e00826 --- /dev/null +++ b/src/conf2/tools/health-check @@ -0,0 +1,210 @@ +#!/usr/bin/python3 +import os +import re +import sys +import yaml + +override_dirs = ['/etc/kylin-config/industry'] +output_file = '' + +# 每个问题类型声明一个列表存储对应的问题类型 +# 键值类型改变 +type_list = [] +# 键值权限改变 +permission_list = [] +# 取值范围改变 +range_list = [] +# 版本不在应用支持范围 +version_list = [] + +# 打印报告 +def print_err(): + with open(output_file, 'w') as file: + if type_list: + file.write('键值类型改变\n') + file.write(' ' * 4 + '描述\n') + file.write(' ' * 8 + '键值类型变化会导致应用读取数据是读不到数据或读到错误数据,导致应用运行结果异常\n') + file.write(' ' * 4 + '如何修复\n') + file.write(' ' * 8 + '联系应用调查原因,商讨修改方案\n') + file.write(' ' * 4 + '问题上下文\n') + for basic_file, override_file, path in type_list: + file.write(' ' * 8 + f'应用文件:{basic_file} 目标文件:{override_file} 位置:{path}\n') + if permission_list: + file.write('键值权限改变\n') + file.write(' ' * 4 + '描述\n') + file.write(' ' * 8 + '键值权限改变可能会导致定制文件的内容无法覆盖应用文件的内容,导致定制内容不生效\n') + file.write(' ' * 4 + '如何修复\n') + file.write(' ' * 8 + '联系应用调查原因,商讨修改方案\n') + file.write(' ' * 4 + '问题上下文\n') + for basic_file, override_file, path in permission_list: + file.write(' ' * 8 + f'应用文件:{basic_file} 目标文件:{override_file} 位置:{path}\n') + if range_list: + file.write('取值范围改变改变\n') + file.write(' ' * 4 + '描述\n') + file.write(' ' * 8 + '取值范围改变,可能会导致应用在读/写数据是读到/写入无意义的数据,导致应用运行出错或设置数据失败\n') + file.write(' ' * 4 + '如何修复\n') + file.write(' ' * 8 + '联系应用调查原因,商讨修改方案\n') + file.write(' ' * 4 + '问题上下文\n') + for basic_file, override_file, path in range_list: + file.write(' ' * 8 + f'应用文件:{basic_file} 目标文件:{override_file} 位置:{path}\n') + if version_list: + file.write('版本不在应用规定范围\n') + file.write(' ' * 4 + '描述\n') + file.write(' ' * 8 + '如果版本不在应用指定支持的版本范围内无法确定配置应用读取的配置是否存在与该版本的配置内容中,可能会导致应用运行错误\n') + file.write(' ' * 4 + '如何修复\n') + file.write(' ' * 8 + '调查文件来源,如果可以删除建议删除,不能删除的话联系应用与定制包的负责人,商讨修改方案\n') + file.write(' ' * 4 + '问题上下文\n') + for basic_file, override_file, path in version_list: + file.write(' ' * 8 + f'应用文件:{basic_file} 目标文件:{override_file} 位置:{path}\n') + +# 查询枚举类型数据的枚举定义 +def _recursive_search(dictionary, key): + if key in dictionary: + return dictionary[key] + else: + for value in dictionary.values(): + if isinstance(value, dict): + result = _recursive_search(value, key) + if result is not None: + return result + return None + +def _compare_versions(src, dest): + src_nums = re.findall(r'\d+', src) + dest_nums = re.findall(r'\d+', dest) + lengh = len(src_nums) if len(src_nums) > len(dest_nums) else len(dest_nums) + ret = -1 if len(src_nums) > len(dest_nums) else 1 if len(src_nums) < len(dest_nums) else 0 + for i in range(0, lengh): + if dest_nums[i] > src_nums[i]: + return 1 + if dest_nums[i] < src_nums[i]: + return -1 + return ret + +def _calculate_default_version(data:dict): + versions = list(data.keys()) + if '_default_version' in versions: + return data.get('_default_version') + default_version = '' + for version in versions: + if default_version == '': + default_version = version + continue + if 1 == _compare_versions(default_version, version): + default_version = version + return default_version + +def check_value_type(basic_data:dict, override_data:dict, path:str, app, version, basic_file, override_file): + basic_group = basic_data + override_group = override_data + for group in path.split('.'): + basic_group = basic_group[group] + override_group = override_group[group] + result = [] + for key, value in override_group.items(): + if key in basic_group: + if not isinstance(value, dict): + continue + basic_key_is_group = True if '_default' in next(iter(value.values())) else False + override_key_is_group = True if '_default' in next(iter(value.values())) else False + # 同名但是一个是组,一个是键 + if basic_key_is_group != override_key_is_group: + result.append((basic_file, override_file, f'{app}/{version}/{path}/{key}')) + else: + # 组 + if basic_key_is_group and override_key_is_group: + check_value_type(basic_data, override_data, f'{path}.{key}', app, version, basic_file, override_file) + else: + basic_key_type = basic_group[key]['_type'] + override_key_type = override_group[key]['_type'] + if basic_key_type != override_key_type: + type_list.append((basic_file, override_file, f'{app}/{version}/{path}/{key}')) + # 获取组的权限,未声明默认'public' + basic_key_permission = basic_group.get('_permission', 'public') + override_key_permission = override_group.get('_permission', 'public') + # 读取键的权限,未声明则使用组权限 + basic_key_permission = basic_group[key].get('_permission', basic_key_permission) + override_key_permission = override_group[key].get('_permission', override_key_permission) + if basic_key_permission != override_key_permission: + permission_list.append((basic_file, override_file, f'{app}/{version}/{path}/{key}')) + + basic_key_range = basic_group[key].get('_range', '') + override_key_range = override_group[key].get('_range', '') + if basic_key_range and override_key_range: + if basic_key_type == 'enum': + basic_key_range = _recursive_search(basic_data, basic_key_range[1:]) + override_key_range = _recursive_search(override_data, override_key_range[1:]) + if basic_key_range != override_key_range: + range_list.append((basic_file, override_file, f'{app}/{version}/{path}/{key}')) + # elif basic_key_range == '' and override_key_range != '': + # range_list.append((basic_file, override_file, f'{app}/{version}/{path}/{key}')) + # elif basic_key_range != '' and override_key_range == '': + # range_list.append((basic_file, override_file, f'{app}/{version}/{path}/{key}')) + return result + +# 检查组配置文件 +def check_group_config(basic_data, override_data, basic_file, override_file): + for app, app_data in basic_data.items(): + for version, version_data in app_data.items(): + groups = set(override_data.keys()) + for group in groups: + if group in version_data: + if not isinstance(version_data[group], dict): + continue + check_value_type(version_data, override_data, group, app, version, basic_file, override_file) + +# 检查应用配置文件 +def check_app_config(basic_data, override_data, basic_file, override_file): + version_err = [] + for app, app_data in override_data.items(): + if app in basic_data: + # 读取应用支持版本号区间 + min_version = '' + max_version = '' + if os.path.exists(f'/etc/kylin-config/compatibility/{app}-compatibility-settings.yaml'): + with open(f'/etc/kylin-config/compatibility/{app}-compatibility-settings.yaml', 'r') as f: + version_range = yaml.safe_load(f) + min_version = version_range[app]['compatibility']['min_version'] + max_version = version_range[app]['compatibility']['max_version'] + versions = set(basic_data[app].keys()) | set(override_data[app].keys()) + for version in versions: + if (version == '_default_version'): + continue + if min_version and max_version: + if -1 == _compare_versions(version, min_version) or 1 == _compare_versions(version, max_version): + version_list.append((basic_file, override_file, f'{app}/{version}')) + else: + # 定制文件版本是否比应用文件版本高 待定? + pass + if version in basic_data[app] and version in override_data[app]: + for group in override_data[app][version]: + if not isinstance(override_data[app][version][group], dict): + continue + check_value_type(basic_data[app][version], override_data[app][version], group, app, version, basic_file, override_file) + +def check_one_app(basic_data, basic_file): + for dir in override_dirs: + for root, dirs, files in os.walk(dir): + for file in files: + override_file = f'{root}/{file}' + with open(override_file, 'r') as f: + override_data = yaml.safe_load(f) + for value in override_data.values(): + is_group_file = True if '_default' in next(iter(value.values())) else False + if is_group_file: + check_group_config(basic_data, override_data, basic_file, override_file) + else: + check_app_config(basic_data, override_data, basic_file, override_file) + +if __name__ == '__main__': + if len(sys.argv) < 2: + print("example: 111.py /home/xxx/output.txt") + sys.exit() + output_file = sys.argv[1] + for root, dirs, files in os.walk('/etc/kylin-config/basic'): + for file in files: + basic_file = f'{root}/{file}' + with open(basic_file, 'r') as f: + basic_data = yaml.safe_load(f) + check_one_app(basic_data, basic_file) + print_err() \ No newline at end of file diff --git a/src/conf2/tools/json2yaml.py b/src/conf2/tools/json2yaml similarity index 100% rename from src/conf2/tools/json2yaml.py rename to src/conf2/tools/json2yaml diff --git a/src/conf2/tools/kconf2-editor.py b/src/conf2/tools/kconf2-editor similarity index 58% rename from src/conf2/tools/kconf2-editor.py rename to src/conf2/tools/kconf2-editor index 7f6840d..8504520 100755 --- a/src/conf2/tools/kconf2-editor.py +++ b/src/conf2/tools/kconf2-editor @@ -9,6 +9,7 @@ import tkinter as tk import tkinter.ttk as ttk import tkinter.messagebox as msgbox import tkinter.filedialog as filedialog +import tkinter.simpledialog as simpledialog import dbus from gi.repository import GLib @@ -25,14 +26,16 @@ def close_menu(event): download_menu.unpost() def on_search(): - pack_list = root.pack_slaves() - if view_frame in pack_list: + text = search_button.cget('text') + if text == 'search': + search_button.config(text='cancel') view_frame.pack_forget() search_frame.pack(side='bottom', fill='both', expand=True) search_tree.delete(*search_tree.get_children()) search_entry.config(state='normal') # search_entry.event_generate("") - else: + elif text == 'cancel': + search_button.config(text='search') search_frame.pack_forget() view_frame.pack(side='bottom', fill='both', expand=True) items = tree.selection() @@ -55,21 +58,60 @@ def on_search_entry_change(event): search_tree.insert('', 'end', text= key) def on_download(): + class MultiSelectDialog(tk.simpledialog.Dialog): + def body(self, master): + self.results = [] + self.options = list(target_view.keys()) + self.vars = [] + for i, option in enumerate(self.options): + var = tk.IntVar() + checkbutton = tk.Checkbutton(master, text=option, variable=var) + checkbutton.grid(row=i, sticky='w') + self.vars.append(var) + + select_all_button = tk.Button(master, text="全选", command=self.all_select) + select_all_button.grid(row=len(self.options), column=0, sticky='w') + + select_none_button = tk.Button(master, text="全不选", command=self.none_select) + select_none_button.grid(row=len(self.options), column=1, sticky='w') + + def apply(self): + self.results = [option for var, option in zip(self.vars, self.options) if var.get() == 1] + + def all_select(self): + for var in self.vars: + var.set(1) + + def none_select(self): + for var in self.vars: + var.set(0) + global target_view - path = filedialog.askdirectory(mustexist=True, title=' Choose a folder') - if path: - success = converter.editor_save(target_view, path) - if success: - msgbox.showinfo(message='Save successed') - else: - msgbox.showinfo(message='Save failed') + dialog = MultiSelectDialog(root, title="Multi-Select Dialog") + if dialog.results != []: + path = filedialog.askdirectory(mustexist=True, title=' Choose a folder') + if path: + try: + converter._value_override_default(target_view) + for app in dialog.results: + yaml_file_path = f'{path}/{app}.yaml' + if os.path.exists(yaml_file_path): + msgbox.askyesno(message=f'{yaml_file_path} is existed. Do you want to replace it') + else: + with open(yaml_file_path, 'w') as yaml_file: + yaml_file.write(yaml.safe_dump({app:target_view[app]}, allow_unicode = True)) + msgbox.showinfo(message='Save successed') + except Exception as e: + msgbox.showinfo(message='Save failed') def on_download_one(): global target_view - key = tree.item(right_select_item, 'text') + app = tree.item(right_select_item, 'text') + apps = [] + apps.append(app) path = filedialog.askdirectory(mustexist=True, title=' Choose a folder') if path: - success = converter.editor_save({key:target_view[key]}, path) + success = converter.editor_save(apps, target_view, path) if success: msgbox.showinfo(message='Save successed') else: @@ -85,40 +127,80 @@ def on_set(): user = destination_file.split('/')[2] - key = id = value = '' + key = id = value = permission = type = range = '' for widget in inner_frame.winfo_children(): if isinstance(widget, tk.Text): - if 'key' in widget.winfo_name: - key = widget.get() - if 'id' in widget.winfo_name: - id = widget.get() - if 'custom' in widget.winfo_name: - value = widget.get() + if 'key' == widget.winfo_name(): + key = widget.get(1.0, 'end') + key = key.strip() + if 'id' == widget.winfo_name(): + id = widget.get(1.0, 'end') + id = id.strip() + if 'type' == widget.winfo_name(): + type = widget.get(1.0, 'end') + type = type.strip() + if 'permission' == widget.winfo_name(): + permission = widget.get(1.0, 'end') + permission = permission.strip() + if 'range' == widget.winfo_name(): + range = widget.get(1.0, 'end') + range = range.strip() + if 'custom' == widget.winfo_name(): + value = widget.get(1.0, 'end') + value = value.strip() path = search_entry.get() version = path.split('/')[1] - print(f'{user} {id} {version} {key} {value}') + + # 类型检测 + try: + if type != 'enum': + variant_type = GLib.VariantType(type) + variant = GLib.Variant.parse(variant_type, value) + except Exception as e: + msgbox.showinfo('unknown keyword') + return + + # 取值范围检测 + if type == 'enum' and value not in range: + msgbox.showinfo(message='Out of range') + return + elif type != 'enum' and range != '': + try: + min = GLib.Variant.parse(variant_type, range.split(',')[0].strip()) + max = GLib.Variant.parse(variant_type, range.split(',')[1].strip()) + if variant.compare(min) < 0 or variant.compare(max) > 0: + msgbox.showinfo(message='Out of range') + return + except Exception as e: + msgbox.showinfo(message=e) + return bus = dbus.SystemBus() obj = bus.get_object('com.kylin.kysdk.conf2', '/com/kylin/kysdk/conf2') - interface = dbus.Interface(obj, 'com.kylin.kysdk.conf2') - # success = interface.set(user, id, version, key, value) - # if success: - # global target_view - # target_view = converter._db2dict(f'{destination_file}/.config/kylin-config/user.db') - # msgbox.showinfo(message='Set successed') - # else: - # msgbox.showinfo(message='Set failed') + obj_interface = dbus.Interface(obj, dbus_interface='com.kylin.kysdk.conf2') + success = obj_interface.set(user, id, version, key, value) + if success: + global target_view + target_view = converter._db2dict(f'{destination_file}/.config/kylin-config/user.db') + msgbox.showinfo(message='Set successed') + else: + msgbox.showinfo(message='Set failed') except Exception as e: print(e) def on_search_tree_select(event): items = search_tree.selection() - text = search_tree.item(items[0], 'text') + text = search_tree.item(items, 'text') + if text == '': + return tree.selection_set(search_list[text]) tree.see(search_list[text]) search_frame.pack_forget() view_frame.pack(side='bottom', fill='both', expand=True) + search_button_text = search_button.cget('text') + if search_button_text == 'cancel': + search_button.config(text='search') def on_tree_select(event): selected_item = tree.selection() @@ -180,7 +262,7 @@ def on_tree_select(event): summary_label = tk.Label(inner_frame, text=f'摘要', anchor='w') summary_label.pack(side='top', fill='x') - summary_text = tk.Text(inner_frame, height=3, width=100, wrap='word') + summary_text = tk.Text(inner_frame, height=3, width=100, wrap='word', name='summary') summary_text.insert('1.0', tmp.get('_summary')) summary_text.config(state='disabled') summary_text.pack(side='top', fill='x', expand=True) @@ -189,7 +271,7 @@ def on_tree_select(event): decription_label = tk.Label(inner_frame, text=f'描述', anchor='w') decription_label.pack(side='top', fill='x') - decription_text = tk.Text(inner_frame, height=3, width=100, wrap='word') + decription_text = tk.Text(inner_frame, height=3, width=100, wrap='word' ,name='description') decription_text.insert('1.0', tmp.get('_description')) decription_text.config(state='disabled') decription_text.pack(side='top', fill='x', expand=True) @@ -198,11 +280,33 @@ def on_tree_select(event): permission_label = tk.Label(inner_frame, text=f'权限', anchor='w') permission_label.pack(side='top', fill='x') - permission_text = tk.Text(inner_frame, height=1, width=100, wrap='word') + permission_text = tk.Text(inner_frame, height=1, width=100, wrap='word', name='permission') permission_text.insert('1.0', permission) permission_text.config(state='disabled') permission_text.pack(side='top', fill='x', expand=True) + if tmp.get('_range') is not None: + decription_label = tk.Label(inner_frame, text=f'取值范围', anchor='w') + decription_label.pack(side='top', fill='x') + range = tmp.get('_range') + if tmp.get('_type') == 'enum': + if range.startswith('@'): + path = search_entry.get() + version_data = target_view[path.split('/')[0]][path.split('/')[1]] + # _开头的应该是内部函数仅在类内部使用,但我实在懒得搬代码了 + element_list = converter._recursive_search(version_data, range[1:]) + value_list = [] + for element in element_list: + value_list.append(element['_nick']) + range = str(value_list) + else: + data = yaml.safe_load(range) + range = str(list(data.keys())) + decription_text = tk.Text(inner_frame, height=3, width=100, wrap='word' ,name='range') + decription_text.insert('1.0', range) + decription_text.config(state='disabled') + decription_text.pack(side='top', fill='x', expand=True) + if '_default' in tmp: default_value = tmp['_default'] if isinstance(default_value, bool): @@ -216,16 +320,17 @@ def on_tree_select(event): default_text.config(state='disabled') default_text.pack(side='top', fill='x', expand=True) - custom_value = tmp.get('_value') - if custom_value is None or custom_value == default_value: - custom_value = '默认值' - custom_label = tk.Label(inner_frame, text=f'当前值', anchor='w') - custom_label.pack(side='top', fill='x') + if combobox.get() == 'custom': + custom_value = tmp.get('_value') + if custom_value is None: + custom_value = '默认值' + custom_label = tk.Label(inner_frame, text=f'当前值', anchor='w') + custom_label.pack(side='top', fill='x') - custom_text = tk.Text(inner_frame, height=5, width=100, wrap='word', name='custom') - custom_text.insert('1.0', custom_value) - custom_text.config(state='disabled') - custom_text.pack(side='top', fill='x', expand=True) + custom_text = tk.Text(inner_frame, height=5, width=100, wrap='word', name='custom') + custom_text.insert('1.0', custom_value) + custom_text.config(state='disabled') + custom_text.pack(side='top', fill='x', expand=True) if type != 'group' and permission == 'public' and combobox.get() == 'custom': custom_text.config(state='normal') @@ -275,7 +380,7 @@ root.bind("", close_menu) download_menu = tk.Menu(root, tearoff=0) download_menu.add_command(label="下载", command=on_download_one) -download_menu.add_command(label="导入到其他目录", command=on_import_file) +# download_menu.add_command(label="导入到其他目录", command=on_import_file) search_list = {} @@ -302,19 +407,19 @@ search_entry = tk.Entry(button_frame, state='readonly') search_entry.bind("", on_search_entry_change) # 搜索按钮 -# search_icon = tk.BitmapImage(data=search_icon_data) -search_button = tk.Button(button_frame, text= 's', command=on_search, width=20) +# search_icon = tk.PhotoImage('/etc/kylin-config/search.png') +search_button = tk.Button(button_frame, text='search', command=on_search, width=20) # 下载按钮 -# download_icon = tk.PhotoImage(file="download_icon.png") -download_button = tk.Button(button_frame, text= 'd', command=on_download, width=20) +# download_icon = tk.PhotoImage(file="/etc/kylin-config/download.png") +download_button = tk.Button(button_frame, text='export', command=on_download, width=20) # 视图选择列表 with open('/etc/kylin-config/conf2.yaml', 'r') as file: configures = yaml.safe_load(file) options = configures['dirs'] if os.path.exists(f'{destination_file}/.config/kylin-config/configs'): - options.append('user') + options.append('mutable') options.append('custom') options.reverse() @@ -354,16 +459,33 @@ right_frame.pack(side='right', fill='both', expand=True) # 创建一个Canvas canvas = tk.Canvas(right_frame) canvas.pack(side="left", fill="both", expand=True) - -# 将Canvas的窗口设置为Frame -inner_frame = tk.Frame(canvas) -inner_frame.grid(row=0, column=0, sticky="nsew") -canvas_window = canvas.create_window((0, 0), window=inner_frame, anchor="nw") +canvas.config(scrollregion=canvas.bbox("all")) right_scrollbar = ttk.Scrollbar(right_frame, orient="vertical", command=canvas.yview) right_scrollbar.pack(side="right", fill="y") canvas.configure(yscrollcommand=right_scrollbar.set) +# 将Canvas的窗口设置为Frame +inner_frame = tk.Frame(canvas) + +canvas_window = canvas.create_window((0, 0), window=inner_frame, anchor="nw") +inner_frame.bind("", lambda event: canvas.config(scrollregion=canvas.bbox("all"))) +# 控制滚动条滚动 Button-4是向上滚动, Button-5是向下滚动 event.num的数值代表按钮id +def on_mouse_scroll(event): + inner_height = inner_frame.winfo_height() + canvas_height = canvas.winfo_height() + # 内容长度是否需要滚动 + if inner_height > canvas_height: + # 仅响应在canvas空间区域的滚轮事件 + if canvas.winfo_containing(event.x_root, event.y_root) == canvas: + if event.num == 4: + canvas.yview_scroll(-2, "units") + elif event.num == 5: + canvas.yview_scroll(2, "units") + +canvas.bind_all("", on_mouse_scroll) +canvas.bind_all("", on_mouse_scroll) + # 创建Treeview显示搜索匹配的路径 search_tree = ttk.Treeview(search_frame, show='tree') search_tree.bind("<>", on_search_tree_select) @@ -373,4 +495,4 @@ search_scrollbar = ttk.Scrollbar(search_frame, orient="vertical", command=search search_scrollbar.pack(side="right", fill="y") search_tree.configure(yscrollcommand=search_scrollbar.set) -root.mainloop() \ No newline at end of file +root.mainloop() diff --git a/src/conf2/tools/kconf2-editor.c b/src/conf2/tools/kconf2-editor.c index 0b7720b..89f98e6 100644 --- a/src/conf2/tools/kconf2-editor.c +++ b/src/conf2/tools/kconf2-editor.c @@ -18,6 +18,9 @@ * */ + +/*于2.5.1.0版本舍弃,专用python实现可视化工具*/ + #include "../api/libkysettings.h" #include "../api/ksettingsschema.h" @@ -847,4 +850,4 @@ int main(int argc, char *argv[]) gtk_main(); return 0; -} \ No newline at end of file +} diff --git a/src/conf2/tools/kconf2-tool.c b/src/conf2/tools/kconf2-tool.c index 60f15c4..3b2535d 100644 --- a/src/conf2/tools/kconf2-tool.c +++ b/src/conf2/tools/kconf2-tool.c @@ -68,6 +68,7 @@ static void print_help() " writable Check if a key is writable\n" " monitor Watch for changes\n" // " monitor-reload Watch for realod\n" + " reload Reload configuration file, retain user configuration" " save Save User config in target folder" "\n" "Use kconf2 help \"COMMAND\" to get detailed help.\n"); @@ -281,11 +282,11 @@ int main(int argc, char *argv[]) if (0 == strcmp(argv[1], "list-schemas")) { - if (argc < 3) - { - print_command("list-schemas"); - exit(0); - } + // if (argc < 3) + // { + // print_command("list-schemas"); + // exit(0); + // } gboolean limit_app = FALSE, limit_version = FALSE; if (argc > 2) limit_app = TRUE; @@ -643,4 +644,4 @@ int main(int argc, char *argv[]) print_help(); } return 0; -} \ No newline at end of file +}