From: José Bollo Date: Thu, 4 Dec 2014 12:32:01 +0000 (+0100) Subject: Initial commit X-Git-Tag: accepted/tizen/common/20150122.101956~4 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fappfw%2Fvconf-buxton.git;a=commitdiff_plain;h=c5a68fe925044c35fcb0c77c1b110881a9a8b979 Initial commit Change-Id: I9ca327b87ab77ab28136ffc0c20b3aec42450dcb Signed-off-by: José Bollo --- diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d12070d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,37 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(vconf-buxton C) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR ${LIB_INSTALL_DIR}) +SET(INCLUDEDIR "\${prefix}/include/vconf") +SET(VERSION_MAJOR 0) +SET(VERSION_MINOR 1) +SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.0") +SET(BINDIR "${PREFIX}/bin") +SET(SYSTEMDDIR "lib/systemd/system") + +set(CMAKE_SKIP_BUILD_RPATH true) + +SET(SRCS vconf-buxton.c) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED glib-2.0 vconf-internal-keys libbuxton) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +#ADD_DEFINITIONS("-Werror") +ADD_DEFINITIONS("-Wall") +#ADD_DEFINITIONS("-Wextra") +#ADD_DEFINITIONS("-ansi") +#ADD_DEFINITIONS("-pedantic") + +ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"") + +add_subdirectory(src) diff --git a/LICENSE.APLv2 b/LICENSE.APLv2 new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE.APLv2 @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packaging/vconf-buxton.manifest b/packaging/vconf-buxton.manifest new file mode 100644 index 0000000..017d22d --- /dev/null +++ b/packaging/vconf-buxton.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/vconf-buxton.spec b/packaging/vconf-buxton.spec new file mode 100644 index 0000000..efadc59 --- /dev/null +++ b/packaging/vconf-buxton.spec @@ -0,0 +1,91 @@ +# set overwrite_vconf by default +%bcond_without overwrite_vconf + +%if %{with overwrite_vconf} +%define libname vconf +%define toolname vconftool +%else +%define libname vconf-buxton +%define toolname vconf-buxton-tool +%endif + +Name: vconf-buxton +Summary: Configuration system library +Version: 0.1 +Release: 1 +Group: System/Libraries +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz +Source1001: vconf-buxton.manifest +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig +BuildRequires: cmake +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(libbuxton) +BuildRequires: pkgconfig(vconf-internal-keys) +Obsoletes: vconf + +%description +Configuration system library having vconf API and buxton backend + +%package devel +Summary: Vconf-buxton (devel) +Requires: %{name} = %{version}-%{release} +Requires: vconf-buxton = %{version}-%{release} +Requires: vconf-buxton-keys-devel = %{version}-%{release} +Obsoletes: vconf-devel + +%description devel +Vconf library (devel) + +%package keys-devel +Summary: Vconf-buxton (devel) +Requires: %{name} = %{version}-%{release} +Requires: vconf-buxton = %{version}-%{release} +Requires: vconf-internal-keys-devel +Obsoletes: vconf-keys-devel + +%description keys-devel +Vconf key management header files + +%prep +%setup -q -n %{name}-%{version} +cp %{SOURCE1001} . + +%build +%cmake -DLIBNAME:STRING=%{libname} -DTOOLNAME:STRING=%{toolname} . +make %{?jobs:-j%jobs} + +%install +%make_install +mv %{buildroot}%{_unitdir}/vconf-buxton-setup.service %{buildroot}%{_unitdir}/%{libname}-setup.service +mkdir -p %{buildroot}%{_unitdir}/basic.target.wants +ln -sf ../%{libname}-setup.service %{buildroot}%{_unitdir}/basic.target.wants/ + +%post +/sbin/ldconfig + +%postun +/sbin/ldconfig + +%files +%manifest %{name}.manifest +%license LICENSE.APLv2 +%{_bindir}/%{toolname} +%{_bindir}/vconf-buxton-init-from-vconf.sh +%{_bindir}/vconf-buxton-restore-mem-layer.sh +%{_bindir}/vconf-buxton-backup-mem-layer.sh +%{_libdir}/lib%{libname}.so.* +%{_unitdir}/basic.target.wants/%{libname}-setup.service +%{_unitdir}/%{libname}-setup.service + +%files devel +%manifest %{name}.manifest +%{_includedir}/vconf/vconf-buxton.h +%{_libdir}/pkgconfig/%{libname}.pc +%{_libdir}/lib%{libname}.so + +%files keys-devel +%manifest %{name}.manifest +%{_includedir}/vconf/vconf-buxton-keys.h + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..8e2701f --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,37 @@ + +SET(SRCS vconf-buxton.c) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,--version-script=vconf-buxton.sym") + +IF(NOT DEFINED LIBNAME) + SET(LIBNAME ${PROJECT_NAME}) +ENDIF() + +IF(NOT DEFINED TOOLNAME) + SET(TOOLNAME vconf-buxton-tool) +ENDIF() + + +ADD_LIBRARY(${LIBNAME} SHARED ${SRCS}) +SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES SOVERSION ${VERSION_MAJOR}) +SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES VERSION ${VERSION}) +TARGET_LINK_LIBRARIES(${LIBNAME} ${glib_pkg_LDFLAGS} ${pkgs_LDFLAGS}) + +ADD_EXECUTABLE(${TOOLNAME} vconf-buxton-tool.c) +TARGET_LINK_LIBRARIES(${TOOLNAME} ${pkgs_LDFLAGS} ${glib_pkg_LDFLAGS} ${LIBNAME}) + +CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${LIBNAME}.pc @ONLY) +SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${LIBNAME}.pc") + +INSTALL(TARGETS ${LIBNAME} DESTINATION ${LIB_INSTALL_DIR}) +INSTALL(TARGETS ${TOOLNAME} DESTINATION bin) +INSTALL(PROGRAMS ${CMAKE_SOURCE_DIR}/src/vconf-buxton-init-from-vconf.sh DESTINATION bin) +INSTALL(PROGRAMS ${CMAKE_SOURCE_DIR}/src/vconf-buxton-restore-mem-layer.sh DESTINATION bin) +INSTALL(PROGRAMS ${CMAKE_SOURCE_DIR}/src/vconf-buxton-backup-mem-layer.sh DESTINATION bin) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LIBNAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) +INSTALL(FILES ${CMAKE_SOURCE_DIR}/src/vconf-buxton.h DESTINATION include/vconf) +INSTALL(FILES ${CMAKE_SOURCE_DIR}/src/vconf-buxton-keys.h DESTINATION include/vconf) +INSTALL(FILES ${CMAKE_SOURCE_DIR}/src/vconf-buxton-setup.service DESTINATION ${SYSTEMDDIR}) + diff --git a/src/log.h b/src/log.h new file mode 100644 index 0000000..2161c8d --- /dev/null +++ b/src/log.h @@ -0,0 +1,103 @@ +/* + * libslp-setting + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hakjoo Ko + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __VCONF_BUXTON_LOG_H__ +#define __VCONF_BUXTON_LOG_H__ + +#include +#include +#include + + +/************** Error ***************/ +#ifdef VCONF_SYSLOG_OUT +#include + +#define INFO(fmt, arg...) \ + do { \ + syslog(LOG_INFO, "[%s:%d] "fmt"\n", __FILE__, __LINE__, ##arg); \ + }while(0) +#define ERR(fmt, arg...) \ + do { \ + syslog(LOG_ERR, "[%s:%d] "fmt"\n", __FILE__, __LINE__, ##arg); \ + }while(0) +#define WARN(fmt, arg...) \ + do { \ + syslog(LOG_ERR, "[%s:%d] "fmt"\n", __FILE__, __LINE__, ##arg); \ + }while(0) + +#else +#include + +#define INFO(fmt, arg...) \ + do { \ + fprintf(stdout,"[%s:%d] "fmt"\n", __FILE__, __LINE__, ##arg); \ + }while(0) +#define WARN(fmt, arg...) \ + do { \ + fprintf(stderr,"[%s:%d] "fmt"\n", __FILE__, __LINE__, ##arg); \ + }while(0) +#define ERR(fmt, arg...) \ + do { \ + fprintf(stderr,"[%s:%d] "fmt"\n", __FILE__, __LINE__, ##arg); \ + }while(0) +#endif + + +/************** Return ***************/ +#define ret_if(expr) \ + do { \ + if (expr) { \ + ERR("(%s) -> %s() return", #expr, __FUNCTION__); \ + return; \ + } \ + } while (0) +#define retv_if(expr, val) \ + do { \ + if (expr) { \ + ERR("(%s) -> %s() return", #expr, __FUNCTION__); \ + return (val); \ + } \ + } while (0) +#define retm_if(expr, fmt, arg...) \ + do { \ + if (expr) { \ + ERR(fmt, ##arg); \ + return; \ + } \ + } while (0) +#define retvm_if(expr, val, fmt, arg...) \ + do { \ + if (expr) { \ + ERR(fmt, ##arg); \ + return (val); \ + } \ + } while (0) +#define retex_if(expr, fmt, arg...) \ + do { \ + if (expr) { \ + ERR(fmt, ##arg); \ + goto CATCH; \ + } \ + } while (0) + + +#endif /* __VCONF_BUXTON_LOG_H__ */ diff --git a/src/vconf-buxton-backup-mem-layer.sh b/src/vconf-buxton-backup-mem-layer.sh new file mode 100755 index 0000000..6fd13cf --- /dev/null +++ b/src/vconf-buxton-backup-mem-layer.sh @@ -0,0 +1,79 @@ +#!/bin/bash +# +# This script backup the buxton system layer temp that is +# in memory to the system layer base. All keys are copied +# prefixed with memory_init/ . +# +# See vconf-buxton-restore-mem-layer.sh +# +# author: jose.bollo@open.eurogiciel.org + +layermem=temp +layerdb=base +groupmem=vconf +groupdb=vconf +label=User + +reset=$(printf '\e[0m') +red=$(printf '\e[1;31m') +green=$(printf '\e[1;32m') + +# +# check that buxton service is available +# +if ! buxtonctl -s check > /dev/null +then + echo "${red}ERROR: can not connect to buxton service${reset}" + exit 1 +fi + +# +# create the group for vconf +# +if buxtonctl -s list-groups "$layerdb" | grep -q "found group $groupdb" +then + echo "${green}group $groupdb already exists${reset}" +elif buxtonctl -s create-group "$layerdb" "$groupdb" +then + echo "${green}group $groupdb succesfully created${reset}" +else + echo "${red}ERROR: can't create group '$groupdb' for layer '$layerdb'${reset}" + exit 1 +fi + +# +# Ensure label for the group +# +if buxtonctl -s set-label "$layerdb" "$groupdb" "$label" +then + echo "${green}group $groupdb succesfully set to label '$label'${reset}" +else + echo "${red}ERROR: can't set label '$label' to group '$groupdb' for layer '$layerdb'${reset}" + exit 1 +fi + + +buxtonctl -s list-keys "$layermem" "$groupmem" | +sed 's:^found key ::' | +while read keymem +do + keydb="memory_init/$keymem" + if ! q=$(buxtonctl -s get "$layermem" "$groupmem" "$keymem") + then + echo "${red}ERROR can't get value of $keymem${reset}" + else + type=$(echo -n "$q" | sed 's/.* = \([^:]*\): .*/\1/') + value=$(echo -n "$q" | sed 's/.* = [^:]*: \(.*\)/\1/') + echo -n "${reset}setting $keydb, $type: $value ..." + if ! buxtonctl -s -- set-$type "$layerdb" "$groupdb" "$keydb" "$value" + then + echo "${red}ERROR WHILE SETTING VALUE${reset}" + elif ! buxtonctl -s set-label "$layerdb" "$groupdb" "$keydb" "$label" + then + echo "${red}ERROR WHILE SETTING LABEL${reset}" + else + echo "${green}done${reset}" + fi + fi +done + diff --git a/src/vconf-buxton-init-from-vconf.sh b/src/vconf-buxton-init-from-vconf.sh new file mode 100755 index 0000000..72e4b61 --- /dev/null +++ b/src/vconf-buxton-init-from-vconf.sh @@ -0,0 +1,101 @@ +#!/bin/bash +# +# This script initialize the buxton database with the values +# from the vconf database. +# +# author: jose.bollo@open.eurogiciel.org + +export LANG= +root=/usr/kdb + +layer=base +group=vconf +label=User + +reset=$(printf '\e[0m') +red=$(printf '\e[1;31m') +green=$(printf '\e[1;32m') + + +# +# create the default group for vconf +# +if buxtonctl list-groups "$layer" | grep -q "found group $group" +then + echo "${green}group $group already exists${reset}" +elif buxtonctl create-group "$layer" "$group" +then + echo "${green}group $group succesfully created${reset}" +else + echo "${red}ERROR: can't create group '$group' for layer '$layer'${reset}" + exit 1 +fi + +# +# Ensure label for the group +# +if buxtonctl set-label "$layer" "$group" "$label" +then + echo "${green}group $group succesfully set to label '$label'${reset}" +else + echo "${red}ERROR: can't set label '$label' to group '$group' for layer '$layer'${reset}" + exit 1 +fi + +# +# loop on keys of the vconf file system +# +find $root -type f | +while read file +do + key=${file#$root/} + # + # extract type and value of the key + # + ktype=$(head -c4 < $file | od -t d4 | awk '{print $2;exit}') + case $ktype in + 40) # string + type=string + value=$(tail -c+5 < $file | sed 's:\(\\\|"\):\\&:g') + ;; + 41) # integer + type=int32 + value=$(tail -c+5 < $file | od -t d4 | awk '{print $2;exit}') + ;; + 42) # double + type=double + value=$(tail -c+5 < $file | od -t f8 | awk '{print $2;exit}') + ;; + 43) # boolean + type=bool + value=$(tail -c+5 < $file | od -t d4 | awk '{print $2;exit}') + ;; + *) # not a known type + echo "${red}ERROR: unknown type $ktype for file $file${reset}" + continue + esac + # + # compute the layer + # + case "${key%%/*}" in + memory_init|db|file) + ;; + *) + echo "${red}ERROR not a valid key prefix $key${reset}" + continue + esac + # + # set the key to buxton + # + echo -n "${reset}setting [$layer.$group:$type] $key = $value ..." + if ! buxtonctl -- "set-$type" "$layer" "$group" "$key" "$value" + then + echo "${red}ERROR WHILE SETTING VALUE${reset}" + elif ! buxtonctl set-label "$layer" "$group" "$key" "$label" + then + echo "${red}ERROR WHILE SETTING LABEL${reset}" + else + echo "${green}done${reset}" + fi +done + diff --git a/src/vconf-buxton-keys.h b/src/vconf-buxton-keys.h new file mode 100644 index 0000000..272e1c6 --- /dev/null +++ b/src/vconf-buxton-keys.h @@ -0,0 +1,345 @@ +/* + * libslp-setting + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hakjoo Ko + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __VCONF_BUXTON_KEYS_H__ +#define __VCONF_BUXTON_KEYS_H__ + +#include "vconf-internal-keys.h" + +/** + * This file defines keys and values. + * + * @file vconf-keys.h + * @defgroup vconf_key Definitions of shared Keys + * @ingroup VCONF + * @author Hyungdeuk Kim (hd3.kim@samsung.com) + * @version 0.3 + * @brief This file has the definitions of shared keys. + * + * add keys(key name) and values(enum) here for shared keys.... + * + */ + +/* + * ========================== System Manager Notification + * ============================= + */ +/** + * @defgroup vconf_key_SystemManager System Manager Keys + * @ingroup vconf_key + * @addtogroup vconf_key_SystemManager + * @{ + * @brief Maintainer: giyeol.ok@samsung.com + */ + +/** + * @brief usbhost status + * + * 0 : Remove \n + * 1 : Add \n + * 2 : Over current \n + */ +#define VCONFKEY_SYSMAN_USB_HOST_STATUS "memory/sysman/usbhost_status" +enum { + VCONFKEY_SYSMAN_USB_HOST_DISCONNECTED = 0, + VCONFKEY_SYSMAN_USB_HOST_CONNECTED, + VCONFKEY_SYSMAN_USB_HOST_OVERCURRENT +}; + +/** + * @brief mmc status + * + * 0 : Remove \n + * 1 : mount \n + * 2 : insert(not mount) \n + */ +#define VCONFKEY_SYSMAN_MMC_STATUS "memory/sysman/mmc" +enum { + VCONFKEY_SYSMAN_MMC_REMOVED = 0, + VCONFKEY_SYSMAN_MMC_MOUNTED, + VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED +}; + +/** + * @brief earkey status + * + * 0 : not press \n + * 1 : press \n + */ +#define VCONFKEY_SYSMAN_EARJACKKEY "memory/sysman/earjack_key" + +/** + * @brief cradle status + * + * 0 : Remove \n + * 1 : Add \n + */ +#define VCONFKEY_SYSMAN_CRADLE_STATUS "memory/sysman/cradle_status" + +/** + * @} + */ + + +/* + * =============================== Wifi + * ====================================== + */ +/** + * @defgroup vconf_key_Wifi Wifi Keys + * @ingroup vconf_key + * @addtogroup vconf_key_Wifi + * @{ + * @brief Maintainer : dwmax.lee@samsung.com + */ + +/** + * @Wi-Fi Direct state + * + * 0: Power off \n + * 1: Power on \n + * 2: Discoverable mode \n + * 3: Connected with peer as GC \n + * 4: Connected with peer as GO + */ +#define VCONFKEY_WIFI_DIRECT_STATE "memory/wifi_direct/state" +enum { + /** Power off */ + VCONFKEY_WIFI_DIRECT_DEACTIVATED = 0, + /** Power on */ + VCONFKEY_WIFI_DIRECT_ACTIVATED, + /** Discoverable mode */ + VCONFKEY_WIFI_DIRECT_DISCOVERING, + /** Connected with peer as GC */ + VCONFKEY_WIFI_DIRECT_CONNECTED, + /** Connected with peer as GO */ + VCONFKEY_WIFI_DIRECT_GROUP_OWNER +}; + +/** + * @} + */ + + + +/* + * ================================= BT + * ===================================== + */ +/** + * @defgroup vconf_key_BT BT Keys + * @ingroup vconf_key + * @addtogroup vconf_key_BT + * @{ + * @brief Maintainer : chanyeol.park@samsung.com + */ + +/** \ + * @brief Bluetooth status + * + * 0x0000 : Bluetooth OFF \n + * 0x0001 : Bluetooth ON \n + * 0x0002 : Discoverable mode \n + * 0x0004 : In transfering \n +*/ +#define VCONFKEY_BT_STATUS "db/bluetooth/status" +enum { + /** Bluetooth OFF */ + VCONFKEY_BT_STATUS_OFF = 0x0000, + /** Bluetooth ON */ + VCONFKEY_BT_STATUS_ON = 0x0001, + /** Discoverable mode */ + VCONFKEY_BT_STATUS_BT_VISIBLE = 0x0002, + /** In transfering */ + VCONFKEY_BT_STATUS_TRANSFER = 0x0004 +}; + +/** + * @brief Bluetooth Connected status + * + * 0x0000 : Not connected \n + * 0x0001 : Headset connected \n + * 0x0002 : A2DP headset connected \n + * 0x0004 : HID connected \n + * 0x0008 : PAN connected \n + * 0x0010 : SAP connected \n + * 0x0020 : PBAP connected \n +*/ +#define VCONFKEY_BT_DEVICE "memory/bluetooth/device" +enum { + /** Not connected */ + VCONFKEY_BT_DEVICE_NONE = 0x0000, + /** Headset connected */ + VCONFKEY_BT_DEVICE_HEADSET_CONNECTED = 0x0001, + /** A2DP headset connected */ + VCONFKEY_BT_DEVICE_A2DP_HEADSET_CONNECTED = 0x0002, + /** HID connected */ + VCONFKEY_BT_DEVICE_HID_CONNECTED = 0x0004, + /** PAN connected */ + VCONFKEY_BT_DEVICE_PAN_CONNECTED = 0x0008, + /** SAP connected */ + VCONFKEY_BT_DEVICE_SAP_CONNECTED = 0x0010, + /** PBAP connected */ + VCONFKEY_BT_DEVICE_PBAP_CONNECTED = 0x0020 +}; + + +/* + * Media sound path for BT + */ +enum { + /** Media Player Select Speaker */ + VCONFKEY_BT_PLAYER_SELECT_SPEAKER = 0x00, + /** Media Player Select Bluetooth */ + VCONFKEY_BT_PLAYER_SELECT_BLUETOOTH = 0x01, + /** BT application Select Speaker */ + VCONFKEY_BT_APP_SELECT_SPEAKER = 0x02, + /** BT application Select Bluetooth */ + VCONFKEY_BT_APP_SELECT_BLUETOOTH = 0x04 +}; + +/** + * @} + */ + +/* + * =========================== IDLE lock + * ======================================= + */ +/** + * @defgroup vconf_key_idleLock idleLock Keys + * @ingroup vconf_key + * @addtogroup vconf_key_idleLock + * @{ + * @brief Maintainer : seungtaek.chung@samsung.com, wonil22.choi@samsung.com hyoyoung.chang@samsung.com angelkim@samsung.com + */ + +/** + * @brief lock screen status + * + * VCONFKEY_IDLE_UNLOCK : unlocked state \n + * VCONFKEY_IDLE_LOCK : locked state \n + */ +#define VCONFKEY_IDLE_LOCK_STATE "memory/idle_lock/state" +enum { + /** unlocked state */ + VCONFKEY_IDLE_UNLOCK = 0x00, + /** locked state */ + VCONFKEY_IDLE_LOCK +}; + +/** + * @brief wallpaper of lock screen + * + * Value : Wallpaper file path in the lock screen \n + */ +#define VCONFKEY_IDLE_LOCK_BGSET "db/idle_lock/bgset" + +/** + * @} + */ + + + +/* + * =========================== pwlock + * ======================================= + */ +/** + * @defgroup vconf_key_pwlock Lock application for password verification: phone, pin, sum, network, etc. + * @ingroup vconf_key + * @addtogroup vconf_key_pwlock + * @{ + * @brief Maintainer : seungtaek.chung@samsung.com miju52.lee@samsung.com + * Used module : pwlock + * + */ + +/** + * @brief mobex engine status + * + * VCONFKEY_PWLOCK_BOOTING_UNLOCK : unlocked state in boointg time \n + * VCONFKEY_PWLOCK_BOOTING_LOCK : locked state in boointg time \n + * VCONFKEY_PWLOCK_RUNNING_UNLOCK : unlocked state in running time \n + * VCONFKEY_PWLOCK_RUNNING_LOCK : locked state in running time \n + */ +#define VCONFKEY_PWLOCK_STATE "memory/pwlock/state" +enum { + /** unlocked state in boointg time */ + VCONFKEY_PWLOCK_BOOTING_UNLOCK = 0x00, + /** locked state in boointg time */ + VCONFKEY_PWLOCK_BOOTING_LOCK, + /** unlocked state in running time */ + VCONFKEY_PWLOCK_RUNNING_UNLOCK, + /** locked state in running time */ + VCONFKEY_PWLOCK_RUNNING_LOCK +}; +/** + * @} + */ + + + +/* + * =========================== browser + * ======================================= + */ +/** + * @defgroup vconf_key_browser browser public keys + * @ingroup vconf_key + * @addtogroup vconf_key_browser + * @{ + * @brief Maintainer : sangpyo7.kim@samsung.com ibchang@samsung.com + * + */ + +/** + * @brief browser user agent string + * + * Value : The user agent string currently being used by embeded browser \n + */ +#define VCONFKEY_BROWSER_USER_AGENT "db/browser/user_agent" + +/** + * @brief browser user agent profile + * + * Value : The user agent string profile currently being used by embeded browser for 2G network \n + */ +#define VCONFKEY_BROWSER_USER_AGENT_PROFILE_2G "db/browser/user_agent_profile_2G" + +/** + * @brief browser user agent profile + * + * Value : The user agent string profile currently being used by embeded browser for 3G network \n + */ +#define VCONFKEY_BROWSER_USER_AGENT_PROFILE_3G "db/browser/user_agent_profile_3G" + +/** + * @brief browser user agent profile + * + * Value : The user agent string profile currently being used by embeded browser for 4G network \n + */ +#define VCONFKEY_BROWSER_USER_AGENT_PROFILE_4G "db/browser/user_agent_profile_4G" + +/** + * @} + */ +#endif /* __VCONF_BUXTON_KEYS_H__ */ diff --git a/src/vconf-buxton-restore-mem-layer.sh b/src/vconf-buxton-restore-mem-layer.sh new file mode 100755 index 0000000..2a74517 --- /dev/null +++ b/src/vconf-buxton-restore-mem-layer.sh @@ -0,0 +1,79 @@ +#!/bin/bash +# +# This script initialize the buxton system layer temp (in memory) +# with values from the system layer base. It searchs the keys of +# prefix memory_init/ and copy their value to memory. +# +# See vconf-buxton-backup-mem-layer.sh +# +# author: jose.bollo@open.eurogiciel.org + +layerdb=base +layermem=temp +groupdb=vconf +groupmem=vconf +label=User + +reset=$(printf '\e[0m') +red=$(printf '\e[1;31m') +green=$(printf '\e[1;32m') + +# +# check that buxton service is available +# +if ! buxtonctl -s check > /dev/null +then + echo "${red}ERROR: can not connect to buxton service${reset}" + exit 1 +fi + +# +# create the group for in memory vconf +# +if buxtonctl -s list-groups "$layermem" | grep -q "found group $groupmem" +then + echo "${green}group $groupmem already exists${reset}" +elif buxtonctl -s create-group "$layermem" "$groupmem" +then + echo "${green}group $groupmem succesfully created${reset}" +else + echo "${red}ERROR: can't create group '$groupmem' for layer '$layermem'${reset}" + exit 1 +fi + +# +# Ensure label for the group +# +if buxtonctl -s set-label "$layermem" "$groupmem" "$label" +then + echo "${green}group $groupmem succesfully set to label '$label'${reset}" +else + echo "${red}ERROR: can't set label '$label' to group '$groupmem' for layer '$layermem'${reset}" + exit 1 +fi + + +buxtonctl -s list-keys "$layerdb" "$groupdb" memory_init/ | +sed 's:^found key ::' | +while read keydb +do + keymem=${keydb#memory_init/} + if ! q=$(buxtonctl -s get "$layerdb" "$groupdb" "$keydb") + then + echo "${red}ERROR can't get value of $keydb${reset}" + else + type=$(echo -n "$q" | sed 's/.* = \([^:]*\): .*/\1/') + value=$(echo -n "$q" | sed 's/.* = [^:]*: \(.*\)/\1/') + echo -n "${reset}setting $keymem, $type: $value ..." + if ! buxtonctl -s -- set-$type "$layermem" "$groupmem" "$keymem" "$value" + then + echo "${red}ERROR WHILE SETTING VALUE${reset}" + elif ! buxtonctl -s set-label "$layermem" "$groupmem" "$keymem" "$label" + then + echo "${red}ERROR WHILE SETTING LABEL${reset}" + else + echo "${green}done${reset}" + fi + fi +done + diff --git a/src/vconf-buxton-setup.service b/src/vconf-buxton-setup.service new file mode 100644 index 0000000..8fbed67 --- /dev/null +++ b/src/vconf-buxton-setup.service @@ -0,0 +1,14 @@ +[Unit] +Description=Initialize the vconf-buxton memory storage +DefaultDependencies=no +Requires=buxton.service +After=buxton.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/vconf-buxton-restore-mem-layer.sh +#ExecStop=/usr/bin/vconf-buxton-backup-mem-layer.sh + +[Install] +WantedBy=basic.target + diff --git a/src/vconf-buxton-tool.c b/src/vconf-buxton-tool.c new file mode 100644 index 0000000..8303911 --- /dev/null +++ b/src/vconf-buxton-tool.c @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2014 Intel Corporation + * + * Author: José Bollo + * Author: Hakjoo Ko + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include "vconf-buxton.h" +#include "log.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +enum +{ + VCONFTOOL_TYPE_NO = 0x00, + VCONFTOOL_TYPE_STRING, + VCONFTOOL_TYPE_INT, + VCONFTOOL_TYPE_DOUBLE, + VCONFTOOL_TYPE_BOOL +}; + +static char *guid = NULL; +static char *uid = NULL; +static char *vconf_type = NULL; +static int is_recursive = FALSE; +static int is_initialization = FALSE; +static int is_forced = FALSE; +static int get_num = 0; + +static GOptionEntry entries[] = { + {"type", 't', 0, G_OPTION_ARG_STRING, &vconf_type, "type of value", + "int|bool|double|string"}, + {"recursive", 'r', 0, G_OPTION_ARG_NONE, &is_recursive, + "retrieve keys recursively", NULL}, + {"guid", 'g', 0, G_OPTION_ARG_STRING, &guid, "group permission", NULL}, + {"uid", 'u', 0, G_OPTION_ARG_STRING, &uid, "user permission", NULL}, + {"initialization", 'i', 0, G_OPTION_ARG_NONE, &is_initialization, + "memory backend initialization", NULL}, + {"force", 'f', 0, G_OPTION_ARG_NONE, &is_forced, + "overwrite vconf values by force", NULL}, + {NULL} +}; + +static void get_operation (const char *input); +static void print_keylist (keylist_t * keylist); + +static char usage[] = + "Usage:\n" + "\n" + "[Set vconf value]\n" + " %1$s set -t \n" + " =int|bool|double|string\n" + "\n" + " Ex) %1$s set -t string db/testapp/key1 \"This is test\" \n" + "\n" + " \n" + " any option is ignored! (compatibility)\n" + "\n" + "[Get vconf value]\n" + " %1$s get \n" + "\n" + " \n" + " -r : retrieve all keys included in sub-directorys \n" + " Ex) %1$s get db/testapp/key1\n" + " %1$s get db/testapp/\n" + "\n" + "[Unset vconf value]\n" + " %1$s unset \n" + "\n" " Ex) %1$s unset db/testapp/key1\n" "\n" + "\n" + "[Set vconf label (Smack)]\n" + " %1$s label \n" + "\n" " Ex) %1$s label db/testapp/key1 User::Share\n" "\n"; + +static void +print_help (const char *cmd) +{ + fprintf (stderr, usage, cmd); +} + +static int +check_type (void) +{ + if (vconf_type) + { + if (!strncasecmp (vconf_type, "int", 3)) + return VCONFTOOL_TYPE_INT; + else if (!strncasecmp (vconf_type, "string", 6)) + return VCONFTOOL_TYPE_STRING; + else if (!strncasecmp (vconf_type, "double", 6)) + return VCONFTOOL_TYPE_DOUBLE; + else if (!strncasecmp (vconf_type, "bool", 4)) + return VCONFTOOL_TYPE_BOOL; + } + return VCONFTOOL_TYPE_NO; +} + +int +main (int argc, char **argv) +{ + int set_type; + + GError *error = NULL; + GOptionContext *context; + + context = g_option_context_new ("- vconf library tool"); + g_option_context_add_main_entries (context, entries, NULL); + g_option_context_set_help_enabled (context, FALSE); + g_option_context_set_ignore_unknown_options (context, TRUE); + + if (!g_option_context_parse (context, &argc, &argv, &error)) + { + g_print ("option parsing failed: %s\n", error->message); + exit (1); + } + + if (argc < 2) + { + print_help (argv[0]); + return 1; + } + + if (!strcmp (argv[1], "set")) + { + set_type = check_type (); + if (argc < 4 || !set_type) + { + print_help (argv[0]); + return 1; + } + + switch (set_type) + { + case VCONFTOOL_TYPE_STRING: + vconf_set_str (argv[2], argv[3]); + break; + case VCONFTOOL_TYPE_INT: + vconf_set_int (argv[2], atoi (argv[3])); + break; + case VCONFTOOL_TYPE_DOUBLE: + vconf_set_dbl (argv[2], atof (argv[3])); + break; + case VCONFTOOL_TYPE_BOOL: + vconf_set_bool (argv[2], !!atoi (argv[3])); + break; + default: + fprintf (stderr, "never reach"); + exit (1); + } + + } + else if (!strcmp (argv[1], "get")) + { + if (argv[2]) + get_operation (argv[2]); + else + print_help (argv[0]); + } + else if (!strcmp (argv[1], "unset")) + { + if (argv[2]) + vconf_unset (argv[2]); + else + print_help (argv[0]); + } + else if (!strcmp (argv[1], "label")) + { + if (argv[2] && argv[3]) + vconf_set_label (argv[2], argv[3]); + else + print_help (argv[0]); + } + else + fprintf (stderr, "%s is a invalid command\n", argv[1]); + return 0; +} + +static void +get_operation (const char *input) +{ + keylist_t *keylist; + + keylist = vconf_keylist_new (); + if (is_recursive) + { + vconf_scan (keylist, input, VCONF_GET_KEY_REC); + } + else + { + vconf_keylist_add_null (keylist, input); + vconf_refresh (keylist); + } + vconf_keylist_sort (keylist); + print_keylist (keylist); + if (!get_num) + printf ("No data\n"); + vconf_keylist_free (keylist); +} + +static void +print_keylist (keylist_t * keylist) +{ + keynode_t *node; + + vconf_keylist_rewind (keylist); + while ((node = vconf_keylist_nextnode (keylist))) + { + switch (vconf_keynode_get_type (node)) + { + case VCONF_TYPE_INT: + printf ("%s, value = %d (int)\n", + vconf_keynode_get_name (node), + vconf_keynode_get_int (node)); + get_num++; + break; + case VCONF_TYPE_BOOL: + printf ("%s, value = %d (bool)\n", + vconf_keynode_get_name (node), + vconf_keynode_get_bool (node)); + get_num++; + break; + case VCONF_TYPE_DOUBLE: + printf ("%s, value = %f (double)\n", + vconf_keynode_get_name (node), + vconf_keynode_get_dbl (node)); + get_num++; + break; + case VCONF_TYPE_STRING: + printf ("%s, value = %s (string)\n", + vconf_keynode_get_name (node), + vconf_keynode_get_str (node)); + get_num++; + break; + default: + break; + } + } +} diff --git a/src/vconf-buxton.c b/src/vconf-buxton.c new file mode 100644 index 0000000..3d9b196 --- /dev/null +++ b/src/vconf-buxton.c @@ -0,0 +1,2077 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2014 Intel Corporation + * + * Author: José Bollo + * Author: Hakjoo Ko + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * Note on conditionnal compilation: The following defines are controlling the compilation. + * + * NO_MULTITHREADING + * Defining NO_MULTITHREADING removes multithreading support. + * Defining it is not a good idea. + * + * NO_GLIB + * Defining NO_GLIB removes support of GLIB main loop used for notification + * Defining it implies to dig code to find some replacement (new API verbs to create). + * + * REMOVE_PREFIXES + * Removes the prefixe of the keys depending (depends on the layer). + * Defining it is not a good idea. + * + * The best is to not define any of the conditional value and let use the default. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#if !defined(NO_GLIB) +#include +#endif +#if !defined(NO_MULTITHREADING) +#include +#endif + +#include "vconf-buxton.h" +#include "log.h" + +#define VCONF_OK 0 +#define VCONF_ERROR -1 + +/*================= SECTION definition of types =============*/ + +/* + * internal types for keys + */ +enum keytype +{ + type_unset, /* type unset or unknown */ + type_directory, /* a directory, not a real key */ + type_delete, /* key to be deleted */ + type_string, /* key of type string */ + type_int, /* key of type integer */ + type_double, /* key of type double */ + type_bool /* key of type boolean */ +}; + +/* + * union for storing values + */ +union keyvalue +{ + int i; /* storage of integers */ + int b; /* storage of booleans */ + double d; /* storage of doubles */ + char *s; /* storage of strings */ +}; + +/* + * structure for keys + */ +struct _keynode_t +{ + enum keytype type; /* type of the key */ + union keyvalue value; /* value of the key */ + keynode_t *next; /* linking to the next key */ + keylist_t *list; /* the containing list */ + const char *keyname; /* name of the key */ +}; + +/* + * structure for list of keys + */ +struct _keylist_t +{ + int num; /* count of keys in the list */ + keynode_t *head; /* first key of the list */ + keynode_t *cursor; /* iterator on keys for clients */ + int cb_active; /* callback global activity */ + int cb_status; /* callback global status */ + unsigned cb_sent; /* callback global count of sent queries */ + unsigned cb_received; /* callback global count of + * received responses */ +}; + +/* + * data for the callback of scanning + */ +struct scanning_data +{ + int pending; /* is the scan pending? */ + int cb_status; /* status of the call back */ + int want_directories; /* is scanning directories? */ + int want_keys; /* is scanning keys? */ + int is_recursive; /* is scanning recursively? */ + size_t dirlen; /* length of the directory */ + keylist_t *keylist; /* keylist to fill */ + const char *prefix; /* prefix to add in front of names */ + const char *directory; /* scanned directory */ +}; + +/* + * data when translating vconf names to buxton names. ** the rule is that + * name == prefix/key + */ +struct layer_key +{ + const char *layer; /* identified layer-name */ + const char *prefix; /* vconf prefix of the name (without + * trailing /) */ + const char *key; /* buxton key-name (without leading /) */ +}; + +/* + * singleton data for facilities + */ +struct singleton +{ + keylist_t list; /* the list */ + keynode_t node; /* its single node */ +}; + +/* + * structure for notifications + */ +struct notify +{ + int status; /* callback status */ + vconf_callback_fn callback; /* the user callback */ + void *userdata; /* the user data */ + keynode_t *keynode; /* the recorded key node */ + struct notify *next; /* tink to the next notification */ +}; + +/*================= SECTION local variables =============*/ + +/* + * maximum length of key-names + */ +static size_t keyname_maximum_length = 2030; + +/* + * maximum length of group-names + */ +static size_t keygroup_maximum_length = 1010; + +/* + * association from prefixes to layers + */ +static const char *assoc_prefix_layer[][2] = { + {"db", "base"}, + {"file", "base"}, + {"memory", "temp"}, + {"memory_init", "base"}, + {"user", "user"}, + {NULL, NULL} +}; + +/* + * default timeout in scanning responses + */ +static int default_timeout = 5000; /* in milliseconds */ + +/* + * instance of the buxton client + */ +static BuxtonClient the_buxton_client = 0; + +/* + * the file handle number for polling buxton events + */ +static int the_buxton_client_fd = 0; + +/* + * flag indacating if the buxton client is set or not + */ +static char the_buxton_client_is_set = 0; + +/* + * the group to use if default group is unset + */ +static const char initial_default_group[] = "vconf"; + +/* + * the default group to use + */ +static char *default_group = NULL; + +/* + * the notify keylist + */ +static keylist_t *notify_keylist = NULL; + +/* + * the notify entries + */ +static struct notify *notify_entries = NULL; + +/* + * the count of lists + */ +static int internal_list_count = 0; + +#if !defined(NO_GLIB) +/* + * link to the glib main loop + */ +static GSource *glib_source = NULL; +#endif + +#if !defined(NO_MULTITHREADING) +/* + * multithreaded protection + * CAUTION: always use the given order! + */ +static pthread_mutex_t mutex_notify = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t mutex_counter = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t mutex_buxton = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t mutex_group = PTHREAD_MUTEX_INITIALIZER; +#define LOCK(x) pthread_mutex_lock(&mutex_##x) +#define UNLOCK(x) pthread_mutex_unlock(&mutex_##x) +#else +#define LOCK(x) +#define UNLOCK(x) +#endif + +/*================= SECTION utils =============*/ + +/* + * duplication of a string with validation of the length + */ +static inline char * +_dup_ (const char *source, size_t maxlen, const char *tag) +{ + size_t length; + char *result; + + assert (source != NULL); + length = strlen (source); + if (length >= maxlen) + { + ERR ("Invalid argument: %s is too long", tag); + return NULL; + } + result = malloc (++length); + if (result == NULL) + { + ERR ("Can't allocate memory for %s", tag); + return NULL; + } + memcpy (result, source, length); + return result; +} + +/*================= SECTION groupname utils =============*/ + +static inline char * +_dup_groupname_ (const char *groupname) +{ + return _dup_ (groupname, keygroup_maximum_length, "group-name"); +} + +static inline int +_ensure_default_group_ () +{ + int result = VCONF_OK; + + LOCK (group); + if (default_group == NULL) + { + default_group = _dup_groupname_ (initial_default_group); + if (default_group == NULL) + result = VCONF_ERROR; + } + UNLOCK (group); + + return result; +} + +/*================= SECTION key utils =============*/ + +static inline void +_keynode_free_ (keynode_t * keynode) +{ + assert (keynode != NULL); + if (keynode->type == type_string) + free (keynode->value.s); + free (keynode); +} + +static inline size_t +_check_keyname_ (const char *keyname) +{ + size_t result; + + assert (keyname != NULL); + + if (*keyname == '/') + { + return 0; + } + + for (result = 0; keyname[result]; result++) + { + if (keyname[result] == '/' && keyname[result + 1] == '/') + { + return 0; + } + } + + return result; +} + +/*================= SECTION list utils =============*/ + +/* + * search in 'keylist' an entry of 'keyname' and return it if found or + * NULL if not found. 'previous' if not NULL and if the entry is found + * will recieve the address of the pointer referencing the returned node. + */ +static inline keynode_t * +_keylist_lookup_ (keylist_t * keylist, + const char *keyname, keynode_t *** previous) +{ + keynode_t *node, **prev; + size_t length = 1 + strlen (keyname); + + prev = &keylist->head; + node = keylist->head; + while (node) + { + assert (node->keyname != NULL); + if (!memcmp (keyname, node->keyname, length)) + { + if (previous) + *previous = prev; + return node; + } + + prev = &node->next; + node = node->next; + } + return NULL; +} + +static inline keynode_t * +_keylist_add_ (keylist_t * keylist, const char *keyname, enum keytype type) +{ + keynode_t *result; + char *name; + size_t length; + + /* + * not found, create it + */ + length = _check_keyname_ (keyname); + retvm_if (!length, NULL, "invalid keyname"); + retvm_if (length > keyname_maximum_length, NULL, "keyname too long"); + result = malloc (1 + length + sizeof *result); + retvm_if (result == NULL, NULL, "allocation of keynode failed"); + result->type = type; + result->value.s = NULL; + + result->list = keylist; + name = (char *) (result + 1); + result->keyname = name; + memcpy (name, keyname, length + 1); + + result->next = keylist->head; + keylist->head = result; + keylist->num++; + + return result; +} + +static inline keynode_t * +_keylist_getadd_ (keylist_t * keylist, const char *keyname, enum keytype type) +{ + keynode_t *result; + + /* + * search keynode of keyname + */ + result = _keylist_lookup_ (keylist, keyname, NULL); + if (result == NULL) + { + /* + * not found, create it + */ + result = _keylist_add_ (keylist, keyname, type); + } + else if (result->type != type) + { + if (result->type == type_string) + free (result->value.s); + result->type = type; + result->value.s = NULL; + } + return result; +} + +static inline int +_keylist_init_singleton_ (struct singleton *singleton, const char *keyname, + enum keytype type) +{ + int status; + + if (!_check_keyname_ (keyname)) + { + ERR ("Invalid key name(%s)", keyname); + return VCONF_ERROR; + } + status = _ensure_default_group_ (); + if (status != VCONF_OK) + return status; + + memset (singleton, 0, sizeof *singleton); + singleton->list.num = 1; + singleton->list.head = &singleton->node; + singleton->node.keyname = keyname; + singleton->node.type = type; + singleton->node.list = &singleton->list; + + return VCONF_OK; +} + + +/*================= SECTION buxton =============*/ + +static void +_check_close_buxton_ () +{ + BuxtonClient bc; + + LOCK (notify); + LOCK (counter); + if (internal_list_count == 0 && notify_entries == NULL) + if (internal_list_count == 0 && notify_entries == NULL) + { + LOCK (buxton); + bc = the_buxton_client; + the_buxton_client_is_set = 0; + the_buxton_client = NULL; + the_buxton_client_fd = -1; + UNLOCK (buxton); + if (bc) + buxton_close (bc); + } + UNLOCK (counter); + UNLOCK (notify); +} + +static void +_try_to_open_buxton_ () +{ + the_buxton_client_fd = buxton_open (&the_buxton_client); + if (the_buxton_client_fd < 0) + { + ERR ("can't connect to buxton server: %m"); + errno = ENOTCONN; + the_buxton_client = NULL; + } +} + +static inline int +_open_buxton_ () +{ + LOCK (buxton); + if (!the_buxton_client_is_set) + { + /* + * first time, try to connect to buxton + */ + the_buxton_client_is_set = 1; + _try_to_open_buxton_ (); + } + UNLOCK (buxton); + return the_buxton_client != NULL; +} + + +static inline BuxtonClient +_buxton_ () +{ + BuxtonClient result = the_buxton_client; + assert (result != NULL); + return result; +} + +static inline int +_handle_buxton_response_ (int lock) +{ + int result; + + if (lock) + LOCK (buxton); + result = buxton_client_handle_response (_buxton_ ()); + if (result < 0) + ERR ("Error in buxton_client_handle_response: %m"); + if (lock) + UNLOCK (buxton); + return result; +} + +static inline int +_dispatch_buxton_ (int writing, int lock) +{ + int status; + struct pollfd pfd; + + assert (_buxton_ () != NULL); + + pfd.fd = the_buxton_client_fd; + pfd.events = writing ? POLLIN | POLLOUT : POLLIN; + for (;;) + { + pfd.revents = 0; + status = poll (&pfd, 1, default_timeout); + if (status == -1) + { + if (errno != EINTR) + { + return VCONF_ERROR; + } + } + else if (status == 1) + { + if (pfd.revents & POLLIN) + { + status = _handle_buxton_response_ (lock); + if (status < 0) + { + return VCONF_ERROR; + } + if (!writing) + { + return VCONF_OK; + } + } + if (pfd.revents & POLLOUT) + { + return VCONF_OK; + } + else + { + return VCONF_ERROR; + } + } + } +} + +static inline int +_wait_buxton_response_ (int *pending) +{ + int result; + + do + { + result = _dispatch_buxton_ (0, 1); + } + while (result == VCONF_OK && *pending); + return result; +} + +static inline int +_get_layer_key_ (const char *keyname, struct layer_key *laykey) +{ + int i, j; + const char *prefix; + + /* + * get the names + */ + i = 0; + prefix = assoc_prefix_layer[i][0]; + while (prefix != NULL) + { + for (j = 0; prefix[j] && prefix[j] == keyname[j]; j++); + if (!prefix[j] && (!keyname[j] || keyname[j] == '/')) + { + laykey->prefix = prefix; + laykey->layer = assoc_prefix_layer[i][1]; +#if defined(REMOVE_PREFIXES) + laykey->key = keyname + j + (keyname[j] == '/'); +#else + laykey->key = keyname; +#endif + return VCONF_OK; + } + i++; + prefix = assoc_prefix_layer[i][0]; + } + ERR ("Invalid argument: wrong prefix of key(%s)", keyname); + return VCONF_ERROR; +} + +static inline BuxtonKey +_get_buxton_key_ (keynode_t * node) +{ + BuxtonDataType type; + struct layer_key laykey; + + /* + * get layer and key + */ + if (_get_layer_key_ (node->keyname, &laykey) != VCONF_OK) + { + return NULL; + } + + /* + * get type + */ + switch (node->type) + { + case type_string: + type = BUXTON_TYPE_STRING; + break; + case type_int: + type = BUXTON_TYPE_INT32; + break; + case type_double: + type = BUXTON_TYPE_DOUBLE; + break; + case type_bool: + type = BUXTON_TYPE_BOOLEAN; + break; + default: + type = BUXTON_TYPE_UNSET; + } + + return buxton_key_create (default_group, laykey.key, laykey.layer, type); +} + +/*================= SECTION set/unset/refresh =============*/ + +static void +_cb_inc_received_ (BuxtonResponse resp, keynode_t * keynode) +{ + keylist_t *list; + + assert (keynode != NULL); + assert (keynode->list != NULL); + + list = keynode->list; + list->cb_received++; + if (buxton_response_status (resp) != 0) + { + ERR ("Buxton returned error %d for key %s", + buxton_response_status (resp), keynode->keyname); + list->cb_status = VCONF_ERROR; + } +} + +static int +_set_response_to_keynode_ (BuxtonResponse resp, keynode_t * keynode, + int force) +{ + enum keytype type; + BuxtonDataType buxtyp; + void *buxval; + + assert (keynode != NULL); + assert (buxton_response_status (resp) == 0); + + buxtyp = buxton_response_value_type (resp); + switch (buxtyp) + { + case BUXTON_TYPE_STRING: + type = type_string; + break; + case BUXTON_TYPE_INT32: + type = type_int; + break; + case BUXTON_TYPE_DOUBLE: + type = type_double; + break; + case BUXTON_TYPE_BOOLEAN: + type = type_bool; + break; + default: + return VCONF_ERROR; + } + + if (force && type != keynode->type && keynode->type != type_unset) + return VCONF_ERROR; + + buxval = buxton_response_value (resp); + if (buxval == NULL) + return VCONF_ERROR; + + if (keynode->type == type_string) + free (keynode->value.s); + + keynode->type = type; + switch (type) + { + case type_string: + keynode->value.s = buxval; + return VCONF_OK; + case type_int: + keynode->value.i = (int) *(int32_t *) buxval; + break; + case type_double: + keynode->value.d = *(double *) buxval; + break; + case type_bool: + keynode->value.b = *(bool *) buxval; + break; + default: + assert (0); + break; + } + free (buxval); + return VCONF_OK; +} + +static void +_cb_refresh_ (BuxtonResponse resp, keynode_t * keynode) +{ + keylist_t *list; + + assert (keynode != NULL); + assert (keynode->list != NULL); + assert (buxton_response_type (resp) == BUXTON_CONTROL_GET); + + list = keynode->list; + list->cb_received++; + if (buxton_response_status (resp) != 0) + { + ERR ("Error %d while getting buxton key %s", + buxton_response_status (resp), keynode->keyname); + list->cb_status = VCONF_ERROR; + } + else if (_set_response_to_keynode_ (resp, keynode, 0) != VCONF_OK) + { + list->cb_status = VCONF_ERROR; + } +} + +static void +_cb_scan_ (BuxtonResponse resp, struct scanning_data *data) +{ + char *buxname; + char *name; + char *term; + uint32_t count; + uint32_t index; + keylist_t *keylist; + keynode_t *keynode; + int length; + + data->pending = 0; + + /* + * check the response status + */ + if (buxton_response_status (resp) != 0) + { + ERR ("Error while getting list of names from buxton"); + data->cb_status = VCONF_ERROR; + return; + } + + /* + * iterate on the list of names + */ + assert (data->directory[data->dirlen - 1] == '/'); + keylist = data->keylist; + count = buxton_response_list_names_count (resp); + index = 0; + while (index < count) + { + /* + * get the name + */ + buxname = buxton_response_list_names_item (resp, index++); + if (buxname == NULL) + { + ERR ("Unexpected NULL name returned by buxton"); + data->cb_status = VCONF_ERROR; + return; + } + + /* + * normalise the name + */ +#if defined(REMOVE_PREFIXES) + length = asprintf (&name, "%s/%s", data->prefix, buxname); +#else + length = asprintf (&name, "%s", buxname); +#endif + free (buxname); + if (length < 0) + { + ERR ("Memory allocation error"); + data->cb_status = VCONF_ERROR; + return; + } + assert (_check_keyname_ (name)); + assert (!memcmp (data->directory, name, data->dirlen)); + + /* + * add key if requested + */ + term = strchr (name + data->dirlen, '/'); + if (data->want_keys && (data->is_recursive || term == NULL)) + { + keynode = _keylist_getadd_ (keylist, name, type_unset); + if (keynode == NULL) + { + free (name); + data->cb_status = VCONF_ERROR; + return; + } + } + + /* + * add directories if requested + */ + if (data->want_directories) + { + while (term != NULL) + { + *term = 0; + keynode = _keylist_getadd_ (keylist, name, type_directory); + if (keynode == NULL) + { + free (name); + data->cb_status = VCONF_ERROR; + return; + } + if (!data->is_recursive) + { + break; + } + *term = '/'; + term = strchr (term + 1, '/'); + } + } + + free (name); + } + data->cb_status = VCONF_OK; +} + + +static inline int +_async_set_ (keynode_t * keynode) +{ + void *data; + int status; + BuxtonKey key; + + assert (keynode != NULL); + + switch (keynode->type) + { + case type_string: + data = keynode->value.s; + break; + case type_int: + case type_double: + case type_bool: + data = &keynode->value; + break; + default: + return 0; + } + + key = _get_buxton_key_ (keynode); + if (key == NULL) + { + return -1; + } + + status = buxton_set_value (_buxton_ (), key, + data, + (BuxtonCallback) _cb_inc_received_, keynode, + false); + buxton_key_free (key); + + if (status == 0) + { + return 1; + } + + ERR ("Error while calling buxton_set_value: %m"); + return -1; +} + +static inline int +_async_unset_ (keynode_t * keynode) +{ + int status; + BuxtonKey key; + + assert (keynode != NULL); + + if (keynode->type != type_delete) + { + return 0; + } + + key = _get_buxton_key_ (keynode); + if (key == NULL) + { + return -1; + } + + status = buxton_unset_value (_buxton_ (), key, + (BuxtonCallback) _cb_inc_received_, + keynode, false); + buxton_key_free (key); + + if (status == 0) + { + return 1; + } + + ERR ("Error while calling buxton_unset_value: %m"); + return -1; +} + +static inline int +_async_set_or_unset_ (keynode_t * keynode, const char *unused) +{ + assert (keynode != NULL); + + switch (keynode->type) + { + case type_unset: + case type_directory: + return 0; + case type_delete: + return _async_unset_ (keynode); + default: + return _async_set_ (keynode); + } +} + +static inline int +_async_refresh_ (keynode_t * keynode, const char *unused) +{ + int status; + BuxtonKey key; + + assert (keynode != NULL); + + switch (keynode->type) + { + case type_unset: + case type_string: + case type_int: + case type_double: + case type_bool: + break; + default: + return 0; + } + + key = _get_buxton_key_ (keynode); + if (key == NULL) + { + return -1; + } + + status = buxton_get_value (_buxton_ (), key, + (BuxtonCallback) _cb_refresh_, keynode, false); + buxton_key_free (key); + + if (status == 0) + { + return 1; + } + + ERR ("Error while calling buxton_get_value: %m"); + return -1; +} + +static inline int +_async_set_label_ (keynode_t * keynode, const char *label) +{ + int status; + BuxtonKey key; + + assert (keynode != NULL); + + key = _get_buxton_key_ (keynode); + if (key == NULL) + { + return -1; + } + + status = buxton_set_label (_buxton_ (), key, label, + (BuxtonCallback) _cb_inc_received_, + keynode, false); + buxton_key_free (key); + + if (status == 0) + { + return 1; + } + + ERR ("Error while calling buxton_set_label: %m"); + return -1; +} + + +static int +_apply_buxton_on_list_ (keylist_t * keylist, + int (*async) (keynode_t *, const char *), + const char *data) +{ + keynode_t *keynode; + int status; + int sent; + + assert (keylist != NULL); + + status = _open_buxton_ (); + retvm_if (!status, VCONF_ERROR, "Can't connect to buxton"); + assert (_buxton_ () != NULL); + + retvm_if (keylist->cb_active != 0, VCONF_ERROR, + "Already active in vconf-buxton"); + + LOCK(buxton); + + keylist->cb_active = 1; + keylist->cb_status = VCONF_OK; + keylist->cb_sent = 0; + keylist->cb_received = 0; + + keynode = keylist->head; + status = _dispatch_buxton_ (1, 0); + while (keynode != NULL && status == VCONF_OK) + { + sent = async (keynode, data); + keynode = keynode->next; + if (sent < 0) + { + status = VCONF_ERROR; + } + else if (sent > 0) + { + keylist->cb_sent += sent; + status = _dispatch_buxton_ (1, 0); + } + } + + /* + * get the responses + */ + while (status == VCONF_OK && keylist->cb_sent != keylist->cb_received) + { + status = _dispatch_buxton_ (0, 0); + } + + if (status == VCONF_OK && keylist->cb_status != VCONF_OK) + status = keylist->cb_status; + keylist->cb_active = 0; + + UNLOCK(buxton); + + _check_close_buxton_ (); + + return status; +} + +/*================= SECTION notification =============*/ + +static void +_cb_notify_ (BuxtonResponse resp, struct notify *notif) +{ + switch (buxton_response_type (resp)) + { + case BUXTON_CONTROL_NOTIFY: + case BUXTON_CONTROL_UNNOTIFY: + notif->status = + buxton_response_status (resp) == 0 ? VCONF_OK : VCONF_ERROR; + break; + case BUXTON_CONTROL_CHANGED: + if (_set_response_to_keynode_ (resp, notif->keynode, 1) == VCONF_OK) + { + UNLOCK (buxton); + notif->callback (notif->keynode, notif->userdata); + LOCK (buxton); + } + break; + default: + break; + } +} + +static int +_notify_reg_unreg_ (struct notify *notif, bool reg) +{ + int status; + BuxtonKey key; + + status = _open_buxton_ (); + retvm_if (!status, VCONF_ERROR, "Can't connect to buxton"); + + LOCK(buxton); + key = _get_buxton_key_ (notif->keynode); + retvm_if (key == NULL, VCONF_ERROR, "Can't create buxton key"); + notif->status = VCONF_OK; /* on success calback isn't called! */ + status = + (reg ? buxton_register_notification : + buxton_unregister_notification) (_buxton_ (), key, + (BuxtonCallback) _cb_notify_, + notif, false); + buxton_key_free (key); + UNLOCK(buxton); + return status == 0 && notif->status == VCONF_OK ? VCONF_OK : VCONF_ERROR; +} + +#if !defined(NO_GLIB) +/*================= SECTION glib =============*/ + +static gboolean +_cb_glib_ (GIOChannel * src, GIOCondition cond, gpointer data) +{ + _handle_buxton_response_ (1); + return G_SOURCE_CONTINUE; +} + +static int +_glib_start_watch_ () +{ + GIOChannel *gio; + + if (glib_source != NULL) + return VCONF_OK; + + gio = g_io_channel_unix_new (the_buxton_client_fd); + retvm_if (gio == NULL, VCONF_ERROR, "Error: create a new GIOChannel"); + + g_io_channel_set_flags (gio, G_IO_FLAG_NONBLOCK, NULL); + + glib_source = g_io_create_watch (gio, G_IO_IN); + if (glib_source == NULL) + { + ERR ("Error: create a new GSource"); + g_io_channel_unref (gio); + return VCONF_ERROR; + } + + g_source_set_callback (glib_source, (GSourceFunc) _cb_glib_, NULL, NULL); + g_source_attach (glib_source, NULL); + g_io_channel_unref (gio); + g_source_unref (glib_source); + + return VCONF_OK; +} + +static void +_glib_stop_watch_ () +{ + if (glib_source != NULL) + { + g_source_destroy (glib_source); + glib_source = NULL; + } +} +#endif + +/*================= SECTION VCONF API =============*/ + +const char * +vconf_keynode_get_name (keynode_t * keynode) +{ + retvm_if (keynode == NULL, NULL, "Invalid argument: keynode is NULL"); + retvm_if (keynode->keyname == NULL, NULL, "The name of keynode is NULL"); + + return keynode->keyname; +} + +int +vconf_keynode_get_type (keynode_t * keynode) +{ + retvm_if (keynode == NULL, + VCONF_ERROR, "Invalid argument: keynode is NULL"); + + switch (keynode->type) + { + case type_directory: + return VCONF_TYPE_DIR; + case type_string: + return VCONF_TYPE_STRING; + case type_int: + return VCONF_TYPE_INT; + case type_double: + return VCONF_TYPE_DOUBLE; + case type_bool: + return VCONF_TYPE_BOOL; + default: + return VCONF_TYPE_NONE; + } +} + +int +vconf_keynode_get_int (keynode_t * keynode) +{ + retvm_if (keynode == NULL, + VCONF_ERROR, "Invalid argument: keynode is NULL"); + retvm_if (keynode->type != type_int, VCONF_ERROR, + "The type of keynode(%s) is not INT", keynode->keyname); + + return keynode->value.i; +} + +double +vconf_keynode_get_dbl (keynode_t * keynode) +{ + retvm_if (keynode == NULL, -1.0, "Invalid argument: keynode is NULL"); + retvm_if (keynode->type != type_double, -1.0, + "The type of keynode(%s) is not DBL", keynode->keyname); + + return keynode->value.d; +} + +int +vconf_keynode_get_bool (keynode_t * keynode) +{ + retvm_if (keynode == NULL, + VCONF_ERROR, "Invalid argument: keynode is NULL"); + retvm_if (keynode->type != type_bool, VCONF_ERROR, + "The type of keynode(%s) is not BOOL", keynode->keyname); + + return !!(keynode->value.b); +} + +char * +vconf_keynode_get_str (keynode_t * keynode) +{ + retvm_if (keynode == NULL, NULL, "Invalid argument: keynode is NULL"); + retvm_if (keynode->type != type_string, NULL, + "The type of keynode(%s) is not STR", keynode->keyname); + + return keynode->value.s; +} + +int +vconf_set_default_group (const char *groupname) +{ + char *copy; + + copy = _dup_groupname_ (groupname); + if (copy == NULL) + return VCONF_ERROR; + free (default_group); + default_group = copy; + return VCONF_OK; +} + +keylist_t * +vconf_keylist_new () +{ + keylist_t *result; + if (_ensure_default_group_ () != VCONF_OK) + return NULL; + result = calloc (1, sizeof (keylist_t)); + LOCK (counter); + internal_list_count += (result != NULL); + UNLOCK (counter); + return result; +} + +int +vconf_keylist_free (keylist_t * keylist) +{ + keynode_t *keynode, *temp; + + retvm_if (keylist == NULL, + VCONF_ERROR, "Invalid argument: keylist is NULL"); + + keynode = keylist->head; + free (keylist); + while (keynode) + { + temp = keynode->next; + _keynode_free_ (keynode); + keynode = temp; + } + + LOCK (counter); + internal_list_count -= (internal_list_count > 0); + UNLOCK (counter); + _check_close_buxton_ (); + return 0; +} + +int +vconf_keylist_rewind (keylist_t * keylist) +{ + retvm_if (keylist == NULL, + VCONF_ERROR, "Invalid argument: keylist is NULL"); + + keylist->cursor = NULL; + + return 0; +} + +keynode_t * +vconf_keylist_nextnode (keylist_t * keylist) +{ + keynode_t *result; + + retvm_if (keylist == NULL, NULL, "Invalid argument: keylist is NULL"); + + result = keylist->cursor; + result = result == NULL ? keylist->head : result->next; + keylist->cursor = result; + + return result; +} + +int +vconf_keylist_lookup (keylist_t * keylist, + const char *keyname, keynode_t ** return_node) +{ + keynode_t *keynode; + + retvm_if (keylist == NULL, + VCONF_ERROR, "Invalid argument: keylist is NULL"); + retvm_if (keyname == NULL, + VCONF_ERROR, "Invalid argument: keyname is NULL"); + retvm_if (return_node == NULL, + VCONF_ERROR, "Invalid argument: return_node is NULL"); + + keynode = _keylist_lookup_ (keylist, keyname, NULL); + if (NULL == keynode) + return 0; + + if (return_node) + *return_node = keynode; + return keynode->type; +} + +static int +_cb_sort_keynodes (const void *a, const void *b) +{ + register const keynode_t *kna = *(const keynode_t **) a; + register const keynode_t *knb = *(const keynode_t **) b; + return strcmp (kna->keyname, knb->keyname); +} + +int +vconf_keylist_sort (keylist_t * keylist) +{ + int index; + keynode_t **nodes, *keynode; + + retvm_if (keylist == NULL, + VCONF_ERROR, "Invalid argument: keylist is NULL"); + + if (keylist->num <= 1) + return VCONF_OK; + + nodes = malloc (keylist->num * sizeof *nodes); + retvm_if (nodes == NULL, VCONF_ERROR, "can't allocate memory for sorting"); + + index = 0; + keynode = keylist->head; + while (keynode != NULL) + { + assert (index < keylist->num); + nodes[index++] = keynode; + keynode = keynode->next; + } + assert (index == keylist->num); + + qsort (nodes, index, sizeof *nodes, _cb_sort_keynodes); + + while (index) + { + nodes[--index]->next = keynode; + keynode = nodes[index]; + } + keylist->head = keynode; + free (nodes); + return VCONF_OK; +} + +int +vconf_keylist_add_int (keylist_t * keylist, const char *keyname, + const int value) +{ + keynode_t *keynode; + + retvm_if (keylist == NULL, + VCONF_ERROR, "Invalid argument: keylist is NULL"); + retvm_if (keyname == NULL, + VCONF_ERROR, "Invalid argument: keyname is NULL"); + + keynode = _keylist_getadd_ (keylist, keyname, type_int); + if (keynode == NULL) + return VCONF_ERROR; + + keynode->value.i = value; + return keylist->num; +} + +int +vconf_keylist_add_bool (keylist_t * keylist, const char *keyname, + const int value) +{ + keynode_t *keynode; + + retvm_if (keylist == NULL, + VCONF_ERROR, "Invalid argument: keylist is NULL"); + retvm_if (keyname == NULL, + VCONF_ERROR, "Invalid argument: keyname is NULL"); + + keynode = _keylist_getadd_ (keylist, keyname, type_bool); + if (keynode == NULL) + return VCONF_ERROR; + + keynode->value.b = !!value; + return keylist->num; +} + +int +vconf_keylist_add_dbl (keylist_t * keylist, + const char *keyname, const double value) +{ + keynode_t *keynode; + + retvm_if (keylist == NULL, VCONF_ERROR, + "Invalid argument: keylist is NULL"); + retvm_if (keyname == NULL, VCONF_ERROR, + "Invalid argument: keyname is NULL"); + + keynode = _keylist_getadd_ (keylist, keyname, type_double); + if (keynode == NULL) + return VCONF_ERROR; + + keynode->value.d = value; + return keylist->num; +} + +int +vconf_keylist_add_str (keylist_t * keylist, + const char *keyname, const char *value) +{ + keynode_t *keynode; + char *copy; + + retvm_if (keylist == NULL, VCONF_ERROR, + "Invalid argument: keylist is NULL"); + retvm_if (keyname == NULL, VCONF_ERROR, + "Invalid argument: keyname is NULL"); + + copy = strdup (value == NULL ? "" : value); + retvm_if (copy == NULL, VCONF_ERROR, "Allocation of memory failed"); + + keynode = _keylist_getadd_ (keylist, keyname, type_string); + if (keynode == NULL) + { + free (copy); + return VCONF_ERROR; + } + + free (keynode->value.s); + keynode->value.s = copy; + return keylist->num; +} + +int +vconf_keylist_add_null (keylist_t * keylist, const char *keyname) +{ + keynode_t *keynode; + + retvm_if (keylist == NULL, VCONF_ERROR, + "Invalid argument: keylist is NULL"); + retvm_if (keyname == NULL, VCONF_ERROR, + "Invalid argument: keyname is NULL"); + + keynode = _keylist_getadd_ (keylist, keyname, type_unset); + if (keynode == NULL) + return VCONF_ERROR; + + return keylist->num; +} + +int +vconf_keylist_del (keylist_t * keylist, const char *keyname) +{ + keynode_t *keynode, **previous = NULL; + + retvm_if (keylist == NULL, VCONF_ERROR, + "Invalid argument: keylist is NULL"); + retvm_if (keyname == NULL, VCONF_ERROR, + "Invalid argument: keyname is NULL"); + + keynode = _keylist_lookup_ (keylist, keyname, &previous); + if (keynode == NULL) + return VCONF_ERROR; + + *previous = keynode->next; + keylist->num--; + _keynode_free_ (keynode); + + return VCONF_OK; +} + +int +vconf_set (keylist_t * keylist) +{ + retvm_if (keylist == NULL, VCONF_ERROR, + "Invalid argument: keylist is NULL"); + + return _apply_buxton_on_list_ (keylist, _async_set_or_unset_, NULL); +} + +int +vconf_set_labels (keylist_t * keylist, const char *label) +{ + retvm_if (keylist == NULL, VCONF_ERROR, + "Invalid argument: keylist is NULL"); + + retvm_if (label == NULL, VCONF_ERROR, "Invalid argument: name is NULL"); + + return _apply_buxton_on_list_ (keylist, _async_set_label_, label); +} + +int +vconf_sync_key (const char *keyname) +{ + /* + * does nothing succefully + */ + return 0; +} + +int +vconf_refresh (keylist_t * keylist) +{ + retvm_if (keylist == NULL, VCONF_ERROR, + "Invalid argument: keylist is NULL"); + + return _apply_buxton_on_list_ (keylist, _async_refresh_, NULL); +} + +int +vconf_scan (keylist_t * keylist, const char *dirpath, get_option_t option) +{ + char *dircopy; + struct layer_key laykey; + struct scanning_data data; + int status; + + retvm_if (keylist == NULL, VCONF_ERROR, + "Invalid argument: keylist is null"); + retvm_if (keylist->num != 0, VCONF_ERROR, + "Invalid argument: keylist not empty"); + retvm_if (dirpath == NULL, VCONF_ERROR, + "Invalid argument: dirpath is null"); + retvm_if (_check_keyname_ (dirpath) == 0, VCONF_ERROR, + "Invalid argument: dirpath is not valid"); + + status = _open_buxton_ (); + if (!status) + { + ERR ("Can't connect to buxton"); + return VCONF_ERROR; + } + + data.keylist = keylist; + + switch (option) + { + case VCONF_GET_KEY: + data.want_directories = 0; + data.want_keys = 1; + data.is_recursive = 0; + break; + case VCONF_GET_ALL: + data.want_directories = 1; + data.want_keys = 1; + data.is_recursive = 0; + break; + case VCONF_GET_DIR: + data.want_directories = 1; + data.want_keys = 0; + data.is_recursive = 0; + break; + case VCONF_GET_KEY_REC: + data.want_directories = 0; + data.want_keys = 1; + data.is_recursive = 1; + break; + case VCONF_GET_ALL_REC: + data.want_directories = 1; + data.want_keys = 1; + data.is_recursive = 1; + break; + case VCONF_GET_DIR_REC: + data.want_directories = 0; + data.want_keys = 1; + data.is_recursive = 1; + break; + default: + ERR ("Invalid argument: Bad option value"); + return VCONF_ERROR; + } + + data.dirlen = strlen (dirpath); + assert (data.dirlen); + if (dirpath[data.dirlen - 1] == '/') + { + data.directory = dirpath; + dircopy = NULL; + } + else + { + status = asprintf (&dircopy, "%s/", dirpath); + retvm_if (status < 0, VCONF_ERROR, + "No more memory for copying dirpath"); + data.directory = dircopy; + data.dirlen++; + } + + status = _get_layer_key_ (data.directory, &laykey); + if (status != VCONF_OK) + { + return status; + } + + data.prefix = laykey.prefix; + if (!laykey.key[0]) + { + laykey.key = NULL; + } + + data.pending = 1; + assert (_buxton_ () != NULL); + status = buxton_list_names (_buxton_ (), laykey.layer, default_group, + laykey.key, (BuxtonCallback) _cb_scan_, + &data, false); + if (!status) + status = _wait_buxton_response_ (&data.pending); + + free (dircopy); + + retvm_if (status, VCONF_ERROR, "Error while calling buxton_list_names: %m"); + if (data.cb_status != VCONF_OK) + { + return VCONF_ERROR; + } + + return vconf_refresh (keylist); +} + +int +vconf_get (keylist_t * keylist, const char *dirpath, get_option_t option) +{ + if (option == VCONF_REFRESH_ONLY + || (option == VCONF_GET_KEY && keylist->num != 0)) + { + return vconf_refresh (keylist); + } + else + { + return vconf_scan (keylist, dirpath, option); + } +} + +int +vconf_unset (const char *keyname) +{ + struct singleton single; + int status; + + retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL"); + + status = _keylist_init_singleton_ (&single, keyname, type_delete); + if (status == VCONF_OK) + { + status = vconf_set (&single.list); + } + return status; + +} + +int +vconf_exists (const char *keyname) +{ + struct singleton single; + int status; + + retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL"); + + status = _keylist_init_singleton_ (&single, keyname, type_unset); + if (status == VCONF_OK) + { + status = vconf_refresh (&single.list); + if (status == VCONF_OK && single.node.type == type_string) + free (single.node.value.s); + } + return status; + +} + +int +vconf_unset_recursive (const char *in_dir) +{ + struct _keylist_t *keylist; + struct _keynode_t *keynode; + int status; + + retvm_if (in_dir == NULL, VCONF_ERROR, "Invalid argument: dir is null"); + + keylist = vconf_keylist_new (); + if (keylist == NULL) + return VCONF_ERROR; + + status = vconf_scan (keylist, in_dir, VCONF_GET_KEY_REC); + if (status == VCONF_OK) + { + for (keynode = keylist->head; keynode; keynode = keynode->next) + keynode->type = type_delete; + status = vconf_set (keylist); + } + vconf_keylist_free (keylist); + return status; +} + +int +vconf_notify_key_changed (const char *keyname, vconf_callback_fn cb, + void *user_data) +{ + int status; + struct notify *notif; + keynode_t *keynode, *aknode; + keylist_t *alist; + + retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is null"); + retvm_if (cb == NULL, VCONF_ERROR, "Invalid argument: cb(%p)", cb); + status = _open_buxton_ (); + retvm_if (!status, VCONF_ERROR, "Can't connect to buxton"); + status = vconf_exists (keyname); + retvm_if (status != VCONF_OK, VCONF_ERROR, "key %s doesn't exist", keyname); + + + /* + * create the notification + */ + notif = malloc (sizeof *notif); + retvm_if (notif == NULL, VCONF_ERROR, + "Allocation of notify structure failed"); + + /* + * ensure existing list + */ + LOCK (notify); + if (notify_keylist == NULL) + { + notify_keylist = vconf_keylist_new (); + if (notify_keylist == NULL) + { + UNLOCK (notify); + free (notif); + return VCONF_ERROR; + } + } + + /* + * search keynode of keyname + */ + keynode = _keylist_lookup_ (notify_keylist, keyname, NULL); + if (keynode == NULL) + { + /* + * not found, create it with type unset + */ + keynode = _keylist_add_ (notify_keylist, keyname, type_unset); + if (keynode == NULL) + { + UNLOCK (notify); + free (notif); + return VCONF_ERROR; + } + } + + /* + * init the notification + */ + notif->callback = cb; + notif->userdata = user_data; + notif->keynode = keynode; + notif->next = notify_entries; + notify_entries = notif; + UNLOCK (notify); + + /* + * record the notification + */ + status = _notify_reg_unreg_ (notif, true); + if (status != VCONF_OK) + { + vconf_ignore_key_changed (keyname, cb); + return VCONF_ERROR; + } + +#if !defined(NO_GLIB) + return _glib_start_watch_ (); +#else + return VCONF_OK; +#endif +} + +int +vconf_ignore_key_changed (const char *keyname, vconf_callback_fn cb) +{ + struct notify *entry, **prevent, *delent, **prevdelent; + keynode_t *keynode, **prevnod; + int fcount; + int status; + + retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is null"); + retvm_if (cb == NULL, VCONF_ERROR, "Invalid argument: cb(%p)", cb); + status = _open_buxton_ (); + retvm_if (!status, VCONF_ERROR, "Can't connect to buxton"); + + fcount = 0; + status = VCONF_ERROR; + delent = NULL; + + LOCK (notify); + if (notify_keylist != NULL) + { + keynode = _keylist_lookup_ (notify_keylist, keyname, &prevnod); + if (keynode != NULL) + { + prevdelent = &delent; + prevent = ¬ify_entries; + entry = notify_entries; + while (entry != NULL) + { + if (entry->keynode == keynode) + { + if (entry->callback == cb) + { + *prevdelent = entry; + prevdelent = &entry->next; + entry = entry->next; + continue; + } + fcount++; + } + *prevent = entry; + prevent = &entry->next; + entry = entry->next; + } + *prevent = NULL; + *prevdelent = NULL; + if (fcount == 0) + *prevnod = keynode->next; +#if !defined(NO_GLIB) + if (notify_entries == NULL) + _glib_stop_watch_ (); +#endif + if (delent != NULL) + { + UNLOCK (notify); + while (delent != NULL) + { + entry = delent; + delent = entry->next; + _notify_reg_unreg_ (entry, false); + free (entry); + } + if (fcount == 0) + _keynode_free_ (keynode); + return VCONF_OK; + } + } + } + UNLOCK (notify); + ERR ("Not found: can't remove notification for key(%s)", keyname); + + return VCONF_ERROR; +} + +int +vconf_set_int (const char *keyname, const int intval) +{ + struct singleton single; + int status; + + retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL"); + + status = _keylist_init_singleton_ (&single, keyname, type_int); + if (status == VCONF_OK) + { + single.node.value.i = intval; + status = vconf_set (&single.list); + } + return status; +} + +int +vconf_set_bool (const char *keyname, const int boolval) +{ + struct singleton single; + int status; + + retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL"); + + status = _keylist_init_singleton_ (&single, keyname, type_bool); + if (status == VCONF_OK) + { + single.node.value.b = (bool) boolval; + status = vconf_set (&single.list); + } + return status; +} + +int +vconf_set_dbl (const char *keyname, const double dblval) +{ + struct singleton single; + int status; + + retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL"); + + status = _keylist_init_singleton_ (&single, keyname, type_double); + if (status == VCONF_OK) + { + single.node.value.d = dblval; + status = vconf_set (&single.list); + } + return status; +} + +int +vconf_set_str (const char *keyname, const char *strval) +{ + struct singleton single; + int status; + + retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL"); + + status = _keylist_init_singleton_ (&single, keyname, type_string); + if (status == VCONF_OK) + { + single.node.value.s = (char *) strval; + status = vconf_set (&single.list); + } + return status; +} + +int +vconf_get_int (const char *keyname, int *intval) +{ + struct singleton single; + int status; + + retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL"); + + status = _keylist_init_singleton_ (&single, keyname, type_int); + if (status == VCONF_OK) + { + status = vconf_refresh (&single.list); + if (status == VCONF_OK) + *intval = single.node.value.i; + } + return status; +} + +int +vconf_set_label (const char *keyname, const char *label) +{ + struct singleton single; + int status; + + retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL"); + + retvm_if (label == NULL, VCONF_ERROR, "Invalid argument: name is NULL"); + + status = _keylist_init_singleton_ (&single, keyname, type_unset); + if (status == VCONF_OK) + { + status = vconf_set_labels (&single.list, label); + } + return status; +} + +int +vconf_get_bool (const char *keyname, int *boolval) +{ + struct singleton single; + int status; + + retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL"); + + status = _keylist_init_singleton_ (&single, keyname, type_bool); + if (status == VCONF_OK) + { + status = vconf_refresh (&single.list); + if (status == VCONF_OK) + *boolval = (int) single.node.value.b; + } + return status; +} + +int +vconf_get_dbl (const char *keyname, double *dblval) +{ + struct singleton single; + int status; + + retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL"); + + status = _keylist_init_singleton_ (&single, keyname, type_double); + if (status == VCONF_OK) + { + status = vconf_refresh (&single.list); + if (status == VCONF_OK) + *dblval = single.node.value.d; + } + return status; +} + +char * +vconf_get_str (const char *keyname) +{ + struct singleton single; + int status; + + retvm_if (keyname == NULL, NULL, "Invalid argument: key is NULL"); + + status = _keylist_init_singleton_ (&single, keyname, type_string); + if (status != VCONF_OK) + return NULL; + + single.node.value.s = NULL; + status = vconf_refresh (&single.list); + if (status != VCONF_OK) + return NULL; + + return single.node.value.s; +} diff --git a/src/vconf-buxton.h b/src/vconf-buxton.h new file mode 100644 index 0000000..1b639bb --- /dev/null +++ b/src/vconf-buxton.h @@ -0,0 +1,976 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2014 Intel Corporation + * + * Author: José Bollo + * Author: Hakjoo Ko + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __VCONF_BUXTON_H__ +#define __VCONF_BUXTON_H__ + +#define VCONF_BUXTON "1.0" + +/** + * @addtogroup APPLICATION_FRAMEWORK + * @{ + * + * @defgroup VCONF VConf + * @author Sangjung Woo (sangjung.woo@samsung.com) + * @version 0.2 + * @brief A library for reading/writing Configuration Data + * + * @section Header To use Them: + * @code + * #include + * @endcode + * + * @section Properties + * - Convenient API + * - Guarantee Transaction(db backend only) + * - Apply Key-List concept + * - Changeable Backend + * - Simple Notification based on inotify + * + * @section Backend key has below backend. + * - db => use libsqlfs ex) db/a/b + * \n Lowest speed, highest robustness, correctly sync + * - memory => use tmpfs ex) memory/a/b + * \n Highest speed, volitile + * - file => use basic file system(not support atomicity) ex) file/a/b + * \n Higher speed, lower robustness(Not guarantee atomicity) + * + * @section example Simple Example + * @code + #include + #include + + const char *key1_name="db/test/key1"; + + int main(int argc, char **argv) + { + int key1_value; + + if(vconf_set_int(key1_name,1)) + fprintf(stderr, "vconf_set_int FAIL\n"); + else + printf("vconf_set_int OK\n"); + + if(vconf_get_int(key1_name, &key1_value)) + fprintf(stderr, "vconf_get_int FAIL\n"); + else + printf("vconf_get_int OK(key1 value is %d)\n", key1_value); + + return 0; + } + * @endcode + * + */ + +/** + * @addtogroup VCONF + * @{ + */ + +#include "vconf-buxton-keys.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * VCONF_GET_KEY, VCONF_GET_ALL, VCONF_GET_DIR + * \n Use for vconf_get() + * @see vconf_get() + */ + enum get_option_t { + VCONF_GET_KEY = 0, + /**< get only keys */ + VCONF_GET_ALL, + /**< get keys and directorys */ + VCONF_GET_DIR, + /**< get only directorys */ + VCONF_REFRESH_ONLY, + /**< get only keys */ + VCONF_GET_KEY_REC, + /**< get only keys recursively */ + VCONF_GET_ALL_REC, + /**< get keys and directorys recursively */ + VCONF_GET_DIR_REC + /**< get only directorys recursively */ + }; + + typedef enum get_option_t get_option_t; + + enum vconf_t { + VCONF_TYPE_NONE = 0, + /**< Vconf none type for Error detection */ + VCONF_TYPE_STRING = 40, + /**< Vconf string type */ + VCONF_TYPE_INT = 41, + /**< Vconf integer type */ + VCONF_TYPE_DOUBLE = 42, + /**< Vconf double type */ + VCONF_TYPE_BOOL = 43, + /**< Vconf boolean type */ + VCONF_TYPE_DIR + /**< Vconf directory type */ + }; + + +/** + * keynode_t is an opaque type, it must be + * used via accessor functions. + * @see vconf_keynode_get_name(), vconf_keynode_get_type() + * @see vconf_keynode_get_bool(), vconf_keynode_get_dbl(), vconf_keynode_get_int(), vconf_keynode_get_str() + */ + typedef struct _keynode_t keynode_t; + +/** + * keylist_t is an opaque type, it must be + * used via accessor functions. + * @see vconf_keylist_new(), vconf_keylist_free() + * @see vconf_keylist_add_bool(),vconf_keylist_add_str(), vconf_keylist_add_dbl(), vconf_keylist_add_int() + * @see vconf_keylist_del(), vconf_keylist_add_null() + * @see vconf_keylist_lookup(), vconf_keylist_nextnode(), vconf_keylist_rewind() + */ + typedef struct _keylist_t keylist_t; + + +/** + * This is the signature of a callback function added with vconf_notify_key_changed(). + * \n The callback function is invoked when the key is set. + * @see keynode_t + */ + typedef void (*vconf_callback_fn) (keynode_t * node, + void *user_data); + +/************************************************ + * keynode handling APIs * + ************************************************/ + +/** + * This function gets Key name of the keynode. + * @param[in] keynode The Key + * @return Key Name of the keynode + * @pre Nome + * @post None + * @remarks None + * @see vconf_notify_key_changed(), vconf_keynode_get_bool, vconf_keynode_get_type, vconf_keynode_get_str, vconf_keynode_get_int, vconf_keynode_get_dbl, keynode_t, vconf_t + */ + const char *vconf_keynode_get_name(keynode_t * keynode); + +/** + * This function gets value type of the keynode. + * @param[in] keynode The Key + * @return Type of the keynode + * @pre Nome + * @post None + * @remarks None + * @see vconf_notify_key_changed(), vconf_keynode_get_name, vconf_keynode_get_bool, vconf_keynode_get_str, vconf_keynode_get_int, vconf_keynode_get_dbl, keynode_t, vconf_t + */ + int vconf_keynode_get_type(keynode_t * keynode); + +/** + * This function gets Integer value of the keynode. + * @param[in] keynode The Key + * @return Integer value, or 0 if no value is obtained + ** @pre Nome + * @post None + * @remarks None + * @see vconf_notify_key_changed(), vconf_keynode_get_name, vconf_keynode_get_bool, vconf_keynode_get_type, vconf_keynode_get_str, vconf_keynode_get_dbl, keynode_t, vconf_t + */ + int vconf_keynode_get_int(keynode_t * keynode); + +/** + * This function gets Double value of the keynode. + * @param[in] keynode The Key + * @return Double value, or 0.0 if no value is obtained + * @pre Nome + * @post None + * @remarks None + * @see vconf_notify_key_changed(), vconf_keynode_get_name, vconf_keynode_get_bool, vconf_keynode_get_type, vconf_keynode_get_str, vconf_keynode_get_int, keynode_t, vconf_t + */ + double vconf_keynode_get_dbl(keynode_t * keynode); + +/** + * This function gets Boolean value of the keynode. + * @param[in] keynode The Key + * @return Boolean value, -1 on error (Integer value 1 is 'True', and 0 is 'False') + * @pre Nome + * @post None + * @remarks None + * @see vconf_notify_key_changed(), vconf_keynode_get_name, vconf_keynode_get_type, vconf_keynode_get_str, vconf_keynode_get_int, vconf_keynode_get_dbl, keynode_t, vconf_t + */ + int vconf_keynode_get_bool(keynode_t * keynode); + +/** + * This function gets String value of the keynode. + * @param[in] keynode The Key + * @return String value, or NULL if no value is obtained + * @pre Nome + * @post None + * @remarks None + * @see vconf_notify_key_changed(), vconf_keynode_get_name, vconf_keynode_get_bool, vconf_keynode_get_type, vconf_keynode_get_int, vconf_keynode_get_dbl, keynode_t, vconf_t + */ + char *vconf_keynode_get_str(keynode_t * keynode); + + +/************************************************ + * keylist handling APIs + ************************************************/ + +/** + * Set the default group of key lists created using vconf_keylist_new. + * @param[in] groupname The name of the default group to bind to + * @return 0 in case of success or -1 in case of error of allocation + * @see vconf_keylist_new() + */ + int vconf_set_default_group(const char *groupname); + +/** + * Allocate, initialize and return a new Keylist object bound to the default group. + * Return value keylist_t* pointer must be relised by calling vconf_keylist_free() + * @return The pointer of New keylist, NULL on error + * @pre None + * @post None + * @see vconf_set(), vconf_get(), vconf_keylist_create(), vconf_keylist_free(), vconf_set_default_group() + */ + keylist_t *vconf_keylist_new(void); + +/** + * A destructor for Keylist objects.
+ * After calling vconf_keylist_new(), developer have to call this function for release internal memory. + * @param[in] keylist Key List + * @return 0 on success, -1 on error + * @pre None + * @post None + * @remarks None + * @see vconf_set(), vconf_get(), vconf_keylist_new() + */ + int vconf_keylist_free(keylist_t * keylist); + +/** + * This function moves the current Keynode position to the first items. + * @param[in] keylist Key List + * @return 0 on success, -1 on error + * @pre None + * @post None + * @remarks None + * @see vconf_set(), vconf_get(), vconf_keylist_nextnode(), vconf_keylist_rewind(), vconf_keylist_nextnode() + * @par example + * @code + int r =0; + keylist_t* pKeyList = NULL; + pKeyList = vconf_keylist_new(); + + r = vconf_get(pKeyList, KEY_PARENT, VCONF_GET_KEY); + if (r) { + tet_infoline("vconf_get() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + + vconf_keylist_nextnode(pKeyList); + vconf_keylist_nextnode(pKeyList); + + // Move first position from KeyList + r = vconf_keylist_rewind(pKeyList); + if (r<0) { + tet_infoline("vconf_keylist_rewind() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + + while(vconf_keylist_nextnode(pKeyList)) ; + * @endcode + */ + int vconf_keylist_rewind(keylist_t * keylist); + +/** + * This function looks for a Keynode contained in keylist that matches keyname. + * @param[in] keylist Key List + * @param[in] keyname Key to find + * @param[out] return_node pointer of keynode to set + * @return Type of the found key that is vconf_t enumeration value + * @pre None + * @post None + * @remarks None + * @see vconf_set(), vconf_get(), keynode_t, vconf_t + * @par example + * @code +#include +#include + +int main() +{ + int r = 0; + int nResult = 0; + keylist_t* pKeyList = NULL; + keynode_t *pKeyNode; + + pKeyList = vconf_keylist_new(); + r = vconf_get(pKeyList, KEY_PARENT, VCONF_GET_KEY); + if (r<0) { + printf("vconf_get() failed in positive test case"); + return -1; + } + + r = vconf_keylist_lookup(pKeyList, KEY_02, &pKeyNode); + if (r<0) { + printf("vconf_get() failed in positive test case"); + return -1; + } + + nResult = vconf_keynode_get_int(pKeyNode); + if(nResult !=KEY_02_INT_VALUE) + { + printf("vconf_get() failed in positive test case"); + return -1; + + } + + vconf_keylist_free(pKeyList); + return 0; +} + * @endcode + */ + int vconf_keylist_lookup(keylist_t * keylist, + const char *keyname, + keynode_t ** return_node); + +/** + * This function returns the next Key in a Keylist. + * Next key is known by the keylist internal cursor. + * @param[in] keylist Key List + * @return The next Keynode, NULL on error + * @pre None + * @post None + * @remarks None + * @see vconf_set(), vconf_get(), vconf_keylist_rewind(), vconf_keylist_nextnode(), keynode_t + */ + keynode_t *vconf_keylist_nextnode(keylist_t * keylist); + +/** + * This function sorts the list in alphabetical order (with LANG=C) + * @param[in] keylist Key List + * @return 0 if done, -1 on error + * @pre None + * @post None + * @remarks None + */ + int vconf_keylist_sort(keylist_t * keylist); + +/** + * This function appends a new Keynode included integer value to the keylist. + * \n If same keyname exist, the keynode will change. + * @param[in] keylist Key List + * @param[in] keyname Key + * @param[in] value The integer value + * @return Number of keynode included in the keylist, -1 on error + * @see vconf_set(), vconf_get() + */ + int vconf_keylist_add_int(keylist_t * keylist, + const char *keyname, + const int value); + +/** + * This function appends a new Keynode included boolean value to the keylist. + * \n If same keyname exist, the keynode will change. + * @param[in] keylist Key List + * @param[in] keyname Key + * @param[in] value The boolean value + * @return Number of keynode included in the keylist, -1 on error + * @pre None + * @post None + * @remarks None + * @see vconf_set(), vconf_get(), vconf_keylist_add_int(), vconf_keylist_add_str(), vconf_keylist_add_dbl(), vconf_keylist_add_bool(), vconf_keylist_del(), vconf_keylist_add_null() + */ + int vconf_keylist_add_bool(keylist_t * keylist, + const char *keyname, + const int value); + +/** + * This function appends a new Keynode included double value to the keylist. + * \n If same keyname exist, the keynode will change. + * @param[in] keylist Key List + * @param[in] keyname Key + * @param[in] value The double value + * @return Number of keynode included in the keylist, -1 on error + * @pre None + * @post None + * @remarks None + * @see vconf_set(), vconf_get(), vconf_keylist_add_int(), vconf_keylist_add_str(), vconf_keylist_add_dbl(), vconf_keylist_add_bool(), vconf_keylist_del(), vconf_keylist_add_null() + */ + int vconf_keylist_add_dbl(keylist_t * keylist, + const char *keyname, + const double value); + +/** + * This function appends a new Keynode included string value to the keylist. + * \n If same keyname exist, the keynode will change. + * @param[in] keylist Key List + * @param[in] keyname Key + * @param[in] value The pointer of string value + * @return Number of keynode included in the keylist, -1 on error + * @pre None + * @post None + * @remarks None + * @see vconf_set(), vconf_get(), vconf_keylist_add_int(), vconf_keylist_add_str(), vconf_keylist_add_dbl(), vconf_keylist_add_bool(), vconf_keylist_del(), vconf_keylist_add_null() + */ + int vconf_keylist_add_str(keylist_t * keylist, + const char *keyname, + const char *value); + +/** + * This function Appends a new Keynode to the keylist without value. + * \n Use for vconf_get() + * @param[in] keylist Key List + * @param[in] keyname Key + * @return Number of keynode included in the keylist, -1 on error + * @pre None + * @post None + * @remarks None + * @see vconf_set(), vconf_get(), vconf_keylist_add_int(), vconf_keylist_add_str(), vconf_keylist_add_dbl(), vconf_keylist_add_bool(), vconf_keylist_del(), vconf_keylist_add_null() + */ + int vconf_keylist_add_null(keylist_t * keylist, + const char *keyname); + +/** + * This function removes the keynode that matches keyname. + * @param[in] keylist the keylist included the keyname + * @param[in] keyname key + * @return 0 on success, -1(Invalid parameter), -2(Not exist keyname in keylist) on error + * @pre None + * @post None + * @remarks None + * @see vconf_set(), vconf_get(), vconf_keylist_add_int(), vconf_keylist_add_str(), vconf_keylist_add_dbl(), vconf_keylist_add_bool(), vconf_keylist_del(), vconf_keylist_add_null() + */ + int vconf_keylist_del(keylist_t * keylist, + const char *keyname); + +/************************************************ + * setting APIs * + ************************************************/ + +/** + * This function sets the keys included in keylist. + * \n If you use db backend, keylist is handled as one transaction. + * @param[in] keylist the keylist which should contain changed keys + * @return 0 on success, -1 on error + * @pre None + * @post None + * @remarks None + * @see vconf_set(), vconf_get(), vconf_keylist_add_int(), vconf_keylist_add_str(), vconf_keylist_add_dbl(), vconf_keylist_add_bool(), vconf_keylist_del(), vconf_keylist_add_null() + * @par example + * @code +#include +#include + +int main() +{ + keylist_t *kl=NULL; + const char *keyname_list[3]={"db/test/key1", "db/test/key2", "db/test/key3"}; + + // Transaction Test(all or nothing is written) + kl = vconf_keylist_new(); + + vconf_keylist_add_int(kl, keyname_list[0], 1); + vconf_keylist_add_str(kl, keyname_list[1], "transaction Test"); + vconf_keylist_add_dbl(kl, keyname_list[2], 0.3); + if(vconf_set(kl)) + fprintf(stderr, "nothing is written\n"); + else + printf("everything is written\n"); + + vconf_keylist_free(kl); + + // You can set items which have different backend. + kl = vconf_keylist_new(); + + vconf_keylist_add_int(kl, "memory/a/xxx1", 4); + vconf_keylist_add_str(kl, "file/a/xxx2", "test 3"); + vconf_keylist_add_dbl(kl, "db/a/xxx3", 0.3); + vconf_set(kl) + + vconf_keylist_free(kl); + return 0; +} + * @endcode + */ + int vconf_set(keylist_t * keylist); + +/** + * This function sets the integer value of given key. + * @param[in] keyname key + * @param[in] intval integer value to set (0 is also allowed as a value.) + * @return 0 on success, -1 on error + * @pre None + * @post None + * @remarks None + * @see vconf_set_bool(), vconf_set_dbl(), vconf_set_str() + */ + int vconf_set_int(const char *keyname, const int intval); + +/** + * This function sets the boolean value of given key. + * @param[in] keyname key + * @param[in] boolval boolean value(1 or 0) to set. (Integer value 1 is 'True', and 0 is 'False') + * @return 0 on success, -1 on error + * @pre None + * @post None + * @remarks None + * @see vconf_set_int(), vconf_set_dbl(), vconf_set_str() + * @par example + * @code +#include +#include + + const char *key1_name="memory/test/key1"; + + int main(int argc, char **argv) + { + int key1_value; + + if(vconf_set_bool(key1_name, 1)) + fprintf(stderr, "vconf_set_bool FAIL\n"); + else + printf("vconf_set_bool OK\n"); + + if(vconf_get_bool(key1_name, &key1_value)) + fprintf(stderr, "vconf_get_bool FAIL\n"); + else + printf("vconf_get_bool OK(key1 value is %d)\n", key1_value); + + return 0; + } + * @endcode + */ + int vconf_set_bool(const char *keyname, const int boolval); + +/** + * This function sets the double value of given key. + * @param[in] keyname key + * @param[in] dblval double value to set (0.0 is also allowed as a value.) + * @return 0 on success, -1 on error + * @pre None + * @post None + * @remarks None + * @see vconf_set_int(), vconf_set_bool(), vconf_set_str() + */ + int vconf_set_dbl(const char *keyname, + const double dblval); + +/** + * This function sets the string value of given key. + * @param[in] keyname key + * @param[in] strval string value to set + * @return 0 on success, -1 on error + * @pre None + * @post None + * @remarks None + * @see vconf_set_bool(), vconf_set_dbl(), vconf_set_int() + */ + int vconf_set_str(const char *keyname, const char *strval); + +/************************************************ + * setting label APIs * + ************************************************/ + +/** + * This function set the smack label of its keys + * @param[in] keylist Key List + * @param[in] label The label to set + * @return 0 if done, -1 on error + * @pre None + * @post None + * @remarks None + */ + int vconf_set_labels(keylist_t * keylist, const char *label); + +/** + * This function set the smack label of its keys + * @param[in] keylist Key List + * @param[in] label The label to set + * @return 0 if done, -1 on error + * @pre None + * @post None + * @remarks None + */ + int vconf_set_label(const char *keyname, const char *label); + +/************************************************ + * getting APIs * + ************************************************/ + +/** + * This function reads the database to refresh the values of + * the keys in 'keylist'. + * @param[in] keylist the keylist whose values have to be refreshed + * @return 0 on success, -1 on error + * @see vconf_keylist_lookup, vconf_keylist_nextnode, vconf_keylist_rewind + */ + int vconf_refresh(keylist_t * keylist); + +/** + * This function retrieves the keys or subdirectory in in_parentDIR.
+ * @param[in] keylist keylist created by vconf_keylist_new(), MUST be empty + * @param[in] in_parentDIR parent DIRECTORY of needed keys + * @param[in] option VCONF_GET_KEY|VCONF_GET_DIR|VCONF_GET_ALL|VCONF_GET_KEY_REC|VCONF_GET_DIR_REC|VCONF_GET_ALL_REC + * @return 0 on success, -1 on error + * @pre None + * @post None + * @remkar None + * @par example + * @code +#include +#include + +int main() +{ + keylist_t *kl=NULL; + keynode_t *temp_node; + const char *vconfkeys1="db/test/key1"; + const char *parent_dir="db/test"; + + kl = vconf_keylist_new(); + if(vconf_scan(kl, parent_dir, VCONF_GET_KEY)) + fprintf(stderr, "vconf_get FAIL(%s)", vconfkeys1); + else + printf("vconf_get OK(%s)", vconfkeys1); + + while((temp_node = vconf_keylist_nextnode(kl))) { + switch(vconf_keynode_get_type(temp_node)) { + case VCONF_TYPE_INT: + printf("key = %s, value = %d\n", + vconf_keynode_get_name(temp_node), vconf_keynode_get_int(temp_node)); + break; + case VCONF_TYPE_BOOL: + printf("key = %s, value = %d\n", + vconf_keynode_get_name(temp_node), vconf_keynode_get_bool(temp_node)); + break; + case VCONF_TYPE_DOUBLE: + printf("key = %s, value = %f\n", + vconf_keynode_get_name(temp_node), vconf_keynode_get_dbl(temp_node)); + break; + case VCONF_TYPE_STRING: + printf("key = %s, value = %s\n", + vconf_keynode_get_name(temp_node), vconf_keynode_get_str(temp_node)); + break; + default: + printf("Unknown Type\n"); + } + } + vconf_keylist_free(kl); +} + * @endcode + */ + int vconf_scan(keylist_t * keylist, + const char *in_parentDIR, + get_option_t option); + +/** + * This function get the keys or subdirectory in in_parentDIR.
+ * If keylist has any key information, vconf only retrieves the keys.
+ * @param[in] keylist keylist created by vconf_keylist_new() + * @param[in] in_parentDIR parent DIRECTORY of needed keys + * @param[in] option VCONF_GET_KEY|VCONF_GET_DIR|VCONF_GET_ALL|VCONF_REFRESH_ONLY|VCONF_GET_KEY_REC|VCONF_GET_DIR_REC|VCONF_GET_ALL_REC + * @return 0 on success, -1 on error + * @pre None + * @post None + * @remkar None + * @par example + * @code +#include +#include + +int main() +{ + keylist_t *kl=NULL; + keynode_t *temp_node; + const char *vconfkeys1="db/test/key1"; + const char *parent_dir="db/test"; + + kl = vconf_keylist_new(); + if(vconf_get(kl, parent_dir, VCONF_GET_KEY)) + fprintf(stderr, "vconf_get FAIL(%s)", vconfkeys1); + else + printf("vconf_get OK(%s)", vconfkeys1); + + while((temp_node = vconf_keylist_nextnode(kl))) { + switch(vconf_keynode_get_type(temp_node)) { + case VCONF_TYPE_INT: + printf("key = %s, value = %d\n", + vconf_keynode_get_name(temp_node), vconf_keynode_get_int(temp_node)); + break; + case VCONF_TYPE_BOOL: + printf("key = %s, value = %d\n", + vconf_keynode_get_name(temp_node), vconf_keynode_get_bool(temp_node)); + break; + case VCONF_TYPE_DOUBLE: + printf("key = %s, value = %f\n", + vconf_keynode_get_name(temp_node), vconf_keynode_get_dbl(temp_node)); + break; + case VCONF_TYPE_STRING: + printf("key = %s, value = %s\n", + vconf_keynode_get_name(temp_node), vconf_keynode_get_str(temp_node)); + break; + default: + printf("Unknown Type\n"); + } + } + vconf_keylist_free(kl); +} + * @endcode + */ + int vconf_get(keylist_t * keylist, + const char *in_parentDIR, + get_option_t option); + +/** + * This function get the integer value of given key. + * + * @param[in] keyname key + * @param[out] intval output buffer + * @return 0 on success, -1 on error + * @pre None + * @post None + * @remkar None + * @see vconf_get_bool, vconf_get_dbl, vconf_get_str + * @par example + * @code +#include +#include + +const char *key1_name="db/test/key1"; + +int main(int argc, char **argv) +{ + int key1_value; + + if(vconf_set_int(key1_name,1)) + fprintf(stderr, "vconf_set_int FAIL\n"); + else + printf("vconf_set_int OK\n"); + + if(vconf_get_int(key1_name, &key1_value)) + fprintf(stderr, "vconf_get_int FAIL\n"); + else + printf("vconf_get_int OK(key1 value is %d)\n", key1_value); + + return 0; +} + * @endcode + */ + int vconf_get_int(const char *keyname, int *intval); + +/** + * This function get the boolean value(1 or 0) of given key. + * @param[in] keyname key + * @param[out] boolval output buffer + * @return 0 on success, -1 on error + * @pre None + * @post None + * @remarks None + * @see vconf_get_int(), vconf_get_dbl(), vconf_get_str() + */ + int vconf_get_bool(const char *keyname, int *boolval); + +/** + * This function get the double value of given key. + * @param[in] keyname key + * @param[out] dblval output buffer + * @return 0 on success, -1 on error + * @pre None + * @post None + * @remarks None + * @see vconf_get_int(), vconf_get_bool(), vconf_get_str() + */ + int vconf_get_dbl(const char *keyname, double *dblval); + +/** + * This function gets the string value of given key. + * \n You have to free this returned value. + * @param[in] keyname key + * @return allocated pointer of key value on success, NULL on error + * @pre None + * @post None + * @remarks None + * @see vconf_get_int(), vconf_get_dbl(), vconf_get_bool() + * @par example + * @code + #include + #include + + char *get_str=vconf_get_str("db/test/test1"); + if(get_str) { + printf("vconf_get_str OK(value = %s)", get_str); + free(get_str); + }else + fprintf(stderr, "vconf_get_str FAIL"); + * @endcode + */ + char *vconf_get_str(const char *keyname); + +/** + * This function deletes given key from backend system. + * @param[in] keyname key + * @return 0 on success, -1 on error + */ + int vconf_unset(const char *keyname); + +/** + * This function checks if the given key exists from backend system. + * @param[in] keyname key + * @return 0 on success: exists, -1 on error or not existing + */ + int vconf_exists(const char *keyname); + +/** + * This function synchronizes the given key(only file backend) with storage device. + * @param[in] keyname key + * @return 0 on success, -1 on error + * @pre Nome + * @post None + * @remarks None + * @par example + * @code + if(vconf_set_int("file/test/key1",1)) + fprintf(stderr, "vconf_set_int FAIL\n"); + else { + printf("vconf_set_int OK\n"); + vconf_sync_key("file/test/key1"); + } + * @endcode + */ + int vconf_sync_key(const char *keyname); + +/** + * This function deletes all keys and directories below given Directory from backend system. + * @param[in] in_dir Directory name for removing + * @return 0 on success, -1 on error + * @pre Nome + * @post None + * @remarks None + * @par example + * @code + vconf_set_int("db/test/key1",1); + vconf_set_int("db/test/test1/key1",1); + vconf_set_int("db/test/test2/key1",1); + vconf_set_int("db/test/key2",1); + + if(vconf_unset_recursive("db/test")) + fprintf(stderr, "vconf_unset_recursive FAIL\n"); + else + printf("vconf_unset_recursive OK(deleted db/test\n"); + + * @endcode + */ + int vconf_unset_recursive(const char *in_dir); + +/** + * This function adds a change callback for given key, + * which is called when the key is set or unset. + * \n Information(#keynode_t) of the key that changed is delivered to #vconf_callback_fn, + * or if the key is deleted, the @link #keynode_t keynode @endlink has #VCONF_TYPE_NONE as type. + * \n Multiple vconf_callback_fn functions may exist for one key. + * \n The callback is issued in the context of the glib main loop. + * \n WARNING: This callback mechanism DOES NOT GUARANTEE consistency of data chage. For example, + * When you have a callback for a certain key, assume that two or more processes are trying to + * change the value of the key competitively. In this case, your callback function will always + * get 'CURRENT' value, not the value raised the notify that caused run of the callback. So, + * do not use vconf callback when competitive write for a key is happening. In such case, use + * socket-based IPC(dbus or something else) instead. + * + * @param[in] keyname key + * @param[in] cb callback function + * @param[in] user_data callback data + * @return 0 on success, -1 on error + * @pre Nome + * @post None + * @remarks None + * @see vconf_ignore_key_changed + * @par example + * @code + void test_cb(keynode_t *key, void* data) + { + switch(vconf_keynode_get_type(key)) + { + case VCONF_TYPE_INT: + printf("key = %s, value = %d(int)\n", + vconf_keynode_get_name(key), vconf_keynode_get_int(key)); + break; + case VCONF_TYPE_BOOL: + printf("key = %s, value = %d(bool)\n", + vconf_keynode_get_name(key), vconf_keynode_get_bool(key)); + break; + case VCONF_TYPE_DOUBLE: + printf("key = %s, value = %f(double)\n", + vconf_keynode_get_name(key), vconf_keynode_get_dbl(key)); + break; + case VCONF_TYPE_STRING: + printf("key = %s, value = %s(string)\n", + vconf_keynode_get_name(key), vconf_keynode_get_str(key)); + break; + default: + fprintf(stderr, "Unknown Type(%d)\n", vconf_keynode_get_type(key)); + break; + } + return; + } + + int main() + { + int i; + GMainLoop *event_loop; + + g_type_init(); + + vconf_notify_key_changed("db/test/test1", test_cb, NULL); + + event_loop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(event_loop); + + vconf_ignore_key_changed("db/test/test1", test_cb); + return 0; + } + * @endcode + */ + int vconf_notify_key_changed(const char *keyname, + vconf_callback_fn cb, + void *user_data); + +/** + * This function removes a change callback for given key, + * which was added by vconf_notify_key_changed(). + * @param[in] keyname key + * @param[in] cb callback function + * @return 0 on success, -1 on error + * @pre Nome + * @post None + * @remarks None + * @see vconf_notify_key_changed() + */ + int vconf_ignore_key_changed(const char *keyname, + vconf_callback_fn cb); + +#ifdef __cplusplus +} +#endif +/** + * @} @} + */ +#endif /* __VCONF_BUXTON_H__ */ diff --git a/src/vconf-buxton.pc.in b/src/vconf-buxton.pc.in new file mode 100644 index 0000000..b107382 --- /dev/null +++ b/src/vconf-buxton.pc.in @@ -0,0 +1,10 @@ +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIBDIR@ +includedir=@INCLUDEDIR@ + +Name: vconf-buxton +Description: configuration system library +Version: @VERSION@ +Libs: -L${libdir} -lvconf-buxton -lpthread +Cflags: -I${includedir} diff --git a/src/vconf-buxton.sym b/src/vconf-buxton.sym new file mode 100644 index 0000000..423f3ff --- /dev/null +++ b/src/vconf-buxton.sym @@ -0,0 +1,44 @@ +VCONF_BUXTON_1.0 { + global: + vconf_keynode_get_name; + vconf_keynode_get_type; + vconf_keynode_get_int; + vconf_keynode_get_dbl; + vconf_keynode_get_bool; + vconf_keynode_get_str; + vconf_set_default_group; + vconf_keylist_new; + vconf_keylist_free; + vconf_keylist_lookup; + vconf_keylist_rewind; + vconf_keylist_nextnode; + vconf_keylist_sort; + vconf_keylist_add_int; + vconf_keylist_add_bool; + vconf_keylist_add_dbl; + vconf_keylist_add_str; + vconf_keylist_add_null; + vconf_keylist_del; + vconf_set; + vconf_set_int; + vconf_set_bool; + vconf_set_dbl; + vconf_set_str; + vconf_refresh; + vconf_scan; + vconf_get; + vconf_get_int; + vconf_get_bool; + vconf_get_dbl; + vconf_get_str; + vconf_unset; + vconf_sync_key; + vconf_unset_recursive; + vconf_notify_key_changed; + vconf_ignore_key_changed; + vconf_set_label; + vconf_set_labels; + local: + *; +}; +