diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..18e2903 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,327 @@ +libkysdk-base (2.5.1.0-0k0.8) nile; urgency=medium + + * BUG:无 + * 需求号:无 + * 其他改动说明: + 1. 配置组新增permission,description,summary属性 + 2. permission权限新增final,stable + 3. conf2与gsettings联动,联动后gsettings设置的同步到conf2,反向同理 + 4. 原本已经做了设置的应用,升级到接入conf2后,原本的设置保留 + 5. 新增trigger,应用装包,目录下出现新的配置文件,自动执行reload + * 其他改动影响域:无 + + -- tianshaoshuai Mon, 20 May 2024 15:18:53 +0800 + +libkysdk-base (2.4.1.0-0k1.7) nile; urgency=medium + + * BUG:#222596 【dbus】libkysdk-base com.kylin.kysdk.conf2系统总线服务级和方法级整改 + * 需求号:无 + * 其他改动说明:1. 修复服务级管控无法读取到白名单问题 + * 其他改动影响域:无 + + -- tianshaoshuai Fri, 17 May 2024 17:59:57 +0800 + +libkysdk-base (2.4.1.0-0k1.6) nile; urgency=medium + + * BUG: + #222596 【dbus】libkysdk-base com.kylin.kysdk.conf2系统总线服务级和方法级整改 + #227605 【华为云】【guesetos】【控制面板】控制面板缺少电源模块 + #227626 【需求26164】【华为云】【guestos】【真机】会话管理器显示/隐藏电源操作-组件自身配置 + * 需求号:无 + * 其他改动说明:无 + * 其他改动影响域:无 + + -- tianshaoshuai Fri, 17 May 2024 09:32:19 +0800 + +libkysdk-base (2.4.1.0-0k1.5) nile; urgency=medium + + * BUG:无 + * 需求号:无 + * 其他改动说明: + 1. 修复xml2yaml工具生成时枚举缩进位置不对的问题 + 2. 修复读数据库到内存(db2dict)的逻辑 + * 其他改动影响域:无 + + -- tianshaoshuai Wed, 15 May 2024 15:34:45 +0800 + +libkysdk-base (2.4.1.0-0k1.4) nile; urgency=medium + + * BUG: + #226776 【conf2】新增对同目录里有相同的配置项的处理中点击下载按钮选择新建文件夹时,终端报错核心已转储 + #226686 【conf2】调整目录优先级执行报错 [用例#909448] + * 需求号:无 + * 其他改动说明: + 1. 更新gschema.xml转yaml工具 + 2. 增加部分日志 + 3. 修复服务管控中,非白名单应用调用dbus接口时虽然报错但接口仍然被调用的问题 + * 其他改动影响域:无 + + -- tianshaoshuai Thu, 09 May 2024 10:44:27 +0800 + +libkysdk-base (2.4.1.0-0k1.3) nile; urgency=medium + + * BUG:#222596 【dbus】libkysdk-base com.kylin.kysdk.conf2系统总线服务级和方法级整改 + * 需求号:无 + * 其他改动说明: + 1. 修改pc文件中的版本号 + 2. 修改session服务启动时kylin-config目录不存在会报错的问题 + 3. 修改kdk_conf2_set_string会多一对单引号的问题 + 4. conf2服务生成统一视图时增加处理final和stable属性,组增加属性 + * 其他改动影响域:无 + + -- tianshaoshuai Tue, 07 May 2024 14:53:36 +0800 + +libkysdk-base (2.4.1.0-0k1.2) nile; urgency=medium + + * BUG:无 + * 需求号:无 + * 其他改动说明:修改control文件依赖 + * 其他改动影响域:无 + + -- shaozhimin Fri, 26 Apr 2024 15:44:33 +0800 + +libkysdk-base (2.4.1.0-0k1.1) nile; urgency=medium + + * BUG:无 + * 需求号:无 + * 其他改动说明:修改数据库表结构 + * 其他改动影响域:无 + + -- szm-min Thu, 25 Apr 2024 14:21:27 +0800 + +libkysdk-base (2.4.1.0-0k1.0) nile; urgency=medium + + * BUG:无 + * 需求号: + #28841 调整目录优先级 + #28842 新增对同目录相同项的处理 + * 其他改动说明: + 1. 新增兼容并发读写功能 + 2. 新增工具类包libkysdk-conf2-tools,工具不在集成在libkysdk-conf2包里 + 3. 新增日志记录功能 + 4. 配置文件里去掉children和keys关键字 + 5. 所有固定关键字前面加下划线统一格式 + 6. 取消common目录,通用配置存放位置可以除basic以外的所有目录 + * 其他改动影响域:无 + + -- tianshaoshuai Fri, 19 Apr 2024 14:43:46 +0800 + +libkysdk-base (2.4.1.0-0k0.2) nile; urgency=medium + + * BUG:无 + * 需求号:无 + * 其他改动说明:整机导入合入bug#221702 【CPM20240409009145】 【PanguX-5.6.0.17 + BIOS 1.01】【HW】【系统功能】【Freetest】系统监视器下物理内存使用量显示不正确,已用内存比物理内存总量还大(2/2 DUTs)。(一般+必现+常用功能)修复 + * 其他改动影响域:无 + + -- szm-min Mon, 15 Apr 2024 16:03:10 +0800 + +libkysdk-base (2.4.1.0-0k0.1) nile; urgency=medium + + * BUG:无 + * 需求号:无 + * 其他改动说明:更新 diagnostics symbols文件 + * 其他改动影响域:无 + + -- szm-min Mon, 01 Apr 2024 18:13:31 +0800 + +libkysdk-base (2.4.1.0-0k0.0) nile; urgency=medium + + * BUG:无 + * 需求号:#26164 华为云桌面默认关闭接口在HWS及HCSO做一个开启关闭休眠接口开关需求 + * 其他改动说明:任务#203739:需求26164的conf2适配内容同步2403u1版本 / 迁移华为云桌面192292 sdk提供conf2机制,支持睡眠、休眠、切换用户、关机可配置 + * 其他改动影响域:无 + + -- szm-min Wed, 27 Mar 2024 09:03:47 +0800 + +libkysdk-base (2.3.0.0-0k0.14) nile; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 : 添加symbols文件 + + -- szm-min Wed, 27 Dec 2023 09:10:05 +0800 + +libkysdk-base (2.3.0.0-0k0.13) nile; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 : 移除CMake对老旧C++的绑定 + + -- szm-min Wed, 20 Dec 2023 16:30:33 +0800 + +libkysdk-base (2.3.0.0-0k0.12) nile; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 : 修复已知的conf2模块导致的崩溃问题,上传可视化工具 + + -- tian-shaoshuai Tue, 12 Dec 2023 16:46:35 +0800 + +libkysdk-base (2.3.0.0-0k0.11) nile; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 : 恢复diagnostics 模块内容 + + -- szm-min Tue, 12 Dec 2023 14:50:30 +0800 + +libkysdk-base (2.3.0.0-0k0.10) nile; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 : conf2模块创建用户配置目录时所有者为root的问题处理 + + -- tian-shaoshuai Mon, 04 Dec 2023 17:24:42 +0800 + +libkysdk-base (2.3.0.0-0k0.9) nile; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 : 修改conf2模块pc文件中的Requires + + -- tian-shaoshuai Fri, 01 Dec 2023 14:15:59 +0800 + +libkysdk-base (2.3.0.0-0k0.8) nile; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 : 修改conf2模块pc文件 + + -- tian-shaoshuai Fri, 01 Dec 2023 10:35:17 +0800 + +libkysdk-base (2.3.0.0-0k0.7) nile; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 : 修改conf2模块pc文件 + + -- tian-shaoshuai Fri, 01 Dec 2023 09:12:19 +0800 + +libkysdk-base (2.3.0.0-0k0.6) nile; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 :修复conf2模块的部分问题 + + -- tian-shaoshuai Thu, 30 Nov 2023 14:11:14 +0800 + +libkysdk-base (2.3.0.0-0k0.5) nile; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 :修改pc文件和动态库版本 + + -- szm-min Tue, 28 Nov 2023 16:52:06 +0800 + +libkysdk-base (2.3.0.0-0k0.4) nile; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 : 上传libkysdk-conf2 + + -- tian-shaoshuai Mon, 27 Nov 2023 15:26:44 +0800 + +libkysdk-base (2.3.0.0-0k0.2) nile; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 :解决i386动态库路径与加载路径不一致问题 + + -- szm-min Mon, 20 Nov 2023 09:39:22 +0800 + +libkysdk-base (2.3.0.0-0k0.1) nile; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 : 改动态库路径到对应的架构下 + + -- szm-min Fri, 20 Oct 2023 09:59:39 +0800 + +libkysdk-base (2.3.0.0-0k0.0) nile; urgency=medium + + * BUG号 : 无 + * 需求号 : 23985 SDK文档完善 + * 其他修改 : 无 + + -- szm-min Fri, 20 Oct 2023 09:59:39 +0800 + +libkysdk-base (2.2.0.0-0k0.4) yangtze; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 : 注释掉log模块的日志转储部分 + 解决安全扫描漏洞 + + -- szm-min Thu, 19 Oct 2023 17:18:40 +0800 + +libkysdk-base (2.2.0.0-0k0.3) yangtze; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 : 添加 diagnostics 模块 + + -- szm-min Mon, 28 Aug 2023 09:59:47 +0800 + +libkysdk-base (2.2.0.0-0k0.2) yangtze; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 : 去掉control文件中的libkysdk-diagnostics依赖 + + -- szm-min Fri, 04 Aug 2023 10:45:16 +0800 + +libkysdk-base (2.2.0.0-0k0.1) yangtze; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 : 删除shlibs自动补全依赖 + + -- szm-min Thu, 13 Jul 2023 14:25:27 +0800 + +libkysdk-base (2.2.0.0-0k0.0) yangtze; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 : update changelog 2.2 + + -- szm-min Wed, 21 Jun 2023 10:03:19 +0800 + +libkysdk-base (2.0.0.0-0k0.6) yangtze; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 : 修改control文件依赖版本 + + -- szm-min Tue, 20 Jun 2023 19:51:55 +0800 + +libkysdk-base (2.0.0.0-0k0.5) yangtze; urgency=medium + + * BUG号 : 无 + * 需求号 : 无 + * 其他修改 : + + -- szm-min Tue, 06 Jun 2023 15:30:08 +0800 + +libkysdk-base (1.2.0.5kylin1-ok1~0715) yangtze; urgency=medium + + * 合并主线v1.2 + * update v1.2 + + -- szm-min Fri, 15 Jul 2022 10:32:27 +0800 + +libkysdk-base (1.1.1kylin1-ok4~0627) yangtze; urgency=medium + + * 修改为quilt格式 + * openkylin 重新导入 + * fix bug#125453,控制面板账户模块缺少"账户信息"设置项 + + -- Xie Wei Fri, 10 Jun 2022 19:35:33 +0800 + +libkysdk-base (1.1.1kylin1) yangtze; urgency=medium + + * BUG号 : 119832 + * 需求号 : 无 + * 其他修改 : + * publish for v1.1 update + + -- liuyunhe Tue, 17 May 2022 16:17:53 +0800 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..da09bdc --- /dev/null +++ b/debian/control @@ -0,0 +1,200 @@ +Source: libkysdk-base +Section: utils +Priority: optional +Maintainer: kylin +Build-Depends: debhelper-compat (= 12), + libc6-dev, + cmake, + libsystemd-dev, + libdbus-1-dev, + libssl-dev, + libgtk-3-dev, + libglib2.0-dev, + libsqlite3-dev +Standards-Version: 4.4.1 +Homepage: http://gitlab2.kylin.com/kysdk/kysdk-base + +Package: libkysdk-base +Architecture: any +Section: utils +Depends: libkysdk-timer (= ${binary:Version}), + libkysdk-log (= ${binary:Version}), + libkysdk-config (= ${binary:Version}), + libkysdk-utils (= ${binary:Version}), + libkysdk-diagnostics (= ${binary:Version}), + libkysdk-basecommon (= ${binary:Version}), + libkysdk-gsetting (= ${binary:Version}) +Multi-Arch: same +Description: 麒麟开发者套件 - 基础层套件,提供日志管理、消息通信、进程守护、线程管理、定时器、调试与埋点、配置文件、utils + +Package: libkysdk-base-dev +Architecture: all +Section: utils +Depends: libkysdk-base (= ${binary:Version}), + libkysdk-timer-dev (= ${binary:Version}), + libkysdk-log-dev (= ${binary:Version}), + libkysdk-config-dev (= ${binary:Version}), + libkysdk-utils-dev (= ${binary:Version}), + libkysdk-diagnostics-dev (= ${binary:Version}), + libkysdk-gsetting-dev (= ${binary:Version}) +Multi-Arch: foreign +Description: 麒麟开发者套件 - 基础层套件 - 开发库,提供日志管理、消息通信、进程守护、线程管理、定时器、调试与埋点、配置文件、utils + +Package: libkysdk-timer +Architecture: any +Section: utils +Depends: libkysdk-basecommon (>=1.2.0), + libkysdk-utils(>=1.2.0), + libc6 +Multi-Arch: same +Description: 定制器模块库 + +Package: libkysdk-timer-dev +Architecture: all +Section: utils +Depends: libkysdk-utils-dev(>=1.2.0), + libkysdk-timer (= ${binary:Version}), + libkysdk-basecommon(>=1.2.0), + libc6 +Multi-Arch: foreign +Description: 定时器模块 - 开发库 + +Package: libkysdk-log +Architecture: any +Section: utils +Depends: libkysdk-config(>=1.2.0), + logrotate, + libkysdk-basecommon(>=1.2.0), + libkysdk-utils(>=1.2.0), + dbus, + libc6, + libdbus-1-3, + libsystemd0 +Multi-Arch: same +Description: 日志库 + +Package: libkysdk-basecommon +Architecture: any +Section: utils +Depends: +Multi-Arch: same +Description: kysdk-base层公用数据包 + +Package: libkysdk-log-dev +Architecture: all +Section: utils +Depends: libkysdk-log (= ${binary:Version}), + libkysdk-config-dev(>=1.2.0), + libkysdk-utils-dev(>=1.2.0), + libsystemd-dev +Multi-Arch: foreign +Description: 日志库 - 开发库 + +Package: libkysdk-config +Architecture: any +Section: utils +Depends: libkysdk-basecommon(>=1.2.0), + libkysdk-utils(>=1.2.0), + libc6 +Multi-Arch: same +Description: 配置文件库 + +Package: libkysdk-config-dev +Architecture: all +Section: utils +Depends: libkysdk-utils-dev(>=1.2.0), + libkysdk-config (= ${binary:Version}) +Multi-Arch: foreign +Description: 配置文件库 - 开发库 + +Package: libkysdk-utils +Architecture: any +Section: utils +Depends: libkysdk-basecommon(>=1.2.0), + libc6 +Multi-Arch: same +Description: 开发者utils + +Package: libkysdk-utils-dev +Architecture: all +Section: utils +Depends: libkysdk-utils (= ${binary:Version}) +Multi-Arch: foreign +Description: 开发者utils - 开发库 + +Package: libkysdk-diagnostics +Architecture: any +Section: utils +Depends: libkysdk-basecommon(>=1.2.0), + libkysdk-utils(>=1.2.0), + libc6, + libdbus-1-3, + libgcc-s1 | libgcc1, + libssl1.1, + libstdc++6 +Multi-Arch: same +Description: 开发者diagnostics + +Package: libkysdk-diagnostics-dev +Architecture: all +Section: utils +Depends: libkysdk-diagnostics (= ${binary:Version}) +Multi-Arch: foreign +Description: 开发者diagnostics - 开发库 + +Package: libkysdk-gsetting +Architecture: any +Section: utils +Depends: libgtk-3-0, + libglib2.0-0, + libkysdk-basecommon(>=1.2.0), + libatk1.0-0, + libc6, + libcairo-gobject2, + libcairo2, + libgdk-pixbuf2.0-0, + libharfbuzz0b, + libpango-1.0-0, + libpangocairo-1.0-0 +Multi-Arch: same +Description: 开发者gsetting + +Package: libkysdk-gsetting-dev +Architecture: all +Section: utils +Depends: libkysdk-gsetting (= ${binary:Version}) +Multi-Arch: foreign +Description: 开发者gsetting - 开发库 + +Package: libkysdk-conf2 +Architecture: any +Section: utils +Depends: libglib2.0-0, + libgtk-3-0, + libkysdk-basecommon(>=2.2.0), + libc6, + libsqlite3-0, + libkysdk-log, + python3.8, + python3-dbus, + python3-watchdog, + ${misc:Depends}, + ${shlibs:Depends} +Multi-Arch: same +Description: 统一配置模块 + +Package: libkysdk-conf2-dev +Architecture: all +Section: utils +Depends: libkysdk-conf2 (= ${binary:Version}) +Multi-Arch: foreign +Description: 统一配置模块 - 开发库 + +Package: libkysdk-conf2-tools +Architecture: any +Section: utils +Depends: libkysdk-conf2 (= ${binary:Version}), + ${misc:Depends}, + ${shlibs:Depends} +Multi-Arch: same +Description: 统一配置模块 - 工具包 diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..bdeab8c --- /dev/null +++ b/debian/copyright @@ -0,0 +1,43 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: kysdk-base +Upstream-Contact: +Source: + +Files: * +Copyright: + +License: + + + . + + +# If you want to use GPL v2 or later for the /debian/* files use +# the following clauses, or change it to suit. Delete these two lines +Files: debian/* +Copyright: 2021 kylin +License: GPL-2+ + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + . + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see + . + On Debian systems, the complete text of the GNU General + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". + +# Please also look if there are files or directories which have a +# different copyright/license attached and list them here. +# Please avoid picking licenses with terms that are more restrictive than the +# packaged work, as it may make Debian's contributions unacceptable upstream. +# +# If you need, there are some extra license texts available in two places: +# /usr/share/debhelper/dh_make/licenses/ +# /usr/share/common-licenses/ diff --git a/debian/gbp.conf b/debian/gbp.conf new file mode 100644 index 0000000..e2232b4 --- /dev/null +++ b/debian/gbp.conf @@ -0,0 +1,2 @@ +[DEFAULT] +compression=xz diff --git a/debian/libkysdk-base-dev.install b/debian/libkysdk-base-dev.install new file mode 100644 index 0000000..3b0680b --- /dev/null +++ b/debian/libkysdk-base-dev.install @@ -0,0 +1 @@ +development-files/kysdk-base.pc usr/share/pkgconfig/ diff --git a/debian/libkysdk-basecommon.install b/debian/libkysdk-basecommon.install new file mode 100644 index 0000000..549796e --- /dev/null +++ b/debian/libkysdk-basecommon.install @@ -0,0 +1 @@ +development-files/kysdk-base.conf etc/ld.so.conf.d diff --git a/debian/libkysdk-conf2-dev.install b/debian/libkysdk-conf2-dev.install new file mode 100644 index 0000000..2377218 --- /dev/null +++ b/debian/libkysdk-conf2-dev.install @@ -0,0 +1,2 @@ +src/conf2/api/libkysettings.h usr/include/kysdk/kysdk-base +development-files/kysdk-conf2.pc usr/share/pkgconfig/ \ No newline at end of file diff --git a/debian/libkysdk-conf2-tools.install b/debian/libkysdk-conf2-tools.install new file mode 100644 index 0000000..575a426 --- /dev/null +++ b/debian/libkysdk-conf2-tools.install @@ -0,0 +1,3 @@ +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 diff --git a/debian/libkysdk-conf2.install b/debian/libkysdk-conf2.install new file mode 100644 index 0000000..7eb9672 --- /dev/null +++ b/debian/libkysdk-conf2.install @@ -0,0 +1,12 @@ +usr/lib/*/libkyconf2.so* +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/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/ diff --git a/debian/libkysdk-conf2.symbols b/debian/libkysdk-conf2.symbols new file mode 100644 index 0000000..48fa02c --- /dev/null +++ b/debian/libkysdk-conf2.symbols @@ -0,0 +1,82 @@ +# SymbolsHelper-Confirmed: 2.4.1.0 amd64 +libkyconf2.so.1 libkysdk-conf2 #MINVER# + app_data_destroy@Base 2.3.0.0 + data_equal@Base 2.3.0.0 + data_hash@Base 2.3.0.0 + k_settings_get_type@Base 2.3.0.0 + kdk_conf2_connect_signal@Base 2.3.0.0 + kdk_conf2_get_boolean@Base 2.3.0.0 + kdk_conf2_get_child@Base 2.3.0.0 + kdk_conf2_get_default_boolean@Base 2.4.1.0 + kdk_conf2_get_default_double@Base 2.4.1.0 + kdk_conf2_get_default_enum@Base 2.4.1.0 + kdk_conf2_get_default_int64@Base 2.4.1.0 + kdk_conf2_get_default_int@Base 2.4.1.0 + kdk_conf2_get_default_string@Base 2.4.1.0 + kdk_conf2_get_default_strv@Base 2.4.1.0 + kdk_conf2_get_default_uint64@Base 2.4.1.0 + kdk_conf2_get_default_uint@Base 2.4.1.0 + kdk_conf2_get_default_value@Base 2.3.0.0 + kdk_conf2_get_descrition@Base 2.3.0.0 + kdk_conf2_get_double@Base 2.3.0.0 + kdk_conf2_get_enum@Base 2.3.0.0 + kdk_conf2_get_id@Base 2.3.0.0 + kdk_conf2_get_int64@Base 2.3.0.0 + kdk_conf2_get_int@Base 2.3.0.0 + kdk_conf2_get_range@Base 2.3.0.0 + kdk_conf2_get_string@Base 2.3.0.0 + kdk_conf2_get_strv@Base 2.3.0.0 + kdk_conf2_get_summary@Base 2.3.0.0 + kdk_conf2_get_type@Base 2.3.0.0 + kdk_conf2_get_uint64@Base 2.3.0.0 + kdk_conf2_get_uint@Base 2.3.0.0 + kdk_conf2_get_value@Base 2.3.0.0 + kdk_conf2_get_version@Base 2.3.0.0 + kdk_conf2_has_key@Base 2.4.1.0 + kdk_conf2_is_schema@Base 2.4.1.0 + kdk_conf2_is_writable@Base 2.3.0.0 + kdk_conf2_ksettings_destroy@Base 2.3.0.0 + kdk_conf2_list_children@Base 2.3.0.0 + kdk_conf2_list_keys@Base 2.3.0.0 + kdk_conf2_list_schemas@Base 2.3.0.0 + kdk_conf2_new@Base 2.3.0.0 + kdk_conf2_new_extends_id@Base 2.4.1.0 + kdk_conf2_range_check@Base 2.3.0.0 + kdk_conf2_reload@Base 2.3.0.0 + kdk_conf2_reset@Base 2.3.0.0 + kdk_conf2_save_user_configure@Base 2.4.1.0 + kdk_conf2_schema_destroy@Base 2.3.0.0 + kdk_conf2_schema_find_child@Base 2.3.0.0 + kdk_conf2_schema_get_id@Base 2.3.0.0 + kdk_conf2_schema_get_key@Base 2.3.0.0 + kdk_conf2_schema_get_version@Base 2.3.0.0 + kdk_conf2_schema_has_key@Base 2.3.0.0 + kdk_conf2_schema_key_get_default_value@Base 2.3.0.0 + kdk_conf2_schema_key_get_description@Base 2.3.0.0 + kdk_conf2_schema_key_get_name@Base 2.3.0.0 + kdk_conf2_schema_key_get_permission@Base 2.3.0.0 + kdk_conf2_schema_key_get_range@Base 2.3.0.0 + kdk_conf2_schema_key_get_summary@Base 2.3.0.0 + kdk_conf2_schema_key_get_value@Base 2.3.0.0 + kdk_conf2_schema_key_range_check@Base 2.3.0.0 + kdk_conf2_schema_key_value_type@Base 2.3.0.0 + kdk_conf2_schema_list_children@Base 2.3.0.0 + kdk_conf2_schema_list_keys@Base 2.3.0.0 + kdk_conf2_schema_reload@Base 2.3.0.0 + kdk_conf2_schema_table_lookup@Base 2.3.0.0 + kdk_conf2_schema_update_schemas_table@Base 2.3.0.0 + kdk_conf2_set_boolean@Base 2.3.0.0 + kdk_conf2_set_double@Base 2.3.0.0 + kdk_conf2_set_enum@Base 2.3.0.0 + kdk_conf2_set_int64@Base 2.3.0.0 + kdk_conf2_set_int@Base 2.3.0.0 + kdk_conf2_set_string@Base 2.3.0.0 + kdk_conf2_set_strv@Base 2.3.0.0 + kdk_conf2_set_uint64@Base 2.3.0.0 + kdk_conf2_set_uint@Base 2.3.0.0 + kdk_conf2_set_value@Base 2.3.0.0 + schema_data_destroy@Base 2.3.0.0 + schemas_table@Base 2.3.0.0 + version_data_destroy@Base 2.3.0.0 + kdk_conf2_get_schema_summary@Base 2.5.1.0 + kdk_conf2_get_schema_desription@Base 2.5.1.0 diff --git a/debian/libkysdk-config-dev.install b/debian/libkysdk-config-dev.install new file mode 100644 index 0000000..c30b446 --- /dev/null +++ b/debian/libkysdk-config-dev.install @@ -0,0 +1,2 @@ +src/config/libkyconf.h usr/include/kysdk/kysdk-base +development-files/kysdk-config.pc usr/share/pkgconfig/ diff --git a/debian/libkysdk-config-dev.manpages b/debian/libkysdk-config-dev.manpages new file mode 100644 index 0000000..9c3caa0 --- /dev/null +++ b/debian/libkysdk-config-dev.manpages @@ -0,0 +1,8 @@ +man/config/kdk_conf_destroy.3 +man/config/kdk_conf_get_value.3 +man/config/kdk_conf_init.3 +man/config/kdk_conf_list_group.3 +man/config/kdk_conf_list_key.3 +man/config/kdk_conf_reload.3 +man/config/kdk_config_freeall.3 +man/config/libkyconf.3 \ No newline at end of file diff --git a/debian/libkysdk-config.install b/debian/libkysdk-config.install new file mode 100644 index 0000000..c0b4144 --- /dev/null +++ b/debian/libkysdk-config.install @@ -0,0 +1 @@ +usr/lib/*/libkyconf.so* diff --git a/debian/libkysdk-config.symbols b/debian/libkysdk-config.symbols new file mode 100644 index 0000000..5e9c3c9 --- /dev/null +++ b/debian/libkysdk-config.symbols @@ -0,0 +1,27 @@ +# SymbolsHelper-Confirmed: 2.0.0.0 amd64 +libkyconf.so.1 libkysdk-cofig #MINVER# + S_destroyParse@Base 1.1.1 + S_getGroupList@Base 1.1.1 + S_getKeyList@Base 1.1.1 + S_getValue@Base 1.1.1 + S_newParse@Base 1.1.1 + S_parseFile@Base 1.1.1 + S_setAssignmentDelimiter@Base 1.1.1 + S_setKeyDelimiter@Base 1.1.1 + S_setValue@Base 1.1.1 + S_setValueDelimiter@Base 1.1.1 + S_write2File@Base 1.1.1 + S_writeBack@Base 1.1.1 + isgsettings@Base 1.1.1 + isjson@Base 1.1.1 + isxml@Base 1.1.1 + kdk_conf_destroy@Base 1.1.1 + kdk_conf_disable_autoreload@Base 1.1.1 + kdk_conf_enable_autoreload@Base 1.1.1 + kdk_conf_get_value@Base 1.1.1 + kdk_conf_init@Base 1.1.1 + kdk_conf_list_group@Base 1.1.1 + kdk_conf_list_key@Base 1.1.1 + kdk_conf_reload@Base 1.1.1 + kdk_conf_set_value@Base 1.1.1 + kdk_config_freeall@Base 2.0.0.0 diff --git a/debian/libkysdk-diagnostics-dev.install b/debian/libkysdk-diagnostics-dev.install new file mode 100644 index 0000000..8fd5d7f --- /dev/null +++ b/debian/libkysdk-diagnostics-dev.install @@ -0,0 +1,2 @@ +src/diagnostics/libkydiagnostics.h usr/include/kysdk/kysdk-base +development-files/kysdk-diagnostics.pc usr/share/pkgconfig/ \ No newline at end of file diff --git a/debian/libkysdk-diagnostics-dev.manpages b/debian/libkysdk-diagnostics-dev.manpages new file mode 100644 index 0000000..0e35d2c --- /dev/null +++ b/debian/libkysdk-diagnostics-dev.manpages @@ -0,0 +1,2 @@ +man/diagnostics/kdk_buried_point.3 +man/diagnostics/libkydiagnostics.3 \ No newline at end of file diff --git a/debian/libkysdk-diagnostics.install b/debian/libkysdk-diagnostics.install new file mode 100644 index 0000000..61e0f32 --- /dev/null +++ b/debian/libkysdk-diagnostics.install @@ -0,0 +1 @@ +usr/lib/*/libkydiagnostics.so* \ No newline at end of file diff --git a/debian/libkysdk-diagnostics.symbols b/debian/libkysdk-diagnostics.symbols new file mode 100644 index 0000000..6619017 --- /dev/null +++ b/debian/libkysdk-diagnostics.symbols @@ -0,0 +1,3 @@ +# SymbolsHelper-Confirmed: 2.2.0.0 amd64 +libkydiagnostics.so.1 libkysdk-diagnostics #MINVER# + kdk_buried_point@Base 2.2.0.0 diff --git a/debian/libkysdk-gsetting-dev.install b/debian/libkysdk-gsetting-dev.install new file mode 100644 index 0000000..54e8004 --- /dev/null +++ b/debian/libkysdk-gsetting-dev.install @@ -0,0 +1,2 @@ +src/gsettings/libkygsetting.h usr/include/kysdk/kysdk-base +development-files/kysdk-gsetting.pc usr/share/pkgconfig/ diff --git a/debian/libkysdk-gsetting-dev.manpages b/debian/libkysdk-gsetting-dev.manpages new file mode 100644 index 0000000..1aec38d --- /dev/null +++ b/debian/libkysdk-gsetting-dev.manpages @@ -0,0 +1,9 @@ +man/gsettings/kdk_gsettings_get.3 +man/gsettings/kdk_gsettings_set.3 +man/gsettings/kdk_settings_get_double.3 +man/gsettings/kdk_settings_get_int.3 +man/gsettings/kdk_settings_get_string.3 +man/gsettings/kdk_settings_reset.3 +man/gsettings/kdk_settings_set_int.3 +man/gsettings/kdk_settings_set_string.3 +man/gsettings/libkygsetting.3 \ No newline at end of file diff --git a/debian/libkysdk-gsetting.install b/debian/libkysdk-gsetting.install new file mode 100644 index 0000000..f470bbe --- /dev/null +++ b/debian/libkysdk-gsetting.install @@ -0,0 +1 @@ +usr/lib/*/libkygsetting.so* diff --git a/debian/libkysdk-gsetting.symbols b/debian/libkysdk-gsetting.symbols new file mode 100644 index 0000000..761c1af --- /dev/null +++ b/debian/libkysdk-gsetting.symbols @@ -0,0 +1,11 @@ +# SymbolsHelper-Confirmed: 2.0.0.0 amd64 +libkygsetting.so.1 libkysdk-gsetting #MINVER# + kdk_gsettings_get@Base 2.0.0.0 + kdk_gsettings_set@Base 2.0.0.0 + kdk_settings_get_double@Base 2.0.0.0 + kdk_settings_get_int@Base 2.0.0.0 + kdk_settings_get_string@Base 2.0.0.0 + kdk_settings_reset@Base 2.0.0.0 + kdk_settings_set_int@Base 2.0.0.0 + kdk_settings_set_string@Base 2.0.0.0 + schema_key_is_exist@Base 2.0.0.0 diff --git a/debian/libkysdk-log-dev.install b/debian/libkysdk-log-dev.install new file mode 100644 index 0000000..8c993f5 --- /dev/null +++ b/debian/libkysdk-log-dev.install @@ -0,0 +1,2 @@ +src/log/libkylog.h usr/include/kysdk/kysdk-base +development-files/kysdk-log.pc usr/share/pkgconfig/ diff --git a/debian/libkysdk-log-dev.manpages b/debian/libkysdk-log-dev.manpages new file mode 100644 index 0000000..f47d65f --- /dev/null +++ b/debian/libkysdk-log-dev.manpages @@ -0,0 +1,5 @@ +man/log/kdk_logger_flush.3 +man/log/kdk_logger_init.3 +man/log/kdk_logger_set_autowrap.3 +man/log/kdk_logger_setdir.3 +man/log/libkylog.3 \ No newline at end of file diff --git a/debian/libkysdk-log.install b/debian/libkysdk-log.install new file mode 100644 index 0000000..e4d46f6 --- /dev/null +++ b/debian/libkysdk-log.install @@ -0,0 +1,4 @@ +usr/lib/*/libkylog.so* +src/log/kylog-default.conf etc/kysdk/kysdk-base +src/log/kylog-rotate-default etc/kysdk/kysdk-base +#src/log/logrotate.cron etc/kysdk/kysdk-base diff --git a/debian/libkysdk-log.symbols b/debian/libkysdk-log.symbols new file mode 100644 index 0000000..550ca90 --- /dev/null +++ b/debian/libkysdk-log.symbols @@ -0,0 +1,29 @@ +# SymbolsHelper-Confirmed: 1.1.1 amd64 +libkylog.so.1 libkysdk-log #MINVER# + append_wrap@Base 1.1.1 + destroyKLogger@Base 1.1.1 + destroyMessageQueue@Base 1.1.1 + emptyMessageQueue@Base 1.1.1 + flushMessageQueue@Base 1.1.1 + formatMessage@Base 1.1.1 + getRecordDate@Base 1.1.1 + initKLogger@Base 1.1.1 + initMessageQueue@Base 1.1.1 + insertMessage@Base 1.1.1 + kdk_logger_flush@Base 1.1.1 + kdk_logger_init@Base 1.1.1 + kdk_logger_set_autowrap@Base 1.1.1 + kdk_logger_setdir@Base 1.1.1 + kdk_logger_write@Base 1.1.1 + klog_printformat@Base 1.1.1 + klog_rotate_init@Base 1.1.1 + loadFormatOptions@Base 1.1.1 + logger@Base 1.1.1 + recycle@Base 1.1.1 + setRootDir@Base 1.1.1 + set_autowrap@Base 1.1.1 + startMQDaemon@Base 1.1.1 + stringLType@Base 1.1.1 + stringLevel@Base 1.1.1 + writeFile@Base 1.1.1 + writeLog@Base 1.1.1 diff --git a/debian/libkysdk-timer-dev.install b/debian/libkysdk-timer-dev.install new file mode 100644 index 0000000..6410cd9 --- /dev/null +++ b/debian/libkysdk-timer-dev.install @@ -0,0 +1,2 @@ +src/timer/libkytimer.h usr/include/kysdk/kysdk-base +development-files/kysdk-timer.pc usr/share/pkgconfig/ diff --git a/debian/libkysdk-timer-dev.manpages b/debian/libkysdk-timer-dev.manpages new file mode 100644 index 0000000..1322bc3 --- /dev/null +++ b/debian/libkysdk-timer-dev.manpages @@ -0,0 +1,6 @@ +man/timer/kdk_timer_destroy.3 +man/timer/kdk_timer_init.3 +man/timer/kdk_timer_reset.3 +man/timer/kdk_timer_start.3 +man/timer/kdk_timer_stop.3 +man/timer/libkytimer.3 \ No newline at end of file diff --git a/debian/libkysdk-timer.install b/debian/libkysdk-timer.install new file mode 100644 index 0000000..ee4f378 --- /dev/null +++ b/debian/libkysdk-timer.install @@ -0,0 +1 @@ +usr/lib/*/libkytimer.so* diff --git a/debian/libkysdk-timer.symbols b/debian/libkysdk-timer.symbols new file mode 100644 index 0000000..18584e1 --- /dev/null +++ b/debian/libkysdk-timer.symbols @@ -0,0 +1,7 @@ +# SymbolsHelper-Confirmed: 1.1.1 amd64 +libkytimer.so.1 libkysdk-timer #MINVER# + kdk_timer_destroy@Base 1.1.1 + kdk_timer_init@Base 1.1.1 + kdk_timer_reset@Base 1.1.1 + kdk_timer_start@Base 1.1.1 + kdk_timer_stop@Base 1.1.1 diff --git a/debian/libkysdk-utils-dev.install b/debian/libkysdk-utils-dev.install new file mode 100644 index 0000000..3a89112 --- /dev/null +++ b/debian/libkysdk-utils-dev.install @@ -0,0 +1,7 @@ +src/utils/sdkmarcos.h usr/include/kysdk/kysdk-base +src/utils/kerr.h usr/include/kysdk/kysdk-base +src/utils/cstring-extension.h usr/include/kysdk/kysdk-base +src/utils/kyutils.h usr/include/kysdk/kysdk-base +src/utils/data-structure/linklist/skip_linklist/skip_linklist.h usr/include/kysdk/kysdk-base +src/utils/data-structure/linklist/listdata.h usr/include/kysdk/kysdk-base +development-files/kysdk-utils.pc usr/share/pkgconfig/ diff --git a/debian/libkysdk-utils-dev.manpages b/debian/libkysdk-utils-dev.manpages new file mode 100644 index 0000000..ec0fd15 --- /dev/null +++ b/debian/libkysdk-utils-dev.manpages @@ -0,0 +1,24 @@ +man/utils/kdkVolumeBaseCharacterConvert.3 +man/utils/kdkVolumeBaseNumericalConvert.3 +man/utils/kysdk_create_skiplist.3 +man/utils/kysdk_destroy_skiplist.3 +man/utils/kysdk_skiplist_delete.3 +man/utils/kysdk_skiplist_insert.3 +man/utils/kysdk_skiplist_search.3 +man/utils/kysdk_skiplist_setmaxlevels.3 +man/utils/libkydatastruct.3 +man/utils/libkyutils.3 +man/utils/str2lower.3 +man/utils/str2upper.3 +man/utils/strcounts.3 +man/utils/strendwith.3 +man/utils/strfirstof.3 +man/utils/strlastof.3 +man/utils/strskipblank.3 +man/utils/strskipspace.3 +man/utils/strsplit.3 +man/utils/strstartswith_nocase.3 +man/utils/strstartswith.3 +man/utils/strstrip.3 +man/utils/strstripblank.3 +man/utils/strstripspace.3 \ No newline at end of file diff --git a/debian/libkysdk-utils.install b/debian/libkysdk-utils.install new file mode 100644 index 0000000..f29dab9 --- /dev/null +++ b/debian/libkysdk-utils.install @@ -0,0 +1,2 @@ +usr/lib/*/libkydatastruct.so* +usr/lib/*/libkyutils.so* diff --git a/debian/libkysdk-utils.symbols b/debian/libkysdk-utils.symbols new file mode 100644 index 0000000..d2a104f --- /dev/null +++ b/debian/libkysdk-utils.symbols @@ -0,0 +1,13 @@ +# SymbolsHelper-Confirmed: 1.2.0.5 amd64 +libkydatastruct.so.1 libkysdk-utils #MINVER# + kysdk_create_skiplist@Base 1.1.1 + kysdk_destroy_skiplist@Base 1.1.1 + kysdk_skiplist_delete@Base 1.1.1 + kysdk_skiplist_insert@Base 1.1.1 + kysdk_skiplist_search@Base 1.1.1 + kysdk_skiplist_setmaxlevels@Base 1.1.1 +libkyutils.so.1 libkysdk-utils #MINVER# + kdkVolumeBaseCharacterConvert@Base 1.2.0.5 + kdkVolumeBaseNumericalConvert@Base 1.2.0.5 + parse_size@Base 1.2.0.5 + size_to_human_string@Base 1.2.0.5 diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..e1c367c --- /dev/null +++ b/debian/rules @@ -0,0 +1,25 @@ +#!/usr/bin/make -f +# See debhelper(7) (uncomment to enable) +# output every command that modifies files on the build system. +#export DH_VERBOSE = 1 + + +# see FEATURE AREAS in dpkg-buildflags(1) +#export DEB_BUILD_MAINT_OPTIONS = hardening=+all + +# see ENVIRONMENT in dpkg-buildflags(1) +# package maintainers to append CFLAGS +#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic +# package maintainers to append LDFLAGS +#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed + + +%: + dh $@ + + +# dh_make generated override targets +# This is example for Cmake (See https://bugs.debian.org/641051 ) +#override_dh_auto_configure: +# dh_auto_configure -- # -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH) + diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..89ae9db --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/development-files/kysdk-base.pc b/development-files/kysdk-base.pc index a6b6bf9..1b07ec8 100644 --- a/development-files/kysdk-base.pc +++ b/development-files/kysdk-base.pc @@ -1,6 +1,6 @@ -base_version=2.3.0.0 +base_version=2.5.0 Name: libkysdk-base Description: kysdk base layer Requires: kysdk-log >= ${base_version} kysdk-config >= ${base_version} kysdk-timer >= ${base_version} kysdk-utils >= ${base_version} -Version: 2.3.0.0 \ No newline at end of file +Version: 2.5.0 \ No newline at end of file diff --git a/development-files/kysdk-conf2.pc b/development-files/kysdk-conf2.pc index 703740b..cf35f3d 100644 --- a/development-files/kysdk-conf2.pc +++ b/development-files/kysdk-conf2.pc @@ -1,5 +1,5 @@ Name: libkysdk-conf2 Description: kysdk base conf2 -Version: 2.3.0.0 +Version: 2.5.0 Cflags: -I/usr/include/kysdk/kysdk-base/ Libs: -lkyconf2 \ No newline at end of file diff --git a/development-files/kysdk-config.pc b/development-files/kysdk-config.pc index 87baedb..b377d54 100644 --- a/development-files/kysdk-config.pc +++ b/development-files/kysdk-config.pc @@ -1,8 +1,8 @@ -base_version=2.3.0.0 +base_version=2.4.0 Name: libkysdk-config Description: kysdk base layer config component Requires: kysdk-utils -Version: 2.3.0.0 +Version: 2.5.0 Cflags: -I/usr/include/kysdk/kysdk-base/ -Libs: -lkysdk-config +Libs: -lkyconf \ No newline at end of file diff --git a/development-files/kysdk-diagnostics.pc b/development-files/kysdk-diagnostics.pc index 6722e87..817d777 100644 --- a/development-files/kysdk-diagnostics.pc +++ b/development-files/kysdk-diagnostics.pc @@ -1,5 +1,5 @@ Name: libkysdk-diagnostics Description: kysdk base layer diagnostics component -Version: 2.3.0.0 +Version: 2.5.0 Cflags: -I/usr/include/kysdk/kysdk-base/ Libs: -lkydiagnostics \ No newline at end of file diff --git a/development-files/kysdk-gsetting.pc b/development-files/kysdk-gsetting.pc index aecd7ea..7bf6c48 100644 --- a/development-files/kysdk-gsetting.pc +++ b/development-files/kysdk-gsetting.pc @@ -1,6 +1,6 @@ Name: libkysdk-gsetting Description: kysdk base layer gsettings component Requires: gtk+-3.0 glib-2.0 -Version: 2.3.0.0 -Libs: -lkysdk-gsetting -Cflags: -I/usr/include/kysdk/kysdk-base/ +Version: 2.5.0 +Libs: -lkygsetting +Cflags: -I/usr/include/kysdk/kysdk-base/ \ No newline at end of file diff --git a/development-files/kysdk-log.pc b/development-files/kysdk-log.pc index 6f066c6..ef167c9 100644 --- a/development-files/kysdk-log.pc +++ b/development-files/kysdk-log.pc @@ -1,6 +1,6 @@ Name: libkysdk-log Description: kysdk base layer log component Requires: kysdk-config kysdk-utils libsystemd -Version: 2.3.0.0 +Version: 2.5.0 Cflags: -I/usr/include/kysdk/kysdk-base/ -Libs: -lkysdk-log +Libs: -lkylog \ No newline at end of file diff --git a/development-files/kysdk-timer.pc b/development-files/kysdk-timer.pc index ef46fe2..7ab4d0f 100644 --- a/development-files/kysdk-timer.pc +++ b/development-files/kysdk-timer.pc @@ -1,6 +1,6 @@ Name: libkysdk-timer Description: kysdk base layer time component Requires: kysdk-utils -Version: 2.3.0.0 +Version: 2.5.0 Cflags: -I/usr/include/kysdk/kysdk-base/ -Libs: -lkysdk-timer +Libs: -lkytimer \ No newline at end of file diff --git a/development-files/kysdk-utils.pc b/development-files/kysdk-utils.pc index c2712cd..92458da 100644 --- a/development-files/kysdk-utils.pc +++ b/development-files/kysdk-utils.pc @@ -1,5 +1,5 @@ Name: libkysdk-utils Description: kysdk base layer utils component -Version: 2.3.0.0 +Version: 2.5.0 Cflags:-I/usr/include/kysdk/kysdk-base/ -Libs: -lkydatastruct -lkyutils +Libs: -lkydatastruct -lkyutils \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 802e821..2de9282 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,6 +3,7 @@ include_directories(utils) include_directories(log) include_directories(timer) include_directories(gsettings) +include_directories(conf2) # add_subdirectory(communication) add_subdirectory(config) diff --git a/src/conf2/.gitignore b/src/conf2/.gitignore deleted file mode 100644 index e2e32cb..0000000 --- a/src/conf2/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.pro* -main.cpp \ No newline at end of file diff --git a/src/conf2/CMakeLists.txt b/src/conf2/CMakeLists.txt index 2c3b2c1..37403db 100644 --- a/src/conf2/CMakeLists.txt +++ b/src/conf2/CMakeLists.txt @@ -12,8 +12,14 @@ target_link_libraries(kconf2 kyconf2) 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) + install(TARGETS kconf2 DESTINATION /usr/bin) install(TARGETS kconf2-editor - DESTINATION /usr/bin) \ No newline at end of file + DESTINATION /usr/bin) + +install(TARGETS kyconf2-test + DESTINATION /usr/bin) diff --git a/src/conf2/api/CMakeLists.txt b/src/conf2/api/CMakeLists.txt index da6f3d0..fa5b787 100644 --- a/src/conf2/api/CMakeLists.txt +++ b/src/conf2/api/CMakeLists.txt @@ -1,8 +1,8 @@ # aux_source_directory(. SOURCESCODE) add_library(kyconf2 SHARED libkysettings.c ksettingsschema.c ) -set_target_properties(kyconf2 PROPERTIES VERSION 2.0.0 SOVERSION 1) -target_link_libraries(kyconf2 ${GLIB_LIBRARIES} ${GIO_LIBRARIES} -lsqlite3) +set_target_properties(kyconf2 PROPERTIES VERSION 2.5.0 SOVERSION 1) +target_link_libraries(kyconf2 ${GLIB_LIBRARIES} ${GIO_LIBRARIES} -lsqlite3 kylog) # 包含 GNU 安装目录设置 include(GNUInstallDirs) diff --git a/src/conf2/api/ksettingsschema.c b/src/conf2/api/ksettingsschema.c index 9d6a8e1..9d4005f 100644 --- a/src/conf2/api/ksettingsschema.c +++ b/src/conf2/api/ksettingsschema.c @@ -25,7 +25,9 @@ #include #include #include -#include +#include + +#include "libkylog.h" /** * @brief 嵌套哈希表, @@ -73,6 +75,10 @@ void schema_data_destroy(gpointer data) KSettingsSchema *schema = (KSettingsSchema *)data; g_free(schema->id); g_free(schema->version); + g_free(schema->permission); + g_free(schema->description); + g_free(schema->summary); + g_free(schema->extends); if (schema->values) { g_hash_table_destroy(schema->values); @@ -153,7 +159,6 @@ static int _sql_call_get_lines(void *data, int argc, char **argv, char **azColNa char **columns = calloc(argc + 1, sizeof(char *)); for (int i = 0; i < argc; i++) { - char *fewf = argv[i]; columns[i] = g_strdup(argv[i]); } char ***tmp = realloc(lines, sizeof(char **) * (line_count + 2)); @@ -184,7 +189,18 @@ static int _sql_call_get_schema(void *data, int argc, char **argv, char **azColN { KSettingsSchema *schema = (KSettingsSchema *)data; - if (NULL == argv[3]) + char *node_name = argv[2]; + char *node_type = argv[3]; + char *permission = argv[4]; + char *description = argv[5]; + char *summary = argv[6]; + char *value_type = argv[8]; + char *custom_value = argv[9]; + char *default_value = argv[10]; + char *value_range = argv[11]; + char *extends = argv[12]; + + if (0 == strcmp(node_type, "key")) { // hash表 s:hash(s:s) if (NULL == schema->values) @@ -193,31 +209,32 @@ static int _sql_call_get_schema(void *data, int argc, char **argv, char **azColN GHashTable *item = g_hash_table_new(g_str_hash, g_str_equal); if (NULL == item) goto err; - if (argv[2]) - g_hash_table_insert(item, "property", g_strdup(argv[2])); // 键名 - if (argv[4]) - g_hash_table_insert(item, "user_value", g_strdup(argv[4])); // 键值 - if (argv[5]) - g_hash_table_insert(item, "data_type", g_strdup(argv[5])); // 类型 - if (argv[6]) - g_hash_table_insert(item, "default_value", g_strdup(argv[6])); // 默认值 - if (argv[7]) - g_hash_table_insert(item, "permission", g_strdup(argv[7])); // 读写权限 - if (argv[8]) - g_hash_table_insert(item, "range", g_strdup(argv[8])); // 取值范围 - if (argv[10]) - g_hash_table_insert(item, "description", g_strdup(argv[10])); // 详细描述 - if (argv[11]) - g_hash_table_insert(item, "summary", g_strdup(argv[11])); // 概要 - g_hash_table_insert(schema->values, g_strdup(argv[2]), item); + if (node_name) + g_hash_table_insert(item, "node_name", g_strdup(node_name)); // 键名 + if (permission) + g_hash_table_insert(item, "permission", g_strdup(permission)); // 读写权限 + if (description) + g_hash_table_insert(item, "description", g_strdup(description)); // 详细描述 + if (summary) + g_hash_table_insert(item, "summary", g_strdup(summary)); // 概要 + if (value_type) + g_hash_table_insert(item, "value_type", g_strdup(value_type)); // 类型 + if (custom_value) + g_hash_table_insert(item, "custom_value", g_strdup(custom_value)); // 键值 + if (default_value) + g_hash_table_insert(item, "default_value", g_strdup(default_value)); // 默认值 + if (value_range) + g_hash_table_insert(item, "range", g_strdup(value_range)); // 取值范围 + + g_hash_table_insert(schema->values, g_strdup(node_name), item); } - else + else if (0 == strcmp(node_type, "schema")) { if (NULL == schema->children) { schema->children = g_array_new(FALSE, FALSE, sizeof(char *)); } - char *tmp = g_strdup(argv[3]); + char *tmp = g_strdup(node_name); g_array_append_val(schema->children, tmp); } return 0; @@ -231,17 +248,28 @@ err: // 读取一个组件 static KSettingsSchema *_get_schema(const char *id, const char *version) { - char *user_name = getlogin(); - if (user_name == NULL) - 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(); + } KSettingsSchema *schema = NULL; char db_file[PATH_MAX]; if (0 == strcmp(user_name, "root")) - sprintf(db_file, "/etc/kylin-config/kylin-config/user.db"); + 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); char **id_list = _split_string(id, '.'); if (!id_list) @@ -251,27 +279,40 @@ static KSettingsSchema *_get_schema(const char *id, const char *version) sqlite3 *db = NULL; char *err_msg = NULL; - // 打开数据库 int rc = sqlite3_open(db_file, &db); if (rc != SQLITE_OK) { - rc = sqlite3_open("/etc/kylin-config/kylin-config/user.db", &db); - if (rc != SQLITE_OK) + if (0 == strcmp(db_file, "/root/.config/kylin-config/user.db")) { - fprintf(stderr, "无法打开数据库: %s\n", sqlite3_errmsg(db)); - goto out; + 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) + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> :open /etc/kylin-config/user.db failed. %s\n", __func__, sqlite3_errmsg(db)); + g_strfreev(id_list); + return NULL; + } } + else + return NULL; + } + + rc = sqlite3_exec(db, "BEGIN TRANSACTION", 0, 0, &err_msg); + if (rc != SQLITE_OK) + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> :无法开始事务: %s\n", __func__, err_msg); + goto out; } // 查询数据 int app_id = 0, version_id = 0, parent_id = 0; - char sql[100]; + char sql[1024]; sprintf(sql, "SELECT * FROM app WHERE app_name = '%s'", id_list[0]); char **columns = NULL; rc = sqlite3_exec(db, sql, _sql_call_get_columns, &columns, &err_msg); if (rc != SQLITE_OK || NULL == columns) { - fprintf(stderr, "查询失败: %s\n", err_msg); + syslog(LOG_INFO, "[kysdk-conf2] %s -> :查询应用%s失败: %s\n", __func__, id_list[0], err_msg); goto out; } app_id = atoi(columns[0]); @@ -283,8 +324,7 @@ static KSettingsSchema *_get_schema(const char *id, const char *version) rc = sqlite3_exec(db, sql, _sql_call_get_columns, &columns, &err_msg); if (rc != SQLITE_OK) { - // TODO: 版本兼容性处理 - fprintf(stderr, "查询失败: %s\n", err_msg); + syslog(LOG_INFO, "[kysdk-conf2] %s -> :查询%s版本号%s失败: %s\n", __func__, version, err_msg); goto out; } version_id = atoi(columns[0]); @@ -293,13 +333,13 @@ static KSettingsSchema *_get_schema(const char *id, const char *version) int i = 1; while (id_list[i]) { - sprintf(sql, "SELECT * FROM configures WHERE version_id = %d AND parent = %d AND group_name = '%s'", + sprintf(sql, "SELECT * FROM configures WHERE version_id = %d AND parent = %d AND node_name = '%s' AND node_type = 'schema'", version_id, parent_id, id_list[i++]); rc = sqlite3_exec(db, sql, _sql_call_get_columns, &columns, &err_msg); if (rc != SQLITE_OK) { - fprintf(stderr, "查询失败: %s\n", err_msg); + syslog(LOG_INFO, "[kysdk-conf2] %s -> :查询组件%s失败: %s\n", __func__, id_list[i], err_msg); goto out; } parent_id = atoi(columns[0]); @@ -316,113 +356,44 @@ static KSettingsSchema *_get_schema(const char *id, const char *version) rc = sqlite3_exec(db, sql, _sql_call_get_schema, schema, &err_msg); if (rc != SQLITE_OK) { - fprintf(stderr, "查询失败: %s\n", err_msg); + syslog(LOG_INFO, "[kysdk-conf2] %s -> :查询失败: %s\n", __func__, err_msg); goto out; } -out: + rc = sqlite3_exec(db, "COMMIT", NULL, NULL, &err_msg); + if (rc != SQLITE_OK) + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> :无法提交事务: %s\n", __func__, err_msg); + goto out; + } + sqlite3_close(db); + g_strfreev(id_list); + return schema; +out: + sqlite3_exec(db, "ROLLBACK", 0, 0, &err_msg); + sqlite3_free(err_msg); + sqlite3_close(db); + g_strfreev(id_list); - if (err_msg) - sqlite3_free(err_msg); - if (db) - sqlite3_close(db); return schema; } -// 递归读取组件配置 -static int _get_component_recursively(char *version, int version_id, int parent_id, char *parent_name, GHashTable *schemas, sqlite3 *db) +static void _get_schemas() { - char *err_msg = NULL; - char sql[128]; - char ***components = NULL; - line_count = 0; - sprintf(sql, "SELECT * FROM configures WHERE version_id = %d AND parent = %d AND group_name IS NOT NULL", version_id, parent_id); - int rc = sqlite3_exec(db, sql, _sql_call_get_lines, &components, &err_msg); - if (rc != SQLITE_OK) - { - fprintf(stderr, "无法打开数据库: %s\n", sqlite3_errmsg(db)); - return rc; - } + char ***apps = NULL, ***versions = NULL, ***configures = NULL; - KSettingsSchema *schema = g_hash_table_lookup(schemas, parent_name); - if (NULL == schema) + uid_t uid = getuid(); // 获取当前进程的用户ID + char user_name[128] = {0}; + struct passwd *pw = getpwuid(uid); // 获取用户ID对应的用户信息结构体 + if (NULL == pw) { - schema = calloc(1, sizeof *schema); - if (NULL == schema) - return SQLITE_NOMEM; - - schema->id = strdup(parent_name); - schema->version = strdup(version); - g_hash_table_insert(schemas, strdup(parent_name), schema); + syslog(LOG_INFO, "[kysdk-conf2] %s -> :Get user name failed! use root config\n", __func__); + strcpy(user_name, "root"); } else { - if (schema->values) - { - g_hash_table_destroy(schema->values); - schema->values = NULL; - } - if (schema->children) - { - g_array_free(schema->children, TRUE); - schema->children = NULL; - } - } - sprintf(sql, "SELECT * FROM configures WHERE version_id = %d AND parent = %d", - version_id, parent_id); - rc = sqlite3_exec(db, sql, _sql_call_get_schema, schema, &err_msg); - if (rc != SQLITE_OK) - { - fprintf(stderr, "查询失败: %s\n", err_msg); - // schema_data_destroy(schema); - return rc; - } - - // components为空 - if (NULL == components) - { - return rc; - } - - for (int i = 0; components[i]; i++) - { - parent_id = atoi(components[i][0]); - char *id = g_strdup_printf("%s.%s", parent_name, components[i][3]); - // 递归读取 - rc = _get_component_recursively(version, version_id, parent_id, id, schemas, db); - if (rc != SQLITE_OK) - { - for (int j = 0; components[j]; j++) - { - for (int k = 0; k < 12; k++) - free(components[j][k]); - free(components[j]); - } - free(components); - return rc; - } - } - - for (int j = 0; components[j]; j++) - { - for (int k = 0; k < 12; k++) - free(components[j][k]); - free(components[j]); - } - free(components); - return rc; -} - -// 读取所有组件配置 -static void _get_schemas() -{ - char *user_name = getlogin(); - if (user_name == NULL) - { - openlog("kysdk-conf2", LOG_PID, LOG_USER); - syslog(LOG_INFO, "Get user name failed! use root config"); - closelog(); - user_name = "root"; + strcpy(user_name, pw->pw_name); + endpwent(); } char db_file[PATH_MAX]; @@ -430,6 +401,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); // 读取数据库数据 sqlite3 *db = NULL; @@ -439,167 +411,352 @@ static void _get_schemas() int rc = sqlite3_open(db_file, &db); if (rc != SQLITE_OK) { - openlog("kysdk-conf2", LOG_PID, LOG_USER); - syslog(LOG_INFO, "open %s failed with error code %d! try to open /etc/kylin-config/user.db.", db_file, rc); - closelog(); - rc = sqlite3_open("/etc/kylin-config/user.db", &db); - if (rc != SQLITE_OK) + if (0 == strcmp(db_file, "/root/.config/kylin-config/user.db")) { - openlog("kysdk-conf2", LOG_PID, LOG_USER); - syslog(LOG_INFO, "open /etc/kylin-config/user.db failed with error code %d", rc); - closelog(); - goto out; + 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) + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> :open /etc/kylin-config/user.db failed. %s\n", __func__, sqlite3_errmsg(db)); + return; + } } + else + return; } - // 顶层hash, 元素为appData:hash(versionData:hash(s:KSettingsSchema)) - if (NULL == schemas_table) - schemas_table = g_hash_table_new_full(data_hash, data_equal, app_data_destroy, (GDestroyNotify)g_hash_table_destroy); - if (NULL == schemas_table) + + char sql[100]; + rc = sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &err_msg); + if (rc != SQLITE_OK) { - openlog("kysdk-conf2", LOG_PID, LOG_USER); - syslog(LOG_INFO, "Creat hash Table failed"); - closelog(); + syslog(LOG_INFO, "[kysdk-conf2] %s -> :无法开始事务: %s\n", __func__, err_msg); goto out; } - int i = 0; - char sql[100]; - char ***apps = NULL; - strcpy(sql, "SELECT * FROM app"); line_count = 0; rc = sqlite3_exec(db, sql, _sql_call_get_lines, &apps, &err_msg); if (rc != SQLITE_OK) { - openlog("kysdk-conf2", LOG_PID, LOG_USER); - syslog(LOG_INFO, "查询失败: %s\n", err_msg); - closelog(); + syslog(LOG_INFO, "[kysdk-conf2] %s -> :查询应用名失败: %s\n", __func__, err_msg); goto out; } - while (apps && apps[i]) + + line_count = 0; + sprintf(sql, "SELECT * FROM version"); + rc = sqlite3_exec(db, sql, _sql_call_get_lines, &versions, &err_msg); + if (rc != SQLITE_OK) { - char ***versions = NULL; - int app_id = atoi(apps[i][0]); - AppData *app_data = calloc(1, sizeof *app_data); - app_data->name = strdup(apps[i][1]); - app_data->default_version = strdup(apps[i][2]); + syslog(LOG_INFO, "[kysdk-conf2] %s -> :查询版本号失败: %s\n", __func__, err_msg); + goto out; + } - line_count = 0; - sprintf(sql, "SELECT * FROM version WHERE app_id = %d", app_id); - rc = sqlite3_exec(db, sql, _sql_call_get_lines, &versions, &err_msg); - if (rc != SQLITE_OK) - { - openlog("kysdk-conf2", LOG_PID, LOG_USER); - syslog(LOG_INFO, "查询失败: %s\n", err_msg); - closelog(); - for (int j = 0; apps[j]; j++) - { - for (int k = 0; k < 3; k++) - free(apps[j][k]); - free(apps[j]); - } - free(apps); - goto out; - } - // 第二层hash,元素为versionData:hash(s:KSettingsSchema) - GHashTable *version = g_hash_table_lookup(schemas_table, app_data); - if (NULL == version) - { - version = g_hash_table_new_full(data_hash, data_equal, version_data_destroy, (GDestroyNotify)g_hash_table_destroy); - if (NULL == version) - { - openlog("kysdk-conf2", LOG_PID, LOG_USER); - syslog(LOG_INFO, "Creat hash2 Table failed"); - closelog(); - goto out; - } - g_hash_table_insert(schemas_table, app_data, version); - } - else - app_data_destroy(app_data); + line_count = 0; + strcpy(sql, "SELECT * FROM configures"); + rc = sqlite3_exec(db, sql, _sql_call_get_lines, &configures, &err_msg); + if (rc != SQLITE_OK) + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> :读取组件所有配置失败: %s\n", __func__, err_msg); + goto out; + } - int version_i = 0; - while (versions[version_i]) + rc = sqlite3_exec(db, "COMMIT", NULL, NULL, &err_msg); + if (rc != SQLITE_OK) + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> :无法提交事务: %s\n", __func__, err_msg); + goto out; + } + sqlite3_close(db); + + if (!apps || !versions || ! configures) + return; + + // 顶层hash, 元素为appData:hash(versionData:hash(s:KSettingsSchema)) + if (NULL == schemas_table) + 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__); + goto out; + } + + int app_id = 0, version_id = 0; + GHashTable *version = NULL; + GHashTable *schemas = NULL; + KSettingsSchema *schema = NULL; + char curr_id[512] = {0}; + +#define APP_COLUMN apps[app_id - 1] +#define VER_COLUMN versions[version_id - 1] + // 遍历配置 + for (int i = 0; configures[i]; i++) + { + // 版本id改变 + if (version_id != atoi(configures[i][1])) { - int version_id = atoi(versions[version_i][0]); - VersionData *version_data = calloc(1, sizeof *version_data); - version_data->name = strdup(versions[version_i][2]); - version_data->compatible = _split_string(versions[version_i][3], '.'); - // 第三层hash,元素为s:KSettingsSchema - GHashTable *schemas = g_hash_table_lookup(version, version_data); + 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); + version_id = atoi(configures[i][1]); + + version_data = calloc(1, sizeof *version_data); + version_data->name = strdup(VER_COLUMN[2]); + version_data->compatible = _split_string(VER_COLUMN[3], '.'); + + // 版本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); + app_id = atoi(VER_COLUMN[1]); + + app_data = calloc(1, sizeof *app_data); + app_data->name = strdup(APP_COLUMN[1]); + app_data->default_version = strdup(APP_COLUMN[2]); + + version = g_hash_table_lookup(schemas_table, app_data); + if (NULL == version) + { + 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__); + app_data_destroy(app_data); + version_data_destroy(version_data); + goto out; + } + g_hash_table_insert(schemas_table, app_data, version); + } + else + app_data_destroy(app_data); + } + + schemas = g_hash_table_lookup(version, version_data); if (NULL == schemas) { schemas = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)schema_data_destroy); g_hash_table_insert(version, version_data, schemas); if (NULL == schemas) { - openlog("kysdk-conf2", LOG_PID, LOG_USER); - syslog(LOG_INFO, "Creat schemas hash Table failed"); - closelog(); + syslog(LOG_INFO, "[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]); - rc = _get_component_recursively(versions[version_i][2], version_id, 0, apps[i][1], schemas, db); - if (rc != SQLITE_OK) + schema = g_hash_table_lookup(schemas, APP_COLUMN[1]); + if (NULL == schema) { - openlog("kysdk-conf2", LOG_PID, LOG_USER); - syslog(LOG_INFO, "Read data failed"); - closelog(); - for (int j = 0; j < i + 1; j++) + syslog(LOG_INFO, "[kysdk-conf2] %s -> Creat node %s\n", __func__, APP_COLUMN[1]); + schema = calloc(1, sizeof *schema); + if (NULL == schema) + goto out; + + schema->id = strdup(APP_COLUMN[1]); + schema->version = strdup(VER_COLUMN[2]); + g_hash_table_insert(schemas, strdup(APP_COLUMN[1]), schema); + } + else + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> Clear node %s\n", __func__, APP_COLUMN[1]); + if (schema->values) { - for (int k = 0; k < 3; k++) - free(apps[j][k]); - free(apps[j]); + g_hash_table_destroy(schema->values); + schema->values = NULL; } - free(apps); - for (int j = 0; versions[j]; j++) + if (schema->children) { - for (int k = 0; k < 4; k++) - free(versions[j][k]); - free(versions[j]); + g_array_free(schema->children, TRUE); + schema->children = NULL; } - free(versions); + } + } + char *node_name = configures[i][2]; + char *node_type = configures[i][3]; + char *permission = configures[i][4]; + char *description = configures[i][5]; + char *summary = configures[i][6]; + char *value_type = configures[i][8]; + char *custom_value = configures[i][9]; + char *default_value = configures[i][10]; + char *value_range = configures[i][11]; + char *extends = configures[i][12]; + // 一个新的组件 + if (0 == strcmp(node_type, "schema")) + { + int parent_id = atoi(configures[i][7]); + char parent_name[512], tmp[512]; + memset(parent_name, 0, 512); + memset(tmp, 0, 512); + if (0 == parent_id) + { + strcpy(parent_name, APP_COLUMN[1]); + } + else + { + while (0 != parent_id) + { + strcat(tmp, "."); + strcat(tmp, configures[parent_id - 1][2]); + parent_id = atoi(configures[parent_id - 1][7]); + } + 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); + + // 给父组件增加子组件名 + KSettingsSchema *parent_schema = g_hash_table_lookup(schemas, parent_name); + if (NULL != parent_schema) + { + if (NULL == parent_schema->children) + { + parent_schema->children = g_array_new(FALSE, FALSE, sizeof(char *)); + } + char *tmp = g_strdup(node_name); + g_array_append_val(parent_schema->children, tmp); + } + + char schema_name[512]; + memset(schema_name, 0, 512); + sprintf(schema_name, "%s.%s", parent_name, node_name); + schema = g_hash_table_lookup(schemas, schema_name); + if (NULL == schema) + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> Creat node %s\n", __func__, schema_name); + schema = calloc(1, sizeof *schema); + if (NULL == schema) + { + goto out; + syslog(LOG_ERR, "[kysdk-conf2] %s -> Creat HashTable fail\n", __func__); + } + + schema->id = strdup(schema_name); + schema->version = strdup(VER_COLUMN[2]); + if (permission) + schema->permission = strdup(permission); + if (description) + schema->description = strdup(description); + if (summary) + schema->summary = strdup(summary); + if (extends) + schema->extends = strdup(extends); + g_hash_table_insert(schemas, strdup(schema_name), schema); + } + else + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> Clear node %s\n", __func__, APP_COLUMN[1]); + if (schema->values) + { + g_hash_table_destroy(schema->values); + schema->values = NULL; + } + if (schema->children) + { + g_array_free(schema->children, TRUE); + schema->children = NULL; + } + g_free(schema->permission); + g_free(schema->description); + g_free(schema->summary); + g_free(schema->extends); + if (permission) + schema->permission = strdup(permission); + if (description) + schema->description = strdup(description); + if (summary) + schema->summary = strdup(summary); + if (extends) + schema->extends = strdup(extends); + } + } + else if (0 == strcmp(node_type, "key")) + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> Read %s configure wiht version number %s\n", __func__, schema->id, VER_COLUMN[2]); + // 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); + // hash表 s:s + GHashTable *item = g_hash_table_new(g_str_hash, g_str_equal); + if (NULL == item) + { + syslog(LOG_ERR, "[kysdk-conf2] %s -> Memary error\n", __func__); goto out; } - version_i++; + if (node_name) + g_hash_table_insert(item, "node_name", g_strdup(node_name)); // 键名 + if (permission) + g_hash_table_insert(item, "permission", g_strdup(permission)); // 读写权限 + if (description) + g_hash_table_insert(item, "description", g_strdup(description)); // 详细描述 + if (summary) + g_hash_table_insert(item, "summary", g_strdup(summary)); // 概要 + if (value_type) + g_hash_table_insert(item, "value_type", g_strdup(value_type)); // 类型 + if (custom_value) + g_hash_table_insert(item, "custom_value", g_strdup(custom_value)); // 键值 + if (default_value) + g_hash_table_insert(item, "default_value", g_strdup(default_value)); // 默认值 + if (value_range) + g_hash_table_insert(item, "range", g_strdup(value_range)); // 取值范围 + + g_hash_table_insert(schema->values, g_strdup(node_name), item); } - if (version) - { - for (int j = 0; versions[j]; j++) - { - for (int k = 0; k < 4; k++) - free(versions[j][k]); - free(versions[j]); - } - free(versions); - } - i++; + } +#undef APP_COLUMN +#undef VER_COLUMN + +out: + if (rc != SQLITE_OK) + { + sqlite3_exec(db, "ROLLBACK", 0, 0, &err_msg); + sqlite3_free(err_msg); + sqlite3_close(db); + + g_hash_table_destroy(schemas_table); + schemas_table = NULL; } if (apps) { for (int j = 0; apps[j]; j++) { for (int k = 0; k < 3; k++) - free(apps[j][k]); + { + if (apps[j][k]) + free(apps[j][k]); + } free(apps[j]); } free(apps); } -out: - if (rc != SQLITE_OK && NULL != schemas_table) + if (versions) { - g_hash_table_destroy(schemas_table); - schemas_table = NULL; + for (int j = 0; versions[j]; j++) + { + for (int k = 0; k < 4; k++) + { + if (versions[j][k]) + free(versions[j][k]); + } + free(versions[j]); + } + free(versions); + } + if (configures) + { + for (int j = 0; configures[j]; j++) + { + for (int k = 0; k < 13; k++) + { + if (configures[j][k]) + free(configures[j][k]); + } + free(configures[j]); + } + free(configures); } - if (err_msg) - sqlite3_free(err_msg); - if (db) - sqlite3_close(db); } -/*读取数据库*/ // 在schemas_table查找指定schema的配置句柄KSettingsSchema KSettingsSchema *kdk_conf2_schema_table_lookup(const char *id, const char *version) @@ -614,6 +771,7 @@ KSettingsSchema *kdk_conf2_schema_table_lookup(const char *id, const char *versi g_hash_table_iter_init(&iter, schemas_table); while (g_hash_table_iter_next(&iter, &app_data, &version_hash)) { + syslog(LOG_INFO, "[kysdk-conf2] %s -> find %s\n", __func__, app_data->name); if (0 == strcmp(app_data->name, list[0])) { VersionData *version_data = NULL; @@ -624,8 +782,16 @@ KSettingsSchema *kdk_conf2_schema_table_lookup(const char *id, const char *versi g_hash_table_iter_init(&iter_version, version_hash); while (g_hash_table_iter_next(&iter_version, &version_data, &schemas)) { + syslog(LOG_INFO, "[kysdk-conf2] %s -> find %s '%s configure\n", __func__, app_data->name, version_data->name); if (0 == strcmp(version_data->name, version)) { + GHashTableIter iter_schema; + g_hash_table_iter_init(&iter_schema, schemas); + char *few = NULL; + while (g_hash_table_iter_next(&iter_schema, &few, &result)) + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> %s with %s version 's id %s\n", __func__, app_data->name, version_data->name, few); + } result = g_hash_table_lookup(schemas, id); break; } @@ -748,12 +914,12 @@ int kdk_conf2_schema_find_child(KSettingsSchema *schema, const char *name) char *kdk_conf2_schema_key_value_type(GHashTable *key) { - GET_KEY_ATTR(data_type) + GET_KEY_ATTR(value_type) } char *kdk_conf2_schema_key_get_value(GHashTable *key) { - GET_KEY_ATTR(user_value) + GET_KEY_ATTR(custom_value) } char *kdk_conf2_schema_key_get_default_value(GHashTable *key) @@ -807,8 +973,8 @@ int kdk_conf2_schema_key_range_check(GHashTable *key, const char *value) // if (NULL == tmp) // { - if (0 == g_strcmp0(value, nick)) - result = TRUE; + if (0 == g_strcmp0(value, nick)) + result = TRUE; // } // else // { @@ -868,7 +1034,7 @@ out: char *kdk_conf2_schema_key_get_name(GHashTable *key) { - GET_KEY_ATTR(property) + GET_KEY_ATTR(node_name) } char *kdk_conf2_schema_key_get_summary(GHashTable *key) @@ -920,9 +1086,14 @@ KSettingsSchema *kdk_conf2_schema_reload(const char *id, const char *version) { if (0 == strcmp(version_data->name, version)) { + result = g_hash_table_lookup(schemas, id); // 用新读取的配置替换掉schemas_table中的老配置 KSettingsSchema *schema = _get_schema(id, version); - result = g_hash_table_lookup(schemas, id); + if (NULL == schema) + { + syslog(LOG_ERR, "[kysdk-conf2] %s -> :Update schema data failed\n", __func__); + break; + } GHashTable *tmp = result->values; result->values = schema->values; diff --git a/src/conf2/api/ksettingsschema.h b/src/conf2/api/ksettingsschema.h index 20b7200..7370bcc 100644 --- a/src/conf2/api/ksettingsschema.h +++ b/src/conf2/api/ksettingsschema.h @@ -22,6 +22,7 @@ #define KSETTINGSSCHEMA_H #include +#include #if __cplusplus extern "C" @@ -45,6 +46,10 @@ extern "C" GArray *children; char *id; char *version; + char *permission; + char *description; + char *summary; + char *extends; } SchemaData; typedef struct _SchemaData KSettingsSchema; diff --git a/src/conf2/api/libkysettings.c b/src/conf2/api/libkysettings.c index f146fcf..aafd73d 100644 --- a/src/conf2/api/libkysettings.c +++ b/src/conf2/api/libkysettings.c @@ -26,11 +26,13 @@ #include #include #include -#include #include +#include +#include #include "libkysettings.h" #include "ksettingsschema.h" +#include "libkylog.h" static GMainLoop *dbus_signal_loop = NULL; // glib主循环,用于处理dbus消息事件,主循环不开启无法接收dbus信号 static guint ref_count = 0; // 记录dbus_signal_loop的引用计数 @@ -44,6 +46,7 @@ typedef struct _KSettingsPrivate GMainContext *main_context; KSettingsSchema *schema; GDBusConnection *conn; + GSettings *gsettings; guint sub_id[2]; } KSettingsPrivate; @@ -104,6 +107,11 @@ 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); @@ -144,11 +152,6 @@ static void k_settings_class_init(KSettingsClass *class) 0); } -static int verify_file(char *file_name) -{ - return 1; -} - /** * @brief _g_main_loop_thread 开启main_loop获取消息循环 * @param data @@ -161,6 +164,20 @@ 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 @@ -180,15 +197,41 @@ static void _on_key_changed(GDBusConnection *connection, gpointer user_data) { KSettings *ksettings = (KSettings *)user_data; - char *id, *version, *key, *user; - g_variant_get(parameters, "(ssss)", &id, &version, &key, &user); + char *id, *version, *key; + g_variant_get(parameters, "(sss)", &id, &version, &key); char *schema_id = kdk_conf2_schema_get_id(ksettings->priv->schema); - if ((0 == strcmp(schema_id, id)) && (0 == strcmp(g_get_user_name(), user))) + char *schema_version = kdk_conf2_schema_get_version(ksettings->priv->schema); + if ((0 == strcmp(schema_id, id)) && (0 == strcmp(schema_version, version))) { 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) + { + char *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(type, value, NULL, &endptr, &error); + if (NULL == variant) + { + klog_err("[kysdk-conf2] %s -> %s\n", __func__, error->message); + return FALSE; + } + g_settings_set_value(ksettings->priv->gsettings, key, variant); + g_variant_unref(variant); + } + g_variant_unref(gsetting_value); + } + } } g_free(schema_id); + g_free(schema_version); mutex = 0; } @@ -243,7 +286,7 @@ static int _type_check(KSettings *ksettings, const char *key, const char *value) GVariant *variant = g_variant_parse(G_VARIANT_TYPE(type), value, NULL, &endptr, &error); if (NULL == variant) { - printf("parser error : %s\n", error->message); + syslog(LOG_ERR, "[kysdk-conf2] % -> parser error : %s\n", __func__, error->message); g_error_free(error); g_free(type); return FALSE; @@ -264,25 +307,21 @@ static int _type_check(KSettings *ksettings, const char *key, const char *value) * @param value 键值,可为NULL,根据method传参。 * @return boolean类型 成功返回1 失败返回0 */ -static int _call_method(GDBusConnection *connection, const char *method, const char *id, const char *version, const char *key, const char *value) +static int _call_method(const char *method, const char *id, const char *version, const char *key, const char *value) { GError *error = NULL; + GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (error != NULL) + { + syslog(LOG_ERR, "[kysdk-conf2] %s -> Connection Error: %s\n", __func__, error->message); + g_error_free(error); + return FALSE; + } + GDBusProxy *proxy; GVariant *result; int response = FALSE; - // 获取 DBus 会话总线 - if (NULL == connection) - { - connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); - if (error != NULL) - { - g_printerr("Connection Error: %s\n", error->message); - g_error_free(error); - return response; - } - } - // 创建代理对象 proxy = g_dbus_proxy_new_sync(connection, G_DBUS_PROXY_FLAGS_NONE, @@ -294,19 +333,33 @@ static int _call_method(GDBusConnection *connection, const char *method, const c &error); if (error != NULL) { - g_printerr("Proxy Error: %s\n", error->message); + syslog(LOG_ERR, "[kysdk-conf2] %s -> Proxy Error: %s\n", __func__, error->message); g_error_free(error); return response; } + 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(); + } + // 调用代理对象的方法 GVariant *variant = NULL; if (0 == strcmp(method, "set")) - variant = g_variant_new("(sssss)", getlogin(), id, version, key, value); + variant = g_variant_new("(sssss)", user_name, id, version, key, value); if (0 == strcmp(method, "reset")) - variant = g_variant_new("(ssss)", getlogin(), id, version, key); + variant = g_variant_new("(ssss)", user_name, id, version, key); if (0 == strcmp(method, "reset_recursively")) - variant = g_variant_new("(sss)", getlogin(), id, version); + variant = g_variant_new("(sss)", user_name, id, version); result = g_dbus_proxy_call_sync(proxy, method, @@ -317,7 +370,7 @@ static int _call_method(GDBusConnection *connection, const char *method, const c &error); if (error != NULL) { - g_printerr("Method Call Error: %s\n", error->message); + syslog(LOG_ERR, "[kysdk-conf2] %s -> %s call fialed: %s\n", __func__, method, error->message); g_error_free(error); return response; } @@ -328,6 +381,7 @@ static int _call_method(GDBusConnection *connection, const char *method, const c // 释放资源 g_variant_unref(result); g_object_unref(proxy); + g_object_unref(connection); return response; } @@ -335,9 +389,7 @@ KSettings *kdk_conf2_new(const char *id, const char *version) { if (NULL == id) { - openlog("kysdk-conf2", LOG_PID, LOG_USER); - syslog(LOG_INFO, "id is nullptr"); - closelog(); + syslog(LOG_INFO, "[kysdk-conf2] id is nullptr\n"); return NULL; } @@ -346,40 +398,66 @@ KSettings *kdk_conf2_new(const char *id, const char *version) if (NULL == schemas_table) { - openlog("kysdk-conf2", LOG_PID, LOG_USER); - syslog(LOG_INFO, "load user.db failed"); - closelog(); + syslog(LOG_INFO, "[kysdk-conf2] load user.db failed\n"); return NULL; } KSettingsSchema *schema = kdk_conf2_schema_table_lookup(id, version); if (NULL == schema) { - openlog("kysdk-conf2", LOG_PID, LOG_USER); - syslog(LOG_INFO, "invalied schema id"); - closelog(); + syslog(LOG_INFO, "[kysdk-conf2] invalied schema id\n"); return NULL; } KSettings *ksettings = g_object_new(K_TYPE_SETTINGS, NULL); if (!K_IS_SETTINGS(ksettings)) { - openlog("kysdk-conf2", LOG_PID, LOG_USER); - syslog(LOG_INFO, "init KSettings failed"); - closelog(); + syslog(LOG_INFO, "[kysdk-conf2] init KSettings failed\n"); return NULL; } + char **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) + { + 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(); + } + // 创建dbus服务的链接,用于调用接口及接收信号 GError *error = NULL; - ksettings->priv->conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + 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) { - openlog("kysdk-conf2", LOG_PID, LOG_USER); - syslog(LOG_INFO, "Connection Error: %s\n", error->message); - closelog(); + syslog(LOG_INFO, "[kysdk-conf2] Connection Error: %s\n", error->message); g_object_unref(ksettings); ksettings = NULL; g_error_free(error); @@ -425,7 +503,6 @@ KSettings *kdk_conf2_new(const char *id, const char *version) void kdk_conf2_ksettings_destroy(KSettings *ksettings) { - // g_assert(K_IS_SETTINGS(ksettings)); if (!K_IS_SETTINGS(ksettings)) return; @@ -443,7 +520,6 @@ void kdk_conf2_ksettings_destroy(KSettings *ksettings) char *kdk_conf2_get_id(KSettings *ksettings) { - // g_assert(K_IS_SETTINGS(ksettings)); if (!K_IS_SETTINGS(ksettings)) return NULL; return kdk_conf2_schema_get_id(ksettings->priv->schema); @@ -451,7 +527,6 @@ char *kdk_conf2_get_id(KSettings *ksettings) char *kdk_conf2_get_version(KSettings *ksettings) { - // g_assert(K_IS_SETTINGS(ksettings)); if (!K_IS_SETTINGS(ksettings)) return NULL; return strdup(kdk_conf2_schema_get_version(ksettings->priv->schema)); @@ -459,9 +534,6 @@ char *kdk_conf2_get_version(KSettings *ksettings) KSettings *kdk_conf2_get_child(KSettings *ksettings, const char *name) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != name); - if (!K_IS_SETTINGS(ksettings) || NULL == name) return NULL; @@ -477,7 +549,6 @@ KSettings *kdk_conf2_get_child(KSettings *ksettings, const char *name) char **kdk_conf2_list_children(KSettings *ksettings) { - // g_assert(K_IS_SETTINGS(ksettings)); if (!K_IS_SETTINGS(ksettings)) return NULL; @@ -486,7 +557,6 @@ char **kdk_conf2_list_children(KSettings *ksettings) char **kdk_conf2_list_keys(KSettings *ksettings) { - // g_assert(K_IS_SETTINGS(ksettings)); if (!K_IS_SETTINGS(ksettings)) return NULL; @@ -495,8 +565,6 @@ char **kdk_conf2_list_keys(KSettings *ksettings) char *kdk_conf2_get_range(KSettings *ksettings, const char *key) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); if (!K_IS_SETTINGS(ksettings) || NULL == key) return NULL; @@ -506,8 +574,6 @@ char *kdk_conf2_get_range(KSettings *ksettings, const char *key) int kdk_conf2_range_check(KSettings *ksettings, const char *key, const char *value) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); if (!K_IS_SETTINGS(ksettings) || NULL == key) return FALSE; @@ -519,20 +585,27 @@ int kdk_conf2_range_check(KSettings *ksettings, const char *key, const char *val int kdk_conf2_set_value(KSettings *ksettings, const char *key, const char *value) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); + syslog(LOG_INFO, "[kysdk-conf2] %s -> Set the key '%s' of %s to %s\n", __func__, key, ksettings->priv->schema->id, value); if (!K_IS_SETTINGS(ksettings) || NULL == key) + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> assert ksettings is KSettings failed\n", __func__); return FALSE; + } - if(0 == kdk_conf2_is_writable(ksettings, key)) + if (0 == kdk_conf2_is_writable(ksettings, key)) + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> %s is unwritable\n", __func__, key); return FALSE; + } if (!_type_check(ksettings, key, value)) { + syslog(LOG_INFO, "[kysdk-conf2] %s -> %s type invalid\n", __func__, key); return FALSE; } if (!kdk_conf2_range_check(ksettings, key, value)) { + syslog(LOG_INFO, "[kysdk-conf2] %s -> %s vlaue is not in range\n", __func__, key); return FALSE; } @@ -546,7 +619,7 @@ 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(ksettings->priv->conn, "set", + result = _call_method("set", id, version, key, value); @@ -555,13 +628,15 @@ int kdk_conf2_set_value(KSettings *ksettings, const char *key, const char *value 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; } char *kdk_conf2_get_value(KSettings *ksettings, const char *key) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); + syslog(LOG_INFO, "[kysdk-conf2] %s -> Get value start\n", __func__); + if (!K_IS_SETTINGS(ksettings) || NULL == key) return NULL; @@ -574,13 +649,12 @@ char *kdk_conf2_get_value(KSettings *ksettings, const char *key) { value = kdk_conf2_schema_key_get_default_value(key_hash); } + syslog(LOG_INFO, "[kysdk-conf2] %s -> Get value end\n", __func__); return value; } char *kdk_conf2_get_default_value(KSettings *ksettings, const char *key) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); if (!K_IS_SETTINGS(ksettings) || NULL == key) return NULL; @@ -590,8 +664,6 @@ char *kdk_conf2_get_default_value(KSettings *ksettings, const char *key) int kdk_conf2_set_boolean(KSettings *ksettings, const char *key, int value) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); if (!K_IS_SETTINGS(ksettings) || NULL == key) return FALSE; @@ -632,8 +704,6 @@ int kdk_conf2_get_default_boolean(KSettings *ksettings, const char *key) int kdk_conf2_set_double(KSettings *ksettings, const char *key, double value) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); if (!K_IS_SETTINGS(ksettings) || NULL == key) return 0; @@ -669,8 +739,6 @@ double kdk_conf2_get_default_double(KSettings *ksettings, const char *key) int kdk_conf2_set_enum(KSettings *ksettings, const char *key, int value) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); if (!K_IS_SETTINGS(ksettings) || NULL == key) return 0; @@ -684,7 +752,7 @@ int kdk_conf2_set_enum(KSettings *ksettings, const char *key, int value) GVariant *variant = g_variant_parse(G_VARIANT_TYPE("a{si}"), range, NULL, &endptr, &error); if (variant == NULL) { - g_print("解析失败: %s\n", error->message); + syslog(LOG_ERR, "[kysdk-conf2] %s -> 解析失败: %s\n", __func__, error->message); g_error_free(error); goto out; } @@ -700,7 +768,7 @@ int kdk_conf2_set_enum(KSettings *ksettings, const char *key, int value) { char set_value[1024]; sprintf(set_value, "%d", value); - result = kdk_conf2_set_value(ksettings, key, set_value); + result = kdk_conf2_set_value(ksettings, key, nick); break; } } @@ -726,7 +794,7 @@ int kdk_conf2_get_enum(KSettings *ksettings, const char *key) GVariant *variant = g_variant_parse(G_VARIANT_TYPE("a{si}"), range, NULL, &endptr, &error); if (variant == NULL) { - g_print("解析失败: %s\n", error->message); + syslog(LOG_ERR, "[kysdk-conf2] %s -> 解析失败: %s\n", __func__, error->message); g_error_free(error); goto out; } @@ -767,7 +835,7 @@ int kdk_conf2_get_default_enum(KSettings *ksettings, const char *key) GVariant *variant = g_variant_parse(G_VARIANT_TYPE("a{si}"), range, NULL, &endptr, &error); if (variant == NULL) { - g_print("解析失败: %s\n", error->message); + syslog(LOG_ERR, "[kysdk-conf2] %s -> 解析失败: %s\n", __func__, error->message); g_error_free(error); goto out; } @@ -795,8 +863,6 @@ out: int kdk_conf2_set_int(KSettings *ksettings, const char *key, int value) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); if (!K_IS_SETTINGS(ksettings) || NULL == key) return 0; @@ -833,8 +899,6 @@ int kdk_conf2_get_default_int(KSettings *ksettings, const char *key) int kdk_conf2_set_int64(KSettings *ksettings, const char *key, long value) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); if (!K_IS_SETTINGS(ksettings) || NULL == key) return 0; @@ -857,8 +921,7 @@ long kdk_conf2_get_int64(KSettings *ksettings, const char *key) return result; } -long kdk_conf2_get_default_int64(KSettings *ksettings, - const char *key) +long kdk_conf2_get_default_int64(KSettings *ksettings, const char *key) { long result = 0; char *value = kdk_conf2_get_default_value(ksettings, key); @@ -872,8 +935,6 @@ long kdk_conf2_get_default_int64(KSettings *ksettings, int kdk_conf2_set_uint(KSettings *ksettings, const char *key, unsigned int value) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); if (!K_IS_SETTINGS(ksettings) || NULL == key) return 0; @@ -910,8 +971,6 @@ unsigned int kdk_conf2_get_default_uint(KSettings *ksettings, const char *key) int kdk_conf2_set_uint64(KSettings *ksettings, const char *key, unsigned long value) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); if (!K_IS_SETTINGS(ksettings) || NULL == key) return 0; @@ -948,14 +1007,10 @@ unsigned long kdk_conf2_get_default_uint64(KSettings *ksettings, const char *key int kdk_conf2_set_string(KSettings *ksettings, const char *key, const char *value) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); if (!K_IS_SETTINGS(ksettings) || NULL == key) return 0; - GVariant *variant = g_variant_new_string(value); - int result = kdk_conf2_set_value(ksettings, key, g_variant_print(variant, FALSE)); - g_variant_unref(variant); + int result = kdk_conf2_set_value(ksettings, key, value); return result; } @@ -972,8 +1027,6 @@ char *kdk_conf2_get_default_string(KSettings *ksettings, const char *key) int kdk_conf2_set_strv(KSettings *ksettings, const char *key, const char *const *value) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); if (!K_IS_SETTINGS(ksettings) || NULL == key) return 0; @@ -1001,7 +1054,7 @@ char **kdk_conf2_get_strv(KSettings *ksettings, const char *key) GVariant *variant = g_variant_parse(G_VARIANT_TYPE("as"), value, NULL, &endptr, &error); if (NULL == variant) { - g_print("解析失败: %s\n", error->message); + syslog(LOG_ERR, "[kysdk-conf2] %s -> 解析失败: %s\n", __func__, error->message); g_free(value); g_error_free(error); return NULL; @@ -1026,7 +1079,7 @@ char **kdk_conf2_get_default_strv(KSettings *ksettings, const char *key) GVariant *variant = g_variant_parse(G_VARIANT_TYPE("as"), value, NULL, &endptr, &error); if (NULL == variant) { - g_print("解析失败: %s\n", error->message); + syslog(LOG_ERR, "[kysdk-conf2] %s -> 解析失败: %s\n", __func__, error->message); g_free(value); g_error_free(error); return NULL; @@ -1040,8 +1093,6 @@ char **kdk_conf2_get_default_strv(KSettings *ksettings, const char *key) char *kdk_conf2_get_descrition(KSettings *ksettings, const char *key) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); if (!K_IS_SETTINGS(ksettings) || NULL == key) return NULL; @@ -1051,8 +1102,6 @@ char *kdk_conf2_get_descrition(KSettings *ksettings, const char *key) char *kdk_conf2_get_summary(KSettings *ksettings, const char *key) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); if (!K_IS_SETTINGS(ksettings) || NULL == key) return NULL; @@ -1062,8 +1111,6 @@ char *kdk_conf2_get_summary(KSettings *ksettings, const char *key) char *kdk_conf2_get_type(KSettings *ksettings, const char *key) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); if (!K_IS_SETTINGS(ksettings) || NULL == key) return NULL; @@ -1073,14 +1120,16 @@ char *kdk_conf2_get_type(KSettings *ksettings, const char *key) void kdk_conf2_reset(KSettings *ksettings, const char *key) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); if (!K_IS_SETTINGS(ksettings) || NULL == key) return; + if (NULL == kdk_conf2_schema_get_key(ksettings->priv->schema, key)) + return; + + 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(ksettings->priv->conn, "reset", + _call_method("reset", id, version, key, NULL); @@ -1090,8 +1139,6 @@ void kdk_conf2_reset(KSettings *ksettings, const char *key) int kdk_conf2_is_writable(KSettings *ksettings, const char *key) { - // g_assert(K_IS_SETTINGS(ksettings)); - // g_assert(NULL != key); if (!K_IS_SETTINGS(ksettings) || NULL == key) return FALSE; @@ -1106,9 +1153,9 @@ int kdk_conf2_has_key(KSettings *ksettings, const char *key) { if (!K_IS_SETTINGS(ksettings) || NULL == key) return FALSE; - + GHashTable *key_hash = kdk_conf2_schema_get_key(ksettings->priv->schema, key); - if(NULL == key_hash) + if (NULL == key_hash) return 0; else return 1; @@ -1116,7 +1163,6 @@ int kdk_conf2_has_key(KSettings *ksettings, const char *key) unsigned long kdk_conf2_connect_signal(KSettings *ksettings, const char *signal_name, KCallBack handler, void *user_data) { - // g_assert(K_IS_SETTINGS(ksettings)); if (!K_IS_SETTINGS(ksettings)) return 0; @@ -1125,15 +1171,7 @@ unsigned long kdk_conf2_connect_signal(KSettings *ksettings, const char *signal_ void kdk_conf2_reload() { - GError *error = NULL; - GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); - if (error != NULL) - { - g_printerr("Connection Error: %s\n", error->message); - g_error_free(error); - return; - } - _call_method(connection, "reload", NULL, NULL, NULL, NULL); + _call_method("reload", NULL, NULL, NULL, NULL); } char **kdk_conf2_list_schemas(const char *app, const char *version) @@ -1183,12 +1221,13 @@ char **kdk_conf2_list_schemas(const char *app, const char *version) int kdk_conf2_save_user_configure(const char *path) { - if(0 != access(path, F_OK)) + syslog(LOG_INFO, "[kysdk-conf2] %s -> save user config start\n", __func__); + char real_path[4096]; + memset(real_path, 0, sizeof(real_path)); + if (!realpath(path, real_path)) { - if(!verify_file(path)) - return FALSE; - if (mkdir(path, 0777) < 0) - return FALSE; + syslog(LOG_INFO, "[kysdk-conf2] %s -> path not exists\n", __func__); + return FALSE; } GDBusConnection *connection; @@ -1204,7 +1243,7 @@ int kdk_conf2_save_user_configure(const char *path) connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); if (error != NULL) { - g_printerr("Connection Error: %s\n", error->message); + syslog(LOG_ERR, "[kysdk-conf2] %s -> Connection Error: %s\n", __func__, error->message); g_error_free(error); return response; } @@ -1221,11 +1260,26 @@ int kdk_conf2_save_user_configure(const char *path) &error); if (error != NULL) { - g_printerr("Proxy Error: %s\n", error->message); + syslog(LOG_ERR, "[kysdk-conf2] %s -> Proxy Error: %s\n", error->message); g_error_free(error); return response; } - GVariant *variant = g_variant_new("(ss)", getlogin(), path); + + uid_t uid = getuid(); // 获取当前进程的用户ID + char user_name[128] = {0}; + struct passwd *pw = getpwuid(uid); // 获取用户ID对应的用户信息结构体 + if (NULL == pw) + { + syslog(LOG_INFO, "【kysdk-conf2】 Get user name failed! use root config\n"); + strcpy(user_name, "root"); + } + else + { + strcpy(user_name, pw->pw_name); + endpwent(); + } + + GVariant *variant = g_variant_new("(ss)", user_name, real_path); result = g_dbus_proxy_call_sync(proxy, "save", variant, @@ -1235,7 +1289,7 @@ int kdk_conf2_save_user_configure(const char *path) &error); if (error != NULL) { - g_printerr("Method Call Error: %s\n", error->message); + syslog(LOG_ERR, "[kysdk-conf2] %s -> Method Call Error: %s\n", __func__, error->message); g_error_free(error); return response; } @@ -1246,5 +1300,132 @@ int kdk_conf2_save_user_configure(const char *path) // 释放资源 g_variant_unref(result); g_object_unref(proxy); + syslog(LOG_INFO, "[kysdk-conf2] %s -> save user config end\n", __func__); return response; } + +KSettings *kdk_conf2_new_extends_id(const char *old_id, const char *new_id, const char *version) +{ + KSettings *setting = kdk_conf2_new(new_id, version); + if (NULL != setting) + return setting; + syslog(LOG_INFO, "[kysdk-conf2] %s -> creat new id : %s\n", __func__, new_id); + GDBusConnection *connection; + GError *error = NULL; + GDBusProxy *proxy; + GVariant *result; + int response = FALSE; + + // 获取 DBus 会话总线 + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) + { + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (error != NULL) + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> Connection Error: %s\n", __func__, error->message); + g_error_free(error); + return NULL; + } + } + + // 创建代理对象 + proxy = g_dbus_proxy_new_sync(connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "com.kylin.kysdk.conf2", + "/com/kylin/kysdk/conf2", + "com.kylin.kysdk.conf2", + NULL, + &error); + if (error != NULL) + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> Proxy Error: %s\n", __func__, error->message); + 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】 Get user name failed! use root config\n"); + strcpy(user_name, "root"); + } + else + { + strcpy(user_name, pw->pw_name); + endpwent(); + } + + GVariant *variant = g_variant_new("(ssss)", + old_id, + new_id, + version ? version : "", + user_name); + result = g_dbus_proxy_call_sync(proxy, + "extends_id", + variant, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (error != NULL) + { + syslog(LOG_INFO, "[kysdk-conf2] %s -> Method Call Error: %s\n", __func__, error->message); + g_error_free(error); + return NULL; + } + + // 处理方法调用的返回值 + g_variant_get(result, "(b)", &response); + + // 释放资源 + g_variant_unref(result); + g_object_unref(proxy); + + if (response) + { + kdk_conf2_schema_update_schemas_table(); + return kdk_conf2_new(new_id, version); + } + return NULL; +} + +int kdk_conf2_is_schema(const char *id, const char *version) +{ + if (NULL == id) + { + syslog(LOG_INFO, "[kysdk-conf2] %s ->: id is NULL\n", __func__); + return FALSE; + } + + if (NULL == schemas_table) + kdk_conf2_schema_update_schemas_table(); + + if (NULL == schemas_table) + { + syslog(LOG_INFO, "[kysdk-conf2] %s ->: load user.db failed\n", __func__); + return FALSE; + } + + KSettingsSchema *schema = kdk_conf2_schema_table_lookup(id, version); + if (NULL == schema) + { + syslog(LOG_INFO, "[kysdk-conf2] %s ->: schema not existed\n", __func__); + return FALSE; + } + + return TRUE; +} + +char *kdk_conf2_get_schema_summary(KSettings *ksettings) +{ + return ksettings->priv->schema->summary ? strdup(ksettings->priv->schema->summary) : NULL; +} + +char *kdk_conf2_get_schema_desription(KSettings *ksettings) +{ + return ksettings->priv->schema->description ? strdup(ksettings->priv->schema->description) : NULL; +} diff --git a/src/conf2/api/libkysettings.h b/src/conf2/api/libkysettings.h index 6db51ac..f46bf50 100644 --- a/src/conf2/api/libkysettings.h +++ b/src/conf2/api/libkysettings.h @@ -178,6 +178,7 @@ extern "C" const char *signal_name, KCallBack handler, void *user_data); + void kdk_conf2_reload (void); char ** kdk_conf2_list_schemas (const char *app, @@ -185,21 +186,16 @@ extern "C" int kdk_conf2_save_user_configure (const char *path); + KSettings * kdk_conf2_new_extends_id (const char *old_id, + const char *new_id, + const char *version); + + int kdk_conf2_is_schema (const char *id, + const char *version); + char * kdk_conf2_get_schema_summary (KSettings *ksettings); - - - - - - - - - - - - - + char * kdk_conf2_get_schema_desription (KSettings *ksettings); #if __cplusplus } #endif // extern "C" diff --git a/src/conf2/configs/conf2.yaml b/src/conf2/configs/conf2.yaml new file mode 100644 index 0000000..b6cbfec --- /dev/null +++ b/src/conf2/configs/conf2.yaml @@ -0,0 +1,13 @@ +dirs: + - basic + - industry + - vendor + - production + - project + - kcm +#通用配置与应用下组名的映射关系 +mapping: + #通用配置组名 + powermanager: + #应用名:组名 + control-center: powermanager \ No newline at end of file diff --git a/src/conf2/service/com.kylin.kysdk.conf2.limit b/src/conf2/service/com.kylin.kysdk.conf2.limit new file mode 100644 index 0000000..667ef78 --- /dev/null +++ b/src/conf2/service/com.kylin.kysdk.conf2.limit @@ -0,0 +1,8 @@ +[whitelist] +key2 = /usr/bin/kconf2 +key3 = /usr/bin/kconf2-editor +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 diff --git a/src/conf2/service/com.kylin.kysdk.conf2.limit.verify b/src/conf2/service/com.kylin.kysdk.conf2.limit.verify new file mode 100644 index 0000000..18c3a99 --- /dev/null +++ b/src/conf2/service/com.kylin.kysdk.conf2.limit.verify @@ -0,0 +1 @@ +f45558b6a1cb69ceb6e4e58d8b9a47b551db8543 \ No newline at end of file diff --git a/src/conf2/service/conf2-server.py b/src/conf2/service/conf2-server.py index 9a7ab45..6c88b87 100644 --- a/src/conf2/service/conf2-server.py +++ b/src/conf2/service/conf2-server.py @@ -1,3 +1,4 @@ +#!/usr/bin/python3.8 # # libkysdk-system's Library # @@ -16,414 +17,91 @@ # You should have received a copy of the GNU General Public License # along with this library. If not, see . # -# Authors: Yunhe Liu +# Authors: tianshaoshuai # # -#!/usr/bin/python3 -import yaml, sqlite3 -import os, re, shutil -import logging, traceback - +import os +import logging import dbus import dbus.service from dbus.mainloop.glib import DBusGMainLoop from gi.repository import GLib +import conf2Utils +from configparser import ConfigParser + +logger = None +programWhiteList = [] +envBlackList = ('LD_PRELOAD', 'LD_LIBRARY_PATH', 'LD_AUDIT',) # 创建一个DBus服务类 class KYSettingsDBusService(dbus.service.Object): - __read_only_view = {} - __root_view = {} - def __init__(self, bus_name, object_path): + logger.info(f'DBus Class init') dbus.service.Object.__init__(self, bus_name, object_path) - os.makedirs('/etc/kylin-config', exist_ok=True) - #初始化日志模块 - logging.basicConfig(filename='/etc/kylin-config/systembus.log', level=logging.DEBUG, format='%(asctime)s %(levelname)s %(name)s \n %(message)s') - self.logger = logging.getLogger('/etc/kylin-config/systembus.log') + self._converter = conf2Utils.Converter(logger) + self._watchdog = conf2Utils.FileWatche('/etc/kylin-config/basic', self) - self.__creat_db_file__() + self._reload() + if os.path.exists('/etc/dbus-1/conf/com.kylin.kysdk.conf2.limit'): + conf = ConfigParser() + conf.read('/etc/dbus-1/conf/com.kylin.kysdk.conf2.limit') + # conf.read('/home/kylin/disk/kylinos-src/libkysdk-base/src/conf2/service/com.kylin.kysdk.conf2.limit') + if conf.has_section('whitelist'): + global programWhiteList + programWhiteList = list(conf['whitelist'].values()) - #读配置文件,创建只读视图数据库和root用户的数据库 - def __creat_db_file__(self): - try: - #加载只读配置,写入数据库 - self.__load_read_only_view__() - self.__dict2db__(self.__read_only_view, '/etc/kylin-config/user.db') + logger.info(f'DBus Class init end') - #copy文件到root用户目录 - if os.path.exists('/etc/kylin-config/user.db'): - if not os.path.exists('/root/.config/kylin-config/user.db'): - os.makedirs(os.path.dirname('/root/.config/kylin-config/'), exist_ok=True) - shutil.copyfile('/etc/kylin-config/user.db', '/root/.config/kylin-config/user.db') - self.__root_view = self.__format_db_file('/root/.config/kylin-config/user.db') - else: - self.__root_view = self.__format_db_file('/root/.config/kylin-config/user.db') - self.__del_discarded_key(self.__root_view, self.__read_only_view) - self.__merge_dict(self.__root_view, self.__read_only_view) - self.__dict2db__(self.__root_view, '/root/.config/kylin-config/user.db') - except Exception as e: - self.logger.error(traceback.format_exc()) - -#统一视图写入数据库 - #递归寻找枚举 - def __recursive_search__(self, dictionary, key): - if key in dictionary: - return dictionary[key] - else: - for value in dictionary.values(): - if isinstance(value, dict): - result = self.__recursive_search__(value, key) - if result is not None: - return result - return None - - #递归写入配置数据到配置表 - def __write_element_in_table__(self, version_data:dict ,data: dict, cursor: sqlite3.Cursor, version_id, parent_id): - #key写入到数据库 - if 'keys' in data: - keys = data['keys'] - for key in keys: - property = key - - user_value = keys[key].get('value') - # if user_value is None: - # user_value = keys[key].get('default') - - type = keys[key].get('_type') - - default_value = keys[key].get('default') - if isinstance(default_value, str) is False: - default_value = str(default_value) - - description = keys[key].get('description') - - summary = keys[key].get('summary') - - permission = keys[key].get('permission') - if permission is None: - permission = 'public' - - #TODO: 计算range取值范围 - range = keys[key].get('range') - # reload时,没有更新的枚举数据的range应该是枚举参数的字符串列表 - # 更新后或初始化时的枚举数据的range是@[枚举名] - if type == 'enum' and isinstance(range, str) and range.startswith('@'): - enum_range = {} - element_list = self.__recursive_search__(version_data,keys[key]['range'][1:]) - for element in element_list: - enum_range[element['nick']] = int(element['value']) - range = str(enum_range) - - cursor.execute('''INSERT INTO configures (version_id, property, user_value, data_type, default_value, permission, range, parent, description, summary) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''',(version_id, property, user_value, type, default_value, permission, range, parent_id, description, summary)) - if 'children' in data: - children = data['children'] - for child in children: - if child.startswith('enum_'): - continue - cursor.execute("INSERT INTO configures (version_id,group_name,parent) VALUES (?, ?, ?)",(version_id,child,parent_id)) - group_id = cursor.lastrowid - self.__write_element_in_table__(version_data,children[child],cursor,version_id,group_id) - - #创建app表 - def __covert_app_table__(self,data: dict, cursor: sqlite3.Cursor): - # 创建app表 - cursor.execute('''CREATE TABLE IF NOT EXISTS app - (id INTEGER PRIMARY KEY AUTOINCREMENT, - app_name TEXT, - defualt_version TEXT)''') - #将app信息写入app表 - for app in data.keys(): - default_version = data[app].get('default_version') - # 如果没有设置默认版本,将默认版本设置为最大版本 - if default_version is None: - for version in data[app]: - if default_version is None: - default_version = version - #比较版本 版本目前认为是2.0.0-0k0格式 - default_list = re.findall(r'\d+', default_version) - list = re.findall(r'\d+', version) - for i in range(0,6): - if len(default_list) == i: - default_version = version - break - if len(list) == i: - break - if int(default_list[i]) < int(list[i]): - default_version = version - break - if int(default_list[i]) > int(list[i]): - break - cursor.execute("INSERT INTO app (app_name, defualt_version) VALUES (?,?)",(app, default_version)) - - #创建版本表 - def __covert_version_table__(self,data: dict, cursor: sqlite3.Cursor): - # 创建version表 - cursor.execute('''CREATE TABLE IF NOT EXISTS version - (id INTEGER PRIMARY KEY AUTOINCREMENT, - app_id INTEGER, - version TEXT, - compatible TEXT, - FOREIGN KEY (app_id) REFERENCES app(id))''') - for app in data.keys(): - cursor.execute("SELECT id FROM app WHERE app_name = ?", (app,)) - appId = cursor.fetchone() - for version in data[app].keys(): - if(version == 'default_version'): - continue - cursor.execute("INSERT INTO version (app_id,version, compatible) VALUES (?, ?, ?)",(appId[0],version, data[app][version].get('compatible'))) - - #创建配置表 - def __covert_configure_table__(self, data: dict, cursor: sqlite3.Cursor): - # 创建version表 - cursor.execute('''CREATE TABLE IF NOT EXISTS configures - (id INTEGER PRIMARY KEY AUTOINCREMENT, - version_id INTEGER, - property TEXT, - group_name TEXT, - user_value TEXT, - data_type TEXT, - default_value TEXT, - permission TEXT, - range TEXT, - parent INTEGER, - description TEXT, - summary TEXT, - FOREIGN KEY (version_id) REFERENCES version(id), - FOREIGN KEY (parent) REFERENCES configures(id))''') - cursor.execute("SELECT * FROM app") - apps = cursor.fetchall() - for app in apps: - cursor.execute("SELECT * FROM version WHERE app_id = ?", (app[0],)) - versions = cursor.fetchall() - for version in versions: - version_data = data[app[1]][version[2]] - #keys写入数据库 - self.__write_element_in_table__(version_data,version_data,cursor,version[0],0) - - #将字典中的配置数据写入数据库 - def __dict2db__(self, dict, path): - try: - # 连接到数据库(如果不存在则创建) - db_file_path = path.rsplit('/',maxsplit=1)[0] - if not os.path.exists(db_file_path): - os.makedirs(db_file_path) - conn = sqlite3.connect(path) - - # 创建游标对象 - cursor = conn.cursor() - conn.execute('BEGIN TRANSACTION') - - # 获取数据库中的所有表名 - cursor.execute("SELECT name FROM sqlite_master WHERE type='table'") - tables = cursor.fetchall() - - # 遍历所有表名,对每个表执行DELETE语句以删除所有行 - for table in tables: - cursor.execute(f"DELETE FROM {table[0]}") - # cursor.execute(f"DELETE FROM sqlite_sequence WHERE name={table[0]}") - - self.__covert_app_table__(dict,cursor) - self.__covert_version_table__(dict,cursor) - self.__covert_configure_table__(dict,cursor) - - # 提交更改 - conn.commit() - conn.close() - return 0 - - except sqlite3.Error as e: - conn.rollback() - conn.close() - self.logger.error(traceback.format_exc()) - return -1 - -#读取数据库数据到内存 - #递归读取数据库数据到字典 - def __format_element(self, parent: dict, cursor: sqlite3.Cursor, version_id, parent_id): - keys = {} - children = {} - cursor.execute('SELECT * FROM configures WHERE version_id = ? AND parent = ?', (version_id,parent_id)) - configure_data = cursor.fetchall() - for configure in configure_data: - #读取子分组 - if configure[3] is not None: - children[configure[3]] = {} - self.__format_element(children[configure[3]],cursor,version_id,configure[0]) - #读取key - else: - keys[configure[2]] = {} - if configure[4] is not None: - keys[configure[2]]['value'] = configure[4] - if configure[5] is not None: - keys[configure[2]]['_type'] = configure[5] - if configure[6] is not None: - keys[configure[2]]['default'] = configure[6] - if configure[7] is not None: - keys[configure[2]]['permission'] = configure[7] - if configure[8] is not None: - keys[configure[2]]['range'] = configure[8] - if configure[10] is not None: - keys[configure[2]]['description'] = configure[10] - if configure[11] is not None: - keys[configure[2]]['summary'] = configure[11] - if keys: - parent['keys'] = keys - if children: - parent['children'] = children - - #将数据库中的内容读取到数据结构中 - def __format_db_file(self, db_file: str): - try: - data = {} - # 连接到数据库(如果不存在则创建) - conn = sqlite3.connect(db_file) - if conn is None: - return data - # 创建游标对象 - cursor = conn.cursor() - conn.execute('BEGIN TRANSACTION') - - #遍历app表 - cursor.execute('SELECT * FROM app') - app_data = cursor.fetchall() - for app in app_data: - data[app[1]] = {} - cursor.execute('SELECT * FROM version WHERE app_id = ?', (app[0],)) - version_data = cursor.fetchall() - for version in version_data: - data[app[1]][version[2]] = {} - self.__format_element(data[app[1]][version[2]],cursor,version[0],0) - conn.close() - return data - except Exception as e: - conn.rollback() - conn.close() - self.logger.error(traceback.format_exc()) - return {} - - #读取yaml配置文件到字典 - def __load_config__(self, yaml_dir): - if not os.path.exists(yaml_dir): - return {} - yaml_data = {} - for root,dirs,files in os.walk(yaml_dir): - for file in files: - if file.endswith('.yaml'): - with open(f'{yaml_dir}/{file}','r') as tmp_file: - yaml_str = tmp_file.read() - tmp_data = yaml.safe_load(yaml_str) - yaml_data.update(tmp_data) - return yaml_data - - #合并、覆盖两个字典 - def __merge_dict(self, dest:dict , src:dict): - if src is None: - return dest - for key, value in src.items(): - if key in dest and isinstance(dest[key], dict) and isinstance(src[key], dict): - self.__merge_dict(dest[key], src[key]) - else: - dest[key] = value - return dest - - def __del_discarded_key(self, dest:dict, src:dict): - keys_to_delete = [] - for key in dest: - if not isinstance(dest[key], dict): - return - if key not in src: - keys_to_delete.append(key) - else: - self.__del_discarded_key(dest[key], src[key]) - - for key in keys_to_delete: - dest.pop(key) - - #统一配置文件内容覆盖 - def __common_override(self, dest:dict, src:dict): - if 'children' not in dest: + def isAllowedCaller(self,sender): + if sender is None: return - for group in src: - if group in dest['children']: - for key in src[group]['keys']: - if key in dest['children'][group]['keys']: - dest['children'][group]['keys'][key].update(src[group]['keys'][key]) - # self.__merge_dict(dest['children'][group], src[group]) - for child in dest['children']: - if child != group: - self.__common_override(dest['children'][child], src) + 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 __load_read_only_view__(self): - self.__read_only_view.clear() - # 只读文件目录 - self.__read_only_view.update(self.__load_config__('/etc/kylin-config/basic')) + 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 - data = self.__load_config__('/etc/kylin-config/production') - self.__merge_dict(self.__read_only_view, data) + 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) - data = self.__load_config__('/etc/kylin-config/vendor') - self.__merge_dict(self.__read_only_view, data) - - data = self.__load_config__('/etc/kylin-config/industry') - self.__merge_dict(self.__read_only_view, data) - - data = self.__load_config__('/etc/kylin-config/project') - self.__merge_dict(self.__read_only_view, data) - - data = self.__load_config__('/etc/kylin-config/control') - self.__merge_dict(self.__read_only_view, data) - - data = self.__load_config__('/etc/kylin-config/common') - if data: - for app in self.__read_only_view: - for version in self.__read_only_view[app]: - self.__common_override(self.__read_only_view[app][version], data) - - #将字典中的配置数据写入数据库 - def __dict2db__(self, dict, path): - try: - # 连接到数据库(如果不存在则创建) - db_file_path = path.rsplit('/',maxsplit=1)[0] - if not os.path.exists(db_file_path): - os.makedirs(db_file_path) - conn = sqlite3.connect(path) - - # 创建游标对象 - cursor = conn.cursor() - conn.execute('BEGIN TRANSACTION') - - # 获取数据库中的所有表名 - cursor.execute("SELECT name FROM sqlite_master WHERE type='table'") - tables = cursor.fetchall() - - # 遍历所有表名,对每个表执行DELETE语句以删除所有行 - for table in tables: - cursor.execute(f"DELETE FROM {table[0]}") - # cursor.execute(f"DELETE FROM sqlite_sequence WHERE name={table[0]}") - - self.__covert_app_table__(dict,cursor) - self.__covert_version_table__(dict,cursor) - self.__covert_configure_table__(dict,cursor) - - # 提交更改 - conn.commit() - conn.close() - return 0 - - except Exception as e: - conn.rollback() - conn.close() - self.logger.error(traceback.format_exc()) - return -1 + # 重载 + def _reload(self): + if self._converter.update_read_only_db(): + if self._converter.update_user_db('/root/.config/kylin-config/user.db'): + return True + return False # key值改变信号 - @dbus.service.signal("com.kylin.kysdk.conf2", signature='ssss') - def key_changed(self, id, version, key, user): + @dbus.service.signal("com.kylin.kysdk.conf2", signature='sss') + def key_changed(self, id, version, key): pass # 配置信息update信号 @@ -432,187 +110,72 @@ class KYSettingsDBusService(dbus.service.Object): pass # 设置一个配置的值 - @dbus.service.method("com.kylin.kysdk.conf2", in_signature='sssss', out_signature='i') - def set(self, user, id, version, key, value): - try: - # 修改用户配置文件,写入到数据库 - group_list = id.split('.') - sql_path = '' - if user == 'root': - sql_path = '/root/.config/kylin-config/user.db' - else: - sql_path = f'/home/{user}/.config/kylin-config/user.db' + @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) + else: + success = self._converter.set(f'/home/{user}/.config/kylin-config/user.db', id, version, key, value) - conn = sqlite3.connect(sql_path) - # 创建游标对象 - cursor = conn.cursor() + if success: + self.key_changed(id, version, key) - # 开始写入事务 - conn.execute('BEGIN TRANSACTION') - cursor.execute("SELECT id FROM app WHERE app_name = ?", (group_list[0],)) - app_id = cursor.fetchone()[0] - cursor.execute("SELECT id FROM version WHERE app_id = ? AND version = ?", (app_id, version)) - version_id = cursor.fetchone()[0] - parent_id = 0 - # 查找组 - for group_name in group_list[1:]: - cursor.execute("SELECT id FROM configures WHERE version_id = ? AND parent = ? AND group_name = ?", (version_id, parent_id, group_name)) - parent_id = cursor.fetchone()[0] - # cursor.execute("SELECT * FROM configures WHERE version_id = ? AND parent = ? AND property = ?", (version_id, parent_id, key)) - # key_data = cursor.fetchone() - - cursor.execute("UPDATE configures SET user_value = ? WHERE version_id = ? AND parent = ? AND property = ?", (value,version_id, parent_id, key)) - conn.commit() - conn.close() - if user == 'root': - self.__merge_dict(self.__root_view, self.__format_db_file('/root/.config/kylin-config/user.db')) - self.key_changed(id, version, key, user) - return 1 - except Exception as e: - conn.rollback() - conn.close() - self.logger.error(traceback.format_exc()) - return 0 + return success # 恢复单个默认值 - @dbus.service.method("com.kylin.kysdk.conf2", in_signature='ssss', out_signature='i') - def reset(self,user, id, version, key): - try: - # 修改用户配置文件,写入到数据库 - group_list = id.split('.') - sql_path = '' - if user == 'root': - sql_path = '/root/.config/kylin-config/user.db' - else: - sql_path = f'/home/{user}/.config/kylin-config/user.db' - - conn = sqlite3.connect(sql_path) - # 创建游标对象 - cursor = conn.cursor() - - # 开始写入事务 - conn.execute('BEGIN TRANSACTION') - cursor.execute("SELECT id FROM app WHERE app_name = ?", (group_list[0],)) - app_id = cursor.fetchone()[0] - cursor.execute("SELECT id FROM version WHERE app_id = ? AND version = ?", (app_id,version)) - version_id = cursor.fetchone()[0] - parent_id = 0 - # 查找组 - for group_name in group_list[1:]: - cursor.execute("SELECT id FROM configures WHERE version_id = ? AND parent = ? AND group_name = ?", (version_id, parent_id, group_name)) - parent_id = cursor.fetchone()[0] - # cursor.execute("SELECT * FROM configures WHERE version_id = ? AND parent = ? AND property = ?", (version_id, parent_id, key)) - cursor.execute("UPDATE configures SET user_value = default_value WHERE version_id = ? AND parent = ? AND property = ?", (version_id, parent_id, key)) - conn.commit() - conn.close() - if user == 'root': - self.__merge_dict(self.__root_view, self.__format_db_file('/root/.config/kylin-config/user.db')) - self.key_changed(id,version,key, user) - return 0 - except Exception as e: - conn.rollback() - conn.close() - self.logger.error(traceback.format_exc()) - return -1 - - # 恢复整个id的默认值 - # @dbus.service.method("com.kylin.kysdk.conf2", in_signature='sss', out_signature='i') - # def reset_recursively(self, user, id, version): - # try: - # # 修改用户配置文件,写入到数据库 - # group_list = id.split('.') - # if user == 'root': - # sql_path = '/root/.config/kylin-config/user.db' - # else: - # sql_path = f'/home/{user}/.config/kylin-config/user.db' - - # conn = sqlite3.connect(sql_path) - # # 创建游标对象 - # cursor = conn.cursor() - - # # 开始写入事务 - # conn.execute('BEGIN TRANSACTION') - # cursor.execute("SELECT id FROM app WHERE app_name = ?", (group_list[0],)) - # app_id = cursor.fetchone()[0] - # cursor.execute("SELECT id FROM version WHERE app_id = ? AND version = ?", (app_id,version)) - # version_id = cursor.fetchone()[0] - # parent_id = 0 - # # 查找组 - # for group_name in group_list[1:]: - # cursor.execute("SELECT id FROM configures WHERE version_id = ? AND parent = ? AND group_name = ?", (version_id, parent_id, group_name)) - # parent_id = cursor.fetchone()[0] - # cursor.execute("UPDATE configures SET value = default_value WHERE version_id = ? AND parent = ?", (version_id, parent_id)) - # conn.commit() - # conn.close() - # if user == 'root': - # self.__merge_dict(self.__root_view, self.__format_db_file('/root/.config/kylin-config/user.db')) - # self.key_changed(id,version,None) - # return 0 - # except sqlite3.Error as e: - # conn.rollback() - # conn.close() - # return -1 - - # 恢复整个id的默认值 - @dbus.service.method("com.kylin.kysdk.conf2", in_signature='', out_signature='i') - def reload(self): - try: - self.__load_read_only_view__() - self.__dict2db__(self.__read_only_view, '/etc/kylin-config/user.db') - - #删除配置文件中删除的键 - self.__del_discarded_key(self.__root_view, self.__read_only_view) - #合并配置新增和修改 - self.__merge_dict(self.__root_view, self.__read_only_view) - self.__dict2db__(self.__root_view, '/root/.config/kylin-config/user.db') - - self.updated() - return 1 - except Exception as e: - self.logger.error(traceback.format_exc()) - return 0 - - def __value_override_default(self, dest:dict, src:dict): - for key, value in src.items(): - if key not in dest: - continue - if isinstance(src[key], dict): - self.__value_override_default(dest[key], src[key]) - else: - if src['value'] is not None: - dest['default'] = src['value'] - return - - - @dbus.service.method("com.kylin.kysdk.conf2", in_signature='ss', out_signature='b') - def save(self, user, path): - if not os.path.exists(path): - return False - data = {} - if 'root' == user: - data = self.__format_db_file('/root/.config/kylin-config/user.db') + @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) else: - data = self.__format_db_file(f'/home/{user}/.config/kylin-config/user.db') - if data == {} or data is None: - return False + success = self._converter.reset(f'/home/{user}/.config/kylin-config/user.db', id, version, key) + + if success: + self.key_changed(id, version, key) - tmp = {} - tmp.update(self.__read_only_view) - if tmp == {} or tmp is None: - return False - #将用户配置写入到复制的只读视图里 - self.__value_override_default(tmp, data) - for key in tmp: - data = {} - data[key] = tmp[key] - yaml_data = yaml.safe_dump(data,allow_unicode = True) - if yaml_data is None: - continue - with open(f'{path}/{key}.yaml', 'w') as yaml_file: - yaml_file.write(yaml_data) - return True + return success + + # 恢复整个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) + else: + success = self._converter.save(f'/home/{user}/.config/kylin-config/user.db', path) + return success + + #复制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') + else: + success = self._converter.extends_id(old_id, new_id, version, f'/home/{user}/.config/kylin-config/user.db') + return success if __name__ == "__main__": + 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() + # 初始化DBus主循环 DBusGMainLoop(set_as_default=True) @@ -626,4 +189,4 @@ if __name__ == "__main__": # 开始DBus主循环 mainloop = GLib.MainLoop() - mainloop.run() \ No newline at end of file + mainloop.run() diff --git a/src/conf2/service/conf2-session-server.py b/src/conf2/service/conf2-session-server.py index 886440f..37e8d23 100644 --- a/src/conf2/service/conf2-session-server.py +++ b/src/conf2/service/conf2-session-server.py @@ -1,3 +1,4 @@ +#!/usr/bin/python3.8 # # libkysdk-system's Library # @@ -16,324 +17,90 @@ # You should have received a copy of the GNU General Public License # along with this library. If not, see . # -# Authors: Yunhe Liu +# Authors: tianshaoshuai # # -#!/usr/bin/python3 +import os +import logging import dbus import dbus.service from dbus.mainloop.glib import DBusGMainLoop from gi.repository import GLib +import conf2Utils -import os, shutil, re -import sqlite3 - -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 __write_element_in_table__(version_data:dict ,data: dict, cursor: sqlite3.Cursor, version_id, parent_id): - #key写入到数据库 - if 'keys' in data: - keys = data['keys'] - for key in keys: - property = key - - user_value = keys[key].get('value') - # if attr is None: - # attr = keys[key].get('default') - - type = keys[key].get('_type') - - default_value = keys[key].get('default') - if isinstance(default_value, str) is False: - default_value = str(default_value) - - description = keys[key].get('description') - - summary = keys[key].get('summary') - - permission = keys[key].get('permission') - if permission is None: - permission = 'public' - - #TODO: 计算range取值范围 - range = keys[key].get('range') - # reload时,没有更新的枚举数据的range应该是枚举参数的字符串列表 - # 更新后或初始化时的枚举数据的range是@[枚举名] - if type == 'enum' and isinstance(range, str) and range.startswith('@'): - enum_range = {} - print(keys[key]['range']) - element_list = __recursive_search__(version_data, keys[key]['range'][1:]) - for element in element_list: - enum_range[element['nick']] = int(element['value']) - range = str(enum_range) - - cursor.execute('''INSERT INTO configures (version_id, property, user_value, data_type, default_value, permission, range, parent, description, summary) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''',(version_id, property, user_value, type, default_value, permission, range, parent_id, description, summary)) - if 'children' in data: - children = data['children'] - for child in children: - if child.startswith('enum_'): - continue - cursor.execute("INSERT INTO configures (version_id,group_name,parent) VALUES (?, ?, ?)",(version_id, child, parent_id)) - group_id = cursor.lastrowid - __write_element_in_table__(version_data,children[child],cursor,version_id,group_id) - -def __covert_app_table__(data: dict, cursor: sqlite3.Cursor): - # 创建app表 - cursor.execute('''CREATE TABLE IF NOT EXISTS app - (id INTEGER PRIMARY KEY AUTOINCREMENT, - app_name TEXT, - defualt_version TEXT)''') - #将app信息写入app表 - for app in data.keys(): - default_version = data[app].get('default_version') - # 如果没有设置默认版本,将默认版本设置为最大版本 - if default_version is None: - for version in data[app]: - if default_version is None: - default_version = version - #比较版本 版本目前认为是2.0.0-0k0格式 - default_list = re.findall(r'\d+', default_version) - list = re.findall(r'\d+', version) - for i in range(0,6): - if len(default_list) == i: - default_version = version - break - if len(list) == i: - break - if int(default_list[i]) < int(list[i]): - default_version = version - break - if int(default_list[i]) > int(list[i]): - break - cursor.execute("INSERT INTO app (app_name, defualt_version) VALUES (?,?)",(app, default_version)) - -def __covert_version_table__(data: dict, cursor: sqlite3.Cursor): - # 创建version表 - cursor.execute('''CREATE TABLE IF NOT EXISTS version - (id INTEGER PRIMARY KEY AUTOINCREMENT, - app_id INTEGER, - version TEXT, - compatible TEXT, - FOREIGN KEY (app_id) REFERENCES app(id))''') - for app in data.keys(): - cursor.execute("SELECT id FROM app WHERE app_name = ?", (app,)) - appId = cursor.fetchone() - for version in data[app].keys(): - if(version == 'default_version'): - continue - cursor.execute("INSERT INTO version (app_id,version, compatible) VALUES (?, ?, ?)",(appId[0],version, data[app][version].get('compatible'))) - -def __covert_configure_table__(data: dict, cursor: sqlite3.Cursor): - # 创建version表 - cursor.execute('''CREATE TABLE IF NOT EXISTS configures - (id INTEGER PRIMARY KEY AUTOINCREMENT, - version_id INTEGER, - property TEXT, - group_name TEXT, - user_value TEXT, - data_type TEXT, - default_value TEXT, - permission TEXT, - range TEXT, - parent INTEGER, - description TEXT, - summary TEXT, - FOREIGN KEY (version_id) REFERENCES version(id), - FOREIGN KEY (parent) REFERENCES configures(id))''') - cursor.execute("SELECT * FROM app") - apps = cursor.fetchall() - for app in apps: - cursor.execute("SELECT * FROM version WHERE app_id = ?", (app[0],)) - versions = cursor.fetchall() - for version in versions: - version_data = data[app[1]][version[2]] - #keys写入数据库 - __write_element_in_table__(version_data,version_data,cursor,version[0],0) - -def __dict2db__(dict, path): - try: - # 连接到数据库(如果不存在则创建) - db_file_path = path.rsplit('/',maxsplit=1)[0] - if not os.path.exists(db_file_path): - os.makedirs(db_file_path) - conn = sqlite3.connect(path) - - # 创建游标对象 - cursor = conn.cursor() - conn.execute('BEGIN TRANSACTION') - - # 获取数据库中的所有表名 - cursor.execute("SELECT name FROM sqlite_master WHERE type='table'") - tables = cursor.fetchall() - - # 遍历所有表名,对每个表执行DELETE语句以删除所有行 - for table in tables: - cursor.execute(f"DELETE FROM {table[0]}") - - __covert_app_table__(dict,cursor) - __covert_version_table__(dict,cursor) - __covert_configure_table__(dict,cursor) - - # 提交更改 - conn.commit() - conn.close() - return 0 - - except Exception as e: - conn.rollback() - conn.close() - return -1 - -#读取一个元素 -def __format_element(parent: dict, cursor: sqlite3.Cursor, version_id, parent_id): - keys = {} - children = {} - cursor.execute('SELECT * FROM configures WHERE version_id = ? AND parent = ?', (version_id,parent_id)) - configure_data = cursor.fetchall() - for configure in configure_data: - #读取子分组 - if configure[3] is not None: - children[configure[3]] = {} - __format_element(children[configure[3]],cursor,version_id,configure[0]) - #读取key - else: - keys[configure[2]] = {} - if configure[4] is not None: - keys[configure[2]]['value'] = configure[4] - if configure[5] is not None: - keys[configure[2]]['_type'] = configure[5] - if configure[6] is not None: - keys[configure[2]]['default'] = configure[6] - if configure[7] is not None: - keys[configure[2]]['permission'] = configure[7] - if configure[8] is not None: - keys[configure[2]]['range'] = configure[8] - if configure[10] is not None: - keys[configure[2]]['description'] = configure[10] - if configure[11] is not None: - keys[configure[2]]['summary'] = configure[11] - if keys: - parent['keys'] = keys - if children: - parent['children'] = children - -#将数据库中的内容读取到数据结构中 -#由于存储数组到数据库不会存储 枚举 所以反序列化出来的数据结构中不存在 枚举 -def __format_db_file(db_file: str): - try: - data = {} - conn = sqlite3.connect(db_file) - if conn is None: - return data - # 创建游标对象 - cursor = conn.cursor() - #遍历app表 - conn.execute('BEGIN TRANSACTION') - cursor.execute('SELECT * FROM app') - app_data = cursor.fetchall() - for app in app_data: - data[app[1]] = {} - cursor.execute('SELECT * FROM version WHERE app_id = ?', (app[0],)) - version_data = cursor.fetchall() - for version in version_data: - data[app[1]][version[2]] = {} - __format_element(data[app[1]][version[2]],cursor,version[0],0) - conn.close() - return data - except Exception as e: - conn.rollback() - conn.close() - return {} - -def __merge_dict(dest:dict , src:dict): - if src is None: - return dest - for key, value in src.items(): - if key in dest and isinstance(dest[key], dict) and isinstance(src[key], dict): - __merge_dict(dest[key], src[key]) - else: - if key != 'user_value': - dest[key] = value - return dest - -def __del_discarded_key(dest:dict, src:dict): - keys_to_delete = [] - for key in dest: - if not isinstance(dest[key], dict): - return - if key not in src: - keys_to_delete.append(key) - else: - __del_discarded_key(dest[key], src[key]) - - for key in keys_to_delete: - dest.pop(key) - -__user_view = {} -__destination_file = '~/.config/kylin-config/user.db' +logger = None +destination_file = '~/.config/kylin-config/user.db' class KYSettingsDBusSessionService(dbus.service.Object): def __init__(self, bus_name, object_path): + logger.info('Session DBus Init') dbus.service.Object.__init__(self, bus_name, object_path) + + conn = dbus.SystemBus() + conn.add_signal_receiver(self._reload_handler, + signal_name='updated', + dbus_interface='com.kylin.kysdk.conf2', + bus_name='com.kylin.kysdk.conf2', + path="/com/kylin/kysdk/conf2") + + conn.add_signal_receiver(self._key_changed_handler, + signal_name='key_changed', + dbus_interface='com.kylin.kysdk.conf2', + bus_name='com.kylin.kysdk.conf2', + path="/com/kylin/kysdk/conf2") + + self._converter = conf2Utils.Converter(logger) + self.Init() + logger.info('Session DBus end') + + def _reload_handler(self): + logger.info('On update') + self.Init() + self.updated() + + def _key_changed_handler(self, id, version, key): + logger.info('On key changed') + self._converter.update_user_dict(destination_file) + self.key_changed(id, version, key) + + # key值改变信号 + @dbus.service.signal("com.kylin.kysdk.conf2", signature='sss') + def key_changed(self, id, version, key): + logger.info(f'emit {key} changed') + + # 重载信号 + @dbus.service.signal("com.kylin.kysdk.conf2", signature='') + def updated(self): + logger.info('emit updated') @dbus.service.method("com.kylin.kysdk.conf2") def Init(self): - try: - source_file = '/etc/kylin-config/user.db' - destination_file = '~/.config/kylin-config/user.db' - destination_file = os.path.expanduser(destination_file) - if os.path.exists(source_file): - if not os.path.exists(destination_file): - os.makedirs(os.path.dirname(destination_file), exist_ok=True) - shutil.copyfile(source_file, destination_file) - except Exception as e: - print(e) - - -def reload_handler(*args, **kwargs): - data = __format_db_file("/etc/kylin-config/user.db") - __del_discarded_key(__user_view, data) - __merge_dict(__user_view, data) - __dict2db__(__user_view, __destination_file) + self._converter.update_user_db(destination_file) if __name__ == "__main__": + destination_file = os.path.expanduser(destination_file) + if not os.path.exists(os.path.dirname(destination_file)): + os.makedirs(os.path.dirname(destination_file), mode=0o777, exist_ok=True) + logging.basicConfig(filename=destination_file.replace('user.db', 'sessionbus.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() + + # 初始化DBus主循环 DBusGMainLoop(set_as_default=True) - try: - __destination_file = os.path.expanduser(__destination_file) + # 连接到DBus系统总线 + bus_session = dbus.SessionBus() - bus_session = dbus.SessionBus() - object_path = '/com/kylin/kysdk/conf2' - bus_sesssion_name = dbus.service.BusName("com.kylin.kysdk.conf2", bus = bus_session) - my_dbus_session_service = KYSettingsDBusSessionService(bus_sesssion_name, object_path) + # 注册一个DBus服务 + object_path = '/com/kylin/kysdk/conf2' + bus_sesssion_name = dbus.service.BusName("com.kylin.kysdk.conf2", bus = bus_session) + my_dbus_session_service = KYSettingsDBusSessionService(bus_sesssion_name, object_path) - ##用户登录,更新用户配置 - __user_view = __format_db_file(__destination_file) - reload_handler(None, None) - - # 连接到DBus系统总线 - bus = dbus.SystemBus() - - # 监听DBus信号 - bus.add_signal_receiver(reload_handler, - signal_name='updated', - dbus_interface='com.kylin.kysdk.conf2', - bus_name='com.kylin.kysdk.conf2', - path="/com/kylin/kysdk/conf2") - except Exception as e: - print(e) + # 开始DBus主循环 mainloop = GLib.MainLoop() mainloop.run() \ No newline at end of file diff --git a/src/conf2/service/conf2Utils.py b/src/conf2/service/conf2Utils.py new file mode 100644 index 0000000..2ade517 --- /dev/null +++ b/src/conf2/service/conf2Utils.py @@ -0,0 +1,918 @@ +import os +import re +import shutil +import yaml +import sqlite3 +import logging +import traceback +from watchdog.observers import Observer +from watchdog.events import FileSystemEventHandler +import subprocess +class Converter: + _ro_db = '/etc/kylin-config/user.db' + _ro_dict = {} + _user_dict = {} + def __init__(self, logger:logging.Logger): + self.logger = logger + + def update_read_only_db(self): + try: + self._update_table_structure(self._ro_db) + self._creat_db_file(self._ro_db) + self._load_stable_dict() + return self._dict2db(self._ro_dict, self._ro_db) + except: + err_msg = traceback.format_exc() + self.logger.error(f'update_read_only_db {err_msg}') + return False + + def update_user_db(self, path): + if not os.path.exists(self._ro_db): + return False + + existed = os.path.exists(path) + if not existed: + os.makedirs(os.path.dirname(path), exist_ok=True) + shutil.copyfile(self._ro_db, path) + self._user_dict = self._db2dict(path) + else: + self._update_table_structure(path) + data = self._db2dict(self._ro_db) + self._del_discarded_key(self._user_dict, data) + self._merge_dict(self._user_dict, data) + + if os.path.exists(f'{os.path.dirname(path)}/map.yaml'): + self.logger.info("override gsettings config") + with open(f'{os.path.dirname(path)}/map.yaml', 'r') as file: + mmap = yaml.safe_load(file) + if mmap is not None: + for app, gsetting_id in mmap.items(): + for version, version_dict in self._user_dict[app].items(): + if not isinstance(version_dict, dict): + continue + self._gsettings_config_get(self._user_dict[app][version], gsetting_id) + os.remove(f'{os.path.dirname(path)}/map.yaml') + + if path.startswith('/root') and not existed: + return True + + if path.startswith('/home'): + self._load_mutable_dict(os.path.dirname(path)) + + self._dict2db(self._user_dict, path) + return True + + def update_user_dict(self, path): + self._user_dict = self._db2dict(path) + + def set(self, path, id, version, key, value): + try: + self.logger.info(f'set begin') + + # 修改用户配置文件,写入到数据库 + group_list = id.split('.') + + conn = sqlite3.connect(path) + cursor = conn.cursor() + + # 开始写入事务 + conn.execute('BEGIN TRANSACTION') + + cursor.execute("SELECT id FROM app WHERE app_name = ?", (group_list[0],)) + app_id = cursor.fetchone()[0] + + cursor.execute("SELECT id FROM version WHERE app_id = ? AND version = ?", (app_id, version)) + version_id = cursor.fetchone()[0] + + # 查找组 + parent_id = 0 + for group_name in group_list[1:]: + cursor.execute("SELECT id FROM configures WHERE version_id = ? AND parent = ? AND node_name = ? AND node_type = 'schema'", (version_id, parent_id, group_name)) + parent_id = cursor.fetchone()[0] + + cursor.execute("UPDATE configures SET custom_value = ? WHERE version_id = ? AND parent = ? AND node_name = ? AND node_type = 'key'", (value, version_id, parent_id, key)) + + conn.commit() + conn.close() + + tmp = self._user_dict[group_list[0]][version] + for group in group_list[1:]: + tmp = tmp[group] + tmp[key]['_value'] = value + + self.logger.info(f'set end') + return True + + except Exception as e: + conn.rollback() + conn.close() + err_msg = traceback.format_exc() + self.logger.error(f'set {err_msg}') + return False + + def reset(self, path, id, version, key): + try: + self.logger.info(f'reset begin') + # 修改用户配置文件,写入到数据库 + group_list = id.split('.') + + conn = sqlite3.connect(path) + cursor = conn.cursor() + + # 开始写入事务 + conn.execute('BEGIN TRANSACTION') + + cursor.execute("SELECT id FROM app WHERE app_name = ?", (group_list[0],)) + app_id = cursor.fetchone()[0] + + cursor.execute("SELECT id FROM version WHERE app_id = ? AND version = ?", (app_id,version)) + version_id = cursor.fetchone()[0] + + # 查找组 + parent_id = 0 + for group_name in group_list[1:]: + cursor.execute("SELECT id FROM configures WHERE version_id = ? AND parent = ? AND node_name = ? AND node_type = 'schema'", (version_id, parent_id, group_name)) + parent_id = cursor.fetchone()[0] + + cursor.execute("UPDATE configures SET custom_value = NULL WHERE version_id = ? AND parent = ? AND node_name = ? AND node_type = 'key'", (version_id, parent_id, key)) + + conn.commit() + conn.close() + + tmp = {} + tmp = self._user_dict[group_list[0]][version] + for group in group_list[1:]: + tmp = tmp[group] + if '_value' in tmp[key]: + tmp[key].pop('_value') + + self.logger.info(f'reset end') + + return True + + except Exception as e: + conn.rollback() + conn.close() + err_msg = traceback.format_exc() + self.logger.error(f'set {err_msg}') + return False + + def save(self, db_file, dest_path): + try: + self.logger.info(f'save begin') + + if not os.path.exists(dest_path): + self.logger.error(f'{dest_path} not exists') + return False + + data = self._db2dict(db_file) + + if data == {}: + self.logger.error(f'read sqlite failed') + return False + + #将用户配置写入到复制的只读视图里 + 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)) + + self.logger.info(f'save end') + return True + + except Exception as e: + err_msg = traceback.format_exc() + self.logger.error(f'save {err_msg}') + return False + + # 用于kconf2-editor保存文件,仅有普通用户权限,root用户没有图形化界面 + def editor_save(self, 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)) + + self.logger.info(f'editor_save end') + return True + + except Exception as e: + err_msg = traceback.format_exc() + self.logger.error(f'editor_save {err_msg}') + return False + + def extends_id(self, old_id:str, new_id:str, version:str, target_file): + try: + self.logger.info(f'extends_id begin') + + target_view = self._db2dict(target_file) + + #获取app的引用 + list = old_id.split('.', -1) + app = target_view.get(list[0]) + + if app is None: + self.logger.error(f'{old_id} is not exists') + return False + + #获取目标版本的引用,如果为空,获取默认版本 + if version == '': + old_data = app[app['_default_version']] + else: + old_data = app.get(version) + + if old_data is None: + self.logger.error(f'{version} is not invalid') + + for iter in list[1:]: + old_data = old_data.get(iter) + if old_data is None: + self.logger.error(f'{old_id} is not exists') + return False + + tmp = {} + tmp.update(old_data) + + list = new_id.split('.', -1) + new_data = target_view.get(list[0]) + if new_data != app: + self.logger.error(f'{new_id} is invalid') + + if version == '': + new_data = app[app['_default_version']] + else: + new_data = app.get(version) + + for iter in list[1:]: + if iter not in new_data: + new_data[iter] = {} + new_data = new_data[iter] + + new_data.update(tmp) + new_data['_extends'] = old_id + self.logger.info(f'extends_id end') + return self._dict2db(target_view, target_file) + + except Exception as e: + err_msg = traceback.format_exc() + self.logger.error(f'extends_id {err_msg}') + return False + + def load_dirs_config(self, dirs:list) -> dict: + try: + result = {} + for dir in dirs: + list = self._sort_diretory(dir) + for file in list: + # self.logger.info('Read conifg file') + data = self._load_one_file(f'{dir}/{file}') + # self.logger.info('Read conifg file') + + if not data: + continue + + # self.logger.info('Merger in view') + is_group_file = False + for value in data.values(): + if isinstance(value, dict): + is_group_file = True if '_default' in next(iter(value.values())) else False + break + if is_group_file: + self._common_override_by_final(result, data) + else: + self._merge_dict_by_final(result, data) + # self.logger.info('Merger in view end') + return result + except: + return {} + + def _load_stable_dict(self): + self.logger.info('Read stable dirs') + + self._ro_dict.clear() + + with open('/etc/kylin-config/conf2.yaml', 'r') as file: + configures = yaml.safe_load(file) + + for dir in configures['dirs']: + list = self._sort_diretory(f'/etc/kylin-config/{dir}') + for file in list: + # self.logger.info('Read conifg file') + data = self._load_one_file(f'/etc/kylin-config/{dir}/{file}') + # self.logger.info('Read conifg file') + + if not data: + continue + + # self.logger.info('Merger in view') + is_group_file = False + for value in data.values(): + if isinstance(value, dict): + is_group_file = True if '_default' in next(iter(value.values())) else False + break + if is_group_file: + self._common_override_by_final(self._ro_dict, data) + else: + self._merge_dict_by_final(self._ro_dict, data) + # self.logger.info('Merger in view end') + self.logger.info('Read stable dirs end') + + def _load_mutable_dict(self, dir): + self.logger.info('Read mutable dirs') + + list = self._sort_diretory(f'{dir}/configs') + for file in list: + # self.logger.info('Read conifg file') + data = self._load_one_file(f'{dir}/configs/{file}') + # self.logger.info('Read conifg file') + + if not data: + continue + + # self.logger.info('Merger in view') + is_group_file = False + for value in data.values(): + if isinstance(value, dict): + is_group_file = True if '_default' in next(iter(value.values())) else False + break + if is_group_file: + self._common_override_by_stable(self._user_dict, data) + else: + self._merge_dict_by_stable(self._user_dict, data) + # self.logger.info('Merger in view end') + self.logger.info('Read mutable dirs end') + + # 按规范对文件名进行排序 + def _sort_diretory(self, yaml_dir): + if not os.path.exists(yaml_dir): + return [] + + # 获取目录内所有文件名 + file_list = os.listdir(yaml_dir) + + # 定义排序函数 + def custom_sort(file_name): + match = re.match(r"(\d+)?-?(.*)", file_name) + if match.group(1): + return (int(match.group(1)), match.group(2)) + else: + return (0, match.group(2)) + + sorted_file_list = sorted(file_list, key=custom_sort) + return sorted_file_list + + # 读取一个文件 + def _load_one_file(self, file:str): + chinese_pattern = re.compile(u'[\u4e00-\u9fa5]+') + if bool(chinese_pattern.search(file)) or file.startswith('.'): + return {} + + yaml_data = {} + if file.endswith('.yaml'): + with open(file,'r') as stream: + yaml_data = yaml.safe_load(stream) + if yaml_data is None: + self.logger.error(f'Load {file} failed. Check the text formatting') + return {} + return yaml_data + + # 合并两个字典 + def _merge_dict(self, dest:dict , src:dict): + if src == {}: + return + + if dest == {}: + dest.update(src) + return + + for key in src.keys(): + if key in dest : + if isinstance(dest[key], dict) and isinstance(src[key], dict): + self._merge_dict(dest[key], src[key]) + else: + dest[key] = src[key] + else: + dest[key] = src[key] + return + + # 合并两个字典, 处理final权限 + def _merge_dict_by_final(self, dest:dict , src:dict): + if src == {}: + return + + if dest == {}: + dest.update(src) + return + if '_permission' in dest: + if dest['_permission'] == 'final': + return + + for key in src.keys(): + if key in dest : + if isinstance(dest[key], dict) and isinstance(src[key], dict): + self._merge_dict_by_final(dest[key], src[key]) + else: + dest[key] = src[key] + else: + dest[key] = src[key] + return + + # 合并两个字典, 处理stable权限 + def _merge_dict_by_stable(self, dest:dict , src:dict): + if src == {}: + return + + if dest == {}: + dest.update(src) + return + + if '_permission' in dest: + if dest['_permission'] == 'final' or dest['_permission'] == 'stable': + return + + for key in src.keys(): + if key in dest : + if isinstance(dest[key], dict) and isinstance(src[key], dict): + self._merge_dict_by_stable(dest[key], src[key]) + else: + dest[key] = src[key] + else: + dest[key] = src[key] + return + + # 全局配置字典覆盖,处理final权限 + def _common_override_by_final(self, dest:dict, src:dict): + for app in dest: + for version in dest[app]: + for group in dest[app][version]: + if group in src: + self._merge_dict_by_final(dest[app][version][group], src[group]) + + # 全局配置字典覆盖,处理stable权限 + def _common_override_by_stable(self, dest:dict, src:dict): + for app in dest: + for version in dest[app]: + for group in dest[app][version]: + if group in src: + self._merge_dict_by_stable(dest[app][version][group], src[group]) + + # 字典写入到数据库 + def _dict2db(self, dict:dict, path:str): + try: + self.logger.info('write config in database') + conn = sqlite3.connect(path) + cursor = conn.cursor() + + conn.execute('BEGIN TRANSACTION') + cursor.execute("SELECT name FROM sqlite_master WHERE type='table'") + tables = cursor.fetchall() + + # 遍历所有表名,对每个表执行DELETE语句以删除所有行 + for table in tables: + cursor.execute(f"DELETE FROM {table[0]}") + + app_id = 0 + version_id = 0 + apps = list(dict.keys()) + for i in range(0, len(apps)): + app = apps[i] + app_id = app_id + 1 + default_version = self._calculate_default_version(dict[app]) + cursor.execute("INSERT INTO app (app_name, default_version) VALUES (?,?)",(app, default_version)) + + versions = list(dict[app].keys()) + for j in range(0, len(versions)): + version = versions[j] + if version == '_default_version': + continue + + version_id = version_id + 1 + cursor.execute("INSERT INTO version (app_id, version, compatible) VALUES (?, ?, ?)", + (app_id, version, dict[app][version].get('_compatible'))) + + configures = dict[app][version] + self._write_group_in_db(configures, configures, cursor, version_id, 0) + conn.commit() + conn.close() + self.logger.info('write config in database end') + return True + + except: + err_msg = traceback.format_exc() + self.logger.error(f'_dict2db {err_msg}') + conn.rollback() + conn.commit() + return False + + # 计算默认版本 + def _calculate_default_version(self, 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 + default_nums = re.findall(r'\d+', default_version) + nums = re.findall(r'\d+', version) + for i in range(0, 6): + if nums[i] > default_nums[i]: + default_version = version + break + return default_version + + #递归写入组到configures表 + def _write_group_in_db(self, version_data:dict, data: dict, cursor: sqlite3.Cursor, version_id, parent_id): + groups = [] + for key, value in data.items(): + if isinstance(value, dict): + if(value.get('_default') is None): + groups.append(key) + else: + self._write_key_in_db(version_data, key, value, cursor, version_id, parent_id, data.get('_permission')) + + for group in groups: + node_name = group + + node_type = 'schema' + + permission = data[group].get('_permission') + if permission is None: + permission = 'public' + + description = data[group].get('_description') + + summary = data[group].get('_summary') + + extends = data[group].get('_extends') + + cursor.execute('''INSERT INTO configures + (version_id, node_name, node_type, permission, description, summary, parent, extends) + VALUES (?, ?, ?, ?, ?, ?, ?, ?)''', + (version_id, node_name, node_type, permission, description, summary, parent_id, extends)) + group_id = cursor.lastrowid + self._write_group_in_db(version_data, data[group], cursor, version_id, group_id) + + # 写入键的数据到configures表内 + def _write_key_in_db(self, version_data:dict, key:str, value:dict, cursor: sqlite3.Cursor, version_id, parent_id, parent_permission): + node_name = key + + node_type = 'key' + + permission = value.get('_permission') + if permission is None: + if parent_permission is None: + permission = 'public' + else: + permission = parent_permission + + description = value.get('_description') + + summary = value.get('_summary') + + value_type = value.get('_type') + + custom_value = value.get('_value') + + default_value = value.get('_default') + if isinstance(default_value, bool): + default_value = 'true' if default_value else 'false' + + range = value.get('_range') + if value_type == 'enum' and isinstance(range, str) and range.startswith('@'): + enum_range = {} + element_list = self._recursive_search(version_data, value['_range'][1:]) + for element in element_list: + num = element['_value'] + if isinstance(num, str): + if num.startswith('0x'): + num = int(num, 16) + else: + num = int(num, 10) + enum_range[element['_nick']] = num + range = str(enum_range) + + cursor.execute('''INSERT INTO configures + (version_id, node_name, node_type, permission, description, summary, parent, value_type, custom_value, default_value, range) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', + (version_id, node_name, node_type, permission, description, summary, parent_id, value_type, custom_value, default_value, range)) + + # 查询枚举类型数据的枚举定义 + def _recursive_search(self, dictionary, key): + if key in dictionary: + return dictionary[key] + else: + for value in dictionary.values(): + if isinstance(value, dict): + result = self._recursive_search(value, key) + if result is not None: + return result + return None + + # 读数据库数据到字典 + def _db2dict(self, path): + try: + conn = sqlite3.connect(path) + cursor = conn.cursor() + + cursor.execute('SELECT * FROM app') + apps = cursor.fetchall() + + cursor.execute('SELECT * FROM version') + versions = cursor.fetchall() + + cursor.execute('SELECT * FROM configures') + configures = cursor.fetchall() + conn.close() + + data = {} + stack = [] + i = j = k = 0 + for i in range(len(apps)): + app = apps[i][1] + app_id = i + 1 + default_value = apps[i][2] + data[app] = {} + if(default_value): + data[app]['_default_version'] = default_value + for j in range(j, len(versions)): + # app_id改变,退出版本循环 + version_app_id = versions[j][1] + if version_app_id != app_id: + break + version = versions[j][2] + data[app][version] = {} + if versions[j][3]: + data[app][version]['compatible'] = versions[j][3] + + stack.append((0, data[app][version])) + # 如果占用内存过大,可以改为在这里读取对应版本的所有配置 + # 不再保存k值,每次循环从0开始 + for k in range(k, len(configures)): + # version_id改变,退出循环 + if configures[k][1] != j + 1: + stack.clear() + break + + while configures[k][7] != stack[-1][0]: + stack.pop() + + node_name = configures[k][2] + node_type = configures[k][3] + permission = configures[k][4] + description = configures[k][5] + summary = configures[k][6] + value_type = configures[k][8] + custom_value = configures[k][9] + default_value = configures[k][10] + value_range = configures[k][11] + extends = configures[k][12] + + if node_type == 'schema': + tmp = stack[-1][1] + tmp[node_name] = {} + stack.append((configures[k][0], tmp[node_name])) + if permission is not None: + tmp[node_name]['_permission'] = permission + if description is not None: + tmp[node_name]['_description'] = description + if summary is not None: + tmp[node_name]['_summary'] = summary + if extends is not None: + tmp[node_name]['_extends'] = extends + elif node_type == 'key': + tmp = stack[-1][1] + tmp[node_name] = {} + if permission is not None: + tmp[node_name]['_permission'] = permission + if description is not None: + tmp[node_name]['_description'] = description + if summary is not None: + tmp[node_name]['_summary'] = summary + if value_type is not None: + tmp[node_name]['_type'] = value_type + if custom_value is not None: + tmp[node_name]['_value'] = custom_value + if default_value is not None: + tmp[node_name]['_default'] = default_value + if value_range is not None: + tmp[node_name]['_range'] = value_range + return data + except: + err_msg = traceback.format_exc() + self.logger.error(f'_db2dict {err_msg}') + return {} + + # 删除dest中存在,但不存在与src中的键或组 + def _del_discarded_key(self, dest:dict, src:dict): + keys_to_delete = [] + for key in dest: + if not isinstance(dest[key], dict): + continue + if key not in src: + if dest[key].get('_extends') is None: + keys_to_delete.append(key) + else: + self._del_discarded_key(dest[key], src[key]) + + for key in keys_to_delete: + dest.pop(key) + + # 导出时,使用value的值替带default值 + def _value_override_default(self, data:dict): + for key, value in data.items(): + if isinstance(value, dict): + self._value_override_default(value) + else: + if '_value' in data: + data['_default'] = data.pop('_value') + return + + def _creat_db_file(self, path): + conn = sqlite3.connect(path) + cursor = conn.cursor() + + conn.execute('BEGIN TRANSACTION') + cursor.execute('''CREATE TABLE IF NOT EXISTS app + (id INTEGER PRIMARY KEY AUTOINCREMENT, + app_name TEXT, + default_version TEXT)''') + cursor.execute('''CREATE TABLE IF NOT EXISTS version + (id INTEGER PRIMARY KEY AUTOINCREMENT, + app_id INTEGER, + version TEXT, + compatible TEXT, + FOREIGN KEY (app_id) REFERENCES app(id))''') + cursor.execute('''CREATE TABLE IF NOT EXISTS configures + (id INTEGER PRIMARY KEY AUTOINCREMENT, + version_id INTEGER, + node_name TEXT, + node_type TEXT, + permission TEXT, + description TEXT, + summary TEXT, + parent INTEGER, + value_type TEXT, + custom_value TEXT, + default_value TEXT, + range TEXT, + extends TEXT, + FOREIGN KEY (version_id) REFERENCES version(id), + FOREIGN KEY (parent) REFERENCES configures(id))''') + conn.commit() + conn.close() + + def _gsettings_config_get(self, data, id): + for key, value in data.items(): + if not isinstance(value, dict): + continue + if '_default' in value: + result = subprocess.run(['gsettings','get', id, key], capture_output=True, text=True) + custom_value = result.stdout.strip() + custom_value = custom_value.split(' ')[-1] if custom_value.startswith('@') else custom_value + value['_value'] = custom_value + else: + self._gsettings_config_get(value, f'{id}.{key}') + + def _update_table_structure(self, path): + try: + if not os.path.exists(path): + return True + + conn = sqlite3.connect(path) + cursor = conn.cursor() + + cursor.execute('BEGIN TRANSACTION') + + # 检查是否是旧的表结构 + is_old = False + cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='configures';") + table_exists = cursor.fetchone() + if table_exists: + cursor.execute("PRAGMA table_info(configures);") + columns = cursor.fetchall() + + for column in columns: + if column[1] == 'group_name': + is_old = True + break + + if is_old: + self.logger.info('Data base table is old structure. Update structure') + # 如果是基础数据库,直接删掉重新生成 + if path == self._ro_db: + os.remove(path) + else: + cursor.execute('''CREATE TABLE IF NOT EXISTS new_configures + (id INTEGER PRIMARY KEY AUTOINCREMENT, + version_id INTEGER, + node_name TEXT, + node_type TEXT, + permission TEXT, + description TEXT, + summary TEXT, + parent INTEGER, + value_type TEXT, + custom_value TEXT, + default_value TEXT, + range TEXT, + extends TEXT, + FOREIGN KEY (version_id) REFERENCES version(id), + FOREIGN KEY (parent) REFERENCES configures(id))''') + + cursor.execute("INSERT INTO new_configures (version_id, node_name, node_type, permission, description, summary, parent, value_type, custom_value, default_value, range, extends) SELECT " + "version_id," + "CASE " + "WHEN property IS NOT NULL THEN property " + "WHEN group_name IS NOT NULL THEN group_name " + "END, " + "CASE " + "WHEN property IS NOT NULL THEN 'key' " + "WHEN group_name IS NOT NULL THEN 'schema' " + "END," + "permission," + "description," + "summary," + "parent," + "data_type," + "user_value," + "default_value," + "range," + "extends " + "FROM configures;") + # 删除原表 + cursor.execute("DROP TABLE configures;") + + # 将新表重命名为原表的名称 + cursor.execute("ALTER TABLE new_configures RENAME TO configures;") + conn.commit() + conn.close() + return True + except Exception as e: + err_msg = traceback.format_exc() + self.logger.error(f'{err_msg}') + return False + +class FileWatche: + class MyHandler(FileSystemEventHandler): + def __init__(self, server): + self._server = server + + def on_modified(self, event): + if event.is_directory: + return + self._server.reload() + + def on_created(self, event): + if event.is_directory or not os.path.dirname(event.src_path) == '/etc/kylin-config/basic': + return + + gsettings_id = os.path.basename(event.src_path).strip(".yaml") + + mmap = {} + with open(event.src_path, 'r') as file: + data = yaml.safe_load(file) + + for app, version in data.items(): + if not isinstance(version, dict): + continue + mmap[app] = gsettings_id + + home_directories = [os.path.expanduser('~' + username) for username in os.listdir('/home')] + home_directories.append('/root') + for home_dir in home_directories: + file_path = os.path.join(home_dir, '.config/kylin-config/map.yaml') + if not os.path.exists(os.path.dirname(file_path)): + continue + # file_path = '/home/kylin/test.yaml' + if os.path.exists(file_path): + with open(file_path, 'r') as file: + tmp = yaml.safe_load(file) + if tmp is not None: + mmap.update(tmp) + + os.remove(file_path) + + with open(file_path, 'w') as file: + file.write(yaml.safe_dump(mmap)) + + os.chmod(file_path, 0o666) + + def __init__(self, path, server) -> None: + self._server = server + self._observer = Observer() + self._event_handler = FileWatche.MyHandler(server) + + self._observer.schedule(self._event_handler, path, recursive=False) + self._observer.start() + + def stopWatche(self): + if self._observer.isAlive(): + self._observer.stop() + self._observer.join() diff --git a/src/conf2/service/kysdk-conf2.service b/src/conf2/service/kysdk-conf2.service index 84ebf3c..488ed28 100644 --- a/src/conf2/service/kysdk-conf2.service +++ b/src/conf2/service/kysdk-conf2.service @@ -1,14 +1,14 @@ [Unit] Description=KYLIN CONF2 DBUS -Wants=systemd-logind.service -Before=systemd-logind.service +Wants=systemd-logind.service lightdm.service +Before=systemd-logind.service lightdm.service [Service] Type=dbus Restart=always RestartSec=1 BusName=com.kylin.kysdk.conf2 -ExecStart=python3 /usr/bin/conf2-server.py +ExecStart=/usr/bin/conf2-server.py [Install] WantedBy=multi-user.target diff --git a/src/conf2/service/verify/amd64/calc_verify b/src/conf2/service/verify/amd64/calc_verify new file mode 100755 index 0000000..448aa82 Binary files /dev/null and b/src/conf2/service/verify/amd64/calc_verify differ diff --git a/src/conf2/service/verify/arm64/calc_verify b/src/conf2/service/verify/arm64/calc_verify new file mode 100755 index 0000000..389ef92 Binary files /dev/null and b/src/conf2/service/verify/arm64/calc_verify differ diff --git a/src/conf2/test/CMakeLists.txt b/src/conf2/test/CMakeLists.txt deleted file mode 100644 index 360de03..0000000 --- a/src/conf2/test/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -find_package(PkgConfig REQUIRED) -pkg_check_modules(CONF2 REQUIRED kysdk-conf2) -include_directories(${CONF2_INCLUDE_DIRS}) - -add_executable(kyconf2-test kyconf2-test.c) -target_link_libraries(kyconf2-test ${CONF2_LIBRARIES}) - -install(TARGETS kyconf2-test - DESTINATION /usr/bin) \ No newline at end of file diff --git a/src/conf2/test/control-center.yaml b/src/conf2/test/control-center.yaml deleted file mode 100644 index f61de28..0000000 --- a/src/conf2/test/control-center.yaml +++ /dev/null @@ -1,402 +0,0 @@ -control-center: - 3.20.1.31-0k2.11: - children: - powermanager: - keys: - sleep: - _type: b - default: 'true' - dormant: - _type: b - default: 'true' - shutdown: - _type: b - default: 'true' - switch-user: - _type: b - default: 'true' - apt: - children: - proxy: - keys: - enabled: - _type: b - default: 'false' - description: This key is used to control whether to open apt-proxy. - summary: Whether open - host: - _type: s - default: '' - description: The machine name to proxy APT through. - summary: APT proxy host name - port: - _type: i - default: '8080' - description: "The port on the machine defined by “/apt/proxy/host”\ - \ that you\n proxy through." - range: 0,65535 - summary: APT proxy port - desktop: - keys: - computer-icon-locking: - _type: b - default: 'true' - description: Whether lock computer icon on start menu or not. - summary: Lock computer icon on start menu - computer-icon-visible: - _type: b - default: 'true' - description: Whether show computer icon on desktop or not. - summary: Show computer icon on desktop - home-icon-visible: - _type: b - default: 'true' - description: Whether show home icon on desktop or not. - summary: Show home icon on desktop - menufull-screen: - _type: b - default: 'false' - description: Whether to always use the start menu in full screen. - summary: menufull-screen switch button - network-icon-visible: - _type: b - default: 'true' - description: Whether show network icon on desktop or not. - summary: Show network icon on desktop - personal-icon-locking: - _type: b - default: 'false' - description: Whether personal icon on start menu or not. - summary: Lock personal icon on start menu - settings-icon-locking: - _type: b - default: 'true' - description: Whether lock settings icon on start menu or not. - summary: Lock settings icon on start menu - trash-icon-locking: - _type: b - default: 'false' - description: Whether lock trash icon on start menu or not. - summary: Lock trash icon on start menu - trash-icon-visible: - _type: b - default: 'true' - description: Whether show trash icon on desktop or not. - summary: Show trash icon on desktop - volumes-visible: - _type: b - default: 'true' - description: Whether show volumes icon on desktop or not. - summary: Show volumes icon on desktop - enum_org.ukui.control-center.noticeorigin.Type: - - nick: none - value: '0' - - nick: corner - value: '1' - - nick: all - value: '2' - experienceplan: - keys: - join: - _type: b - default: 'true' - description: Whether this plugin would be activated by ukui-settings-daemon - or not - summary: join user experience plan - keybinding: - keys: - action: - _type: s - default: '' - description: Command associated with a custom keybinding. - summary: Command - binding: - _type: s - default: '' - description: Keybinding associated with a custom shortcut. - summary: Keybinding - name: - _type: s - default: '' - description: Description associated with a custom keybinding. - summary: Name - keyboard: {} - notice: - keys: - blacklist: - _type: as - default: '[]' - description: Hidden DektopList - summary: '' - enable-notice: - _type: b - default: 'true' - description: Whether an OSD notification is shown to notify about changes - summary: Show OSD notification - iscn-env: - _type: b - default: 'true' - description: Determine whether the environment is Chinese - summary: '' - show-new-feature: - _type: b - default: 'true' - description: Whether this plugin would be activated by ukui-settings-daemon - or not - summary: Activation of this plugin - show-on-lockscreen: - _type: b - default: 'true' - description: Binding to eject an optical disc. - summary: Eject - noticeorigin: - keys: - maximize: - _type: i - default: '3' - description: The maximize num of messages on notice window. - summary: maximize num of messages - messages: - _type: b - default: 'true' - description: . - summary: messages notice - name-cn: - _type: s - default: '' - description: The name passed to the sidebar - summary: app's name - name-us: - _type: s - default: '' - description: The name passed to the sidebar - summary: app's name - notification-style: - _type: s - default: mutative - description: 'Select the notification style. Supported values are "none", - - "mutative","always". - - - If this is "none", notifications don''t show up on the screen, - - but go to the notification center - - - If this is "mutative", show on the upper right corner of the screen, - - it will disappear automatically. - - - If this is "always", remain on the screen until turned off.' - summary: The display style of the notification - show-detail: - _type: b - default: 'false' - description: Whether the notification show detail on screenlock - summary: '' - show-on-screenlock: - _type: b - default: 'false' - description: Whether the notification show on screenlock - summary: '' - type: - _type: enum - default: corner - description: the type of notice in system. - range: '@enum_org.ukui.control-center.noticeorigin.Type' - summary: type of notice message - voice: - _type: b - default: 'true' - description: . - summary: voice notice - osd: - keys: - show-lock-tip: - _type: b - default: 'true' - description: show keyboard tip or not. eg. Caps Lock. Num Lock - summary: show keyboard tip - panel: - children: - plugins: - keys: - calendar: - _type: s - default: lunar - description: calendar system used in UKUI Desktop Environment ,ontrol - by ukui-panel and ukui-control-center - summary: Lunar calendar - date: - _type: s - default: cn - description: date format - summary: date formate - firstday: - _type: s - default: monday - description: Select the first day of the week - summary: first of week - hoursystem: - _type: s - default: '24' - description: hoursystem used in UKUI Desktop Environment ,ontrol by - ukui-panel and ukui-control-center - summary: HourSystem status - nightmodestatus: - _type: b - default: 'false' - description: '' - summary: ukui-control-center sets the night mode status so that ukui-panel - can get the status - ntp: - _type: s - default: '' - description: user-defined ntp server address - summary: customize ntp server address - showlanguage: - _type: as - default: '[]' - description: show language in plugin area - summary: show language in plugin area - synctime: - _type: b - default: 'true' - description: '' - summary: sync time from network - themebynight: - _type: b - default: 'false' - description: '' - summary: ukui-control-center theme changes follow with the night - mode - time: - _type: s - default: '24' - description: Select the first day of the week - summary: first of week - timezones: - _type: as - default: '[]' - description: other time zones - summary: all time zones of time display - personalise: - keys: - blurry: - _type: i - default: '3' - description: 1- Low effect;2-Middle effect;3-High effect - summary: Control the frosted glass effect of the component - custompower: - _type: b - default: 'false' - description: Used to determine that the control panel user has customized - a power plan - summary: Whether to customize the power plan - effect: - _type: b - default: 'true' - description: 'ture:Special effects open; false: Special effects off' - summary: Control panel special effects transmit signal - save-transparency: - _type: i - default: '100' - description: Save the transparency before the special effects mode is - turned off - summary: Save the transparency before the special effects mode is turned - off - transparency: - _type: d - default: '0.65' - description: Control the transparency of all components - summary: Control the transparency of all components - plugins: - keys: - plugin-name: - _type: s - default: '' - description: the name to match status - summary: plugin's name - show: - _type: b - default: 'true' - description: . - summary: whether the plugin's status - pluginstatus: {} - wifi: - children: - switch: - keys: - switch: - _type: b - default: 'true' - description: wifi switch - summary: wifi switch - switchor: - _type: b - default: 'true' - description: wifi switch of kylin network manager - summary: wifi switchor - wificard: - _type: b - default: 'true' - description: Determine if the wireless network card is inserted - summary: Wireless network card - keys: - fonts-list: - _type: as - default: '[''CESI仿宋-GB13000'',''CESI_FS_GB13000'', ''CESI仿宋-GB18030'',''CESI_FS_GB18030'', - ''CESI仿宋-GB2312'',''CESI_FS_GB2312'', ''CESI宋体-GB13000'',''CESI_SS_GB13000'', - ''CESI宋体-GB18030'',''CESI_SS_GB18030'', ''CESI宋体-GB2312'',''CESI_SS_GB2312'', - ''CESI小标宋-GB13000'',''CESI_XBS_GB13000'', ''CESI小标宋-GB18030'',''CESI_XBS_GB18030'', - ''CESI小标宋-GB2312'',''CESI_XBS_GB2312'', ''CESI楷体-GB13000'',''CESI_KT_GB13000'', - ''CESI楷体-GB18030'',''CESI_KT_GB18030'', ''CESI楷体-GB2312'',''CESI_KT_GB2312'', - ''CESI黑体-GB13000'',''CESI_HT_GB13000'', ''CESI黑体-GB18030'',''CESI_HT_GB18030'', - ''CESI黑体-GB2312'',''CESI_HT_GB2312'', ''仿宋'', ''黑体'', ''楷体'', ''宋体'', ''华文彩云'',''STCaiyun'', - ''华文仿宋'',''STFangsong'', ''华文琥珀'',''STHupo'', ''华文楷体'',''STKaiti'', ''华文隶书'',''STLiti'', - ''华文宋体'',''STSong'', ''华文细黑'',''STXihei'', ''华文行楷'',''STXingkai'', ''华文新魏'',''STXinwei'', - ''Noto Sans CJK SC'', ''Noto Sans CJK SC Black'', ''Noto Sans Mono CJK SC'', - ''Noto Sans CJK SC DemiLight'', ''Noto Sans CJK SC Light'', ''Noto Sans - CJK SC Medium'', ''Noto Sans CJK SC'', ''Noto Sans CJK SC Thin'',''Dotted - Songti Square'',''WenQuanYi Bitmap Song'']' - description: Control panel default font list - summary: Control panel default font list - 2.0.0.0-0k0.0: - children: - powermanager: - keys: - sleep: - _type: b - default: 'true' - dormant: - _type: b - default: 'true' - shutdown: - _type: b - default: 'true' - switch-user: - _type: b - default: 'true' - apt: - children: - proxy: - keys: - enabled: - _type: b - default: 'false' - description: This key is used to control whether to open apt-proxy. - summary: Whether open - host: - _type: s - default: '' - description: The machine name to proxy APT through. - summary: APT proxy host name - port: - _type: i - default: '8080' - description: "The port on the machine defined by “/apt/proxy/host”\ - \ that you\n proxy through." - range: 0,65535 - summary: APT proxy port diff --git a/src/conf2/test/kyconf2-test.c b/src/conf2/test/kyconf2-test.c index 5d0e519..a199be3 100644 --- a/src/conf2/test/kyconf2-test.c +++ b/src/conf2/test/kyconf2-test.c @@ -18,72 +18,318 @@ * */ - #include "../api/libkysettings.h" #include #include +#include -//键值改变信号回调函数 +// 键值改变信号回调函数 static void on_key_changed(KSettings *setting, char *key, void *user_data) { - printf("on key change signal\n"); + char *value = kdk_conf2_get_value(setting, key); + printf("%s change to %s\n", key, value); +} + +// 键值改变信号回调函数 +static void on_reload(KSettings *setting, void *user_data) +{ + printf("reload signal\n"); } int main(int argc, char *argv[]) { - KSettings *setting = kdk_conf2_new("systemd.powermanager", NULL); - if(NULL == setting) + KSettings *setting = kdk_conf2_new("test.notice", NULL); + if (NULL == setting) { printf("get handle failed\n"); return 0; } - //链接键值改变信号 /** * 只有已连接切读过一次配置时才能接收到该信号 * 接收信号需要开启主程序的消息循环 */ - // kdk_conf2_connect_signal(setting, "changed::sleep", on_key_changed, NULL); + // kdk_conf2_connect_signal(setting, "changed::int", on_key_changed, NULL); - //读配置 - char *value = kdk_conf2_get_value(setting, "sleep"); - if(NULL != value) + char *schema_summary = kdk_conf2_get_schema_summary(setting); + if (schema_summary) { - printf("sleep user value: %s\n", value); - free(value); + printf("test.notice summary\t: %s\n", schema_summary); + free(schema_summary); } - //读默认配置 - value = kdk_conf2_get_default_value(setting, "sleep"); - if (NULL != value) + char *schema_description = kdk_conf2_get_schema_desription(setting); + if (schema_description) { - printf("sleep default value: %s\n", value); - free(value); + printf("test.notice description\t: %s\n", schema_description); + free(schema_description); } - //读对应数据类型的值 - //调用获取对应数据类型的接口前,调用has_key确保键存在。否则无法保证返回值的准确性 - if(kdk_conf2_has_key(setting, "sleep")) + char *id = kdk_conf2_get_id(setting); + if (id) { - int b_sleep = kdk_conf2_get_boolean(setting, "sleep"); - printf("sleep user boolean: %s\n", b_sleep ? "true" : "false"); - - b_sleep = kdk_conf2_get_default_boolean(setting, "sleep"); - printf("sleep defalut boolean: %s\n", b_sleep ? "true" : "false"); + printf("id is\t: %s\n", id); + free(id); } - //设置键值 - int success = kdk_conf2_set_value(setting, "sleep", "true"); - if(0 == success) + char *version = kdk_conf2_get_version(setting); + if (version) { - printf("set value failed\n"); + printf("version is\t: %s\n", version); + free(version); } - //其它接口参考头文件或接口文档 + char **children = kdk_conf2_list_children(setting); + if (children) + { + printf("children:\n"); + for (int i = 0; children[i]; i++) + { + printf("\t%s\n", children[i]); + free(children[i]); + } + free(children); + } - usleep(10); - //注销句柄 + char **keys = kdk_conf2_list_keys(setting); + if (keys) + { + printf("keys:\n"); + for (int i = 0; keys[i]; i++) + { + printf("\t%s\n", keys[i]); + free(keys[i]); + } + free(keys); + } + + // 把childname替换为正确的子组名 + KSettings *child = kdk_conf2_get_child(setting, "proxy"); + if (child) + { + printf("get child :test.notice.proxy\n"); + } + + char *range = kdk_conf2_get_range(setting, "type"); + if (range) + { + printf("Type range is %s\n", range); + free(range); + range = NULL; + } + + int success = 0; + success = kdk_conf2_range_check(setting, "int", "65540"); + printf("value is %s\n", success ? "valid" : "invalid"); + + { + /**********通用读写**********/ + char *value = kdk_conf2_get_default_value(setting, "int"); + if (NULL != value) + { + printf("Int default value: %s\n", value); + free(value); + } + + value = kdk_conf2_get_value(setting, "int"); + if (NULL != value) + { + printf("Int value: %s\n", value); + free(value); + } + + success = kdk_conf2_set_value(setting, "int", "8081"); + if (0 == success) + { + printf("set int failed\n"); + } + + /**********枚举读写**********/ + int e = kdk_conf2_get_default_enum(setting, "type"); + printf("Type default value is %d\n", e); + + e = kdk_conf2_get_enum(setting, "type"); + printf("Type value is %d\n", e); + + success = kdk_conf2_set_enum(setting, "type", 0x2); + if (0 == success) + { + printf("set type failed\n"); + } + + /**********整形读写**********/ + int i = kdk_conf2_get_default_int(setting, "int"); + printf("Int default value is %d\n", i); + + i = kdk_conf2_get_int(setting, "int"); + printf("Int value is %d\n", i); + + success = kdk_conf2_set_int(setting, "int", i + 1); + if (0 == success) + { + printf("set int failed\n"); + } + + /**********长整形读写**********/ + long l = kdk_conf2_get_default_int(setting, "long"); + printf("Long default value is %d\n", l); + + l = kdk_conf2_get_int(setting, "long"); + printf("Long value is %d\n", l); + + success = kdk_conf2_set_int(setting, "long", l + 1); + if (0 == success) + { + printf("set long failed\n"); + } + + /**********无符号整形读写**********/ + unsigned int u = kdk_conf2_get_default_int(setting, "uint"); + printf("Uint default value is %d\n", u); + + u = kdk_conf2_get_int(setting, "uint"); + printf("Uint value is %d\n", u); + + success = kdk_conf2_set_int(setting, "uint", u + 1); + if (0 == success) + { + printf("set uint failed\n"); + } + + /**********无符号长整形读写**********/ + unsigned long t = kdk_conf2_get_default_int(setting, "ulong"); + printf("Ulong default value is %d\n", t); + + t = kdk_conf2_get_int(setting, "ulong"); + printf("Ulong value is %d\n", t); + + success = kdk_conf2_set_int(setting, "ulong", t + 1); + if (0 == success) + { + printf("set ulong failed\n"); + } + + /**********布尔型读写**********/ + int b = kdk_conf2_get_default_boolean(setting, "enable"); + printf("Enable default value is %s\n", b ? "true" : "false"); + + b = kdk_conf2_get_boolean(setting, "enable"); + printf("Enable value is %s\n", b ? "true" : "false"); + + success = kdk_conf2_set_boolean(setting, "enable", !b); + if (0 == success) + { + printf("set enable failed\n"); + } + + /**********浮点型读写**********/ + double d = kdk_conf2_get_default_double(setting, "transparency"); + printf("Transparency default value is %lf\n", d); + + d = kdk_conf2_get_double(setting, "transparency"); + printf("Transparency value is %lf\n", d); + + success = kdk_conf2_set_double(setting, "transparency", d + 1); + if (0 == success) + { + printf("Set transparency failed\n"); + } + + /**********字符串读写**********/ + char *s = kdk_conf2_get_default_string(setting, "name"); + printf("Name default value is %s\n", s); + + s = kdk_conf2_get_string(setting, "name"); + printf("Name value is %s\n", s); + + success = kdk_conf2_set_string(setting, "name", "dsefe"); + if (0 == success) + { + printf("Set name failed\n"); + } + + /**********字符串列表读写**********/ + char **sv = kdk_conf2_get_default_strv(setting, "list"); + if (sv) + { + printf("List default value :\n"); + for (int i = 0; sv[i]; i++) + { + printf("\t%s\n", sv[i]); + } + g_strfreev(sv); + } + + sv = kdk_conf2_get_strv(setting, "list"); + if (sv) + { + printf("List value :\n"); + for (int i = 0; sv[i]; i++) + { + printf("\t%s\n", sv[i]); + } + g_strfreev(sv); + } + const char *v[] = {"CESI仿宋-GB13000", "CESI_FS_GB13000", NULL}; + success = kdk_conf2_set_strv(setting, "list", v); + if (0 == success) + { + printf("Set list failed\n"); + } + } + + char *description = kdk_conf2_get_descrition(setting, "int"); + if (description) + { + printf("Int description: %s\n", description); + free(description); + } + + char *summary = kdk_conf2_get_summary(setting, "int"); + if (summary) + { + printf("Int summary: %s\n", summary); + free(summary); + } + + char *type = kdk_conf2_get_type(setting, "int"); + if (type) + { + printf("Int type: %s\n", type); + free(type); + } + + kdk_conf2_reset(setting, "int"); + + int writable = kdk_conf2_is_writable(setting, "int"); + printf("Int is %s\n", writable ? "writable" : "not writable"); + + // kdk_conf2_connect_signal(setting, "reload", on_reload, NULL); + kdk_conf2_reload(); + + char **schemas = kdk_conf2_list_schemas("test", NULL); + if (schemas) + { + printf("test schemas:\n"); + for (int i = 0; schemas[i]; i++) + { + printf("\t%s\n", schemas[i]); + free(schemas[i]); + } + free(schemas); + } + + KSettings *externds_setting = kdk_conf2_new_extends_id("test.notice", "test.notice.tss", NULL); + if (externds_setting) + { + printf("kdk_conf2_new_extends_id successed\n"); + } + + int is_schema = kdk_conf2_is_schema("control-center.notice", NULL); + printf("control-center.notice is a %s shcema\n", is_schema ? "valid" : "invalid"); + + // 注销句柄 kdk_conf2_ksettings_destroy(setting); return 0; -} \ No newline at end of file +} diff --git a/src/conf2/test/test.yaml b/src/conf2/test/test.yaml new file mode 100644 index 0000000..92b7a09 --- /dev/null +++ b/src/conf2/test/test.yaml @@ -0,0 +1,97 @@ +test: + 3.20.1.31-0k2.11: + powermanager: + sleep: + _type: b + _default: 'true' + dormant: + _type: b + _default: 'true' + shutdown: + _type: b + _default: 'true' + _permission: final + switch-user: + _type: b + _default: 'true' + _permission: stable + enum_org.ukui.test.Type: + - _nick: none + _value: 0x00 + - _nick: corner + _value: 0x01 + - _nick: all + _value: 0x02 + notice: + _summary: This is test schema + _description: This schema contains various basic types of keys + enable: + _type: b + _default: 'true' + _description: Whether an OSD notification is shown to notify about changes + _summary: Show OSD notification + int: + _type: i + _default: '8080' + _description: "The port on the machine defined by “/apt/proxy/host”\ + \ that you\n proxy through." + _range: 0,65535 + _summary: APT proxy port + long: + _type: x + _default: '8080' + _description: "The port on the machine defined by “/apt/proxy/host”\ + \ that you\n proxy through." + _summary: APT proxy port + uint: + _type: u + _default: '8080' + _description: "The port on the machine defined by “/apt/proxy/host”\ + \ that you\n proxy through." + _summary: APT proxy port + ulong: + _type: t + _default: '8080' + _description: "The port on the machine defined by “/apt/proxy/host”\ + \ that you\n proxy through." + _summary: APT proxy port + name: + _type: s + _default: '' + _description: The name passed to the sidebar + _summary: app's name + type: + _type: enum + _default: corner + _description: the type of notice in system. + _range: '@enum_org.ukui.test.Type' + _summary: type of notice message + transparency: + _type: d + _default: '0.65' + _description: Control the transparency of all components + _summary: Control the transparency of all components + list: + _type: as + _default: '[''CESI仿宋-GB13000'',''CESI_FS_GB13000'', ''CESI仿宋-GB18030'']' + _description: Control panel _default font list + _summary: Control panel _default font list + proxy: + key: + _type: i + _default: 0 + 2.0.0.0-0k0.0: + powermanager: + _permission: final + sleep: + _type: b + _default: 'true' + dormant: + _type: b + _default: 'true' + shutdown: + _type: b + _default: 'true' + switch-user: + _type: b + _default: 'true' diff --git a/src/conf2/tools/conf2yaml.py b/src/conf2/tools/conf2yaml.py index 22b077a..bb58a43 100755 --- a/src/conf2/tools/conf2yaml.py +++ b/src/conf2/tools/conf2yaml.py @@ -1,3 +1,4 @@ +#!/usr/bin/python3 # # libkysdk-system's Library # @@ -16,11 +17,10 @@ # You should have received a copy of the GNU General Public License # along with this library. If not, see . # -# Authors: Yunhe Liu +# Authors: tianshaoshuai # # -#!/usr/bin/python3 import configparser import yaml import sys, os @@ -31,24 +31,28 @@ def convert_one_file(file): config.read(file) # 将配置文件数据转换为字典 - data = {'app':{'version':{'children':{}}}} - version = data['app']['version']['children'] + data = {'app':{'2.0.0.0-0k0.0':{}}} + version = data['app']['2.0.0.0-0k0.0'] for section in config.sections(): version[section] = {} for option in config.options(section): value = config.get(section, option) - if 'keys' not in version[section]: - version[section]['keys'] = {} - version[section]['keys'][option] = {} - version[section]['keys'][option]["default"] = value - version[section]['keys'][option]["_type"] = 's' + value = value.strip() + value = value.strip("'") + value = value.strip('"') + version[section][option] = {} + version[section][option]["_default"] = value + version[section][option]["_type"] = 's' if not os.path.exists('yaml'): os.makedirs('yaml') # 将字典转换为YAML格式并写入文件 - with open(f'/home/kylin/yaml/{file.rsplit("/",maxsplit=1)[1].rsplit(".", maxsplit = 1)[0]}.yaml', 'w') as yaml_file: + home = os.getenv('HOME') + with open(f'{home}/yaml/{file.rsplit("/",maxsplit=1)[1].rsplit(".", maxsplit = 1)[0]}.yaml', 'w') as yaml_file: yaml.dump(data, yaml_file, allow_unicode = True) +# 参数传入.conf或.ini结尾的ini格式配置文件或目录路径 +# 将传入的所有配置文件或目录下的所有配置文件转换为yaml格式,生成在~/yaml路径下 if __name__ == "__main__": args = sys.argv[1:] for arg in args: @@ -61,4 +65,4 @@ if __name__ == "__main__": if arg.endswith('.conf') or arg.endswith('.ini'): convert_one_file(arg) else: - print(f'argument{arg} is not a conf file') \ No newline at end of file + print(f'argument{arg} is not a conf file') diff --git a/src/conf2/tools/gschema_xml2yaml.py b/src/conf2/tools/gschema_xml2yaml.py index 283910c..bb4b2cd 100755 --- a/src/conf2/tools/gschema_xml2yaml.py +++ b/src/conf2/tools/gschema_xml2yaml.py @@ -1,3 +1,4 @@ +#!/usr/bin/python3 # # libkysdk-system's Library # @@ -16,132 +17,115 @@ # You should have received a copy of the GNU General Public License # along with this library. If not, see . # -# Authors: Yunhe Liu +# Authors: tianshaoshuai # # -#!/usr/bin/python3 +import os +import re +import sys import xml.etree.ElementTree as ET import yaml -import ast -import sys, os, re -def convert_one_file(file): +def convert_one_file(data:dict, path:str, file:str): + + global organization + # 解析XML文件到树中 - tree = ET.parse(file) - root = tree.getroot() - # 将XML数据转换为Python字典 - data = {} - #处理枚举 - for enum in root.findall('.//enum'): - list = [] - id = enum.attrib.get('id') - for value in enum: - item = {} - item['nick'] = value.get('nick') - item['value'] = value.get('value') - list.append(item) - data[f'enum_{id}'] = list - #处理schema下的key, schema不管 - schema_list = root.findall('.//schema') - for schema in schema_list: - schema_map = {} - keys = {} - for key in schema.findall('.//key'): - item = {} - key_name = key.attrib.get('name') - key_type = key.attrib.get('type') - #type 不存在 就是枚举类型 - if key_type is None: - enumid = key.attrib.get('enum') - item['range'] = f'@enum_{enumid}' - item['_type'] = 'enum' - for child in key: - tag = child.tag - item[tag] = child.text.strip('\'') - else: - item['_type'] = key_type - for child in key: - text = "" - tag = child.tag - text = child.text - if text is None: - text = '' - text = text.strip() #去掉前后空白,否则可能影响ast.literal_eval解析字符串 - text = text.strip('\'') #部分xml空字符串默认值会写'' - text = text.strip('\"') #部分xml空字符串默认值会写'' - text = text.replace('\t','') #删除原xml中使下一行缩进而使用的制表符 - if tag == 'range': - item['range'] = f'{child.attrib.get("min")},{child.attrib.get("max")}' - # if tag == 'default': - # if key_type[0] in 'isbdtou': - # item['default'] = text - # else: - # parser_data = ast.literal_eval(text.strip()) - # item['default'] = parser_data - else: - item[tag] = text - keys[key_name] = item - if keys: - schema_map['keys'] = keys - data[schema.attrib.get('id').rsplit('.', maxsplit = 1)[1]] = schema_map - return data + if os.path.exists(f'{path}/{file}'): + + tree = ET.parse(f'{path}/{file}') + root = tree.getroot() + + #处理枚举 + for enum in root.findall('.//enum'): + list = [] + id = enum.attrib.get('id') + group_list = id[len(organization) + 1:].split('.') + if group_list[0] not in data: + data[group_list[0]] = {version:{}} + tmp = data[group_list[0]][version] + for value in enum: + item = {} + item['_nick'] = value.get('nick') + item['_value'] = value.get('value') + list.append(item) + tmp[f'enum_{id}'] = list + + #处理schema下的key, schema不管 + schema_list = root.findall('.//schema') + + for schema in schema_list: + id = schema.attrib.get('id') + group_list = id[len(organization) + 1:].split('.') + if group_list[0] not in data: + data[group_list[0]] = {version:{}} + tmp = data[group_list[0]][version] + for group in group_list[1:]: + if group not in tmp: + tmp[group] = {} + tmp = tmp[group] + + for key in schema.findall('.//key'): + item = {} + key_name = key.attrib.get('name') + key_type = key.attrib.get('type') + #type 不存在 就是枚举类型 + if key_type is None: + enumid = key.attrib.get('enum') + item['_range'] = f'@enum_{enumid}' + item['_type'] = 'enum' + else: + item['_type'] = key_type + for child in key: + tag = child.tag + text = '' if child.text is None else child.text + text = text.strip() + text = text.strip('\'') #部分xml空字符串默认值会写'' + text = text.strip('\"') #部分xml空字符串默认值会写"" + text = text.replace('\n\t','') #删除原xml中使下一行缩进而使用的制表符 + if tag == 'range': + text = f'{child.attrib.get("min")},{child.attrib.get("max")}' + item[f'_{tag}'] = text + tmp[key_name] = item + else: + print(f'{path}/{file} not exists') -# 转换单个app的所有配置文件,并生成到一个yaml文件中 if __name__ == '__main__': - app_name = sys.argv[1] + app = sys.argv[1] version = '2.0.0-0k0.0' if 3 == len(sys.argv): version = sys.argv[2] - # 读取app的所有配置文件 - app_config_files = {} - file_list = [] - for root, dirs, files in os.walk("/usr/share/glib-2.0/schemas"): - if f'{app_name}.gschema.xml' in files: - app_config_files[app_name] = convert_one_file(os.path.join(root, f'{app_name}.gschema.xml')) - for file in files: - if re.match(app_name + r'\..*' + '.gschema.xml' + r'$', file): - file_path = os.path.join(root, file) - app_config_files[file_path[28:-12]] = convert_one_file(file_path) - file_list.append(file_path[28:-12]) - # 将配置合并 - # 按照每个元素分割后的字符串个数对列表进行降序排序 - file_list = sorted(file_list, key=lambda x: len(x.split('.')), reverse= True) - # if app_name in file_list: - # file_list.remove(app_name) - parent = '' - child = '' - for key in file_list: - if key == app_name: - break - list = key.rsplit('.',maxsplit=1) - parent = list[0] - child = list[1] - # 将本文件的字典 添加到父文件的 'children'组中 - if parent in app_config_files: - if 'children' not in app_config_files[parent][parent.rsplit('.',maxsplit = 1)[1]]: - app_config_files[parent][parent.rsplit('.',maxsplit = 1)[1]]['children'] = {} - app_config_files[parent][parent.rsplit('.',maxsplit = 1)[1]]['children'].update(app_config_files[key]) - else: - tmp_map = {parent.rsplit('.',maxsplit = 1)[1]:{'children':{}}} - tmp_map[parent.rsplit('.',maxsplit = 1)[1]]['children'].update(app_config_files[key]) - key = parent - app_config_files[parent] = tmp_map - file_list.append(parent) - # 添加假的版本号 生成后需要手改为包的正确版本 - data = {} - data[app_name.rsplit('.',1)[1]] = {} - data[app_name.rsplit('.',1)[1]][version] = app_config_files[app_name][app_name.rsplit('.',maxsplit=1)[1]] + path = '/usr/share/glib-2.0/schemas' - if 'keys' in app_config_files[app_name][app_name.rsplit('.',maxsplit=1)[1]].keys(): - data[app_name.rsplit('.',1)[1]][version]['keys'] = app_config_files[app_name][app_name.rsplit('.',maxsplit=1)[1]]['keys'] + if len(sys.argv) > 3: + path = sys.argv[3] + + organization = app.rsplit('.', 1)[0] + + result = {} + + # 读取app的所有配置文件 + file_list = [] + pattren = re.compile(r'^{}.*\.gschema\.xml$'.format(re.escape(app))) + for root, dirs, files in os.walk(path): + for file in files: + if pattren.match(file): + file_list.append(file) + + # 按照每个元素分割后的字符串个数对列表进行降序排序 + file_list = sorted(file_list, key=lambda x: len(x.split('.')), reverse=False) + for file in file_list: + convert_one_file(result, path, file) - # 生成yaml文件 - yaml_data = yaml.safe_dump(data,allow_unicode = True) + # 生成yaml文件 + yaml_data = yaml.safe_dump(result, allow_unicode = True) # 将YAML数据写入文件 - file = f"/home/kylin/yaml/{app_name}.yaml" - if not os.path.exists('/home/kylin/yaml'): - os.makedirs('/home/kylin/yaml') + home = os.getenv('HOME') + file = f"{home}/yaml/{app}.yaml" + if not os.path.exists(os.path.dirname(file)): + os.makedirs(os.path.dirname(file), exist_ok=True) + with open(file, 'w') as yaml_file: yaml_file.write(yaml_data) diff --git a/src/conf2/tools/json2yaml.py b/src/conf2/tools/json2yaml.py new file mode 100644 index 0000000..968a4cd --- /dev/null +++ b/src/conf2/tools/json2yaml.py @@ -0,0 +1,74 @@ +#!/usr/bin/python3 +# +# libkysdk-system's Library +# +# Copyright (C) 2023, KylinSoft Co., Ltd. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 3 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this library. If not, see . +# +# Authors: tianshaoshuai +# +# + +import yaml, json +import sys, os + +def retrofit_the_structure(src:dict, dest:dict): + if not isinstance(src, dict): + # dest.update({'value':str(src)}) + print(f"{src}'s root node not a dict") + return + for key, value in src.items(): + if isinstance(value, dict): + dest[key] = {} + retrofit_the_structure(src[key], dest[key]) + else: + dest[key] = {} + if isinstance(value, list): + dest[key]['_type'] = 'as' + dest[key]['_default'] = str(src[key]) + else: + dest[key]['_type'] = 's' + dest[key]['_default'] = src[key] + +def convert_one_file(src:str): + with open(src, 'r') as file: + data = json.loads(file.read()) + base_name = os.path.basename(src) + name = os.path.splitext(base_name)[0] + result = {name : {'2.0.0.0-0k0.0': {}}} + retrofit_the_structure(data, result[name]['2.0.0.0-0k0.0']) + + home = os.getenv('HOME') + if not os.path.exists(f'{home}/yaml'): + os.mkdir(f'{home}/yaml') + with open(f'{home}/yaml/{base_name[:-5]}.yaml', 'w') as yaml_file: + yaml_file.write(yaml.safe_dump(result, allow_unicode = True)) + +# 参数传入.json结尾的json格式配置文件或目录路径 +# 将传入的所有配置文件或目录下的所有配置文件转换为yaml格式,生成在~/yaml路径下 +if __name__ == '__main__': + args = sys.argv[1:] + for arg in args: + if os.path.isdir(arg): + for root, dirs, files in os.walk(arg): + for file in files: + if file.endswith('.json'): + + convert_one_file(f'{root}/{file}') + else: + if arg.endswith('.json'): + convert_one_file(arg) + else: + print(f'argument{arg} is not a json file') diff --git a/src/conf2/tools/kconf2-editor.c b/src/conf2/tools/kconf2-editor.c index c5fb6e9..1aec11f 100644 --- a/src/conf2/tools/kconf2-editor.c +++ b/src/conf2/tools/kconf2-editor.c @@ -22,19 +22,21 @@ #include "../api/ksettingsschema.h" #include +#include +#include #include static GtkWidget *window = NULL; static GtkScrolledWindow *left_scrolled_window = NULL; static GtkScrolledWindow *right_scrolled_window = NULL; -//左侧配置树 +// 左侧配置树 static GtkTreeView *tree_folders = NULL; -//左侧树选中节点对应的键值表 +// 左侧树选中节点对应的键值表 static GtkTreeView *table_configure = NULL; -//tree_folders节点路径: 路径组成的schema id的配置数据 +// tree_folders节点路径: 路径组成的schema id的配置数据 static GHashTable *configure_models = NULL; enum ConfigureAttr @@ -72,7 +74,7 @@ void on_entry_button_clicked(GtkButton *button, gpointer user_data) int is_compliance = 0; const gchar *endptr = NULL; GError *error = NULL; - char *type = g_hash_table_lookup(schema_key, "data_type"); + char *type = g_hash_table_lookup(schema_key, "value_type"); if (0 != strcmp(type, "enum")) { GVariant *variant = g_variant_parse(G_VARIANT_TYPE(type), text, NULL, &endptr, &error); @@ -145,7 +147,20 @@ void on_entry_button_clicked(GtkButton *button, gpointer user_data) goto out; } - GVariant *variant = g_variant_new("(sssss)", getlogin(), schema->id, schema->version, list[1], text); + uid_t uid = getuid(); // 获取当前进程的用户ID + char user_name[128] = {0}; + struct passwd *pw = getpwuid(uid); // 获取用户ID对应的用户信息结构体 + if (NULL == pw) + { + strcpy(user_name, "root"); + } + else + { + strcpy(user_name, pw->pw_name); + endpwent(); + } + + GVariant *variant = g_variant_new("(sssss)", user_name, schema->id, schema->version, list[1], text); result = g_dbus_proxy_call_sync(proxy, "set", variant, @@ -155,6 +170,7 @@ void on_entry_button_clicked(GtkButton *button, gpointer user_data) &error); if (error != NULL) { + printf("%s", error->message); g_error_free(error); goto out; } @@ -171,7 +187,7 @@ out: g_object_unref(connection); if (response) { - g_hash_table_replace(schema_key, "user_value", text); + g_hash_table_replace(schema_key, "custom_value", text); GtkTreeIter iter; GtkListStore *store = gtk_tree_view_get_model(table_configure); @@ -185,9 +201,9 @@ out: { gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, - COLUMN_NAME, g_hash_table_lookup(value, "property"), - COLUMN_TYPE, g_hash_table_lookup(value, "data_type"), - COLUMN_VALUE, g_hash_table_lookup(value, "user_value") ? g_hash_table_lookup(value, "user_value") : g_hash_table_lookup(value, "default_value"), + COLUMN_NAME, g_hash_table_lookup(value, "node_name"), + COLUMN_TYPE, g_hash_table_lookup(value, "value_type"), + COLUMN_VALUE, g_hash_table_lookup(value, "custom_value") ? g_hash_table_lookup(value, "custom_value") : g_hash_table_lookup(value, "default_value"), COLUMN_SUMMARY, g_hash_table_lookup(value, "summary"), -1); } @@ -250,7 +266,7 @@ static void on_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeVi GtkWidget *vbox = gtk_vbox_new(FALSE, 15); - sprintf(tmp, "%s%s", title_array[0], g_hash_table_lookup(schema_key, "property")); + sprintf(tmp, "%s%s", title_array[0], g_hash_table_lookup(schema_key, "node_name")); GtkWidget *name_label = gtk_label_new(tmp); gtk_widget_set_halign(name_label, GTK_ALIGN_START); gtk_box_pack_start(vbox, name_label, TRUE, TRUE, 0); @@ -271,13 +287,13 @@ static void on_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeVi gtk_widget_set_halign(description_label, GTK_ALIGN_START); gtk_box_pack_start(vbox, description_label, TRUE, TRUE, 0); - sprintf(tmp, "%s%s", title_array[4], g_hash_table_lookup(schema_key, "data_type")); + sprintf(tmp, "%s%s", title_array[4], g_hash_table_lookup(schema_key, "value_type")); GtkWidget *type_label = gtk_label_new(tmp); gtk_widget_set_halign(type_label, GTK_ALIGN_START); gtk_box_pack_start(vbox, type_label, TRUE, TRUE, 0); char *range = g_hash_table_lookup(schema_key, "range"); - if ((NULL != range) && (0 != strcmp("enum", g_hash_table_lookup(schema_key, "data_type")))) + if ((NULL != range) && (0 != strcmp("enum", g_hash_table_lookup(schema_key, "value_type")))) { char **list = g_strsplit(range, ",", -1); sprintf(tmp, "%s%s", title_array[5], list[0]); @@ -299,7 +315,7 @@ static void on_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeVi gtk_widget_set_halign(default_label, GTK_ALIGN_START); gtk_box_pack_start(vbox, default_label, TRUE, TRUE, 0); - sprintf(tmp, "%s%s", title_array[8], g_hash_table_lookup(schema_key, "user_value") ? g_hash_table_lookup(schema_key, "user_value") : "默认值"); + sprintf(tmp, "%s%s", title_array[8], g_hash_table_lookup(schema_key, "custom_value") ? g_hash_table_lookup(schema_key, "custom_value") : "默认值"); GtkWidget *value_label = gtk_label_new(tmp); gtk_label_set_line_wrap_mode(GTK_LABEL(value_label), GTK_WRAP_WORD); // gtk_label_set_line_wrap(GTK_LABEL(value_label), TRUE); @@ -314,7 +330,7 @@ static void on_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeVi GtkWidget *entry_button = gtk_button_new_with_label("设置自定义值"); gtk_widget_set_halign(entry_button, GTK_ALIGN_START); // name 用来传参。。。。。。 - sprintf(tmp, "%s|%s", gtk_tree_path_to_string(path), g_hash_table_lookup(schema_key, "property")); + sprintf(tmp, "%s|%s", gtk_tree_path_to_string(path), g_hash_table_lookup(schema_key, "node_name")); gtk_widget_set_name(entry_button, tmp); gtk_box_pack_start(entry_vbox, entry_button, TRUE, TRUE, 0); @@ -323,9 +339,9 @@ static void on_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeVi gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text_view), GTK_WRAP_WORD); gtk_box_pack_start(vbox, text_view, TRUE, TRUE, 0); - char *user_value = g_hash_table_lookup(schema_key, "user_value") ? g_hash_table_lookup(schema_key, "user_value") : g_hash_table_lookup(schema_key, "default_value"); + char *custom_value = g_hash_table_lookup(schema_key, "custom_value") ? g_hash_table_lookup(schema_key, "custom_value") : g_hash_table_lookup(schema_key, "default_value"); GtkWidget *buffer = gtk_text_buffer_new(NULL); - gtk_text_buffer_set_text(GTK_TEXT_BUFFER(buffer), user_value, strlen(user_value)); + gtk_text_buffer_set_text(GTK_TEXT_BUFFER(buffer), custom_value, strlen(custom_value)); gtk_text_view_set_buffer(GTK_TEXT_VIEW(text_view), GTK_TEXT_BUFFER(buffer)); if ((NULL != writable) && (0 != strcmp(writable, "public"))) @@ -367,24 +383,27 @@ static void on_selection_changed(GtkTreeSelection *selection, gpointer data) GtkTreePath *path = gtk_tree_model_get_path(model, &iter); KSettingsSchema *schema = g_hash_table_lookup(configure_models, gtk_tree_path_to_string(path)); + char *select_path = gtk_tree_path_to_string(path); - char node_path[2048]; + char node_path[2048], tmp_path[64]; memset(node_path, 0, 2048); - char *tmp_path = gtk_tree_path_to_string(path); - GValue node_name = G_VALUE_INIT; - for (int i = 1; i <= strlen(tmp_path); i += 2) + memset(tmp_path, 0, 64); + char **nodes = g_strsplit(select_path, ":", -1); + for (int i = 0; nodes[i]; i++) { - char tmp[1024]; - memset(tmp, 0, 1024); - strncpy(tmp, tmp_path, i); - gtk_tree_model_get_iter_from_string(model, &iter, tmp); + GValue node_name = G_VALUE_INIT; + strcat(tmp_path, nodes[i]); + gtk_tree_model_get_iter_from_string(model, &iter, tmp_path); gtk_tree_model_get_value(model, &iter, 0, &node_name); if (0 < strlen(node_path)) sprintf(node_path, "%s/%s", node_path, g_value_get_string(&node_name)); else strcpy(node_path, g_value_get_string(&node_name)); g_value_unset(&node_name); + strcat(tmp_path, ":"); } + g_strfreev(nodes); + gtk_entry_set_text(GTK_ENTRY(data), node_path); GtkListStore *store = gtk_tree_view_get_model(table_configure); @@ -401,9 +420,9 @@ static void on_selection_changed(GtkTreeSelection *selection, gpointer data) { gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, - COLUMN_NAME, g_hash_table_lookup(value, "property"), - COLUMN_TYPE, g_hash_table_lookup(value, "data_type"), - COLUMN_VALUE, g_hash_table_lookup(value, "user_value") ? g_hash_table_lookup(value, "user_value") : g_hash_table_lookup(value, "default_value"), + COLUMN_NAME, g_hash_table_lookup(value, "node_name"), + COLUMN_TYPE, g_hash_table_lookup(value, "value_type"), + COLUMN_VALUE, g_hash_table_lookup(value, "custom_value") ? g_hash_table_lookup(value, "custom_value") : g_hash_table_lookup(value, "default_value"), COLUMN_SUMMARY, g_hash_table_lookup(value, "summary"), -1); } @@ -454,7 +473,7 @@ static void _find_search_node(char **list, GtkTreePath **path, GtkTreeModel *mod static void on_search_entry_activated(GtkWidget *entry, gpointer user_data) { const gchar *text = gtk_entry_get_text(GTK_ENTRY(entry)); - if(g_str_equal("", text)) + if (g_str_equal("", text)) return; char **list = g_strsplit(text, "/", -1); @@ -484,23 +503,27 @@ static void on_search_entry_activated(GtkWidget *entry, gpointer user_data) if (gtk_tree_selection_get_selected(selection, &model, &iter)) { GtkTreePath *path = gtk_tree_model_get_path(model, &iter); - char node_path[2048]; + char *select_path = gtk_tree_path_to_string(path); + + char node_path[2048], tmp_path[64]; memset(node_path, 0, 2048); - char *tmp_path = gtk_tree_path_to_string(path); - GValue node_name = G_VALUE_INIT; - for (int i = 1; i <= strlen(tmp_path); i += 2) + memset(tmp_path, 0, 64); + char **nodes = g_strsplit(select_path, ":", -1); + for (int i = 0; nodes[i]; i++) { - char tmp[1024]; - memset(tmp, 0, 1024); - strncpy(tmp, tmp_path, i); - gtk_tree_model_get_iter_from_string(model, &iter, tmp); + GValue node_name = G_VALUE_INIT; + strcat(tmp_path, nodes[i]); + gtk_tree_model_get_iter_from_string(model, &iter, tmp_path); gtk_tree_model_get_value(model, &iter, 0, &node_name); if (0 < strlen(node_path)) sprintf(node_path, "%s/%s", node_path, g_value_get_string(&node_name)); else strcpy(node_path, g_value_get_string(&node_name)); g_value_unset(&node_name); + strcat(tmp_path, ":"); } + g_strfreev(nodes); + gtk_entry_set_text(GTK_ENTRY(entry), node_path); } g_strfreev(list); @@ -509,6 +532,7 @@ static void on_search_entry_activated(GtkWidget *entry, gpointer user_data) g_strfreev(list); GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_folders); gtk_tree_view_expand_to_path(GTK_TREE_VIEW(tree_folders), path); + gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(tree_folders), path, NULL, FALSE, 0.0, 0.0); gtk_tree_selection_select_path(selection, path); gtk_widget_queue_draw(tree_folders); @@ -526,10 +550,10 @@ static void on_folder_selected(GtkFileChooser *chooser, gint response_id, gpoint if (0 == success) { GtkWidget *dialog = gtk_message_dialog_new(NULL, - GTK_DIALOG_MODAL, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - "保存配置数据到文件失败"); + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + "保存配置数据到文件失败"); // 运行消息框 gtk_dialog_run(GTK_DIALOG(dialog)); @@ -538,7 +562,7 @@ static void on_folder_selected(GtkFileChooser *chooser, gint response_id, gpoint gtk_widget_destroy(dialog); } } - break; + break; default: break; } @@ -573,12 +597,12 @@ static gboolean entry_match_func(GtkEntryCompletion *completion, const char *key gtk_tree_model_get(model, iter, 0, &value, -1); char *p = value, *q = p; - for(; *p != '\0'; p++) + for (; *p != '\0'; p++) { - if(*p == '/') + if (*p == '/') q = p; } - if(strstr(q, key)) + if (strstr(q, key)) return TRUE; else return FALSE; @@ -644,6 +668,8 @@ static void draw_scrolled_window(GtkTreeStore *store_app, GtkTreeStore *store_co { if (NULL == schemas_table) kdk_conf2_schema_update_schemas_table(); + if (NULL == schemas_table) + exit(0); GtkTreeIter iter; @@ -687,7 +713,7 @@ int main(int argc, char *argv[]) gtk_init(&argc, &argv); - // 创建窗口 + // 创建窗口 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); // gtk_window_set_title(GTK_WINDOW(window), "conf2-editor"); gtk_window_set_default_size(GTK_WINDOW(window), 1024, 768); @@ -700,7 +726,6 @@ int main(int argc, char *argv[]) gtk_widget_set_size_request(search_entry, -1, 10); gtk_box_pack_start(GTK_BOX(box), search_entry, FALSE, FALSE, 0); g_signal_connect(search_entry, "activate", G_CALLBACK(on_search_entry_activated), NULL); - GtkWidget *completion = gtk_entry_completion_new(); gtk_entry_completion_set_text_column(GTK_ENTRY_COMPLETION(completion), 0); diff --git a/src/conf2/tools/kconf2-editor.py b/src/conf2/tools/kconf2-editor.py new file mode 100755 index 0000000..7f6840d --- /dev/null +++ b/src/conf2/tools/kconf2-editor.py @@ -0,0 +1,376 @@ +#!/usr/bin/python3 +import os +import sys +import yaml +import logging +sys.path.append('/home/kylin/disk/kylinos-src/libkysdk-base/src/conf2/service') +import conf2Utils +import tkinter as tk +import tkinter.ttk as ttk +import tkinter.messagebox as msgbox +import tkinter.filedialog as filedialog +import dbus +from gi.repository import GLib + +target_view = {} + +def on_tree_right_click(event): + global right_select_item + item = tree.identify_row(event.y) + if item and tree.parent(item) == "": + right_select_item = item + download_menu.post(event.x_root, event.y_root) + +def close_menu(event): + download_menu.unpost() + +def on_search(): + pack_list = root.pack_slaves() + if view_frame in pack_list: + 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: + search_frame.pack_forget() + view_frame.pack(side='bottom', fill='both', expand=True) + items = tree.selection() + if items: + text = tree.item(items[0], 'tags')[0] + search_entry.delete(0, 'end') + search_entry.insert(0, text) + else: + search_entry.delete(0, 'end') + search_entry.config(state='readonly') + +def on_search_entry_change(event): + new_text = event.widget.get() + search_tree.delete(*search_tree.get_children()) + if new_text == '': + return + for key in search_list.keys(): + name_list = key.split('/') + if new_text in name_list[-1] or key.startswith(new_text): + search_tree.insert('', 'end', text= key) + +def on_download(): + 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') + +def on_download_one(): + global target_view + key = tree.item(right_select_item, 'text') + path = filedialog.askdirectory(mustexist=True, title=' Choose a folder') + if path: + success = converter.editor_save({key:target_view[key]}, path) + if success: + msgbox.showinfo(message='Save successed') + else: + msgbox.showinfo(message='Save failed') + +def on_import_file(): + pass + +def on_set(): + try: + if combobox.get() != 'custom': + msgbox.showinfo(message='Not custom veiw') + + user = destination_file.split('/')[2] + + key = id = value = '' + 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() + + path = search_entry.get() + version = path.split('/')[1] + print(f'{user} {id} {version} {key} {value}') + + 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') + except Exception as e: + print(e) + +def on_search_tree_select(event): + items = search_tree.selection() + text = search_tree.item(items[0], 'text') + tree.selection_set(search_list[text]) + tree.see(search_list[text]) + search_frame.pack_forget() + view_frame.pack(side='bottom', fill='both', expand=True) + +def on_tree_select(event): + selected_item = tree.selection() + global target_view + if not selected_item: + return + item = selected_item[0] + tag = tree.item(item, 'tags')[0] + + search_entry.config(state='normal') + search_entry.delete(0, 'end') + search_entry.insert(0, tag) + search_entry.config(state='readonly') + + if tree.parent(item) == '': + return + + group_list = tag.split('/') + tmp = target_view + for group in group_list: + tmp = tmp[group] + for widget in inner_frame.winfo_children(): + widget.destroy() + + text = tree.item(item, 'text') + + name_label = tk.Label(inner_frame, text=f'名称', anchor='w') + name_label.pack(side='top', fill='x') + + name_text = tk.Text(inner_frame, height=1, width=100, wrap='word', name='key') + name_text.insert('1.0', text) + name_text.config(state='disabled') + name_text.pack(side='top', fill='x', expand=True) + + type = tmp['_type'] if '_type' in tmp else 'group' + + if len(group_list) > 1: + group_list.pop(1) + if type != 'group': + group_list.pop(-1) + + id_label = tk.Label(inner_frame, text=f'路径', anchor='w') + id_label.pack(side='top', fill='x') + + id_text = tk.Text(inner_frame, height=1, width=100, wrap='word', name='id') + id_text.insert('1.0', '.'.join(group_list)) + id_text.config(state='disabled') + id_text.pack(side='top', fill='x', expand=True) + + type_label = tk.Label(inner_frame, text=f'类型', anchor='w') + type_label.pack(side='top', fill='x') + + type_text = tk.Text(inner_frame, height=1, width=100, wrap='word', name='type') + type_text.insert('1.0', type) + type_text.config(state='disabled') + type_text.pack(side='top', fill='x', expand=True) + + if tmp.get('_summary') is not None: + 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.insert('1.0', tmp.get('_summary')) + summary_text.config(state='disabled') + summary_text.pack(side='top', fill='x', expand=True) + + if tmp.get('_description') is not None: + 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.insert('1.0', tmp.get('_description')) + decription_text.config(state='disabled') + decription_text.pack(side='top', fill='x', expand=True) + + permission = tmp.get('_permission', 'public') + 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.insert('1.0', permission) + permission_text.config(state='disabled') + permission_text.pack(side='top', fill='x', expand=True) + + if '_default' in tmp: + default_value = tmp['_default'] + if isinstance(default_value, bool): + default_value = 'true' if tmp['_default'] else 'false' + + default_label = tk.Label(inner_frame, text=f'默认值', anchor='w') + default_label.pack(side='top', fill='x') + + default_text = tk.Text(inner_frame, height=5, width=100, wrap='word', name='default') + default_text.insert('1.0', tmp['_default']) + 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') + + 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') + set_button = tk.Button(inner_frame, text='Set', command=on_set) + set_button.pack(side='top') + +def on_combobox_select(event): + selected_item = combobox.get() + global target_view + if selected_item == 'custom': + target_view = converter._db2dict(f'{destination_file}/.config/kylin-config/user.db') + else: + dirs = [] + for dir in list(reversed(options)): + if dir == 'user': + dirs.append(f'{destination_file}/.config/kylin-config/configs') + else: + dirs.append(f'/etc/kylin-config/{dir}') + if dir == selected_item: + break + target_view = converter.load_dirs_config(dirs) + + tree.delete(*tree.get_children()) + for widget in inner_frame.winfo_children(): + widget.destroy() + search_list.clear() + populate_tree(tree, '', target_view) + view_frame.update() + +def populate_tree(tree, node, dictionary): + global search_list + tag = tree.item(node, 'tags') + for key, value in dictionary.items(): + if isinstance(value, dict): + child_node = tree.insert(node, 'end', text=key) + if isinstance(tag, str): + tree.item(child_node, tags=(key)) + else: + tree.item(child_node, tags=(f'{tag[0]}/{key}')) + search_list[f'{tag[0]}/{key}'] = child_node + populate_tree(tree, child_node, value) + +root = tk.Tk() +root.title("kconf2-editor") +root.geometry('1024x768') +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) + +search_list = {} + +destination_file = os.getenv('HOME') +logger = logging.getLogger(f'{destination_file}/.log/widget.log') +converter = conf2Utils.Converter(logger) + +# 读取统一视图 +target_view = converter._db2dict(f'{destination_file}/.config/kylin-config/user.db') + +# 创建一个Frame来包含按钮,使其一直位于界面上方 +button_frame = tk.Frame(root, height=10) +# 创建一个Frame来包含Treeview,占满界面其他空余部分 +view_frame = tk.Frame(root) +# 创建一个Frame来显示搜索结果,它与view_frame只会显示一个 +search_frame = tk.Frame(root) + +# 排列root的三个子组件 +button_frame.pack(side="top", fill="x") +view_frame.pack(side='top', fill='both', expand=True) + +# 搜索栏 +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) + +# 下载按钮 +# download_icon = tk.PhotoImage(file="download_icon.png") +download_button = tk.Button(button_frame, text= 'd', 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('custom') +options.reverse() + +combobox = ttk.Combobox(button_frame, values=options, width=20, state='readonly') +combobox.set(options[0]) +combobox.bind("<>", on_combobox_select) + +# 排列button_frame子组件 +search_entry.pack(side="left", fill="both", expand= True) +combobox.pack(side='right') +download_button.pack(side="right", fill="x") +search_button.pack(side="right", fill="x") + +# 创建Frame在view_frame的左侧,显示配置树 +left_frame = tk.Frame(view_frame) +left_frame.pack(side='left', fill='both') + +# 创建Treeview,显示配置树 +tree = ttk.Treeview(left_frame) +tree.column('#0', width=200, stretch=True) +tree.heading('#0', text='SubFolders') +tree.bind("<>", on_tree_select) +tree.bind("", on_tree_right_click) +search_list.clear() +populate_tree(tree, '', target_view) +tree.pack(side='left', fill='both') + +# 创建滚动条 +tree_scrollbar = ttk.Scrollbar(left_frame, orient="vertical", command=tree.yview) +tree_scrollbar.pack(side="right", fill="y") +tree.configure(yscrollcommand=tree_scrollbar.set) + +# 创建Frame在view_frame的右侧,显示配置信息 +right_frame = tk.Frame(view_frame) +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") + +right_scrollbar = ttk.Scrollbar(right_frame, orient="vertical", command=canvas.yview) +right_scrollbar.pack(side="right", fill="y") +canvas.configure(yscrollcommand=right_scrollbar.set) + +# 创建Treeview显示搜索匹配的路径 +search_tree = ttk.Treeview(search_frame, show='tree') +search_tree.bind("<>", on_search_tree_select) +search_tree.pack(side='left', fill='both', expand=True) + +search_scrollbar = ttk.Scrollbar(search_frame, orient="vertical", command=search_tree.yview) +search_scrollbar.pack(side="right", fill="y") +search_tree.configure(yscrollcommand=search_scrollbar.set) + +root.mainloop() \ No newline at end of file diff --git a/src/conf2/tools/kconf2-tool.c b/src/conf2/tools/kconf2-tool.c index ff6a5e1..1e6ca79 100644 --- a/src/conf2/tools/kconf2-tool.c +++ b/src/conf2/tools/kconf2-tool.c @@ -23,13 +23,18 @@ #include -void key_changed(KSettings *ksettigns, const char *key, void *user_data) +void on_key_changed(KSettings *ksettigns, const char *key, void *user_data) { char *value = kdk_conf2_get_value(ksettigns, key); printf("%s changed to %s\n", key, value); free(value); } +void on_reload(KSettings *ksettigns, void *user_data) +{ + printf("view reload\n"); +} + /*句柄结构体内部元素*/ typedef struct _KSettingsPrivate { @@ -62,6 +67,7 @@ static void print_help() // " reset-recursively Reset all values in a given schema\n" " writable Check if a key is writable\n" " monitor Watch for changes\n" + // " monitor-reload Watch for realod\n" " save Save User config in target folder" "\n" "Use kconf2 help \"COMMAND\" to get detailed help.\n"); @@ -211,10 +217,21 @@ static void print_command(char *command) " VERSION Specify the version of the schema\n" " KEY Key in the schema\n"); } + // else if (0 == strcmp(command, "monitor-reload")) + // { + // printf("Usage:\n" + // " kconf2 monitor-reload\n" + // "\n" + // "Monitor reload to the view.\n" + // "Use ^C to stop monitoring.\n" + // "\n" + // "Args\n" + // " SCHEMA The name of the schema\n"); + // } else if (0 == strcmp(command, "list-schemas")) { printf("Usage:\n" - " kconf2 list-scemas [APP] [VERSION]\n" + " kconf2 list-scemas APP [VERSION]\n" "\n" "If you don't specify an app and version, list all installed schemas.\n" "otherwise list schemas items that specify the app and version.\n" @@ -265,7 +282,10 @@ int main(int argc, char *argv[]) if (0 == strcmp(argv[1], "list-schemas")) { if (argc < 3) - print_help("list-schemas"); + { + print_command("list-schemas"); + exit(0); + } gboolean limit_app = FALSE, limit_version = FALSE; if (argc > 2) limit_app = TRUE; @@ -296,13 +316,13 @@ int main(int argc, char *argv[]) g_hash_table_iter_init(&ver_iter, app_hash); while (g_hash_table_iter_next(&ver_iter, &version, &version_hash)) { - if (limit_version && 0 != strcmp(argv[3], app->name)) + if (limit_version && 0 != strcmp(argv[3], version->name)) continue; printf("\t%s:\n", version->name); GList *schemas = g_hash_table_get_keys(version_hash); for (GList *tmp = schemas; tmp; tmp = tmp->next) { - printf("\t\t%s\n", (char *)schemas->data); + printf("\t\t%s\n", (char *)tmp->data); } g_list_free(schemas); } @@ -311,7 +331,10 @@ int main(int argc, char *argv[]) else if (0 == strcmp(argv[1], "list-children")) { if (argc < 3) - print_help("list-children"); + { + print_command("list-children"); + exit(0); + } KSettings *ksettings = kdk_conf2_new(id, version); if (NULL == ksettings) { @@ -333,7 +356,10 @@ int main(int argc, char *argv[]) else if (0 == strcmp(argv[1], "list-keys")) { if (argc < 3) - print_help("list-keys"); + { + print_command("list-keys"); + exit(0); + } KSettings *ksettings = kdk_conf2_new(id, version); if (NULL == ksettings) @@ -356,8 +382,10 @@ int main(int argc, char *argv[]) else if (0 == strcmp(argv[1], "list-recursively")) { if (argc < 3) - print_help("list-recursively"); - + { + print_command("list-recursively"); + exit(0); + } KSettings *ksettings = kdk_conf2_new(id, version); if (NULL == ksettings) { @@ -380,7 +408,10 @@ int main(int argc, char *argv[]) else if (0 == strcmp(argv[1], "get")) { if (argc < 4) - print_help("get"); + { + print_command("get"); + exit(0); + } KSettings *ksettings = kdk_conf2_new(id, version); if (NULL == ksettings) @@ -400,7 +431,10 @@ int main(int argc, char *argv[]) else if (0 == strcmp(argv[1], "set")) { if (argc < 5) - print_help('set'); + { + print_command("set"); + exit(0); + } KSettings *ksettings = kdk_conf2_new(id, version); if (NULL == ksettings) @@ -416,7 +450,10 @@ int main(int argc, char *argv[]) else if (0 == strcmp(argv[1], "range")) { if (argc < 4) - print_help('range'); + { + print_command("range"); + exit(0); + } KSettings *ksettings = kdk_conf2_new(id, version); if (NULL == ksettings) @@ -438,15 +475,16 @@ int main(int argc, char *argv[]) { if (0 == strcmp(type, "enum")) { - char *endptr, *error; + char *endptr; + GError *error; GVariant *variant = g_variant_parse(G_VARIANT_TYPE("a{si}"), range, NULL, &endptr, &error); if (NULL == variant) { - printf("parser enum error %s\n", error); + printf("parser enum error %s\n", error->message); exit(0); } - printf("enum\n"); + printf("enum:\n"); char *nick = NULL; gint32 value = 0; @@ -454,16 +492,14 @@ int main(int argc, char *argv[]) g_variant_get(variant, "a{si}", &iter); while (g_variant_iter_loop(iter, "{si}", &nick, &value)) { - printf("'%s'\n", nick); + printf(" '%s'\n", nick); } g_variant_iter_free(iter); g_variant_unref(variant); } else { - printf("%s\n", range); p = range; - printf("%x\n", ','); while (*p != ',' && *p != '\0') p++; *p = '\0'; @@ -476,16 +512,17 @@ int main(int argc, char *argv[]) else if (0 == strcmp(argv[1], "reset")) { if (argc < 4) - print_help('reset'); - + { + print_command("reset"); + exit(0); + } KSettings *ksettings = kdk_conf2_new(id, version); if (NULL == ksettings) { printf("Wrong schema id\n"); exit(0); } - - if (NULL == kdk_conf2_schema_get_key(ksettings, argv[argc - 1])) + if (NULL == kdk_conf2_schema_get_key(ksettings->priv->schema, argv[argc - 1])) { printf("Wrong key\n"); exit(0); @@ -496,7 +533,10 @@ int main(int argc, char *argv[]) else if (0 == strcmp(argv[1], "monitor")) { if (argc < 3) - print_help('monitor'); + { + print_command("monitor"); + exit(0); + } KSettings *ksettings = kdk_conf2_new(id, version); if (NULL == ksettings) @@ -509,10 +549,10 @@ int main(int argc, char *argv[]) if (4 == argc) { char *signal_name = g_strdup_printf("changed::%s", argv[3]); - id = kdk_conf2_connect_signal(ksettings, signal_name, key_changed, NULL); + id = kdk_conf2_connect_signal(ksettings, signal_name, on_key_changed, NULL); } else - id = kdk_conf2_connect_signal(ksettings, "changed", key_changed, NULL); + id = kdk_conf2_connect_signal(ksettings, "changed", on_key_changed, NULL); if (id <= 0) { @@ -523,10 +563,39 @@ int main(int argc, char *argv[]) for (;;) g_main_context_iteration(NULL, TRUE); } + else if (0 == strcmp(argv[1], "monitor-reload")) + { + if (argc < 2) + { + print_command("monitor-reload"); + exit(0); + } + + KSettings *ksettings = kdk_conf2_new("test.notice", NULL); + if (NULL == ksettings) + { + printf("Wrong schema id\n"); + exit(0); + } + + guint id = 0; + id = kdk_conf2_connect_signal(ksettings, "reload", on_reload, NULL); + if (id <= 0) + { + printf("Connect signal failed\n"); + exit(0); + } + + for (;;) + g_main_context_iteration(NULL, TRUE); + } else if (0 == strcmp(argv[1], "writable")) { if (argc < 4) - print_help('writable'); + { + print_command("writable"); + exit(0); + } KSettings *ksettings = kdk_conf2_new(id, version); if (NULL == ksettings) @@ -544,7 +613,10 @@ int main(int argc, char *argv[]) else if (0 == strcmp(argv[1], "describe")) { if (argc < 4) - print_help('describe'); + { + print_command("describe"); + exit(0); + } KSettings *ksettings = kdk_conf2_new(id, version); if (NULL == ksettings) @@ -558,10 +630,13 @@ int main(int argc, char *argv[]) else if (0 == strcmp(argv[1], "save")) { if (argc < 3) - print_help('save'); + { + print_command("save"); + exit(0); + } int success = kdk_conf2_save_user_configure(argv[2]); - if(0 == success) - printf("save configure failed"); + if (0 == success) + printf("save configure failed\n"); } else { diff --git a/src/conf2/接口说明.md b/src/conf2/接口说明.md deleted file mode 100644 index f59197f..0000000 --- a/src/conf2/接口说明.md +++ /dev/null @@ -1,1183 +0,0 @@ -# 接口说明文档 - -## 接口 - -[TOC] - -### new - -> 声明 -> -> ```C -> KSettings *kdk_conf2_new ( -> const char *id, -> const char *version -> ) -> ``` - -> 描述 -> -> ​ 读取指定id指定版本的句柄。 - -> 参数 -> -> ​ id : 组的路径 -> -> ​ version: 版本号 -> -> ​ 传NULL,使用配置文件内设置默认版本 -> -> ​ 如果配置文件内没有设置默认版本,取最高版本为默认版本 - -> 返回值 -> -> ​ 指定id的配置句柄,失败返回NULL -> -> ​ 调用方获得句柄的所有权,并负责释放数据 - -### destroy - -> 声明 -> -> ```C -> void kdk_conf2_ksettings_destory( -> KSettings *ksettings -> ) -> ``` - -> 描述 -> -> ​ 销毁由kdk_conf2_new取得的配置句柄 - -> 参数 -> -> ​ ksettings: 由kdk_conf2_new获取的句柄 - ->返回 -> ->​ 无 - -### get_id - -> 声明 -> -> ```C -> char * -> kdk_conf2_get_id( -> KSettings *settings -> ) -> ``` - -> 描述 -> -> ​ 获取配置句柄对应的配置id - -> 参数 -> -> ​ settings: 句柄 - -> 返回值 -> -> ​ 配置id -> -> ​ 该方法的调用方取得数据的所有权,并负责释放数据 - -### get_version - -> 声明 -> -> ```C -> char * -> kdk_conf2_get_version( -> KSettings *settings -> ) -> ``` - -> 描述 -> -> ​ 获取配置句柄对应的配置版本 - -> 参数 -> -> ​ settings: 句柄 - -> 返回值 -> -> ​ 配置版本号 -> -> ​ 该方法的调用方取得数据的所有权,并负责释放数据 - -### get_child - -> 声明 -> -> ```C -> KSettings * -> kdk_conf2_get_child ( -> KSettings *ksettings, -> const char *name -> ) -> ``` - -> 描述 -> -> ​ 获取当前句柄子id的配置句柄 - -> 参数 -> -> ​ ksettings: 配置句柄 -> -> ​ name: 子组名 - -> 返回值 -> -> ​ 子id句柄,失败返回NULL -> -> ​ 该方法的调用方取得数据的所有权,并负责释放数据 - -### list_children - -> 声明 -> -> ```C -> char ** -> kdk_conf2_list_children ( -> KSettings *ksettings -> ) -> ``` - -> 描述 -> -> ​ 获取当前句柄所有子组的名称 - -> 参数 -> -> ​ ksettings: 句柄 - -> 返回值 -> -> ​ 以NULL结尾的字符串数组 -> -> ​ 该方法的调用方取得数据的所有权,并负责释放数据。 -> -> ​ 获取失败返回NULL - -### list_keys - -> 声明 -> -> ```C -> char ** -> kdk_conf2_list_keys ( -> KSettings *ksettings -> ) -> ``` - -> 描述 -> -> ​ 获取当前句柄所有的键名 - -> 参数 -> -> ​ settings: 句柄 - -> 返回值 -> -> ​ 以NULL结尾的字符串数组 -> -> ​ 该方法的调用方取得数据的所有权,并负责释放数据。 -> -> ​ 获取失败返回NULL - -### get_boolean - -> 声明 -> -> ```C -> int -> kdk_conf2_get_boolean ( -> KSettings *ksettings, -> const char *key -> ) -> ``` - -> 描述 -> -> ​ 获取设置中`bool`类型的键的值。 -> -> ​ 调用方调用此接口时需确认键值确为`bool`类型 - -> 参数 -> -> ​ settings: 句柄 -> -> ​ key: 键名 - -> 返回值 -> -> ​ 布尔值 -> -> ​ 1:True -> -> ​ 0:False - -### get_default_value - -> 声明 -> -> ```C -> char * -> kdk_conf2_get_default_value ( -> KSettings *ksettings, -> const char *key -> ) -> ``` - -> 描述 -> -> ​ 获取设置中键的默认值 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 - -> 返回值 -> -> ​ 符合配置类型标签的字符串,失败返回NULL -> -> ​ 该方法的调用方取得数据的所有权,并负责释放数据。 - -### get_double - -> 声明 -> -> ```C -> double -> kdk_conf2_get_double ( -> KSettings *ksettings, -> const char *key -> ) -> ``` - -> 描述 -> -> ​ 获取设置中`double`类型的键的值 -> -> ​ 调用方需确认键值确为`double`类型 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 - -> 返回值 -> -> ​ 浮点型值 - -### get_enum - -> 声明 -> -> ```C -> int -> kdk_conf2_get_enum ( -> KSettings *ksettings, -> const char *key -> ) -> ``` - -> 描述 -> -> ​ 获取设置中`enum`类型的键的值 -> -> ​ 调用方请确认键值类型确为`emum`类型 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 - -> 返回值 -> -> ​ 枚举的值,类型为`int`型 - -### get_int - -> 声明 -> -> ```C -> int -> kdk_conf2_get_int ( -> KSettings *ksettings, -> const char *key -> ) -> ``` - -> 描述 -> -> ​ 获取设置中`int`类型的键的值 -> -> ​ 调用方请确认键值确为`int`类型 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 - -> 返回值 -> -> ​ 整型值 - -### get_int64 - -> 声明 -> -> ```C -> long -> kdk_conf2_get_int ( -> KSettings *ksettings, -> const char *key -> ) -> ``` - -> 描述 -> -> ​ 获取设置中`int64`类型的键的值 -> -> ​ 调用方请确认键值确为`int64`类型 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 - -> 返回值 -> -> ​ 长整型数值 - -### get_range - -> 声明 -> -> ```C -> char * -> kdk_conf2_get_range ( -> KSettings *ksettings, -> const char *key -> ) -> ``` - -> 描述 -> -> ​ 获取设置中键的取值范围 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 - -> 返回值 -> -> ​ 取值范围,不存在取值范围返回NULL -> -> ​ 针对枚举类型,返回`"a{si}"`类型的字符串 -> -> ​ 针对取值区间,返回`“min,max”`类型的字符串 -> -> ​ 该方法的调用方取得数据的所有权,并负责释放数据。 - -### get_string - -> 声明 -> -> ```C -> char * -> kdk_conf2_get_string ( -> KSettings *ksettings, -> const char *key -> ) -> ``` - -> 描述 -> -> ​ 获取设置中`string`类型的键值 -> -> ​ 调用方请确认键值的确为`string`类型 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 - -> 返回值 -> -> ​ 字符串,失败返回NULL -> -> ​ 该方法的调用方取得数据的所有权,并负责释放数据。 - -### get_strv - -> 声明 -> -> ```C -> char ** -> kdk_conf2_get_strv ( -> KSettings *ksettings, -> const char *key -> ) -> ``` - -> 描述 -> -> ​ 获取设置中`strv`类型的键值 -> -> ​ 调用方请确认键值确为`strv`类型 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 - -> 返回值 -> -> ​ 以NULL结尾的字符串数组,失败返回NULL -> -> ​ 该方法的调用方取得数据的所有权,并负责释放数据。 - -### get_uint - -> 声明 -> -> ```C -> unsigned int -> kdk_conf2_get_uint ( -> KSettings *ksettings, -> const char *key -> ) -> ``` - -> 描述 -> -> ​ 获取设置中`uint`类型的键值 -> -> ​ 调用方请确认键值确为`uint`类型 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 - -> 返回值 -> -> ​ 无符号整型值 - -### get_uint64 - -> 声明 -> -> ```C -> unsigned long -> kdk_conf2_get_uint64 ( -> KSettings *ksettings, -> const char *key -> ) -> ``` - -> 描述 -> -> ​ 获取设置中`uint64`类型的键值 -> -> ​ 调用方请确认键值的确为`uint64`类型 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 - -> 返回值 -> -> ​ 无符号长整型值 - -### get_value - -> 声明 -> -> ```C -> char * -> kdk_conf2_get_value ( -> KSettings *ksettings, -> const char *key -> ) -> ``` - -> 描述 -> -> ​ 获取设置中键的值 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 - -> 返回值 -> -> ​ 符合键值类型标签的字符串,失败返回NULL -> -> ​ 该方法的调用方取得数据的所有权,并负责释放数据。 - -### get_description - -> 声明 -> -> ```C -> char * -> kdk_conf2_get_description ( -> KSettings *ksettings, -> const char *key -> ) -> ``` - -> 描述 -> -> ​ 获取键的`description`字段 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 - -> 返回值 -> -> ​ 键的`descritpion`字段 -> -> ​ 该方法的调用方取得数据的所有权,并负责释放数据。 - -### get_summary - -> 声明 -> -> ```C -> char * -> kdk_conf2_get_summary( -> KSettings *settings, -> const char *key -> ) -> ``` - -> 描述 -> -> ​ 获取键的`summary`字段 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 - -> 返回值 -> -> ​ 键的`summary`字段 -> -> ​ 该方法的调用方取得数据的所有权,并负责释放数据 - -### is_writable - -> 声明 -> -> ```C -> int -> kdk_conf2_is_writable ( -> KSettings *ksettings, -> const char *key -> ) -> ``` - -> 描述 -> -> ​ 检测键值是否可写 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 - -> 返回值 -> -> ​ 布尔值 -> -> ​ 1: True -> -> ​ 0: False - - - -### range_check - -> 声明 -> -> ```C -> int -> kdk_conf2_range_check ( -> KSettings *settings, -> const char *key, -> const char *value -> ) -> ``` - -> 描述 -> -> ​ 检查要设置值是否在取值区间 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 应该存在取值区间或是枚举类型 -> -> ​ value: 要设置的值 - -> 返回值 -> -> ​ 布尔值 -> -> ​ 1: True -> -> ​ 0: False - -### reset - -> 声明 -> -> ```C -> void -> kdk_conf2_reset ( -> KSettings *settings, -> const char *key -> ) -> ``` - -> 描述 -> -> ​ 将键的值重制为默认值 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 - -> 返回值 -> -> ​ 无 - -### reload - -> 声明 -> -> ```C -> void -> kdk_conf2_reload (); -> ``` - -> 描述 -> -> ​ 重新读取配置文件,并与当前用户的配置合并 - -> 参数 -> -> ​ 无 - -> 返回值 -> -> ​ 无 - -### set_boolean - -> 声明 -> -> ```C -> int -> kdk_conf2_set_boolean( -> KSettings *settings, -> const char *key, -> int value -> ) -> ``` - -> 描述 -> -> ​ 设置`bool`类型的键值 -> -> ​ 调用方请确认键值确为`bool`类型 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 -> -> ​ value: 要设置的值 - -> 返回值 -> -> ​ 布尔值 -> -> ​ 1: True -> -> ​ 0: False - -### set_double - -> 声明 -> -> ```C -> int -> kdk_conf2_set_double( -> KSettings *ksettings, -> const char *key, -> double value -> ) -> ``` - -> 描述 -> -> ​ 设置`double`类型的键值 -> -> ​ 调用方请确认键值确为`double`类型 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 -> -> ​ value: 要设置的值 - -> 返回值 -> -> ​ 布尔值 -> -> ​ 1: True -> -> ​ 0: False - -### set_enum - -> 声明 -> -> ```C -> int -> kdk_conf2_set_enum( -> KSettings *settings, -> const char *key, -> int value -> ) -> ``` - -> 描述 -> -> ​ 设置`enum`类型的键值 -> -> ​ 调用方请确认键值存在于`enum`中 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 -> -> ​ value: 要设置的值 - -> 返回值 -> -> ​ 布尔值 -> -> ​ 1: True -> -> ​ 0: False - -### set_int - -> 声明 -> -> ```C -> int -> kdk_conf2_set_int( -> KSettings *settings, -> const char *key, -> int value -> ) -> ``` - -> 描述 -> -> ​ 设置`int`类型的键值 -> -> ​ 调用方请确认键值类型确为`int`类型 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 -> -> ​ value: 要设置的值 - -> 返回值 -> -> ​ 布尔值 -> -> ​ 1: True -> -> ​ 0: False - -### set_int64 - -> 声明 -> -> ```C -> int -> kdk_conf2_set_int64( -> KSettings *ksettings, -> const char *key, -> long value -> ) -> ``` - -> 描述 -> -> ​ 设置`int64`类型的键值 -> -> ​ 调用方请确认键值类型确为`int64`类型 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 -> -> ​ value: 要设置的值 - -> 返回值 -> -> ​ 布尔值 -> -> ​ 1: True -> -> ​ 0: False - -### set_string - -> 声明 -> -> ```C -> int -> kdk_conf2_set_string( -> Ksettings *ksettings, -> const char *key, -> const char *value -> ) -> ``` - -> 描述 -> -> ​ 设置`char *`类型的键值 -> -> ​ 调用方请确认键值类型确为`char *`类型 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 -> -> ​ value: 要设置的值 - -> 返回值 -> -> ​ 布尔值 -> -> ​ 1: True -> -> ​ 0: False - -### set_strv - -> 声明 -> -> ```C -> int -> kdk_conf2_set_strv( -> KSettings *ksettings, -> const char *key, -> const char *const *value -> ) -> ``` - -> 描述 -> -> ​ 设置`char **`类型的键值 -> -> ​ 调用方请确认键值类型确为`char **`类型 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 -> -> ​ value: 要设置的值 - -> 返回值 -> -> ​ 布尔值 -> -> ​ 1: True -> -> ​ 0: False - -### set_uint - -> 声明 -> -> ```C -> int -> kdk_conf2_set_uint( -> KSettings *ksettings, -> const char *key, -> unsigned int value -> ) -> ``` - -> 描述 -> -> ​ 设置`uint`类型的键值 -> -> ​ 调用方请确认键值类型确为`uint`类型 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 -> -> ​ value: 要设置的值 - -> 返回值 -> -> ​ 布尔值 -> -> ​ 1: True -> -> ​ 0: False - -### set_uint64 - -> 声明 -> -> ```C -> int -> kdk_conf2_set_uint64( -> KSettings *ksettings, -> const char *key, -> unsigned long value -> ) -> ``` - -> 描述 -> -> ​ 设置`uint64`类型的键值 -> -> ​ 调用方请确认键值类型确为`uint64`类型 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 -> -> ​ value: 要设置的值 - -> 返回值 -> -> ​ 布尔值 -> -> ​ 1: True -> -> ​ 0: False - -### set_value - -> 声明 -> -> ```C -> int -> kdk_conf2_set_value( -> KSettings *ksettings, -> const char *key, -> const char *value -> ) -> ``` - -> 描述 -> -> ​ 设置键值 - -> 参数 -> -> ​ ksettings: 句柄 -> -> ​ key: 键名 -> -> ​ value: 符合配置项类型标签的键值字符串 - -> 返回值 -> -> ​ 布尔值 -> -> ​ 1: True -> -> ​ 0: False - -### connect_signal - -> 声明 -> -> ```C -> unsigned long -> kdk_conf2_connect_signal( -> KSettngs *ksettings, -> const char *signal_name, -> KCallBack handler, -> void *user_data -> ) -> typedef void (*KCallBack) (void); -> ``` - -> 描述 -> -> ​ 注册回调函数以相应键值改变信号 - -> 参数 -> -> ​ ksettings: 信号链接的对象 -> -> ​ signal_name: 信号的详细描述,格式"signal-name::detailed". 例如"changed"或"changed::key" -> -> ​ handler: 信号处理函数的C函数指针 -> -> ​ user_data: 传递给信号处理函数的用户数据 - -> 返回 -> -> ​ 信号处理函数的ID,销毁句柄时会自动销毁句柄绑定的信号处理ID - -### list-shcemas - -> 声明 -> -> ```c -> char** -> kdk_conf2_list_schemas( -> const char *app, -> const char *version -> ) -> ``` - -> 描述 -> -> ​ 查看指定应用拥有的所有schema id。可指定版本,不指定则读取默认版本 - -> 参数 -> -> ​ app: 应用名 -> -> ​ version: 版本号,可以传NULL - -> 返回 -> -> ​ 成功返回id列表, 失败返回NULL - -### save - -> 声明 -> -> ```c -> int -> kdk_conf2_save_user_configure( -> const char *path -> ) -> ``` - -> 描述 -> -> ​ 将数据库中的用户配置导出为配置文件,存放到目标路径 - -> 参数 -> -> ​ path: 目标路径,请确定有写权限 - -> 返回 -> -> ​ 成功返回1, 失败返回0 - -## 信号 - -### changed - -> 声明 -> -> ```C -> void -> changed( -> KSettings *传递给信号处理函数的用户数据, -> char *key, -> void *user_data -> ) -> ``` -> -> - -> 描述 -> -> ​ "changed"信号会在配置的设置值被修改时发出,您应该调用kdk_conf2_get()系列接口来获取新值。 -> -> ​ 该信号支持详细链接,可以连接到详细信号"changed::detailed",增加"detailed"修饰符可以仅在键"detailed"更改时接收回调。 -> -> ​ 注意,只有在信号已连接且您至少读取过一次配置时,这个信号才会发出。 -> -> ​ 回调函数: -> -> ​ 使用`kdk_conf2_connect_signal()`注册"changed"信号的回调函数 - -> 参数 -> -> ​ key: 被更改的键名 - -### update - -> 声明 -> -> ​ updated() -> () - -> 描述 -> -> ​ 在对配置进行reload动作后,发送此信号 - -> 参数 -> -> ​ 无 \ No newline at end of file diff --git a/src/config/CMakeLists.txt b/src/config/CMakeLists.txt index 2224a42..ae2f6ad 100644 --- a/src/config/CMakeLists.txt +++ b/src/config/CMakeLists.txt @@ -1,8 +1,8 @@ aux_source_directory(. SOURCESCODE) -add_library(kysdk-config SHARED ${SOURCESCODE}) -set_target_properties(kysdk-config PROPERTIES VERSION 2.3.0 SOVERSION 2) +add_library(kyconf SHARED ${SOURCESCODE}) +set_target_properties(kyconf PROPERTIES VERSION 2.5.0 SOVERSION 1) add_executable(kyconf-test-struct test/test_structlist.c) -target_link_libraries(kyconf-test-struct kysdk-config) +target_link_libraries(kyconf-test-struct kyconf) # 包含 GNU 安装目录设置 include(GNUInstallDirs) @@ -18,7 +18,7 @@ else() set(CMAKE_INSTALL_LIBDIR "/usr/lib/${CMAKE_HOST_SYSTEM_PROCESSOR}-linux-gnu/") endif() # 安装库文件 -install(TARGETS kysdk-config +install(TARGETS kyconf DESTINATION ${CMAKE_INSTALL_LIBDIR}) # install(TARGETS kyconf diff --git a/src/config/Makefile b/src/config/Makefile new file mode 100644 index 0000000..fea3701 --- /dev/null +++ b/src/config/Makefile @@ -0,0 +1,20 @@ +OBJ=gsettingsparse.o jsonparse.o structparse.o xmlparse.o + +CFLAGS=-g -O0 -Wall -fPIC -I../ -I../utils/ -I../config/ +CLIBS=-lpthread +CC:=$(shell bash -c 'type $(CC) &> /dev/null && echo $(CC) || echo gcc') +TARGET=libkyconf.so +LIBINST=libkyconf.so.1.0.0 +LIBHEAD=kyconf.h +LIBINSTHEADER=/usr/include/kysdk/base/ + +all:$(OBJ) + $(CC) -o $(LIBINST) configure.c $(OBJ) $(CFLAGS) $(CLIBS) -shared + mkdir -p lib/ + mv -f $(LIBINST) lib/ + cd lib/ && ln -sf $(LIBINST) $(TARGET) && cd .. + -rm *.o &> /dev/null + +clean: + -rm *.o &> /dev/null + -rm ../lib/$(TARGET) &> /dev/null \ No newline at end of file diff --git a/src/diagnostics/CMakeLists.txt b/src/diagnostics/CMakeLists.txt index 9f16f9f..084d8cb 100644 --- a/src/diagnostics/CMakeLists.txt +++ b/src/diagnostics/CMakeLists.txt @@ -5,7 +5,7 @@ project(kydiagnostics LANGUAGES CXX) set(DIAGNOSTICS_TOP_DIR ${CMAKE_CURRENT_LIST_DIR}) add_library(${PROJECT_NAME} SHARED) -set_target_properties(kydiagnostics PROPERTIES VERSION 2.3.0 SOVERSION 1) +set_target_properties(kydiagnostics PROPERTIES VERSION 2.5.0 SOVERSION 1) target_compile_options(${PROJECT_NAME} PRIVATE -Wall -g) target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_11) diff --git a/src/diagnostics/libkydiagnostics.cpp b/src/diagnostics/libkydiagnostics.cpp index 19e1933..3327fc7 100644 --- a/src/diagnostics/libkydiagnostics.cpp +++ b/src/diagnostics/libkydiagnostics.cpp @@ -36,4 +36,4 @@ int kdk_buried_point(char *appName , char *messageType , KBuriedPoint *data , in } return -1; -} +} \ No newline at end of file diff --git a/src/diagnostics/test/testburiedpoint/main.c b/src/diagnostics/test/testburiedpoint/main.c index de18a8a..ef84c4e 100644 --- a/src/diagnostics/test/testburiedpoint/main.c +++ b/src/diagnostics/test/testburiedpoint/main.c @@ -41,4 +41,4 @@ int main(void) printf("buried point success !\n"); return 0; -} +} \ No newline at end of file diff --git a/src/gsettings/CMakeLists.txt b/src/gsettings/CMakeLists.txt index 4fe4659..d82c5b7 100755 --- a/src/gsettings/CMakeLists.txt +++ b/src/gsettings/CMakeLists.txt @@ -6,12 +6,12 @@ include_directories(${GTK3_INCLUDE_DIRS}) link_directories(${GTK3_LIBRARY_DIRS}) add_definitions(${GTK3_CFLAGS_OTHER}) -add_library(kysdk-gsetting SHARED ${SOURCESCODE}) -set_target_properties(kysdk-gsetting PROPERTIES VERSION 2.3.0 SOVERSION 2) +add_library(kygsetting SHARED ${SOURCESCODE}) +set_target_properties(kygsetting PROPERTIES VERSION 2.5.0 SOVERSION 1) add_executable(test-kygsetting test/test-gsetting.c) -target_link_libraries(kysdk-gsetting ${GTK3_LIBRARIES}) -target_link_libraries(test-kygsetting kysdk-gsetting) +target_link_libraries(kygsetting ${GTK3_LIBRARIES}) +target_link_libraries(test-kygsetting kygsetting) # install(TARGETS kygsetting # DESTINATION lib/kysdk/kysdk-base) @@ -30,7 +30,7 @@ else() set(CMAKE_INSTALL_LIBDIR "/usr/lib/${CMAKE_HOST_SYSTEM_PROCESSOR}-linux-gnu/") endif() # 安装库文件 -install(TARGETS kysdk-gsetting +install(TARGETS kygsetting DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(FILES libkygsetting.h diff --git a/src/log/CMakeLists.txt b/src/log/CMakeLists.txt index 0e05b97..a6f3d7c 100644 --- a/src/log/CMakeLists.txt +++ b/src/log/CMakeLists.txt @@ -4,19 +4,19 @@ include(FindPkgConfig) pkg_check_modules(DBus REQUIRED dbus-1) include_directories(${DBus_INCLUDE_DIRS}) -add_library(kysdk-log SHARED ${SOURCESCODE}) -set_target_properties(kysdk-log PROPERTIES VERSION 2.3.0 SOVERSION 2) +add_library(kylog SHARED ${SOURCESCODE}) +set_target_properties(kylog PROPERTIES VERSION 2.5.0 SOVERSION 1) add_executable(kylog-testlog test/test-log.c) add_executable(kylog-testsetdir test/test-setdir.c) add_executable(kylog-testpressure test/test-pressure.c) add_executable(kylog-testautowrap test/test-autowrap.c) find_library(SYSTEMD_LIB systemd) find_library(DBUS_LIB dbus-1) -target_link_libraries(kysdk-log kysdk-config pthread ${SYSTEMD_LIB} ${DBUS_LIB}) -target_link_libraries(kylog-testlog kysdk-log) -target_link_libraries(kylog-testsetdir kysdk-log) -target_link_libraries(kylog-testautowrap kysdk-log) -target_link_libraries(kylog-testpressure kysdk-log) +target_link_libraries(kylog kyconf pthread ${SYSTEMD_LIB} ${DBUS_LIB}) +target_link_libraries(kylog-testlog kylog) +target_link_libraries(kylog-testsetdir kylog) +target_link_libraries(kylog-testautowrap kylog) +target_link_libraries(kylog-testpressure kylog) # install(TARGETS kylog # DESTINATION lib/kysdk/kysdk-base) diff --git a/src/log/Makefile b/src/log/Makefile new file mode 100644 index 0000000..7a664a7 --- /dev/null +++ b/src/log/Makefile @@ -0,0 +1,20 @@ +OBJ=core.o format.o klog_mqueue.o kylog.o write.o writeFile.o + +CFLAGS=-g -O0 -Wall -fPIC -I../ -I../utils/ -I../config/ +# CLIBS=-lpthread -lsystemd +CC:=$(shell bash -c 'type $(CC) &> /dev/null && echo $(CC) || echo gcc') +TARGET=libkylog.so +LIBINST=libkylog.so.1.0.0 +LIBHEAD=kylog.h +LIBINSTHEADER=/usr/include/kylog/ + +all:$(OBJ) + $(CC) -o $(LIBINST) $(OBJ) $(CFLAGS) $(CLIBS) -shared + mkdir -p lib/ + mv -f $(LIBINST) lib/ + cd lib/ && ln -sf $(LIBINST) $(TARGET) && cd .. + -rm *.o &> /dev/null + +clean: + -rm *.o &> /dev/null + -rm ../lib/$(TARGET) &> /dev/null \ No newline at end of file diff --git a/src/log/test/Makefile b/src/log/test/Makefile index ce304da..2f52090 100644 --- a/src/log/test/Makefile +++ b/src/log/test/Makefile @@ -1,7 +1,7 @@ all: - gcc -o test-log test-log.c -g -O0 -I../ -I../../utils/ -L../lib -L../../config/lib/ -lkysdk-log -lkysdk-config -lpthread -lsystemd -Wl,-rpath=../lib:../../config/lib/ - gcc -o test-setdir test-setdir.c -g -O0 -I../ -I../../utils/ -L../lib -L../../config/lib/ -lkysdk-log -lkysdk-config -lpthread -lsystemd -Wl,-rpath=../lib:../../config/lib/ - gcc -o test-pressure test-pressure.c -g -O0 -I../ -I../../utils/ -L../lib -L../../config/lib/ -lkysdk-log -lkysdk-config -lpthread -lsystemd -Wl,-rpath=../lib:../../config/lib/ + gcc -o test-log test-log.c -g -O0 -I../ -I../../utils/ -L../lib -L../../config/lib/ -lkylog -lkyconf -lpthread -lsystemd -Wl,-rpath=../lib:../../config/lib/ + gcc -o test-setdir test-setdir.c -g -O0 -I../ -I../../utils/ -L../lib -L../../config/lib/ -lkylog -lkyconf -lpthread -lsystemd -Wl,-rpath=../lib:../../config/lib/ + gcc -o test-pressure test-pressure.c -g -O0 -I../ -I../../utils/ -L../lib -L../../config/lib/ -lkylog -lkyconf -lpthread -lsystemd -Wl,-rpath=../lib:../../config/lib/ clean: - -rm test-log test-setdir test-pressure + -rm test-log test-setdir test-pressure \ No newline at end of file diff --git a/src/timer/CMakeLists.txt b/src/timer/CMakeLists.txt index ebdf39c..d5f9d63 100644 --- a/src/timer/CMakeLists.txt +++ b/src/timer/CMakeLists.txt @@ -1,9 +1,9 @@ aux_source_directory(. SOURCESCODE) -add_library(kysdk-timer SHARED ${SOURCESCODE}) -set_target_properties(kysdk-timer PROPERTIES VERSION 2.3.0 SOVERSION 2) +add_library(kytimer SHARED ${SOURCESCODE}) +set_target_properties(kytimer PROPERTIES VERSION 2.5.0 SOVERSION 1) add_executable(test-kytimer test/test-kytimer.c) -target_link_libraries(kysdk-timer pthread) -target_link_libraries(test-kytimer kysdk-timer) +target_link_libraries(kytimer pthread) +target_link_libraries(test-kytimer kytimer) # install(TARGETS kytimer # DESTINATION lib/kysdk/kysdk-base) @@ -22,7 +22,7 @@ else() set(CMAKE_INSTALL_LIBDIR "/usr/lib/${CMAKE_HOST_SYSTEM_PROCESSOR}-linux-gnu/") endif() # 安装库文件 -install(TARGETS kysdk-timer +install(TARGETS kytimer DESTINATION ${CMAKE_INSTALL_LIBDIR}) # install(FILES libkytimer.h diff --git a/src/timer/Makefile b/src/timer/Makefile new file mode 100644 index 0000000..feb4fc1 --- /dev/null +++ b/src/timer/Makefile @@ -0,0 +1,26 @@ +CLIBS=-lpthread -lrt +CFLAGS=-g -O0 -Wall -fPIC -shared + +CC=cc +TARGET=libkytimer.so +LIBINSTALLNAME=libkytimer.so.1.0.0 +LIBINSTALLDIR=/usr/lib/ +HEADERINSTALLDIR=/usr/include/ +HEADERS=kytimer.h + +.PHONY:all +.PHONY:clean +.PHONY:lib + +all:lib + +lib: + $(CC) $(CFLAGS) $(CLIBS) -o $(TARGET) libkytimer.c + mkdir -p lib/ + mv $(TARGET) lib/$(LIBINSTALLNAME) + +clean: + -rm ../lib/$(LIBINSTALLNAME) + +target_install:TARGET + cp $(LIBINSTALLNAME) $(LIBINSTALLDIR) diff --git a/src/timer/test/Makefile b/src/timer/test/Makefile index 4331f2c..912767d 100644 --- a/src/timer/test/Makefile +++ b/src/timer/test/Makefile @@ -1,5 +1,5 @@ all: - gcc -g -O0 -o test-kytimer test-kytimer.c -lkysdk-timer -lpthread + gcc -g -O0 -o test-kytimer test-kytimer.c -lkytimer -lpthread clean: - rm demo + rm demo \ No newline at end of file diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index 77be7fc..4f99124 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -1,6 +1,6 @@ aux_source_directory(. SOURCESCODE) add_library(kyutils SHARED ${SOURCESCODE}) -set_target_properties(kyutils PROPERTIES VERSION 2.3.0 SOVERSION 2) +set_target_properties(kyutils PROPERTIES VERSION 2.5.0 SOVERSION 1) include_directories(.) # install(TARGETS kyutils # DESTINATION lib/kysdk/kysdk-base) diff --git a/src/utils/kyutils.c b/src/utils/kyutils.c index 45f523e..cdfc6c6 100644 --- a/src/utils/kyutils.c +++ b/src/utils/kyutils.c @@ -280,10 +280,11 @@ char *size_to_human_string(int options, uint64_t bytes, int base) // if (frac % 10 == 0) // frac /= 10; /* convert N.90 to N.9 */ sprintf(res, "%.2f", result); - frac = (frac / (1ULL << (exp - 10)) + 5) / 10; + double num = atof(res); + double ret = num - dec; + frac = ret * 100; if (frac % 10 == 0) - sprintf(res, "%.f", result); - + sprintf(res, "%.1f", result); } else { // frac = (frac / (1ULL << (exp - 10)) + 50) / 100; // if (frac == 10) diff --git a/src/utils/sample/kyutils_sample.c b/src/utils/sample/kyutils_sample.c index 726f579..f16701c 100644 --- a/src/utils/sample/kyutils_sample.c +++ b/src/utils/sample/kyutils_sample.c @@ -54,4 +54,4 @@ int main() printf("%.2f\n", result_numberical); return 0; -} +} \ No newline at end of file