pax_global_header00006660000000000000000000000064137021550150014511gustar00rootroot0000000000000052 comment=5126fff683752fd640af10557214a5e50ad7b2ca libeconf-0.3.8/000077500000000000000000000000001370215501500133025ustar00rootroot00000000000000libeconf-0.3.8/.github/000077500000000000000000000000001370215501500146425ustar00rootroot00000000000000libeconf-0.3.8/.github/workflows/000077500000000000000000000000001370215501500166775ustar00rootroot00000000000000libeconf-0.3.8/.github/workflows/ccpp.yml000066400000000000000000000005401370215501500203460ustar00rootroot00000000000000name: C/C++ CI on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: cmake configure with asan checks run: cmake -B build -DCMAKE_BUILD_TYPE=SanitizeAddress - name: make with asan checks run: make -C build - name: make check run: make -C build check libeconf-0.3.8/.github/workflows/meson-build.yml000066400000000000000000000004131370215501500216360ustar00rootroot00000000000000name: meson build on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-python@v1 - uses: BSFishy/meson-build@v1.0.1 with: action: build options: --verbose libeconf-0.3.8/.github/workflows/meson-test.yml000066400000000000000000000004111370215501500215140ustar00rootroot00000000000000name: meson test on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-python@v1 - uses: BSFishy/meson-build@v1.0.1 with: action: test options: --verbose libeconf-0.3.8/.gitignore000066400000000000000000000020311370215501500152660ustar00rootroot00000000000000Makefile.in /autom4te.cache /aclocal.m4 /compile /configure /depcomp /install-sh /missing /libtool /ltmain.sh /m4 # files generated by example example/.dirstamp example/test.ini # files generated by cmake build/ CMakeCache.txt CMakeFiles/ cmake_install.cmake *.pc *.cmake # files generated by configure .deps .libs Makefile config.h *.o *.lo *.la *.a *~ *.rej *.orig core config.log config.status config.sub config.guess libeconf-*.tar.* bin/example src/.dirstamp test-driver tests/*.log tests/*.trs tests/tst-filedoesnotexit1 tests/tst-merge1 tests/tst-merge2 tests/tst-merge3 tests/tst-merge4 tests/tst-merge5 tests/tst-arguments1 tests/tst-arguments2 tests/tst-arguments3 tests/tst-arguments4 tests/tst-arguments5 tests/tst-logindefs1 tests/tst-logindefs2 tests/tst-getconfdirs1 tests/tst-getconfdirs2 tests/tst-getconfdirs3 tests/tst-getconfdirs4 tests/tst-getconfdirs5 tests/tst-getconfdirs6 tests/tst-econf_errstring1 tests/tst-setgetvalues1 tests/tst-groups1 tests/tst-groups2 tests/tst-groups3 tests/tst-groups4 tests/tst-parseconfig1 build libeconf-0.3.8/CMakeLists.txt000066400000000000000000000043401370215501500160430ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.12) # Ensure built-in policies from CMake are used, (e.g. improved policies for macOS) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) project(libeconf VERSION 0.3.8 DESCRIPTION "Enhanced config file parser, which merges config files placed in several locations into one." LANGUAGES C ) # Set up GNU conventions and standard FHS paths include(GNUInstallDirs) # Activate CMake package configuration helpers include(CMakePackageConfigHelpers) # Ensure _GNU_SOURCE is available include(CheckSymbolExists) # check if _GNU_SOURCE is available if (NOT _GNU_SOURCE) check_symbol_exists(__GNU_LIBRARY__ "features.h" _GNU_SOURCE) if (NOT _GNU_SOURCE) unset(_GNU_SOURCE CACHE) check_symbol_exists(_GNU_SOURCE "features.h" _GNU_SOURCE) endif () endif () if (_GNU_SOURCE) add_definitions(-D_GNU_SOURCE) endif () # set the minimum C standard set(CMAKE_C_STANDARD 11) # Build Types set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel SanitizeAddress RelWithDebInfoStrict" FORCE ) # AddressSanitize set(CMAKE_C_FLAGS_SANITIZEADDRESS "-O2 -g -Wall -fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer" CACHE STRING "Flags used by the C compiler during AddressSanitizer builds." FORCE ) set(CMAKE_LINK_FLAGS_SANITIZEADDRESS "-fsanitize=address" CACHE STRING "Flags used by the linker during AddressSanitizer builds." FORCE ) # RelWithDebInfoStrict set(CMAKE_C_FLAGS_RELWITHDEBINFOSTRICT "-O2 -g -Werror -W -Wall -DXTSTRINGDEFINES -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -Werror=return-type -flto=8 -Wbad-function-cast -Wcast-align -Wcast-qual -Winline -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wshadow -Wstrict-prototypes -Wundef" CACHE STRING "Flags used by the C compiler during strict RelWithDebInfo builds." FORCE ) add_subdirectory(lib) add_subdirectory(example) # Enable testing include(CTest) enable_testing() add_subdirectory(tests) libeconf-0.3.8/INSTALL.md000066400000000000000000000013621370215501500147340ustar00rootroot00000000000000# Building and installing libeconf libeconf supports two options to build it: Meson (preferred) or CMake (alternate) ## Building with Meson libeconf requires a relatively recent version of Meson, version 0.49 or newer. Building with Meson is quite simple: ```shell $ meson build $ ninja -C build $ ninja -C build test ``` If you want to build with the address sanitizer enabled, add `-Db_sanitize=address` as an argument to `meson build`. ## Building with CMake libeconf requires CMake 3.12 or newer. Building with CMake is straightforward: ```shell $ cmake -B build $ make -C build $ make -C build check ``` If you want to build with the address sanitizer enabled, add `-DCMAKE_BUILD_TYPE=SanitizeAddress` as an argument to `cmake -B build`. libeconf-0.3.8/LICENSE000066400000000000000000000020341370215501500143060ustar00rootroot00000000000000Copyright (c) 2019 SUSE LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. libeconf-0.3.8/NEWS000066400000000000000000000014401370215501500140000ustar00rootroot00000000000000Version 0.3.8 * Convert the build to include CMake as an option, remove autotools Version 0.3.7 * Fix issues identified with i586 build thanks to the move to meson Version 0.3.6 * Add C++ compatibility and Add support for Meson Version 0.3.5 * Initial Haiku Port * Bugfix: helpers.c - Check for empty value (NULL pointer) before calling strdup. Version 0.3.4 * Fix parsing of quoted strings, and values starting with delimiters * Fix buffer overflow in econf_readDirs Version 0.3.3 * Reset *key_file to NULL after free Version 0.3.2 * Bugfix for merging empty configuration files Version 0.3.1 * Bugfix for writing files (Set delimiter in readFile) Version 0.3.0 * New parser * Add econf_get*ValueDef functions Version 0.2.0 * Reading of files is stable now Version 0.1.0 * Initial release libeconf-0.3.8/README.md000066400000000000000000000032771370215501500145720ustar00rootroot00000000000000# libeconf **libeconf** is a highly flexible and configureable library to parse and manage key=value configuration files. It reads configuration file snippets from different directories and builds the final configuration file for the application from it. The first file is the vendor provided configuration file. There are two methods of overriding this vendor settings: copy the file from /usr/_vendordir_ to /etc and modify the settings. Alternatively, a directory named _file_._suffix_.d/ within /etc can be created, with drop-in files in the form _name_._suffix_. This files contain only the changes of the specific settings the user is interested in. There can be serveral such drop-in files, they are processed in lexicographic order of their filename. The first method is useful to override the complete configuration file with an own one, the vendor supplied configuration is ignored. So, if /etc/_example_._suffix_ exists, /usr/_vendor_/_example_._suffix_ will not be read. The disadvantage is, that changes of the vendor configuration file are ignored and the user has to manually merge them. The other method will continue to use /usr/_vendor_/_example_._suffix_ as base configuration file and merge all changes from /etc/_example_._suffix_/*._suffix_. So the user will automatically get improvements of the vendor, with the drawback, that they could be incompatible with the user made changes. The list of files and directories read if no /etc/_example_._suffix_ file exists: * /usr/_vendor_/_example_._suffix_ * /usr/_vendor_/_example_._suffix_.d/*._suffix_ * /etc/_example_._suffix_.d/*._suffix_ If a /etc/_example_._suffix_ files exists: * /etc/_example_._suffix_ * /etc/_example_._suffix_.d/*._suffix_ libeconf-0.3.8/TODO.md000066400000000000000000000012631370215501500143730ustar00rootroot00000000000000# libeconf TODO * Implement/Fix parts marked with TODO or XXX * Reformat the code (should have uniform coding style) * Complete NULL value and error checking * Rework internal data structure for better group and key handling: * adding new groups and keys * faster searching * deletion of groups and keys * Rework function to write the configuration to a file * Implement a function to write the changes back into the source file * Support for comments: comments should be preserved when rewriting a file * Support writing files into a '.d' directory. * Implement econf_setOpt function to modify behavior of loading a configuration file for special cases * Add more to the list ... libeconf-0.3.8/cmake/000077500000000000000000000000001370215501500143625ustar00rootroot00000000000000libeconf-0.3.8/cmake/libeconf.pc.in000066400000000000000000000004341370215501500170750ustar00rootroot00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ Name: @PROJECT_NAME@ Description: @PROJECT_DESCRIPTION@ Version: @PROJECT_VERSION@ Libs: -L${libdir} -leconf -lm Cflags: -I${includedir} libeconf-0.3.8/cmake/libeconfConfig.cmake.in000066400000000000000000000001141370215501500206740ustar00rootroot00000000000000@PACKAGE_INIT@ include ("${CMAKE_CURRENT_LIST_DIR}/libeconfTargets.cmake") libeconf-0.3.8/example/000077500000000000000000000000001370215501500147355ustar00rootroot00000000000000libeconf-0.3.8/example/CMakeLists.txt000066400000000000000000000001771370215501500175020ustar00rootroot00000000000000# Create the binary/executable add_executable(example EXCLUDE_FROM_ALL example.c) target_link_libraries(example PRIVATE econf) libeconf-0.3.8/example/etc/000077500000000000000000000000001370215501500155105ustar00rootroot00000000000000libeconf-0.3.8/example/etc/example/000077500000000000000000000000001370215501500171435ustar00rootroot00000000000000libeconf-0.3.8/example/etc/example/conf.d/000077500000000000000000000000001370215501500203125ustar00rootroot00000000000000libeconf-0.3.8/example/etc/example/conf.d/10-First_Group.ini000066400000000000000000000000671370215501500234770ustar00rootroot00000000000000[First Group] FirstKey=3.14 SecondKey=" Hello World! " libeconf-0.3.8/example/etc/example/conf.d/20-Second_Group.ini000066400000000000000000000000621370215501500236170ustar00rootroot00000000000000[Second Group] FirstKey=false AnotherKey=Test123! libeconf-0.3.8/example/etc/example/conf.d/30-Third_Group.ini000066400000000000000000000000501370215501500234540ustar00rootroot00000000000000[Third Group] FirstKey=10e5 NewKey=true libeconf-0.3.8/example/etc/example/example.ini000066400000000000000000000004441370215501500213010ustar00rootroot00000000000000[Another Group] Numbers=2;20;-200;0;232 Booleans=true;false [First Group] Name=Keys File Example\tthis value shows\nescaping Welcome[fr_FR]=Bojour Welcome[la]=Salve Welcome[it] = Ci o Welcome[be@latin]=Hello Welcome[de]=Hallo Welcome=Hello [Group] Bla=12311 Welcome[la]=Salve Welcome=Hello libeconf-0.3.8/example/example.c000066400000000000000000000067261370215501500165470ustar00rootroot00000000000000/* Copyright (C) 2019 SUSE LLC Author: Pascal Arlt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include int main(void) { printf("------------------------ OUTPUT START ------------------------\n"); clock_t begin = clock(); //econf_file *key_file = econf_newIniFile(); //econf_file *key_file = econf_readFile("example/etc/example/example.ini", "=", "#"); econf_file *key_file; if (econf_readDirs(&key_file, "example/usr/etc", "example/etc", "example", ".ini", "=", "#")) return 1; /* XXX better error handling */ econf_setInt64Value(key_file, "[Basic Types]", "Int", INT64_MAX); int64_t i64val; econf_getInt64Value(key_file, "[Basic Types]", "Int", &i64val); printf("Int: %" PRId64 "\n", i64val); econf_setUInt64Value(key_file, "[Basic Types]", "UInt", UINT64_MAX); uint64_t u64val; econf_getUInt64Value(key_file, "[Basic Types]", "UInt", &u64val); printf("Unsigned Int: %" PRIu64 "\n", u64val); econf_setFloatValue(key_file, "[Basic Types]", "Float", M_PI); float fval; econf_getFloatValue(key_file, "[Basic Types]", "Float", &fval); printf("Float: %.*g\n", 8, fval); econf_setDoubleValue(key_file, "[Basic Types]", "Double", M_PI); double dval; econf_getDoubleValue(key_file, "[Basic Types]", "Double", &dval); printf("Double: %.*g\n", 16, dval); econf_setStringValue(key_file, "[Basic Types]", "String", "\" Hello World! \""); char *string; econf_getStringValue(key_file, "[Basic Types]", "String", &string); printf("String: %s\n", string); free(string); // Square brackets around the group/section are not needed econf_setBoolValue(key_file, "Basic Types", "Bool", "YeS"); bool bval; econf_getBoolValue(key_file, "[Basic Types]", "Bool", &bval); printf("Bool: %d\n", bval); econf_setValue(key_file, "Basic Types", "Generic", "Any value can go here!"); size_t key_number = 0; char **keys; if (econf_getKeys(key_file, "Basic Types", &key_number, &keys)) return 1; /* XXX better error handling */ printf("Keys: "); for (size_t i = 0; i < key_number; i++) { printf("%s, ", keys[i]); } puts("\n"); econf_free(keys); econf_writeFile(key_file, "example/", "test.ini"); econf_free(key_file); clock_t end = clock(); printf("Execution time: %fms\n", (double)(end - begin) / CLOCKS_PER_SEC * 1000); printf("------------------------- OUTPUT END -------------------------\n"); } libeconf-0.3.8/example/usr/000077500000000000000000000000001370215501500155465ustar00rootroot00000000000000libeconf-0.3.8/example/usr/etc/000077500000000000000000000000001370215501500163215ustar00rootroot00000000000000libeconf-0.3.8/example/usr/etc/example.ini000066400000000000000000000006271370215501500204620ustar00rootroot00000000000000# this is just an example # there can be comments before the first group [First Group] Name=Key File Example\tthis value shows\nescaping # localized strings are stored in multiple key-value pairs Welcome=Hello Welcome[de]=Hallo Welcome[fr_FR]=Bonjour Welcome[it]=Ciao #Comment not parsed Welcome[be@latin]=Hello Welcome[@latin]=Hello [Another Group] Numbers=2;20;-200;0# Booleans=true;false;true;true libeconf-0.3.8/include/000077500000000000000000000000001370215501500147255ustar00rootroot00000000000000libeconf-0.3.8/include/libeconf.h000066400000000000000000000167351370215501500166730ustar00rootroot00000000000000/* Copyright (C) 2019 SUSE LLC Author: Pascal Arlt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #pragma once /* libeconf.h */ #include #include #include #ifdef __cplusplus extern "C" { #endif /* Public API for the econf library */ /* libeconf error codes */ enum econf_err { ECONF_SUCCESS = 0, /* General purpose success code */ ECONF_ERROR = 1, /* Generic Error */ ECONF_NOMEM = 2, /* Out of memory */ ECONF_NOFILE = 3, /* Config file not found */ ECONF_NOGROUP = 4, /* Group not found */ ECONF_NOKEY = 5, /* Key not found */ ECONF_EMPTYKEY = 6, /* Key has empty value */ ECONF_WRITEERROR = 7, /* Error creating or writing to a file */ ECONF_PARSE_ERROR = 8 /* Syntax error in input file */ }; typedef enum econf_err econf_err; /* Generic macro calls setter function depending on value type Use: econf_setValue(econf_file *key_file, char *group, char *key, _generic_ value); Replace _generic_ with one of the supported value types. Supported Types: int, long, unsigned int, unsigned long, float, double, string (as *char). Note: Does not detect "yes", "no", 1 and 0 as boolean type. If you want to set a bool value use "true" or "false" or use setBoolValue() directly. */ #define econf_setValue(kf, group, key, value) (( \ _Generic((value), \ int: econf_setIntValue, \ long: econf_setInt64Value, \ unsigned int: econf_setUIntValue, \ unsigned long: econf_setUInt64Value, \ float: econf_setFloatValue, \ double: econf_setDoubleValue, \ char*: econf_setStringValue, void*: econf_setStringValue)) \ (kf, group, key, value)) /* Generic macro to free memory allocated by econf_ functions Use: econf_free(_generic_ value); Replace _generic_ with one of the supported value types. Supported Types: char** and econf_file*. */ #define econf_free(value) (( \ _Generic((value), \ econf_file*: econf_freeFile , \ char**: econf_freeArray)) \ (value)) typedef struct econf_file econf_file; // Process the file of the given file_name and save its contents into key_file extern econf_err econf_readFile(econf_file **result, const char *file_name, const char *delim, const char *comment); // Merge the contents of two key files extern econf_err econf_mergeFiles(econf_file **merged_file, econf_file *usr_file, econf_file *etc_file); extern econf_err econf_readDirs(econf_file **key_file, const char *usr_conf_dir, const char *etc_conf_dir, const char *project_name, const char *config_suffix, const char *delim, const char *comment); /* The API/ABI of the following three functions (econf_newKeyFile, econf_newIniFile and econf_writeFile) are not stable and will change */ /* Create a new econf_file object */ extern econf_err econf_newKeyFile(econf_file **result, char delimiter, char comment); extern econf_err econf_newIniFile(econf_file **result); /* Write content of a econf_file struct to specified location */ extern econf_err econf_writeFile(econf_file *key_file, const char *save_to_dir, const char *file_name); /* --- GETTERS --- */ extern econf_err econf_getGroups(econf_file *kf, size_t *length, char ***groups); extern econf_err econf_getKeys(econf_file *kf, const char *group, size_t *length, char ***keys); extern econf_err econf_getIntValue(econf_file *kf, const char *group, const char *key, int32_t *result); extern econf_err econf_getInt64Value(econf_file *kf, const char *group, const char *key, int64_t *result); extern econf_err econf_getUIntValue(econf_file *kf, const char *group, const char *key, uint32_t *result); extern econf_err econf_getUInt64Value(econf_file *kf, const char *group, const char *key, uint64_t *result); extern econf_err econf_getFloatValue(econf_file *kf, const char *group, const char *key, float *result); extern econf_err econf_getDoubleValue(econf_file *kf, const char *group, const char *key, double *result); /* Returns a newly allocated string or NULL in error case. */ extern econf_err econf_getStringValue(econf_file *kf, const char *group, const char *key, char **result); extern econf_err econf_getBoolValue(econf_file *kf, const char *group, const char *key, bool *result); /* If key is not found, the default value is returned and error is ECONF_NOKEY */ extern econf_err econf_getIntValueDef(econf_file *kf, const char *group, const char *key, int32_t *result, int32_t def); extern econf_err econf_getInt64ValueDef(econf_file *kf, const char *group, const char *key, int64_t *result, int64_t def); extern econf_err econf_getUIntValueDef(econf_file *kf, const char *group, const char *key, uint32_t *result, uint32_t def); extern econf_err econf_getUInt64ValueDef(econf_file *kf, const char *group, const char *key, uint64_t *result, uint64_t def); extern econf_err econf_getFloatValueDef(econf_file *kf, const char *group, const char *key, float *result, float def); extern econf_err econf_getDoubleValueDef(econf_file *kf, const char *group, const char *key, double *result, double def); /* Returns a newly allocated string, even if "default" is returned. */ extern econf_err econf_getStringValueDef(econf_file *kf, const char *group, const char *key, char **result, char *def); extern econf_err econf_getBoolValueDef(econf_file *kf, const char *group, const char *key, bool *result, bool def); /* --- SETTERS --- */ extern econf_err econf_setIntValue(econf_file *kf, const char *group, const char *key, int32_t value); extern econf_err econf_setInt64Value(econf_file *kf, const char *group, const char *key, int64_t value); extern econf_err econf_setUIntValue(econf_file *kf, const char *group, const char *key, uint32_t value); extern econf_err econf_setUInt64Value(econf_file *kf, const char *group, const char *key, uint64_t value); extern econf_err econf_setFloatValue(econf_file *kf, const char *group, const char *key, float value); extern econf_err econf_setDoubleValue(econf_file *kf, const char *group, const char *key, double value); extern econf_err econf_setStringValue(econf_file *kf, const char *group, const char *key, const char *value); extern econf_err econf_setBoolValue(econf_file *kf, const char *group, const char *key, const char *value); /* --- HELPERS --- */ /* convert an econf_err type to a string */ extern const char *econf_errString (const econf_err); // Free an array of type char** created by econf_getGroups() or econf_getKeys() extern void econf_freeArray(char **array); // Free memory allocated by key_file extern void econf_freeFile(econf_file *key_file); #ifdef __cplusplus } #endif libeconf-0.3.8/lib/000077500000000000000000000000001370215501500140505ustar00rootroot00000000000000libeconf-0.3.8/lib/CMakeLists.txt000066400000000000000000000042351370215501500166140ustar00rootroot00000000000000# Create the library set(econf_SRCS libeconf.c getfilecontents.c mergefiles.c helpers.c keyfile.c econf_errString.c get_value_def.c ) set(econf_HDRS defines.h getfilecontents.h mergefiles.h helpers.h keyfile.h ) add_library(econf SHARED ${econf_SRCS} ${econf_HDRS} "${PROJECT_SOURCE_DIR}/include/libeconf.h") target_include_directories(econf PUBLIC $ $ ) set_target_properties(econf PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR} VERSION ${PROJECT_VERSION} COMPILE_FLAGS "-D_REENTRANT=1" C_STANDARD 11 C_STANDARD_REQUIRED ON PUBLIC_HEADER "${PROJECT_SOURCE_DIR}/include/libeconf.h" LINK_FLAGS "-Wl,--no-undefined -Wl,--version-script,\"${PROJECT_SOURCE_DIR}/lib/libeconf.map\"" ) # Install the library configure_file(${PROJECT_SOURCE_DIR}/cmake/libeconf.pc.in ${CMAKE_BINARY_DIR}/libeconf.pc @ONLY) install(FILES ${CMAKE_BINARY_DIR}/libeconf.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) install(TARGETS econf EXPORT libeconfTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) # Generate and install the exports export(EXPORT libeconfTargets FILE ${CMAKE_BINARY_DIR}/libeconfTargets.cmake ) install(EXPORT libeconfTargets FILE libeconfTargets.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libeconf ) configure_package_config_file(${PROJECT_SOURCE_DIR}/cmake/libeconfConfig.cmake.in ${CMAKE_BINARY_DIR}/libeconfConfig.cmake INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libeconf NO_SET_AND_CHECK_MACRO NO_CHECK_REQUIRED_COMPONENTS_MACRO ) install(FILES ${CMAKE_BINARY_DIR}/libeconfConfig.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libeconf ) write_basic_package_version_file( ${CMAKE_BINARY_DIR}/libeconfConfigVersion.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY SameMinorVersion ) install(FILES ${CMAKE_BINARY_DIR}/libeconfConfigVersion.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libeconf ) libeconf-0.3.8/lib/defines.h000066400000000000000000000030521370215501500156360ustar00rootroot00000000000000/* Copyright (C) 2019 LLC Author: Pascal Arlt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #pragma once /* --- defines.h --- */ #include "helpers.h" /* Defines default values used in the library */ /* Default econf_file length on creation */ #define KEY_FILE_DEFAULT_LENGTH 8 /* NULL value */ #define KEY_FILE_NULL_VALUE "_none_" #define KEY_FILE_NULL_VALUE_HASH hashstring(KEY_FILE_NULL_VALUE) /* Bool values */ #define YES hashstring("yes") #define NO hashstring("no") #define TRUE hashstring("true") #define FALSE hashstring("false") libeconf-0.3.8/lib/econf_errString.c000066400000000000000000000040211370215501500173420ustar00rootroot00000000000000/* Copyright (C) 2019 SUSE LLC Author: Pascal Arlt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "libeconf.h" static const char *messages[] = { "Success", /* ECONF_SUCCESS */ "Unknown error", /* ECONF_ERROR */ "Out of memory", /* ECONF_NOMEM */ "Configuration file not found", /*ECONF_NOFILE */ "Group not found", /* ECONF_NOGROUP */ "Key not found", /* ECONF_NOKEY */ "Key has empty value", /* ECONF_EMPTYKEY */ "Error creating or writing to a file", /* ECONF_WRITEERROR */ "Parse error" /* ECONF_PARSE_ERROR */ }; const char * econf_errString (const econf_err error) { if (error >= sizeof(messages)/sizeof(messages[0])) { static char buffer[1024]; /* should always be big enough, else truncate */ const char *unknown = "Unknown libeconf error %i"; snprintf (buffer, sizeof (buffer) - 1, unknown, error); buffer[sizeof(buffer)-1] = '\0'; return buffer; } else return messages[error]; } libeconf-0.3.8/lib/get_value_def.c000066400000000000000000000035611370215501500170120ustar00rootroot00000000000000/* Copyright (C) 2019 SUSE LLC Author: Thorsten Kukuk Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "libeconf.h" #define econf_getValueDef(FCT_TYPE, TYPE, STRDUP) \ econf_err econf_get ## FCT_TYPE ## ValueDef(econf_file *ef, const char *group, \ const char *key, TYPE *result, TYPE def) { \ if (!ef) \ return ECONF_ERROR; \ \ econf_err error = econf_get ## FCT_TYPE ## Value(ef, group, key, result); \ if (error == ECONF_NOKEY) \ *result = STRDUP(def); \ return error; \ } econf_getValueDef(Int, int32_t, ) econf_getValueDef(Int64, int64_t, ) econf_getValueDef(UInt, uint32_t, ) econf_getValueDef(UInt64, uint64_t, ) econf_getValueDef(Float, float, ) econf_getValueDef(Double, double, ) econf_getValueDef(String, char *, strdup) econf_getValueDef(Bool, bool, ) libeconf-0.3.8/lib/getfilecontents.c000066400000000000000000000146571370215501500174260ustar00rootroot00000000000000/* Copyright (C) 2019 SUSE LLC Author: Pascal Arlt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "libeconf.h" #include "defines.h" #include "getfilecontents.h" #include "helpers.h" #include #include #include #include #include static econf_err store (econf_file *ef, const char *group, const char *key, const char *value, uint64_t line_number) { if (ef->alloc_length == ef->length) { struct file_entry *tmp; tmp = realloc(ef->file_entry, (ef->length + 1) * sizeof(struct file_entry)); if (!tmp) return ECONF_NOMEM; ef->file_entry = tmp; ef->length++; ef->alloc_length = ef->length; } ef->file_entry[ef->length-1].line_number = line_number; if (group) ef->file_entry[ef->length-1].group = strdup(group); else ef->file_entry[ef->length-1].group = strdup(KEY_FILE_NULL_VALUE); if (key) ef->file_entry[ef->length-1].key = strdup(key); else ef->file_entry[ef->length-1].key = strdup(KEY_FILE_NULL_VALUE); if (value) ef->file_entry[ef->length-1].value = strdup(value); else ef->file_entry[ef->length-1].value = NULL; return ECONF_SUCCESS; } static void check_delim(const char *str, bool *has_wsp, bool *has_nonwsp) { const char *p; *has_wsp = *has_nonwsp = false; if (str == NULL) return; for (p = str; *p && !(*has_wsp && *has_nonwsp); p++) { if (isspace((unsigned)*p)) *has_wsp = true; else *has_nonwsp = true; } } /* Read the file line by line and parse for comments, keys and values */ econf_err read_file(econf_file *ef, const char *file, const char *delim, const char *comment) { char buf[BUFSIZ]; char *current_group = NULL; econf_err retval = ECONF_SUCCESS; uint64_t line = 0; bool has_wsp, has_nonwsp; FILE *kf = fopen(file, "rbe"); if (kf == NULL) return ECONF_NOFILE; check_delim(delim, &has_wsp, &has_nonwsp); ef->path = strdup (file); if (ef->path == NULL) { fclose (kf); return ECONF_NOMEM; } ef->delimiter = *delim; while (fgets(buf, sizeof(buf), kf)) { char *p, *name, *data = NULL; bool quote_seen = false, delim_seen = false; line++; if (*buf == '\n') continue; /* ignore empty lines */ /* go throug all comment characters and check, if one of could be found */ for (size_t i = 0; i < strlen(comment); i++) { p = strchr(buf, comment[i]); if (p) *p = '\0'; } /* Remove trailing newline character */ size_t n = strlen(buf); if (n && *(buf + n - 1) == '\n') *(buf + n - 1) = '\0'; if (!*buf) continue; /* empty line */ /* ignore space at begin of the line */ name = buf; while (*name && isspace((unsigned)*name)) name++; /* check for groups */ if (name[0] == '[') { p = name + strlen(name) - 1; /* XXX Remove [] around group name */ while (isspace (*p)) p--; if (*p != ']') { retval = ECONF_PARSE_ERROR; goto out; } p++; *p = '\0'; if (current_group) free (current_group); current_group = strdup (name); continue; } /* go to the end of the name */ data = name; while (*data && !(isspace((unsigned)*data) || strchr(delim, *data) != NULL)) data++; if (data > name && *data) { if (has_wsp && has_nonwsp) /* * delim contains both whitespace and non-whitespace characters. * In this case delim_seen has the special meaning "non-whitespace * delim seen". See comment below. */ delim_seen = !isspace((unsigned)*data) && strchr(delim, *data) != NULL; else delim_seen = strchr(delim, *data) != NULL; *data++ = '\0'; } if (!*name || data == name) continue; if (*data == '\0') /* No seperator -> return NULL pointer, there is no value, not even an empty key */ data = NULL; else { /* go to the begin of the value */ while (*data && isspace((unsigned)*data)) data++; if (!has_wsp && !delim_seen) { /* * If delim consists only of non-whitespace characters, * require at least one delimiter, and skip more whitespace * after it. */ if (!*data || strchr(delim, *data) == NULL) { retval = ECONF_PARSE_ERROR; goto out; } data++; while (*data && isspace((unsigned)*data)) data++; } else if (has_wsp && has_nonwsp && !delim_seen && *data && strchr(delim, *data) != NULL) { /* * If delim contains both whitespace and non-whitespace characters, * use any combination of one non-whitespace delimiter and * many whitespace delimiters as separator, but not multiple * non-whitespace delimiters. Example with delim = " =": * key value -> "value" * key=value -> "value" * key = value -> "value" * key= value -> "value" * key == value -> "= value" * key==value -> "=value" */ data++; while (*data && isspace((unsigned)*data)) data++; } if (*data == '"') { quote_seen = true; data++; } /* remove space at the end of the value */ p = data + strlen(data); if (p > data) p--; while (p > data && (isspace((unsigned)*p))) p--; /* Strip double quotes only if both leading and trainling quote exist. */ if (p > data && quote_seen) { if (*p == '"') p--; else data--; } if (*(p + 1) != '\0') *(p + 1) = '\0'; } retval = store(ef, current_group, name, data, line); if (retval) goto out; } out: fclose (kf); if (current_group) free (current_group); return retval; } libeconf-0.3.8/lib/getfilecontents.h000066400000000000000000000025301370215501500174160ustar00rootroot00000000000000/* Copyright (C) 2019 SUSE LLC Author: Pascal Arlt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #pragma once #include "libeconf.h" #include "keyfile.h" /* Fill the econf_file struct with values from the given file */ extern econf_err read_file(econf_file *read_file, const char *file, const char *delim, const char *comment); libeconf-0.3.8/lib/helpers.c000066400000000000000000000142041370215501500156570ustar00rootroot00000000000000/* Copyright (C) 2019, 2020 SUSE LLC Author: Pascal Arlt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "libeconf.h" #include "defines.h" #include "helpers.h" #include #include #include #include #include // Combine file path and file name char *combine_strings(const char *string_one, const char *string_two, const char delimiter) { size_t combined_len = strlen(string_one) + strlen(string_two) + 2; char *combined = malloc(combined_len); snprintf(combined, combined_len, "%s%c%s", string_one, delimiter, string_two); return combined; } // Set null value defined in include/defines.h void initialize(econf_file *key_file, size_t num) { key_file->file_entry[num].group = strdup(KEY_FILE_NULL_VALUE); key_file->file_entry[num].key = strdup(KEY_FILE_NULL_VALUE); key_file->file_entry[num].value = strdup(KEY_FILE_NULL_VALUE); } // Remove whitespace from beginning and end, append string terminator char *clearblank(size_t *vlen, char *string) { if (!*vlen) return string; char *buffer = string, *ptr = string; string[*vlen] = 0; while (*string != 0) { if (ptr == buffer && (*string == ' ' || *string == '\t')) { (*vlen)--; } else { *ptr++ = *string; } string++; } while (buffer[*vlen - 1] == ' ' || buffer[*vlen - 1] == '\t') (*vlen)--; buffer[*vlen] = 0; return buffer; } char *get_absolute_path(const char *path, econf_err *error) { char *absolute_path; if(*path != '/') { char buffer[PATH_MAX]; if(!realpath(path, buffer)) { if (error) *error = ECONF_NOFILE; return NULL; } absolute_path = strdup(buffer); } else { absolute_path = strdup(path); } if (absolute_path == NULL && error) *error = ECONF_NOMEM; return absolute_path; } // Remove '[' and ']' from beginning and end char *stripbrackets(char *string) { char *ptr = string, *buffer = string; size_t length = strlen(string) - 1; if (*string == '[' && string[length] == ']') { while (*(++string) != ']') { *buffer++ = *string; } *buffer = 0; } return ptr; } // Add '[' and ']' to the given string char *addbrackets(const char *string) { size_t length = strlen(string); if (!(*string == '[' && string[length - 1] == ']')) { char *buffer = malloc(length + 3); char *cp = buffer; *cp++ = '['; cp = stpcpy (cp, string); *cp++ = ']'; *cp = '\0'; return buffer; } return strdup(string); } // Turn the given string into lower case char *toLowerCase(char *string) { char *ptr = string; while (*string) { *string = tolower(*string); string++; } return ptr; } // Turn the given string into a hash value // Hash function djb2 from Dan J. Bernstein size_t hashstring(const char *string) { size_t hash = 5381; char c; while ((c = *string++)) { hash = ((hash << 5) + hash) + c; } return hash; } // Look for matching key econf_err find_key(econf_file key_file, const char *group, const char *key, size_t *num) { char *grp = (!group || !*group) ? strdup(KEY_FILE_NULL_VALUE) : addbrackets(group); if (grp == NULL) return ECONF_NOMEM; if (!key || !*key) { free(grp); return ECONF_ERROR; } for (size_t i = 0; i < key_file.length; i++) { if (!strcmp(key_file.file_entry[i].group, grp) && !strcmp(key_file.file_entry[i].key, key)) { free(grp); *num = i; return ECONF_SUCCESS; } } // Key not found free(grp); return ECONF_NOKEY; } // Append a new key to an existing econf_file // TODO: If the group is already known the new key should be appended // at the end of that group not at the end of the file. static econf_err new_key (econf_file *key_file, const char *group, const char *key) { econf_err error; char *grp = (!group || !*group) ? strdup(KEY_FILE_NULL_VALUE) : addbrackets(group); if (grp == NULL) return ECONF_NOMEM; if (key_file == NULL || key == NULL) { free(grp); return ECONF_ERROR; } if ((error = key_file_append(key_file))) { free(grp); return error; } if ((error = setGroup(key_file, key_file->length - 1, grp))) { free(grp); return error; } free(grp); return setKey(key_file, key_file->length - 1, key); } // Set value for the given group, key combination. If the combination // does not exist it is created. // TODO: function/void pointer might not be necessary if the value is converted // into a string beforehand. econf_err setKeyValue(econf_err (*function) (econf_file*, size_t, const void*), econf_file *kf, const char *group, const char *key, const void *value) { size_t num; econf_err error = find_key(*kf, group, key, &num); if (error) { if (error != ECONF_NOKEY) { return error; } if ((error = new_key(kf, group, key))) { return error; } num = kf->length - 1; } return function(kf, num, value); } struct file_entry cpy_file_entry(struct file_entry fe) { struct file_entry copied_fe; copied_fe.group = strdup(fe.group); copied_fe.key = strdup(fe.key); if (fe.value) copied_fe.value = strdup(fe.value); else copied_fe.value = NULL; return copied_fe; } libeconf-0.3.8/lib/helpers.h000066400000000000000000000057121370215501500156700ustar00rootroot00000000000000/* Copyright (C) 2019 SUSE LLC Author: Pascal Arlt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #pragma once /* -- helpers.h --- */ #include "keyfile.h" /* This file contains the declaration of functions used by other functions to perform certain basic tasks on multiple instances. */ /* Combine the two given strings with the given delimiter and return the resulting string. */ char *combine_strings(const char *string_one, const char *string_two, const char delimiter); /* Remove whitespace from beginning and end, append string terminator */ char *clearblank(size_t *vlen, char *string); /* Returns the absolute path of a given path */ char *get_absolute_path(const char *path, econf_err *error); /* Remove '[' and ']' from beginning and end */ /* TODO: Function is currently not in use. But needs to be used to strip the brackets from group elements before returning them to the user */ char *stripbrackets(char *string); /* Add '[' and ']' to the given string */ char *addbrackets(const char *string); /* Set default value defined in include/defines.h */ void initialize(econf_file *key_file, size_t num); /* Return the lower case version of a string */ char *toLowerCase(char *str); /* Turn given string into a hash value */ size_t hashstring(const char *str); /* Look for a matching key in the given econf_file. If the key is found num will point to the number of the array which contains the key, if not it will point to -1. */ econf_err find_key(econf_file key_file, const char *group, const char *key, size_t *num); /* Set value for the given group, key combination. If the combination does not exist it is created. */ econf_err setKeyValue(econf_err (*function) (econf_file*, size_t, const void*), econf_file *kf, const char *group, const char *key, const void *value); /* Copy the contents of a file_entry struct */ struct file_entry cpy_file_entry(struct file_entry fe); libeconf-0.3.8/lib/keyfile.c000066400000000000000000000141711370215501500156500ustar00rootroot00000000000000/* Copyright (C) 2019 SUSE LLC Author: Pascal Arlt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "libeconf.h" #include "defines.h" #include "helpers.h" #include "keyfile.h" #include #include #include #include #include #include econf_err key_file_append(econf_file *kf) { /* XXX check return values and for NULL pointers */ if(kf->length++ >= kf->alloc_length) { kf->alloc_length++; kf->file_entry = realloc(kf->file_entry, (kf->alloc_length) * sizeof(struct file_entry)); initialize(kf, kf->alloc_length - 1); } return ECONF_SUCCESS; } /* --- GETTERS --- */ /* XXX all get*ValueNum functions are missing error handling */ econf_err getIntValueNum(econf_file key_file, size_t num, int32_t *result) { *result = strtol(key_file.file_entry[num].value, NULL, 10); return ECONF_SUCCESS; } econf_err getInt64ValueNum(econf_file key_file, size_t num, int64_t *result) { *result = strtoll(key_file.file_entry[num].value, NULL, 10); return ECONF_SUCCESS; } econf_err getUIntValueNum(econf_file key_file, size_t num, uint32_t *result) { *result = strtoul(key_file.file_entry[num].value, NULL, 10); return ECONF_SUCCESS; } econf_err getUInt64ValueNum(econf_file key_file, size_t num, uint64_t *result) { *result = strtoull(key_file.file_entry[num].value, NULL, 10); return ECONF_SUCCESS; } econf_err getFloatValueNum(econf_file key_file, size_t num, float *result) { *result = strtof(key_file.file_entry[num].value, NULL); return ECONF_SUCCESS; } econf_err getDoubleValueNum(econf_file key_file, size_t num, double *result) { *result = strtod(key_file.file_entry[num].value, NULL); return ECONF_SUCCESS; } econf_err getStringValueNum(econf_file key_file, size_t num, char **result) { if (key_file.file_entry[num].value) *result = strdup(key_file.file_entry[num].value); else *result = NULL; return ECONF_SUCCESS; } econf_err getBoolValueNum(econf_file key_file, size_t num, bool *result) { char *value, *tmp; tmp = strdup(key_file.file_entry[num].value); value = toLowerCase(tmp); size_t hash = hashstring(toLowerCase(key_file.file_entry[num].value)); econf_err err = ECONF_SUCCESS; if ((*value == '1' && strlen(tmp) == 1) || hash == YES || hash == TRUE) *result = true; else if ((*value == '0' && strlen(tmp) == 1) || !*value || hash == NO || hash == FALSE) *result = false; else err = ECONF_PARSE_ERROR; free(tmp); return err; } /* --- SETTERS --- */ econf_err setGroup(econf_file *key_file, size_t num, const char *value) { if (key_file == NULL || value == NULL) return ECONF_ERROR; if (key_file->file_entry[num].group) free(key_file->file_entry[num].group); key_file->file_entry[num].group = strdup(value); if (key_file->file_entry[num].group == NULL) return ECONF_NOMEM; return ECONF_SUCCESS; } econf_err setKey(econf_file *key_file, size_t num, const char *value) { if (key_file == NULL || value == NULL) return ECONF_ERROR; if (key_file->file_entry[num].key) free(key_file->file_entry[num].key); key_file->file_entry[num].key = strdup(value); if (key_file->file_entry[num].key == NULL) return ECONF_NOMEM; return ECONF_SUCCESS; } #define econf_setValueNum(FCT_TYPE, TYPE, FMT, PR) \ econf_err set ## FCT_TYPE ## ValueNum(econf_file *ef, size_t num, const void *v) { \ const TYPE *value = (const TYPE*) v; \ char *ptr; \ \ if (asprintf (&ptr, FMT PR, *value) == -1) \ return ECONF_NOMEM; \ \ if (ef->file_entry[num].value) \ free(ef->file_entry[num].value); \ \ ef->file_entry[num].value = ptr; \ \ return ECONF_SUCCESS; \ } econf_setValueNum(Int, int32_t, "%", PRId32) econf_setValueNum(Int64, int64_t, "%", PRId64) econf_setValueNum(UInt, uint32_t, "%", PRIu32) econf_setValueNum(UInt64, uint64_t, "%", PRIu64) #define PRFLOAT ,FLT_DECIMAL_DIG econf_setValueNum(Float, float, "%.*g", PRFLOAT) #define PRDOUBLE ,DBL_DECIMAL_DIG econf_setValueNum(Double, double, "%.*g", PRDOUBLE) econf_err setStringValueNum(econf_file *ef, size_t num, const void *v) { const char *value = (const char*) (v ? v : ""); char *ptr; if ((ptr = strdup (value)) == NULL) return ECONF_NOMEM; if (ef->file_entry[num].value) free(ef->file_entry[num].value); ef->file_entry[num].value = ptr; return ECONF_SUCCESS; } /* XXX This needs to be optimised and error checking added */ econf_err setBoolValueNum(econf_file *kf, size_t num, const void *v) { const char *value = (const char*) (v ? v : ""); econf_err error = ECONF_SUCCESS; char *tmp = strdup(value); size_t hash = hashstring(toLowerCase(tmp)); if ((*value == '1' && strlen(tmp) == 1) || hash == YES || hash == TRUE) { free(kf->file_entry[num].value); kf->file_entry[num].value = strdup("true"); } else if ((*value == '0' && strlen(tmp) == 1) || !*value || hash == NO || hash == FALSE) { free(kf->file_entry[num].value); kf->file_entry[num].value = strdup("false"); } else if (hash == KEY_FILE_NULL_VALUE_HASH) { free(kf->file_entry[num].value); kf->file_entry[num].value = strdup(KEY_FILE_NULL_VALUE); } else { error = ECONF_ERROR; } free(tmp); return error; } libeconf-0.3.8/lib/keyfile.h000066400000000000000000000116541370215501500156600ustar00rootroot00000000000000/* Copyright (C) 2019 SUSE LLC Author: Pascal Arlt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #pragma once /* --- keyfile.h --- */ #include #include #include /* This file contains the definition of the econf_file struct declared in libeconf.h as well as the functions to get and set a specified element of the struct. All functions return an error code != 0 on error defined in libeconf.h. */ /* Definition of the econf_file struct and its inner file_entry struct. */ typedef struct econf_file { /* The file_entry struct contains the group, key and value of every key/value entry found in a config file or set via the set functions. If no group is found or provided the group is set to KEY_FILE_NULL_VALUE. */ struct file_entry { char *group, *key, *value; uint64_t line_number; } * file_entry; /* length represents the current amount of key/value entries in econf_file and alloc_length the the amount of currently allocated file_entry elements within the struct. If length would exceed alloc_length it's increased. */ size_t length, alloc_length; /* delimiter: char used to assign a value to a key comment: Used to specify which char to regard as comment indicator. */ /* TODO: Should eventually be of type *char to allow multiple character delimiters and comment indicators. Alternatively they could be removed from the struct and be passed as parameters to the read/write functions for config files */ char delimiter, comment; /* Binary variable to determine whether econf_file should be freed after being merged with another econf_file. */ bool on_merge_delete; char *path; } econf_file; /* Increases both length and alloc_length of key_file by one and initializes new elements of struct file_entry. */ econf_err key_file_append(econf_file *key_file); /* GETTERS */ /* Functions used to get a set value from key_file depending on num. Expects a pointer of fitting type and writes the result into the pointer. num corresponds to the respective instance of the file_entry array. TODO: Error checking and defining return value on error needs to done. */ econf_err getIntValueNum(econf_file key_file, size_t num, int32_t *result); econf_err getInt64ValueNum(econf_file key_file, size_t num, int64_t *result); econf_err getUIntValueNum(econf_file key_file, size_t num, uint32_t *result); econf_err getUInt64ValueNum(econf_file key_file, size_t num, uint64_t *result); econf_err getFloatValueNum(econf_file key_file, size_t num, float *result); econf_err getDoubleValueNum(econf_file key_file, size_t num, double *result); econf_err getStringValueNum(econf_file key_file, size_t num, char **result); econf_err getBoolValueNum(econf_file key_file, size_t num, bool *result); /* SETTERS */ /* Set the group of the file_entry element number num */ econf_err setGroup(econf_file *key_file, size_t num, const char *value); /* Set the key of the file_entry element number num */ econf_err setKey(econf_file *key_file, size_t num, const char *value); /* Functions used to set a value from key_file depending on num. Expects a void pointer to the value which is cast to the corresponding type inside the function. num corresponds to the respective instance of the file_entry array. */ econf_err setIntValueNum(econf_file *key_file, size_t num, const void *value); econf_err setInt64ValueNum(econf_file *key_file, size_t num, const void *value); econf_err setUIntValueNum(econf_file *key_file, size_t num, const void *value); econf_err setUInt64ValueNum(econf_file *key_file, size_t num, const void *value); econf_err setFloatValueNum(econf_file *key_file, size_t num, const void *value); econf_err setDoubleValueNum(econf_file *key_file, size_t num, const void *value); econf_err setStringValueNum(econf_file *key_file, size_t num, const void *value); econf_err setBoolValueNum(econf_file *key_file, size_t num, const void *value); libeconf-0.3.8/lib/libeconf.c000066400000000000000000000330741370215501500160040ustar00rootroot00000000000000/* Copyright (C) 2019 SUSE LLC Author: Pascal Arlt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "libeconf.h" #include "defines.h" #include "getfilecontents.h" #include "helpers.h" #include "keyfile.h" #include "mergefiles.h" #include #include #include // Create a new econf_file. Allocation is based on // KEY_FILE_KEY_FILE_KEY_FILE_DEFAULT_LENGTH // defined in include/defines.h econf_err econf_newKeyFile(econf_file **result, char delimiter, char comment) { econf_file *key_file = calloc(1, sizeof(econf_file)); if (key_file == NULL) return ECONF_NOMEM; key_file->alloc_length = KEY_FILE_DEFAULT_LENGTH; key_file->length = 0; key_file->delimiter = delimiter; key_file->comment = comment; key_file->file_entry = malloc(KEY_FILE_DEFAULT_LENGTH * sizeof(struct file_entry)); if (key_file->file_entry == NULL) { free (key_file); return ECONF_NOMEM; } for (size_t i = 0; i < KEY_FILE_DEFAULT_LENGTH; i++) initialize(key_file, i); *result = key_file; return ECONF_SUCCESS; } econf_err econf_newIniFile(econf_file **result) { return econf_newKeyFile(result, '=', '#'); } // Process the file of the given file_name and save its contents into key_file econf_err econf_readFile(econf_file **key_file, const char *file_name, const char *delim, const char *comment) { econf_err t_err; if (key_file == NULL || file_name == NULL || delim == NULL) return ECONF_ERROR; // Get absolute path if not provided char *absolute_path = get_absolute_path(file_name, &t_err); if (absolute_path == NULL) return t_err; *key_file = calloc(1, sizeof(econf_file)); if (*key_file == NULL) { free (absolute_path); return ECONF_NOMEM; } if (comment && *comment) (*key_file)->comment = comment[0]; else (*key_file)->comment = '#'; t_err = read_file(*key_file, absolute_path, delim, comment); free (absolute_path); if(t_err) { econf_free(*key_file); *key_file = NULL; return t_err; } return ECONF_SUCCESS; } // Merge the contents of two key files econf_err econf_mergeFiles(econf_file **merged_file, econf_file *usr_file, econf_file *etc_file) { if (merged_file == NULL || usr_file == NULL || etc_file == NULL) return ECONF_ERROR; *merged_file = calloc(1, sizeof(econf_file)); if (*merged_file == NULL) return ECONF_NOMEM; (*merged_file)->delimiter = usr_file->delimiter; (*merged_file)->comment = usr_file->comment; struct file_entry *fe = malloc((etc_file->length + usr_file->length) * sizeof(struct file_entry)); if (fe == NULL) { free (*merged_file); *merged_file = NULL; return ECONF_NOMEM; } size_t merge_length = 0; if ((etc_file->file_entry == NULL || !strcmp(etc_file->file_entry->group, KEY_FILE_NULL_VALUE)) && (usr_file->file_entry == NULL || strcmp(usr_file->file_entry->group, KEY_FILE_NULL_VALUE))) { merge_length = insert_nogroup(&fe, etc_file); } merge_length = merge_existing_groups(&fe, usr_file, etc_file, merge_length); merge_length = add_new_groups(&fe, usr_file, etc_file, merge_length); (*merged_file)->length = merge_length; (*merged_file)->alloc_length = merge_length; (*merged_file)->file_entry = fe; return ECONF_SUCCESS; } econf_err econf_readDirs(econf_file **result, const char *dist_conf_dir, const char *etc_conf_dir, const char *project_name, const char *config_suffix, const char *delim, const char *comment) { size_t size = 0; const char *suffix, *default_dirs[3] = {NULL, NULL, NULL}; char *distfile, *etcfile, *cp; econf_file **key_files, *key_file; econf_err error; /* config_suffix must be provided and should not be "" */ if (config_suffix == NULL || strlen (config_suffix) == 0 || project_name == NULL || strlen (project_name) == 0 || delim == NULL) return ECONF_ERROR; // Prepend a . to the config suffix if not provided if (config_suffix[0] == '.') suffix = config_suffix; else { cp = alloca (strlen(config_suffix) + 2); cp[0] = '.'; strcpy(cp+1, config_suffix); suffix = cp; } /* create file names for etc and distribution config */ if (dist_conf_dir != NULL) { distfile = alloca(strlen (dist_conf_dir) + strlen (project_name) + strlen (suffix) + 2); cp = stpcpy (distfile, dist_conf_dir); *cp++ = '/'; cp = stpcpy (cp, project_name); stpcpy (cp, suffix); } else distfile = NULL; if (etc_conf_dir != NULL) { etcfile = alloca(strlen (etc_conf_dir) + strlen (project_name) + strlen (suffix) + 2); cp = stpcpy (etcfile, etc_conf_dir); *cp++ = '/'; cp = stpcpy (cp, project_name); stpcpy (cp, suffix); } else etcfile = NULL; if (etcfile) { error = econf_readFile(&key_file, etcfile, delim, comment); if (error && error != ECONF_NOFILE) return error; } if (etcfile && !error) { /* /etc/. does exist, ignore /usr */ default_dirs[0] = etc_conf_dir; size = 1; } else { /* /etc/. does not exist, so read /usr/etc and merge all *.d files. */ if (distfile) { error = econf_readFile(&key_file, distfile, delim, comment); if (error && error != ECONF_NOFILE) return error; } if (distfile && !error) /* /usr/etc/. does exist */ size = 1; default_dirs[0] = dist_conf_dir; default_dirs[1] = etc_conf_dir; } /* XXX Re-add get_default_dirs in a reworked version, which adds additional directories to look at, e.g. XDG or home directory */ /* create space to store the econf_files for merging */ key_files = calloc((++size), sizeof(econf_file*)); if (key_files == NULL) return ECONF_NOMEM; if (size == 2) { key_file->on_merge_delete = 1; key_files[0] = key_file; } int i = 0; while (default_dirs[i]) { /* Indicate which directories to look for. The order is: "default_dirs/project_name.suffix.d/" XXX make this configureable: "default_dirs/project_name/conf.d/" "default_dirs/project_name.d/" "default_dirs/project_name/" */ const char *conf_dirs[] = { NULL, /* "/conf.d/", ".d/", "/", */ NULL}; char *project_path = combine_strings(default_dirs[i], project_name, '/'); char *suffix_d = malloc (strlen(suffix) + 4); /* + strlen(".d/") */ /* XXX ENOMEM/NULL pointer check */ cp = stpcpy(suffix_d, suffix); stpcpy(cp, ".d/"); conf_dirs[0] = suffix_d; key_files = traverse_conf_dirs(key_files, conf_dirs, &size, project_path, suffix, delim, comment); /* XXX ENOMEM/NULL pointer check */ free(suffix_d); free(project_path); i++; } key_files[size - 1] = NULL; // Merge the list of acquired key_files into merged_file error = merge_econf_files(key_files, result); free(key_files); if (size == 1) return ECONF_NOFILE; else return error; } // Write content of a econf_file struct to specified location econf_err econf_writeFile(econf_file *key_file, const char *save_to_dir, const char *file_name) { if (!key_file) return ECONF_ERROR; // Check if the directory exists // XXX use stat instead of opendir DIR *dir = opendir(save_to_dir); if (dir) closedir(dir); else return ECONF_NOFILE; // Create a file handle for the specified file char *save_to = combine_strings(save_to_dir, file_name, '/'); if (save_to == NULL) return ECONF_NOMEM; FILE *kf = fopen(save_to, "w"); if (kf == NULL) return ECONF_WRITEERROR; // Write to file for (size_t i = 0; i < key_file->length; i++) { if (!i || strcmp(key_file->file_entry[i - 1].group, key_file->file_entry[i].group)) { if (i) fprintf(kf, "\n"); if (strcmp(key_file->file_entry[i].group, KEY_FILE_NULL_VALUE)) fprintf(kf, "%s\n", key_file->file_entry[i].group); } fprintf(kf, "%s%c%s\n", key_file->file_entry[i].key, key_file->delimiter, key_file->file_entry[i].value); } // Clean up free(save_to); fclose(kf); return ECONF_SUCCESS; } /* GETTER FUNCTIONS */ // TODO: Currently only works with a sorted econf_file. If a new // key with an existing group is appended at the end the group // will show twice. So the key file either needs to be sorted // upon entering a new key or the function must ensure only // unique values are returned. econf_err econf_getGroups(econf_file *kf, size_t *length, char ***groups) { if (!kf || groups == NULL) return ECONF_ERROR; size_t tmp = 0; bool *uniques = calloc(kf->length,sizeof(bool)); if (uniques == NULL) return ECONF_NOMEM; for (size_t i = 0; i < kf->length; i++) { if ((!i || strcmp(kf->file_entry[i].group, kf->file_entry[i - 1].group)) && strcmp(kf->file_entry[i].group, KEY_FILE_NULL_VALUE)) { uniques[i] = 1; tmp++; } } if (!tmp) { free(uniques); return ECONF_ERROR; } *groups = calloc(tmp + 1, sizeof(char*)); if (*groups == NULL) return ECONF_NOMEM; tmp = 0; for (size_t i = 0; i < kf->length; i++) if (uniques[i]) (*groups)[tmp++] = strdup(kf->file_entry[i].group); if (length != NULL) *length = tmp; free(uniques); return ECONF_SUCCESS; } // TODO: Same issue as with getGroups() econf_err econf_getKeys(econf_file *kf, const char *grp, size_t *length, char ***keys) { if (!kf) return ECONF_ERROR; size_t tmp = 0; char *group = ((!grp || !*grp) ? strdup(KEY_FILE_NULL_VALUE) : addbrackets(grp)); if (group == NULL) return ECONF_NOMEM; bool *uniques = calloc(kf->length, sizeof(bool)); if (uniques == NULL) { free(group); return ECONF_NOMEM; } for (size_t i = 0; i < kf->length; i++) { if (!strcmp(kf->file_entry[i].group, group) && (!i || strcmp(kf->file_entry[i].key, kf->file_entry[i - 1].key))) { uniques[i] = 1; tmp++; } } free(group); if (!tmp) { free (uniques); return ECONF_NOKEY; } *keys = calloc(tmp + 1, sizeof(char*)); if (*keys == NULL) { free (uniques); return ECONF_NOMEM; } for (size_t i = 0, j = 0; i < kf->length; i++) if (uniques[i]) (*keys)[j++] = strdup(kf->file_entry[i].key); if (length != NULL) *length = tmp; free(uniques); return ECONF_SUCCESS; } /* The econf_get*Value functions are identical except for result value type, so let's create them via a macro. */ #define econf_getValue(FCT_TYPE, TYPE) \ econf_err econf_get ## FCT_TYPE ## Value(econf_file *kf, const char *group, \ const char *key, TYPE *result) { \ if (!kf) \ return ECONF_ERROR; \ \ size_t num; \ econf_err error = find_key(*kf, group, key, &num); \ if (error) \ return error; \ return get ## FCT_TYPE ## ValueNum(*kf, num, result); \ } econf_getValue(Int, int32_t) econf_getValue(Int64, int64_t) econf_getValue(UInt, uint32_t) econf_getValue(UInt64, uint64_t) econf_getValue(Float, float) econf_getValue(Double, double) econf_getValue(String, char *) econf_getValue(Bool, bool) /* SETTER FUNCTIONS */ /* The econf_set*Value functions are identical except for set value type, so let's create them via a macro. */ #define libeconf_setValue(TYPE, VALTYPE, VALARG) \ econf_err econf_set ## TYPE ## Value(econf_file *kf, const char *group, \ const char *key, VALTYPE value) { \ if (!kf) \ return ECONF_ERROR; \ return setKeyValue(set ## TYPE ## ValueNum, kf, group, key, VALARG); \ } libeconf_setValue(Int, int32_t, &value) libeconf_setValue(Int64, int64_t, &value) libeconf_setValue(UInt, uint32_t, &value) libeconf_setValue(UInt64, uint64_t, &value) libeconf_setValue(Float, float, &value) libeconf_setValue(Double, double, &value) libeconf_setValue(String, const char *, value) libeconf_setValue(Bool, const char *, value) /* --- DESTROY FUNCTIONS --- */ void econf_freeArray(char** array) { if (!array) { return; } char *tmp = (char*) array; while (*array) free(*array++); free(tmp); } // Free memory allocated by key_file void econf_freeFile(econf_file *key_file) { if (!key_file) return; for (size_t i = 0; i < key_file->alloc_length; i++) { if (key_file->file_entry[i].group) free(key_file->file_entry[i].group); if (key_file->file_entry[i].key) free(key_file->file_entry[i].key); if (key_file->file_entry[i].value) free(key_file->file_entry[i].value); } if (key_file->file_entry) free(key_file->file_entry); if (key_file->path) free(key_file->path); free(key_file); } libeconf-0.3.8/lib/libeconf.map000066400000000000000000000020001370215501500163200ustar00rootroot00000000000000LIBECONF_0.2 { global: econf_errString; econf_freeArray; econf_freeFile; econf_getBoolValue; econf_getDoubleValue; econf_getFloatValue; econf_getGroups; econf_getInt64Value; econf_getIntValue; econf_getKeys; econf_getStringValue; econf_getUInt64Value; econf_getUIntValue; econf_mergeFiles; econf_readDirs; econf_readFile; econf_setBoolValue; econf_setDoubleValue; econf_setFloatValue; econf_setIntValue; econf_setInt64Value; econf_setStringValue; econf_setUIntValue; econf_setUInt64Value; local: *; }; LIBECONF_ALPHA { global: econf_newIniFile; econf_newKeyFile; econf_writeFile; } LIBECONF_0.2; LIBECONF_0.3 { global: econf_getBoolValueDef; econf_getDoubleValueDef; econf_getFloatValueDef; econf_getGroupsDef; econf_getInt64ValueDef; econf_getIntValueDef; econf_getKeysDef; econf_getStringValueDef; econf_getUInt64ValueDef; econf_getUIntValueDef; } LIBECONF_0.2; libeconf-0.3.8/lib/mergefiles.c000066400000000000000000000175321370215501500163460ustar00rootroot00000000000000/* Copyright (C) 2019 SUSE LLC Author: Pascal Arlt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "libeconf.h" #include "defines.h" #include "helpers.h" #include "mergefiles.h" #include #include #include #include // Insert the content of "etc_file.file_entry" into "fe" if there is no // group specified size_t insert_nogroup(struct file_entry **fe, econf_file *ef) { size_t etc_start = 0; while (etc_start < ef->length && !strcmp(ef->file_entry[etc_start].group, KEY_FILE_NULL_VALUE)) { (*fe)[etc_start] = cpy_file_entry(ef->file_entry[etc_start]); etc_start++; } return etc_start; } // Merge contents from existing usr_file groups // uf: usr_file, ef: etc_file size_t merge_existing_groups(struct file_entry **fe, econf_file *uf, econf_file *ef, const size_t etc_start) { char new_key; size_t merge_length = etc_start, tmp = etc_start, added_keys = etc_start; for (size_t i = 0; i <= uf->length; i++) { // Check if the group has changed in the last iteration if (i == uf->length || (i && strcmp(uf->file_entry[i].group, uf->file_entry[i - 1].group))) { for (size_t j = etc_start; j < ef->length; j++) { // Check for matching groups if (!strcmp(uf->file_entry[i - 1].group, ef->file_entry[j].group)) { new_key = 1; for (size_t k = merge_length; k < i + tmp; k++) { // If an existing key is found in ef take the value from ef if (!strcmp((*fe)[k].key, ef->file_entry[j].key)) { free((*fe)[k].value); (*fe)[k].value = strdup(ef->file_entry[j].value); new_key = 0; break; } } // If a new key is found for an existing group append it to the group if (new_key) (*fe)[i + added_keys++] = cpy_file_entry(ef->file_entry[j]); } } merge_length = i + added_keys; // Temporary value to reduce amount of iterations in inner for loop tmp = added_keys; } if (i != uf->length) (*fe)[i + added_keys] = cpy_file_entry(uf->file_entry[i]); } return merge_length; } // Add entries from etc_file exclusive groups size_t add_new_groups(struct file_entry **fe, econf_file *uf, econf_file *ef, const size_t merge_length) { size_t added_keys = merge_length; char new_key; for (size_t i = 0; i < ef->length; i++) { if (!strcmp(ef->file_entry[i].group, KEY_FILE_NULL_VALUE)) continue; new_key = 1; for (size_t j = 0; j < uf->length; j++) { if (!strcmp(uf->file_entry[j].group, ef->file_entry[i].group)) { new_key = 0; break; } } if (new_key) (*fe)[added_keys++] = cpy_file_entry(ef->file_entry[i]); } *fe = realloc(*fe, added_keys * sizeof(struct file_entry)); return added_keys; } #if 0 // TODO: Make this function configureable with econf_set_opt() // TODO: provide the initial array from the calling function (needs to be // already big enough to hold this additional two entries) char **get_default_dirs(const char *usr_conf_dir, const char *etc_conf_dir) { size_t default_dir_number = 3, dir_num = 0; char **default_dirs = malloc(default_dir_number * sizeof(char *)); if (default_dirs == NULL) return NULL; if (etc_conf_dir) { // Set config directory in /etc default_dirs[dir_num++] = strdup(etc_conf_dir); /* XXX ENOMEM check */ } if (usr_conf_dir) { // Set config directory in /usr default_dirs[dir_num++] = strdup(usr_conf_dir); /* XXX ENOMEM check */ } // TODO: Use secure_getenv() instead and check if the variable is actually set // For security reasons, this code should only be enabled if the application // sets a flag to do so (introduce econf_set_opt() for this. // Using user supplied configs can lead to a security problem (e.g. su) // If XDG_CONFIG_DIRS is set check it as well if(getenv("XDG_CONFIG_DIRS")) { default_dirs = realloc(default_dirs, ++default_dir_number * sizeof(char *)); default_dirs[dir_num++] = strdup(getenv("XDG_CONFIG_DIRS")); } // XDG config home if (getenv("XDG_CONFIG_HOME")) { default_dirs[dir_num++] = strdup(getenv("XDG_CONFIG_HOME")); } else { sprintf(default_dirs[dir_num++] = malloc(strlen("/home//.config") + strlen(getenv("USERNAME")) + 1), "/home/%s/.config", getenv("USERNAME")); } default_dirs[dir_num] = NULL; return default_dirs; } #endif // Check if the given directory exists. If so look for config files // with the given suffix static econf_file ** check_conf_dir(econf_file **key_files, size_t *size, const char *path, const char *config_suffix, const char *delim, const char *comment) { struct dirent **de; int num_dirs = scandir(path, &de, NULL, alphasort); if(num_dirs > 0) { for (int i = 0; i < num_dirs; i++) { size_t lenstr = strlen(de[i]->d_name); size_t lensuffix = strlen(config_suffix); if (lensuffix < lenstr && strncmp(de[i]->d_name + lenstr - lensuffix, config_suffix, lensuffix) == 0) { char *file_path = combine_strings(path, de[i]->d_name, '/'); econf_file *key_file; econf_err error = econf_readFile(&key_file, file_path, delim, comment); free(file_path); if(!error && key_file) { key_file->on_merge_delete = 1; key_files[(*size) - 1] = key_file; key_files = realloc(key_files, ++(*size) * sizeof(econf_file *)); } } free(de[i]); } free(de); } return key_files; } /* XXX Convert to return econf_err */ econf_file **traverse_conf_dirs(econf_file **key_files, const char *config_dirs[], size_t *size, const char *path, const char *config_suffix, const char *delim, const char *comment) { int i; if (config_dirs == NULL) return NULL; /* XXX ECONF_ERROR */ i = 0; while (config_dirs[i] != NULL) { char *fulldir, *cp; if ((fulldir = malloc (strlen(path) + strlen (config_dirs[i]) + 1)) == NULL) return NULL; cp = stpcpy (fulldir, path); stpcpy (cp, config_dirs[i++]); key_files = check_conf_dir(key_files, size, fulldir, config_suffix, delim, comment); free (fulldir); } return key_files; } econf_err merge_econf_files(econf_file **key_files, econf_file **merged_files) { if (key_files == NULL || merged_files == NULL) return ECONF_ERROR; *merged_files = *key_files++; if(*merged_files == NULL) return ECONF_ERROR; while(*key_files) { econf_err error; econf_file *tmp = *merged_files; error = econf_mergeFiles(merged_files, *merged_files, *key_files); if (error || *merged_files == NULL) return error; (*merged_files)->on_merge_delete = 1; if(tmp->on_merge_delete) { econf_free(tmp); } if((*key_files)->on_merge_delete) { econf_free(*key_files); } key_files++; } return ECONF_SUCCESS; } libeconf-0.3.8/lib/mergefiles.h000066400000000000000000000046531370215501500163530ustar00rootroot00000000000000/* Copyright (C) 2019 SUSE LLC Author: Pascal Arlt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #pragma once #include "keyfile.h" #include /* This file contains the declaration of the functions used by econf_mergeFiles to merge the contents of two econf_files. */ /* Insert the content of "etc_file.file_entry" into "fe" if there is no group specified. */ size_t insert_nogroup(struct file_entry **fe, econf_file *ef); /* Merge contents from existing usr_file groups */ size_t merge_existing_groups(struct file_entry **fe, econf_file *uf, econf_file *ef, const size_t etc_start); /* Add entries from etc_file exclusive groups */ size_t add_new_groups(struct file_entry **fe, econf_file *uf, econf_file *ef, const size_t merge_length); /* Returns the default dirs to iterate through when merging */ char **get_default_dirs(const char *usr_conf_dir, const char *etc_conf_dir); /* Receives a list of config directories to look for and calls 'check_conf_dir' */ econf_file **traverse_conf_dirs(econf_file **key_files, const char *conf_dirs[], size_t *size, const char *path, const char *config_suffix, const char *delim, const char *comment); /* Merge an array of given econf_files into one */ econf_err merge_econf_files(econf_file **key_files, econf_file **merged_files); libeconf-0.3.8/meson.build000066400000000000000000000035501370215501500154470ustar00rootroot00000000000000project( 'libeconf', 'c', meson_version : '>= 0.49.0', default_options : ['buildtype=debugoptimized', 'default_library=shared', 'b_pie=true', 'warning_level=3',], license : 'MIT', version : '0.3.8', ) cc = meson.get_compiler('c') pkg = import('pkgconfig') inc = include_directories('include') add_project_arguments(['-D_GNU_SOURCE=1', '-DXTSTRINGDEFINES', '-D_FORTIFY_SOURCE=2'], language : 'c') possible_cc_flags = [ '-Werror', '-fstack-protector-strong', '-funwind-tables', '-fasynchronous-unwind-tables', '-fstack-clash-protection', '-Werror=return-type', '-flto=8', '-Wbad-function-cast', '-Wcast-align', '-Wcast-qual', '-Winline', '-Wmissing-declarations', '-Wmissing-prototypes', '-Wnested-externs', '-Wshadow', '-Wstrict-prototypes', '-Wundef', ] add_project_arguments(cc.get_supported_arguments(possible_cc_flags), language : 'c') libeconf_src = files( 'lib/econf_errString.c', 'lib/get_value_def.c', 'lib/getfilecontents.c', 'lib/helpers.c', 'lib/keyfile.c', 'lib/libeconf.c', 'lib/mergefiles.c', ) example_src = ['example/example.c'] mapfile = 'lib/libeconf.map' version_flag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile) lib = library( 'econf', libeconf_src, include_directories : inc, install : true, link_args : version_flag, link_depends : mapfile, version : meson.project_version(), soversion : '0', ) install_headers('include/libeconf.h') pkg.generate( lib, name : 'libeconf', description : 'highly flexible library to manage key=value configuration files', version : meson.project_version(), ) libeconf_dep = declare_dependency( link_with : lib, include_directories : inc, ) # Example executable('example', example_src, dependencies : libeconf_dep) # Unit tests subdir('tests') libeconf-0.3.8/tests/000077500000000000000000000000001370215501500144445ustar00rootroot00000000000000libeconf-0.3.8/tests/CMakeLists.txt000066400000000000000000000032631370215501500172100ustar00rootroot00000000000000# Set make check target add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}) # Set up macro for building and adding tests macro(BuildAndAddTest TESTNAME) if (${TESTNAME} STREQUAL "tst-getconfdirs2") add_executable(${TESTNAME} EXCLUDE_FROM_ALL tst-getconfdirs1.c) else() add_executable(${TESTNAME} EXCLUDE_FROM_ALL ${TESTNAME}.c) endif() target_link_libraries(${TESTNAME} PRIVATE econf) if (${TESTNAME} STREQUAL "tst-getconfdirs1") target_compile_options(${TESTNAME} PRIVATE -DTESTSDIR=\"${PROJECT_SOURCE_DIR}/tests/\" -DSUFFIX=\".conf\") elseif (${TESTNAME} STREQUAL "tst-getconfdirs2") target_compile_options(${TESTNAME} PRIVATE -DTESTSDIR=\"${PROJECT_SOURCE_DIR}/tests/\" -DSUFFIX=\"conf\") else() target_compile_options(${TESTNAME} PRIVATE -DTESTSDIR=\"${PROJECT_SOURCE_DIR}/tests/\") endif() add_test(NAME ${TESTNAME} COMMAND ${TESTNAME}) add_dependencies(check ${TESTNAME}) endmacro() set(TESTS tst-filedoesnotexit1 tst-merge1 tst-merge2 tst-merge3 tst-merge4 tst-merge5 tst-logindefs1 tst-logindefs2 tst-arguments1 tst-arguments2 tst-arguments3 tst-arguments4 tst-arguments5 tst-getconfdirs1 tst-getconfdirs2 tst-getconfdirs3 tst-getconfdirs4 tst-getconfdirs5 tst-getconfdirs6 tst-getconfdirs7 tst-econf_errstring1 tst-setgetvalues1 tst-groups1 tst-groups2 tst-groups3 tst-groups4 tst-parseconfig1 tst-quote1 ) foreach (TESTCASE ${TESTS}) BuildAndAddTest(${TESTCASE}) endforeach() libeconf-0.3.8/tests/data/000077500000000000000000000000001370215501500153555ustar00rootroot00000000000000libeconf-0.3.8/tests/data/append-option/000077500000000000000000000000001370215501500201325ustar00rootroot00000000000000libeconf-0.3.8/tests/data/append-option/README.md000066400000000000000000000007321370215501500214130ustar00rootroot00000000000000Append options -------------- Append options are an extension to list options: * Existing values in the list are not overwritten, but the new values are appended instead. * Appending an empty value resets the list. Example: key = one two -> {"key": ["one", "two"]} key = three four -> {"key": ["one", "two", "three", "four"]} key = -> {"key": []} key = five -> {"key": ["five"]} libeconf-0.3.8/tests/data/append-option/int-append-option-append/000077500000000000000000000000001370215501500247445ustar00rootroot00000000000000libeconf-0.3.8/tests/data/append-option/int-append-option-append/input.ini000066400000000000000000000001001370215501500265730ustar00rootroot00000000000000[main] append_option = 1 2 [main] append_option = 3 4 libeconf-0.3.8/tests/data/append-option/int-append-option-append/output.json000066400000000000000000000001051370215501500271730ustar00rootroot00000000000000{ "main": { "string_append_option": [1, 2, 3, 4] } } libeconf-0.3.8/tests/data/append-option/int-append-option-init/000077500000000000000000000000001370215501500244405ustar00rootroot00000000000000libeconf-0.3.8/tests/data/append-option/int-append-option-init/input.ini000066400000000000000000000000431370215501500262750ustar00rootroot00000000000000[main] append_option = 1 2 libeconf-0.3.8/tests/data/append-option/int-append-option-init/output.json000066400000000000000000000000771370215501500266770ustar00rootroot00000000000000{ "main": { "string_append_option": [1, 2] } } libeconf-0.3.8/tests/data/append-option/int-append-option-reset-append/000077500000000000000000000000001370215501500260645ustar00rootroot00000000000000libeconf-0.3.8/tests/data/append-option/int-append-option-reset-append/input.ini000066400000000000000000000001301370215501500277160ustar00rootroot00000000000000[main] append_option = 1 2 [main] append_option = [main] append_option = 3 libeconf-0.3.8/tests/data/append-option/int-append-option-reset-append/output.json000066400000000000000000000000741370215501500303200ustar00rootroot00000000000000{ "main": { "string_append_option": [3] } } libeconf-0.3.8/tests/data/append-option/int-append-option-reset/000077500000000000000000000000001370215501500246175ustar00rootroot00000000000000libeconf-0.3.8/tests/data/append-option/int-append-option-reset/input.ini000066400000000000000000000000751370215501500264610ustar00rootroot00000000000000[main] append_option = 1 2 [main] append_option = libeconf-0.3.8/tests/data/append-option/int-append-option-reset/output.json000066400000000000000000000000731370215501500270520ustar00rootroot00000000000000{ "main": { "string_append_option": [] } } libeconf-0.3.8/tests/data/append-option/string-append-option-append/000077500000000000000000000000001370215501500254605ustar00rootroot00000000000000libeconf-0.3.8/tests/data/append-option/string-append-option-append/input.ini000066400000000000000000000001241370215501500273150ustar00rootroot00000000000000[main] append_option = one two [main] append_option = three four libeconf-0.3.8/tests/data/append-option/string-append-option-append/output.json000066400000000000000000000001301370215501500277050ustar00rootroot00000000000000{ "main": { "string_append_option": ["one", "two", "three", "four"] } } libeconf-0.3.8/tests/data/append-option/string-append-option-init/000077500000000000000000000000001370215501500251545ustar00rootroot00000000000000libeconf-0.3.8/tests/data/append-option/string-append-option-init/input.ini000066400000000000000000000000471370215501500270150ustar00rootroot00000000000000[main] append_option = one two libeconf-0.3.8/tests/data/append-option/string-append-option-init/output.json000066400000000000000000000001071370215501500274050ustar00rootroot00000000000000{ "main": { "string_append_option": ["one", "two"] } } libeconf-0.3.8/tests/data/append-option/string-append-option-reset-append/000077500000000000000000000000001370215501500266005ustar00rootroot00000000000000libeconf-0.3.8/tests/data/append-option/string-append-option-reset-append/input.ini000066400000000000000000000001401370215501500304330ustar00rootroot00000000000000[main] append_option = one two [main] append_option = [main] append_option = three libeconf-0.3.8/tests/data/append-option/string-append-option-reset-append/output.json000066400000000000000000000001021370215501500310240ustar00rootroot00000000000000{ "main": { "string_append_option": ["three"] } } libeconf-0.3.8/tests/data/append-option/string-append-option-reset/000077500000000000000000000000001370215501500253335ustar00rootroot00000000000000libeconf-0.3.8/tests/data/append-option/string-append-option-reset/input.ini000066400000000000000000000001011370215501500271630ustar00rootroot00000000000000[main] append_option = one two [main] append_option = libeconf-0.3.8/tests/data/append-option/string-append-option-reset/output.json000066400000000000000000000000731370215501500275660ustar00rootroot00000000000000{ "main": { "string_append_option": [] } } libeconf-0.3.8/tests/data/basic-types/000077500000000000000000000000001370215501500176005ustar00rootroot00000000000000libeconf-0.3.8/tests/data/basic-types/input.ini000066400000000000000000000026331370215501500214440ustar00rootroot00000000000000[main] # strings string_null = _null_ string_empty = string_with_spaces = string with spaces string_escaped_with_leading_and_trailing_spaces = " string with spaces " string_with_newlines = line one line two string_escaped_with_newlines = "line one line two" string_with_quotes = \" string_with_quotes_v2 = "\"" # string lists string_list_null = _null_ string_list_empty = string_list_one_line = line one string_list_multiple_lines = line one line two string_list_multiple_lines_v2 = line one line two line three # numbers int64_null = _null_ int64_min = -9223372036854775808 int64_max = 9223372036854775807 # number lists int64_list_null = _null_ int64_list_empty = int64_list_multiple_lines = 1 2 int64_list_multiple_lines_v2 = 1 2 3 4 5 # bool bool_null = _null_ bool_false_0 = 0 bool_false_false = false bool_false_False = False bool_false_no = no bool_false_No = No bool_true_0 = 0 bool_true_true = true bool_true_True = True bool_true_yes = yes bool_true_Yes = Yes # human readable time interval converted to seconds # no units == seconds time_interval_null = _null_ time_interval_number = 1 time_interval_s = 1s time_interval_S = 1S time_interval_m = 1m time_interval_M = 1M time_interval_h = 1h time_interval_H = 1H time_interval_d = 1d time_interval_D = 1D # TODO: date, time, datetime # https://en.wikipedia.org/wiki/ISO_8601 # https://tools.ietf.org/html/rfc3339 libeconf-0.3.8/tests/data/basic-types/output.json000066400000000000000000000030031370215501500220270ustar00rootroot00000000000000{ "main": { "string_empty": "", "string_with_spaces": "string with spaces", "string_null": null, "string_with_newlines": "line one\nline two", "string_escaped_with_newlines": "line one\n line two", "string_with_quotes": "\"", "string_with_quotes_v2": "\"", "string_list_null": null, "string_list_empty": [], "string_list_one_line": ["line one"], "string_list_multiple_lines": ["line one", "line two"], "string_list_multiple_lines_v2": ["line one", "line two", "line three"], "int64_min": -9223372036854775808, "int64_max": 9223372036854775807, "int64_null": null, "int64_list_null": null, "int64_list_empty": [], "int64_list_multiple_lines": [1, 2], "int64_list_multiple_lines_v2": [1, 2, 3, 4, 5], "bool_null": null, "bool_false_0": false, "bool_false_false": false, "bool_false_False": false, "bool_false_no": false, "bool_false_No": false, "bool_true_0": true, "bool_true_true": true, "bool_true_True": true, "bool_true_yes": true, "bool_true_Yes": true, "time_interval_null": null, "time_interval_number": 1, "time_interval_s": 1, "time_interval_S": 1, "time_interval_m": 60, "time_interval_M": 60, "time_interval_h": 3600, "time_interval_H": 3600, "time_interval_d": 86400, "time_interval_D": 86400 } } libeconf-0.3.8/tests/meson.build000066400000000000000000000111161370215501500166060ustar00rootroot00000000000000# This file builds and runs the unit tests testdir = join_paths(meson.source_root(), 'tests/') test_args = ['-DTESTSDIR="' + testdir + '"'] tst_filedoesnotexit1_exe = executable('tst-filedoesnotexit1', 'tst-filedoesnotexit1.c', c_args: test_args, dependencies : libeconf_dep) test('tst-filedoesnotexit1', tst_filedoesnotexit1_exe) tst_merge1_exe = executable('tst-merge1', 'tst-merge1.c', c_args: test_args, dependencies : libeconf_dep) test('tst-merge1', tst_merge1_exe) tst_merge2_exe = executable('tst-merge2', 'tst-merge2.c', c_args: test_args, dependencies : libeconf_dep) test('tst-merge2', tst_merge2_exe) tst_merge3_exe = executable('tst-merge3', 'tst-merge3.c', c_args: test_args, dependencies : libeconf_dep) test('tst-merge3', tst_merge3_exe) tst_merge4_exe = executable('tst-merge4', 'tst-merge4.c', c_args: test_args, dependencies : libeconf_dep) test('tst-merge4', tst_merge4_exe) tst_merge5_exe = executable('tst-merge5', 'tst-merge5.c', c_args: test_args, dependencies : libeconf_dep) test('tst-merge5', tst_merge5_exe) tst_logindefs1_exe = executable('tst-logindefs1', 'tst-logindefs1.c', c_args: test_args, dependencies : libeconf_dep) test('tst-logindefs1', tst_logindefs1_exe) tst_logindefs2_exe = executable('tst-logindefs2', 'tst-logindefs2.c', c_args: test_args, dependencies : libeconf_dep) test('tst-logindefs2', tst_logindefs2_exe) tst_arguments1_exe = executable('tst-arguments1', 'tst-arguments1.c', c_args: test_args, dependencies : libeconf_dep) test('tst-arguments1', tst_arguments1_exe) tst_arguments2_exe = executable('tst-arguments2', 'tst-arguments2.c', c_args: test_args, dependencies : libeconf_dep) test('tst-arguments2', tst_arguments2_exe) tst_arguments3_exe = executable('tst-arguments3', 'tst-arguments3.c', c_args: test_args, dependencies : libeconf_dep) test('tst-arguments3', tst_arguments3_exe) tst_arguments4_exe = executable('tst-arguments4', 'tst-arguments4.c', c_args: test_args, dependencies : libeconf_dep) test('tst-arguments4', tst_arguments4_exe) tst_arguments5_exe = executable('tst-arguments5', 'tst-arguments5.c', c_args: test_args, dependencies : libeconf_dep) test('tst-arguments5', tst_arguments5_exe) tst_getconfdirs1_exe = executable('tst-getconfdirs1', 'tst-getconfdirs1.c', c_args: ['-DSUFFIX=".conf"', test_args], dependencies : libeconf_dep) test('tst-getconfdirs1', tst_getconfdirs1_exe) tst_getconfdirs2_exe = executable('tst-getconfdirs2', 'tst-getconfdirs1.c', c_args: ['-DSUFFIX="conf"', test_args], dependencies : libeconf_dep) test('tst-getconfdirs2', tst_getconfdirs2_exe) tst_getconfdirs3_exe = executable('tst-getconfdirs3', 'tst-getconfdirs3.c', c_args: test_args, dependencies : libeconf_dep) test('tst-getconfdirs3', tst_getconfdirs3_exe) tst_getconfdirs4_exe = executable('tst-getconfdirs4', 'tst-getconfdirs4.c', c_args: test_args, dependencies : libeconf_dep) test('tst-getconfdirs4', tst_getconfdirs4_exe) tst_getconfdirs5_exe = executable('tst-getconfdirs5', 'tst-getconfdirs5.c', c_args: test_args, dependencies : libeconf_dep) test('tst-getconfdirs5', tst_getconfdirs5_exe) tst_getconfdirs6_exe = executable('tst-getconfdirs6', 'tst-getconfdirs6.c', c_args: test_args, dependencies : libeconf_dep) test('tst-getconfdirs6', tst_getconfdirs6_exe) tst_getconfdirs7_exe = executable('tst-getconfdirs7', 'tst-getconfdirs7.c', c_args: test_args, dependencies : libeconf_dep) test('tst-getconfdirs7', tst_getconfdirs7_exe) tst_econf_errstring1_exe = executable('tst-econf_errstring1', 'tst-econf_errstring1.c', c_args: test_args, dependencies : libeconf_dep) test('tst-econf_errstring1', tst_econf_errstring1_exe) tst_setgetvalues1_exe = executable('tst-setgetvalues1', 'tst-setgetvalues1.c', c_args: test_args, dependencies : libeconf_dep) test('tst-setgetvalues1', tst_setgetvalues1_exe) tst_groups1_exe = executable('tst-groups1', 'tst-groups1.c', c_args: test_args, dependencies : libeconf_dep) test('tst-groups1', tst_groups1_exe) tst_groups2_exe = executable('tst-groups2', 'tst-groups2.c', c_args: test_args, dependencies : libeconf_dep) test('tst-groups2', tst_groups2_exe) tst_groups3_exe = executable('tst-groups3', 'tst-groups3.c', c_args: test_args, dependencies : libeconf_dep) test('tst-groups3', tst_groups3_exe) tst_groups4_exe = executable('tst-groups4', 'tst-groups4.c', c_args: test_args, dependencies : libeconf_dep) test('tst-groups4', tst_groups4_exe) tst_parseconfig1_exe = executable('tst-parseconfig1', 'tst-parseconfig1.c', c_args: test_args, dependencies : libeconf_dep) test('tst-parseconfig1', tst_parseconfig1_exe) tst_quote1_exe = executable('tst-quote1', 'tst-quote1.c', c_args: test_args, dependencies : libeconf_dep) test('tst-quote1', tst_quote1_exe) libeconf-0.3.8/tests/tst-arguments-data/000077500000000000000000000000001370215501500201705ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-arguments-data/etc/000077500000000000000000000000001370215501500207435ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-arguments-data/etc/arguments.conf000066400000000000000000000000121370215501500236100ustar00rootroot00000000000000KEY=VALUE libeconf-0.3.8/tests/tst-arguments1.c000066400000000000000000000014231370215501500175060ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: Provide some NULL pointers as arguments. libeconf shouldn't crash but do a correct error handling */ int main(void) { econf_file *key_file = NULL; char *val; econf_err error; error = econf_readFile (&key_file, TESTSDIR"tst-arguments-data/etc/arguments.conf", "=", "#"); if (error) { fprintf (stderr, "ERROR: couldn't read configuration file: %s\n", econf_errString(error)); return 1; } if ((error = econf_getStringValue (key_file, "", "KEY", &val)) || val == NULL || strlen(val) == 0) { fprintf (stderr, "KEY returns nothing!\n"); return 1; } free (val); econf_free (key_file); return 0; } libeconf-0.3.8/tests/tst-arguments2.c000066400000000000000000000013501370215501500175060ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: * Provide a NULL pointer for the group. Means there is no group. */ int main(void) { econf_file *key_file = NULL; char *val; econf_err error; if ((error = econf_readFile (&key_file, TESTSDIR"tst-arguments-data/etc/arguments.conf", "=", "#"))) { fprintf (stderr, "ERROR: couldn't read configuration file: %s\n", econf_errString(error)); return 1; } if ((error = econf_getStringValue (key_file, NULL, "KEY", &val)) || val == NULL || strlen(val) == 0) { fprintf (stderr, "KEY returns nothing!\n"); return 1; } free (val); econf_free (key_file); return 0; } libeconf-0.3.8/tests/tst-arguments3.c000066400000000000000000000013211370215501500175050ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: * Provide a NULL pointer for the key. We should return an error, not crash */ int main(void) { econf_file *key_file = NULL; char *val; econf_err error; if ((error = econf_readFile (&key_file, TESTSDIR"tst-arguments-data/etc/arguments.conf", "=", "#"))) { fprintf (stderr, "ERROR: couldn't read configuration file: %s\n", econf_errString(error)); return 1; } if (!econf_getStringValue (key_file, "", NULL, &val)) { fprintf (stderr, "ERROR: return values for NULL key_file are wrong!\n"); return 1; } econf_free (key_file); return 0; } libeconf-0.3.8/tests/tst-arguments4.c000066400000000000000000000013201370215501500175050ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: * Provide a NULL pointer for key_file. We should return an error, not crash */ int main(void) { econf_file *key_file = NULL; char *val; econf_err error; if ((error = econf_readFile (&key_file, TESTSDIR"tst-arguments-data/etc/arguments.conf", "=", "#"))) { fprintf (stderr, "ERROR: couldn't read configuration file: %s\n", econf_errString(error)); return 1; } if (!econf_getStringValue (NULL, "", "KEY", &val)) { fprintf (stderr, "ERROR: return values for NULL key_file are wrong!\n"); return 1; } econf_free (key_file); return 0; } libeconf-0.3.8/tests/tst-arguments5-data/000077500000000000000000000000001370215501500202555ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-arguments5-data/etc/000077500000000000000000000000001370215501500210305ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-arguments5-data/etc/arguments5.conf000066400000000000000000000000221370215501500237630ustar00rootroot00000000000000KEY1=etc ETC=true libeconf-0.3.8/tests/tst-arguments5.c000066400000000000000000000010121370215501500175040ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: * Provide NULL pointers as argument. We should return an error, not crash */ int main(void) { econf_file *key_file = NULL; econf_err error; if ((error = econf_readFile (&key_file, TESTSDIR"tst-arguments5-data/etc/arguments5.conf", NULL, NULL))) { printf ("Not crashed, but error: %s\n", econf_errString(error)); return 0; } econf_free (key_file); return 0; } libeconf-0.3.8/tests/tst-econf_errstring1.c000066400000000000000000000006201370215501500206700ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test Case: print more econf error strings than we did define. Only way to crash is by off by one errors. */ int main(void) { int i; for (i = 0; i < 10; i++) printf ("%.3i: %s\n", i, econf_errString(i)); printf ("MAX: %s\n", econf_errString(INT_MAX)); return 0; } libeconf-0.3.8/tests/tst-filedoesnotexit1.c000066400000000000000000000011671370215501500207130ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include "libeconf.h" /* Test case: Try to open a non existing configuration file and cleanup afterwards */ int main(void) { econf_file *key_file = NULL; econf_err error; error = econf_readFile (&key_file, "doesnotexist1.conf", "=", "#"); if (key_file) { fprintf (stderr, "Got key_file for non-existing configuration file!\n"); econf_free(key_file); return 1; } if (error != ECONF_NOFILE) { fprintf (stderr, "Wrong error code: [%i] %s\n", error, econf_errString(error)); return 1; } return 0; } libeconf-0.3.8/tests/tst-getconfdirs1-data/000077500000000000000000000000001370215501500205535ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs1-data/etc/000077500000000000000000000000001370215501500213265ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs1-data/etc/getconfdir.conf000066400000000000000000000000221370215501500243130ustar00rootroot00000000000000KEY1=etc ETC=true libeconf-0.3.8/tests/tst-getconfdirs1-data/etc/getconfdir.conf.d/000077500000000000000000000000001370215501500246205ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs1-data/etc/getconfdir.conf.d/1-override.conf000066400000000000000000000000161370215501500274410ustar00rootroot00000000000000KEY1=etcconfd libeconf-0.3.8/tests/tst-getconfdirs1-data/etc/getconfdir.conf.d/5-override.conf000066400000000000000000000000161370215501500274450ustar00rootroot00000000000000OVERRIDE=true libeconf-0.3.8/tests/tst-getconfdirs1-data/etc/getconfdir.conf.d/9-broken000066400000000000000000000000201370215501500261610ustar00rootroot00000000000000OVERRIDE=broken libeconf-0.3.8/tests/tst-getconfdirs1-data/usr/000077500000000000000000000000001370215501500213645ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs1-data/usr/etc/000077500000000000000000000000001370215501500221375ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs1-data/usr/etc/getconfdir.conf000066400000000000000000000000301370215501500251230ustar00rootroot00000000000000KEY1=usretc USRETC=true libeconf-0.3.8/tests/tst-getconfdirs1.c000066400000000000000000000033071370215501500200130ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: Test the systemd like behavior: /usr/etc/getconfdir.conf exists /etc/getconfdir.conf exists /etc/getconfidr.conf.d/.conf exists libeconf should ignore /usr/etc/getconfdir.conf, as this contains */ static int check_key(econf_file *key_file, char *key, char *expected_val) { char *val = NULL; econf_err error = econf_getStringValue (key_file, "", key, &val); if (expected_val == NULL) { if (val == NULL) return 0; fprintf (stderr, "ERROR: %s has value \"%s\"\n", key, val); return 1; } if (val == NULL || strlen(val) == 0) { fprintf (stderr, "ERROR: %s returns nothing! (%s)\n", key, econf_errString(error)); return 1; } if (strcmp (val, expected_val) != 0) { fprintf (stderr, "ERROR: %s is not \"%s\"\n", key, expected_val); return 1; } printf("Ok: %s=%s\n", key, val); free (val); return 0; } int main(void) { econf_file *key_file = NULL; int retval = 0; econf_err error; error = econf_readDirs (&key_file, TESTSDIR"tst-getconfdirs1-data/usr/etc", TESTSDIR"tst-getconfdirs1-data/etc", "getconfdir", SUFFIX, "=", "#"); if (error) { fprintf (stderr, "ERROR: econf_readDirs: %s\n", econf_errString(error)); return 1; } if (check_key(key_file, "KEY1", "etcconfd") != 0) retval = 1; if (check_key(key_file, "USRETC", NULL) != 0) retval = 1; if (check_key(key_file, "ETC", "true") != 0) retval = 1; if (check_key(key_file, "OVERRIDE", "true") != 0) retval = 1; econf_free (key_file); return retval; } libeconf-0.3.8/tests/tst-getconfdirs3-data/000077500000000000000000000000001370215501500205555ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs3-data/usr/000077500000000000000000000000001370215501500213665ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs3-data/usr/etc/000077500000000000000000000000001370215501500221415ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs3-data/usr/etc/getconfdir.conf000066400000000000000000000000301370215501500251250ustar00rootroot00000000000000KEY1=usretc USRETC=true libeconf-0.3.8/tests/tst-getconfdirs3.c000066400000000000000000000032541370215501500200160ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: Test the systemd like behavior: /usr/etc/getconfdir.conf exists No configuration files in /etc exists libeconf should only use /usr/etc/getconfdir.conf */ static int check_key(econf_file *key_file, char *key, char *expected_val) { char *val = NULL; econf_err error = econf_getStringValue (key_file, "", key, &val); if (expected_val == NULL) { if (val == NULL) return 0; fprintf (stderr, "ERROR: %s has value \"%s\"\n", key, val); return 1; } if (val == NULL || strlen(val) == 0) { fprintf (stderr, "ERROR: %s returns nothing! (%s)\n", key, econf_errString(error)); return 1; } if (strcmp (val, expected_val) != 0) { fprintf (stderr, "ERROR: %s is not \"%s\"\n", key, expected_val); return 1; } printf("Ok: %s=%s\n", key, val); free (val); return 0; } int main(void) { econf_file *key_file = NULL; int retval = 0; econf_err error; error = econf_readDirs (&key_file, TESTSDIR"tst-getconfdirs3-data/usr/etc", TESTSDIR"tst-getconfdirs3-data/etc", "getconfdir", ".conf", "=", "#"); if (error) { fprintf (stderr, "ERROR: econf_readDirs returned NULL: %s\n", econf_errString(error)); return 1; } if (check_key(key_file, "KEY1", "usretc") != 0) retval = 1; if (check_key(key_file, "USRETC", "true") != 0) retval = 1; if (check_key(key_file, "ETC", NULL) != 0) retval = 1; if (check_key(key_file, "OVERRIDE", NULL) != 0) retval = 1; econf_free (key_file); return retval; } libeconf-0.3.8/tests/tst-getconfdirs4-data/000077500000000000000000000000001370215501500205565ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs4-data/etc/000077500000000000000000000000001370215501500213315ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs4-data/etc/getconfdir.conf000066400000000000000000000000221370215501500243160ustar00rootroot00000000000000KEY1=etc ETC=true libeconf-0.3.8/tests/tst-getconfdirs4.c000066400000000000000000000032601370215501500200140ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: /etc/getconfdir.conf exists No configuration files in /usr/etc exists This is to make migration easier, if the same config file is read by different projects. */ static int check_key(econf_file *key_file, char *key, char *expected_val) { char *val = NULL; econf_err error = econf_getStringValue (key_file, "", key, &val); if (expected_val == NULL) { if (val == NULL) return 0; fprintf (stderr, "ERROR: %s has value \"%s\"\n", key, val); return 1; } if (val == NULL || strlen(val) == 0) { fprintf (stderr, "ERROR: %s returns nothing! (%s)\n", key, econf_errString(error)); return 1; } if (strcmp (val, expected_val) != 0) { fprintf (stderr, "ERROR: %s is not \"%s\"\n", key, expected_val); return 1; } printf("Ok: %s=%s\n", key, val); free (val); return 0; } int main(void) { econf_file *key_file = NULL; int retval = 0; econf_err error; error = econf_readDirs (&key_file, TESTSDIR"tst-getconfdirs4-data/usr/etc", TESTSDIR"tst-getconfdirs4-data/etc", "getconfdir", ".conf", "=", "#"); if (error) { fprintf (stderr, "ERROR: econf_readDirs returned NULL: %s\n", econf_errString(error)); return 1; } if (check_key(key_file, "KEY1", "etc") != 0) retval = 1; if (check_key(key_file, "ETC", "true") != 0) retval = 1; if (check_key(key_file, "USRETC", NULL) != 0) retval = 1; if (check_key(key_file, "OVERRIDE", NULL) != 0) retval = 1; econf_free (key_file); return retval; } libeconf-0.3.8/tests/tst-getconfdirs5-data/000077500000000000000000000000001370215501500205575ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs5-data/etc/000077500000000000000000000000001370215501500213325ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs5-data/etc/sysctl.conf.d/000077500000000000000000000000001370215501500240215ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs5-data/etc/sysctl.conf.d/getconfdir.conf000066400000000000000000000000221370215501500270060ustar00rootroot00000000000000KEY1=etc ETC=true libeconf-0.3.8/tests/tst-getconfdirs5-data/usr/000077500000000000000000000000001370215501500213705ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs5-data/usr/etc/000077500000000000000000000000001370215501500221435ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs5-data/usr/etc/sysctl.conf.d/000077500000000000000000000000001370215501500246325ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs5-data/usr/etc/sysctl.conf.d/getconfdir.conf000066400000000000000000000000301370215501500276160ustar00rootroot00000000000000KEY1=usretc USRETC=true libeconf-0.3.8/tests/tst-getconfdirs5.c000066400000000000000000000031611370215501500200150ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: /usr/etc/sysctl.d/<*>.conf and /etc/sysctl.d/<*>.conf files are read. There are no /usr/etc/sysctl.conf nor /etc/sysctl.conf */ static int check_key(econf_file *key_file, char *key, char *expected_val) { char *val = NULL; econf_err error = econf_getStringValue (key_file, "", key, &val); if (expected_val == NULL) { if (val == NULL) return 0; fprintf (stderr, "ERROR: %s has value \"%s\"\n", key, val); return 1; } if (val == NULL || strlen(val) == 0) { fprintf (stderr, "ERROR: %s returns nothing! (%s)\n", key, econf_errString(error)); return 1; } if (strcmp (val, expected_val) != 0) { fprintf (stderr, "ERROR: %s is not \"%s\"\n", key, expected_val); return 1; } printf("Ok: %s=%s\n", key, val); free (val); return 0; } int main(void) { econf_file *key_file = NULL; int retval = 0; econf_err error; error = econf_readDirs (&key_file, TESTSDIR"tst-getconfdirs5-data/usr/etc", TESTSDIR"tst-getconfdirs5-data/etc", "sysctl", "conf", "=", ";#"); if (error) { fprintf (stderr, "ERROR: econf_readDirs: %s\n", econf_errString(error)); return 1; } if (check_key(key_file, "KEY1", "etc") != 0) retval = 1; if (check_key(key_file, "ETC", "true") != 0) retval = 1; if (check_key(key_file, "USRETC", "true") != 0) retval = 1; if (check_key(key_file, "OVERRIDE", NULL) != 0) retval = 1; econf_free (key_file); return retval; } libeconf-0.3.8/tests/tst-getconfdirs6-data/000077500000000000000000000000001370215501500205605ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs6-data/etc/000077500000000000000000000000001370215501500213335ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs6-data/etc/getconfdir.ini.d/000077500000000000000000000000001370215501500244575ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs6-data/etc/getconfdir.ini.d/1-override.ini000066400000000000000000000000151370215501500271310ustar00rootroot00000000000000KEY1=etcinid libeconf-0.3.8/tests/tst-getconfdirs6-data/etc/getconfdir.ini.d/5-override.ini000066400000000000000000000000161370215501500271360ustar00rootroot00000000000000OVERRIDE=true libeconf-0.3.8/tests/tst-getconfdirs6-data/etc/getconfdir.ini.d/9-broken000066400000000000000000000000201370215501500260200ustar00rootroot00000000000000OVERRIDE=broken libeconf-0.3.8/tests/tst-getconfdirs6-data/usr/000077500000000000000000000000001370215501500213715ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs6-data/usr/etc/000077500000000000000000000000001370215501500221445ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs6-data/usr/etc/getconfdir.ini.d/000077500000000000000000000000001370215501500252705ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs6-data/usr/etc/getconfdir.ini.d/getconfdir.ini000066400000000000000000000000341370215501500301120ustar00rootroot00000000000000KEY1=usretcinid USRETC=true libeconf-0.3.8/tests/tst-getconfdirs6.c000066400000000000000000000033031370215501500200140ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: /usr/etc/getconfdir.ini.d/.ini exists /etc/getconfdir.ini does not exist /etc/getconfidr.ini.d/.ini exists libeconf should not ignore /usr/etc/getconfdir.ini.d */ static int check_key(econf_file *key_file, char *key, char *expected_val) { char *val = NULL; econf_err error = econf_getStringValue (key_file, "", key, &val); if (expected_val == NULL) { if (val == NULL) return 0; fprintf (stderr, "ERROR: %s has value \"%s\"\n", key, val); return 1; } if (val == NULL || strlen(val) == 0) { fprintf (stderr, "ERROR: %s returns nothing! (%s)\n", key, econf_errString(error)); return 1; } if (strcmp (val, expected_val) != 0) { fprintf (stderr, "ERROR: %s is \"%s\" instead of \"%s\".\n", key, val, expected_val); return 1; } printf("Ok: %s=%s\n", key, val); free (val); return 0; } int main(void) { econf_file *key_file = NULL; int retval = 0; econf_err error; error = econf_readDirs (&key_file, TESTSDIR"tst-getconfdirs6-data/usr/etc", TESTSDIR"tst-getconfdirs6-data/etc", "getconfdir", "ini", "=", "#"); if (error) { fprintf (stderr, "ERROR: econf_readDirs: %s\n", econf_errString(error)); return 1; } if (check_key(key_file, "KEY1", "etcinid") != 0) retval = 1; if (check_key(key_file, "USRETC", "true") != 0) retval = 1; if (check_key(key_file, "ETC", NULL) != 0) retval = 1; if (check_key(key_file, "OVERRIDE", "true") != 0) retval = 1; econf_free (key_file); return retval; } libeconf-0.3.8/tests/tst-getconfdirs7-data/000077500000000000000000000000001370215501500205615ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs7-data/etc/000077500000000000000000000000001370215501500213345ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs7-data/etc/lcdnetmon.conf.d/000077500000000000000000000000001370215501500244655ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs7-data/etc/lcdnetmon.conf.d/lcd2004-ip.conf000066400000000000000000000000731370215501500270120ustar00rootroot00000000000000ROWS=4 LINE1="eth0/eth1" LINE2="\4{eth0}" LINE3="\4{eth1}" libeconf-0.3.8/tests/tst-getconfdirs7-data/usr/000077500000000000000000000000001370215501500213725ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs7-data/usr/etc/000077500000000000000000000000001370215501500221455ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-getconfdirs7-data/usr/etc/lcdnetmon.conf000066400000000000000000000001161370215501500247750ustar00rootroot00000000000000BUSID=1 ADDRESS=0x27 ROWS=2 LINE1="IP Address" LINE2="\4{eth0}" LINE3= LINE4= libeconf-0.3.8/tests/tst-getconfdirs7.c000066400000000000000000000034611370215501500200220ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: Read /usr/etc with empty values, add overide file which replaces empty values with values */ static int check_key(econf_file *key_file, char *key, char *expected_val) { char *val = NULL; econf_err error = econf_getStringValue (key_file, "", key, &val); if (expected_val == NULL) { if (val == NULL) return 0; fprintf (stderr, "ERROR: %s has value \"%s\"\n", key, val); return 1; } if (val == NULL || strlen(val) == 0) { fprintf (stderr, "ERROR: %s returns nothing! (%s)\n", key, econf_errString(error)); return 1; } if (strcmp (val, expected_val) != 0) { fprintf (stderr, "ERROR: %s is \"%s\" instead of \"%s\".\n", key, val, expected_val); return 1; } printf("Ok: %s=%s\n", key, val); free (val); return 0; } int main(void) { econf_file *key_file = NULL; int retval = 0; econf_err error; error = econf_readDirs (&key_file, TESTSDIR"tst-getconfdirs7-data/usr/etc", TESTSDIR"tst-getconfdirs7-data/etc", "lcdnetmon", "conf", "=", "#"); if (error) { fprintf (stderr, "ERROR: econf_readDirs: %s\n", econf_errString(error)); return 1; } if (check_key(key_file, "BUSID", "1") != 0) retval = 1; if (check_key(key_file, "ADDRESS", "0x27") != 0) retval = 1; if (check_key(key_file, "ROWS", "4") != 0) retval = 1; if (check_key(key_file, "LINE1", "eth0/eth1") != 0) retval = 1; if (check_key(key_file, "LINE2", "\\4{eth0}") != 0) retval = 1; if (check_key(key_file, "LINE3", "\\4{eth1}") != 0) retval = 1; if (check_key(key_file, "LINE4", NULL) != 0) retval = 1; econf_free (key_file); return retval; } libeconf-0.3.8/tests/tst-groups1.c000066400000000000000000000046751370215501500170340ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include "libeconf.h" /* Test case: Create new file in memory, store all kind of types and read them again to verify, they where correctly stored. */ static int print_error_set (const char *type, econf_err error) { fprintf (stderr, "ERROR: couldn't set type '%s': %s\n", type, econf_errString(error)); return 1; } static int print_error_get (const char *value, const char *setgroup, const char *getgroup, econf_err error) { fprintf (stderr, "ERROR: set '%s' in group '%s', tried to get from '%s': %s\n", value, setgroup, getgroup, econf_errString(error)); return 1; } /* check_type(const char *, String, "String", "%s") */ static bool check_String (econf_file *key_file, const char *value, const char *setgroup, const char *getgroup) { econf_err error; if ((error = econf_setStringValue(key_file, setgroup, "KEY", value))) { print_error_set ("String", error); return false; } char *val_String; if ((error = econf_getStringValue(key_file, getgroup, "KEY", &val_String))) { print_error_get (value, setgroup, getgroup, error); return false; } /* NULL means empty string */ if (strcmp(val_String, value?value:"") != 0) { fprintf (stderr, "ERROR: Set String: '%s', Got: '%s'\n", value, val_String); return false; } free(val_String); return true; } int main(void) { econf_file *key_file = NULL; econf_err error; int retval = 0; if ((error = econf_newKeyFile(&key_file, '=', '#'))) { fprintf (stderr, "ERROR: couldn't create new file: %s\n", econf_errString(error)); return 1; } /* test reading a key from an empty key_file */ int dummy; if ((error = econf_getIntValue(key_file, "doesnotexist", "KEY", &dummy)) != ECONF_NOKEY) { print_error_get ("int", "doesnotexist", "doesnotexist", error); retval = 1; } if (!check_String (key_file, NULL, NULL, NULL)) retval=1; if (!check_String (key_file, NULL, "group1", "[group1]")) retval=1; if (!check_String (key_file, "", "group2", "[group2]")) retval=1; if (!check_String (key_file, "TaTa", "[group2]", "group2")) retval=1; if (!check_String (key_file, "TeST", "[group3]", "[group3]")) retval=1; if (!check_String (key_file, "dummy", "group4", "group4")) retval=1; econf_free (key_file); return retval; } libeconf-0.3.8/tests/tst-groups2.c000066400000000000000000000034621370215501500170260ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: Create internal econf_file with one group and key, check it's valid, list all groups, which should return exactly this one. */ int main(void) { econf_file *key_file = NULL; char **groups; size_t group_number; const char *group = "towel"; const char *key = "42"; const char *val = "The answer, not question"; econf_err error; int retval = 0; if ((error = econf_newKeyFile (&key_file, '=', '#'))) { fprintf (stderr, "ERROR: couldn't read configuration file: %s\n", econf_errString(error)); return 1; } if ((error = econf_setStringValue(key_file, group, key, val))) { fprintf (stderr, "Error setting key '%s' with value '%s' in group '%s': %s\n", key, val, group, econf_errString(error)); return 1; } char *gval; if ((error = econf_getStringValue(key_file, group, key, &gval))) { fprintf (stderr, "Error getting keys: %s\n", econf_errString(error)); return 1; } if (strcmp(val, gval) != 0) { fprintf (stderr, "Wrong value: expected='%s', got='%s'\n", val, gval); return 1; } free (gval); if ((error = econf_getGroups(key_file, &group_number, &groups))) { fprintf (stderr, "Error getting all groups: %s\n", econf_errString(error)); return 1; } if (group_number == 0) { fprintf (stderr, "No groups found?\n"); return 1; } if (group_number > 1) { fprintf (stderr, "Too many groups found? (got %zu, expected 1)\n", group_number); retval = 1; } for (size_t i = 0; i < group_number; i++) { printf ("%zu: %s\n", i, groups[i]); } econf_free (groups); econf_free (key_file); return retval; } libeconf-0.3.8/tests/tst-groups3-data/000077500000000000000000000000001370215501500175655ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-groups3-data/groups.conf000066400000000000000000000002211370215501500217460ustar00rootroot00000000000000[global] key=global [section2] key=section2 section3 key=section3 [blablabla] key=blablabla [section5] key=section5 [section6] key=section6 libeconf-0.3.8/tests/tst-groups3.c000066400000000000000000000031731370215501500170260ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: Open file and read all group entries and list them. */ int main(void) { econf_file *key_file = NULL; char **groups; size_t group_number; char *val; econf_err error; int retval = 0; if ((error = econf_readFile (&key_file, TESTSDIR"tst-groups3-data/groups.conf", "=", "#"))) { fprintf (stderr, "ERROR: couldn't read configuration file: %s\n", econf_errString(error)); return 1; } if ((error = econf_getGroups(key_file, &group_number, &groups))) { fprintf (stderr, "Error getting all groups: %s\n", econf_errString(error)); econf_free (key_file); return 1; } if (group_number == 0) { fprintf (stderr, "No groups found?\n"); econf_free (key_file); return 1; } if (group_number != 5) { fprintf (stderr, "Wrong number of groups found, got %zu, expected 5\n", group_number); retval = 1; } printf ("Found the following groups:\n"); for (size_t i = 0; i < group_number; i++) printf ("%zu: %s\n", i, groups[i]); /* Try to get the key for each group and check, it is the correct one */ for (size_t i = 0; i < group_number; i++) { if ((error = econf_getStringValue(key_file, groups[i], "key", &val))) { fprintf (stderr, "Error getting key for group '%s': %s\n", groups[i], econf_errString(error)); retval = 1; } else { printf ("%zu: Group: %s, Value: %s\n", i, groups[i], val); free (val); } } econf_free (groups); econf_free (key_file); return retval; } libeconf-0.3.8/tests/tst-groups4.c000066400000000000000000000025651370215501500170330ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: Create internal econf_file with one group and key, check it's valid, list all groups with NULLs as last two arguments. */ int main(void) { econf_file *key_file = NULL; const char *group = "towel"; const char *key = "42"; const char *val = "The answer, not question"; econf_err error; if ((error = econf_newKeyFile (&key_file, '=', '#'))) { fprintf (stderr, "ERROR: couldn't read configuration file: %s\n", econf_errString(error)); return 1; } if ((error = econf_setStringValue(key_file, group, key, val))) { fprintf (stderr, "Error setting key '%s' with value '%s' in group '%s': %s\n", key, val, group, econf_errString(error)); return 1; } char *gval; if ((error = econf_getStringValue(key_file, group, key, &gval))) { fprintf (stderr, "Error getting keys: %s\n", econf_errString(error)); return 1; } if (strcmp(val, gval) != 0) { fprintf (stderr, "Wrong value: expected='%s', got='%s'\n", val, gval); return 1; } free (gval); if (!(error = econf_getGroups(key_file, NULL, NULL))) { fprintf (stderr, "No error getting all groups, but should give one\n"); return 1; } econf_free (key_file); return 0; } libeconf-0.3.8/tests/tst-logindefs1-data/000077500000000000000000000000001370215501500202165ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-logindefs1-data/etc/000077500000000000000000000000001370215501500207715ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-logindefs1-data/etc/login.defs000066400000000000000000000257361370215501500227610ustar00rootroot00000000000000# # /etc/login.defs - Configuration control definitions for the shadow package. # # $Id$ # # # Delay in seconds before being allowed another attempt after a login failure # Note: When PAM is used, some modules may enforce a minimum delay (e.g. # pam_unix(8) enforces a 2s delay) # FAIL_DELAY 3 # # Enable logging and display of /var/log/faillog login(1) failure info. # FAILLOG_ENAB yes # # Enable display of unknown usernames when login(1) failures are recorded. # LOG_UNKFAIL_ENAB no # # Enable logging of successful logins # LOG_OK_LOGINS no # # Enable logging and display of /var/log/lastlog login(1) time info. # LASTLOG_ENAB yes # # Limit the highest user ID number for which the lastlog entries should # be updated. # # No LASTLOG_UID_MAX means that there is no user ID limit for writing # lastlog entries. # #LASTLOG_UID_MAX # # Enable checking and display of mailbox status upon login. # # Disable if the shell startup files already check for mail # ("mailx -e" or equivalent). # MAIL_CHECK_ENAB yes # # Enable additional checks upon password changes. # OBSCURE_CHECKS_ENAB yes # # Enable checking of time restrictions specified in /etc/porttime. # PORTTIME_CHECKS_ENAB yes # # Enable setting of ulimit, umask, and niceness from passwd(5) gecos field. # QUOTAS_ENAB yes # # Enable "syslog" logging of su(1) activity - in addition to sulog file logging. # SYSLOG_SG_ENAB does the same for newgrp(1) and sg(1). # SYSLOG_SU_ENAB yes SYSLOG_SG_ENAB yes # # If defined, either full pathname of a file containing device names or # a ":" delimited list of device names. Root logins will be allowed only # from these devices. # CONSOLE /etc/securetty #CONSOLE console:tty01:tty02:tty03:tty04 # # If defined, all su(1) activity is logged to this file. # #SULOG_FILE /var/log/sulog # # If defined, ":" delimited list of "message of the day" files to # be displayed upon login. # MOTD_FILE /etc/motd #MOTD_FILE /etc/motd:/usr/lib/news/news-motd # # If defined, this file will be output before each login(1) prompt. # #ISSUE_FILE /etc/issue # # If defined, file which maps tty line to TERM environment parameter. # Each line of the file is in a format similar to "vt100 tty01". # #TTYTYPE_FILE /etc/ttytype # # If defined, login(1) failures will be logged here in a utmp format. # last(1), when invoked as lastb(1), will read /var/log/btmp, so... # FTMP_FILE /var/log/btmp # # If defined, name of file whose presence will inhibit non-root # logins. The content of this file should be a message indicating # why logins are inhibited. # NOLOGINS_FILE /etc/nologin # # If defined, the command name to display when running "su -". For # example, if this is defined as "su" then ps(1) will display the # command as "-su". If not defined, then ps(1) will display the # name of the shell actually being run, e.g. something like "-sh". # SU_NAME su # # *REQUIRED* # Directory where mailboxes reside, _or_ name of file, relative to the # home directory. If you _do_ define both, MAIL_DIR takes precedence. # MAIL_DIR /var/spool/mail #MAIL_FILE .mail # # If defined, file which inhibits all the usual chatter during the login # sequence. If a full pathname, then hushed mode will be enabled if the # user's name or shell are found in the file. If not a full pathname, then # hushed mode will be enabled if the file exists in the user's home directory. # HUSHLOGIN_FILE .hushlogin #HUSHLOGIN_FILE /etc/hushlogins # # If defined, either a TZ environment parameter spec or the # fully-rooted pathname of a file containing such a spec. # #ENV_TZ TZ=CST6CDT #ENV_TZ /etc/tzname # # If defined, an HZ environment parameter spec. # # for Linux/x86 ENV_HZ HZ=100 # For Linux/Alpha... #ENV_HZ HZ=1024 # # *REQUIRED* The default PATH settings, for superuser and normal users. # # (they are minimal, add the rest in the shell startup files) ENV_SUPATH PATH=/sbin:/bin:/usr/sbin:/usr/bin ENV_PATH PATH=/bin:/usr/bin # # Terminal permissions # # TTYGROUP Login tty will be assigned this group ownership. # TTYPERM Login tty will be set to this permission. # # If you have a write(1) program which is "setgid" to a special group # which owns the terminals, define TTYGROUP as the number of such group # and TTYPERM as 0620. Otherwise leave TTYGROUP commented out and # set TTYPERM to either 622 or 600. # TTYGROUP tty TTYPERM 0600 # # Login configuration initializations: # # ERASECHAR Terminal ERASE character ('\010' = backspace). # KILLCHAR Terminal KILL character ('\025' = CTRL/U). # ULIMIT Default "ulimit" value. # # The ERASECHAR and KILLCHAR are used only on System V machines. # The ULIMIT is used only if the system supports it. # (now it works with setrlimit too; ulimit is in 512-byte units) # # Prefix these values with "0" to get octal, "0x" to get hexadecimal. # ERASECHAR 0177 KILLCHAR 025 ULIMIT 2097152 # Default initial "umask" value used by login(1) on non-PAM enabled systems. # Default "umask" value for pam_umask(8) on PAM enabled systems. # UMASK is also used by useradd(8) and newusers(8) to set the mode for new # home directories. # 022 is the default value, but 027, or even 077, could be considered # for increased privacy. There is no One True Answer here: each sysadmin # must make up their mind. UMASK 022 # # Password aging controls: # # PASS_MAX_DAYS Maximum number of days a password may be used. # PASS_MIN_DAYS Minimum number of days allowed between password changes. # PASS_MIN_LEN Minimum acceptable password length. # PASS_WARN_AGE Number of days warning given before a password expires. # PASS_MAX_DAYS 99999 PASS_MIN_DAYS 0 PASS_MIN_LEN 5 PASS_WARN_AGE 7 # # If "yes", the user must be listed as a member of the first gid 0 group # in /etc/group (called "root" on most Linux systems) to be able to "su" # to uid 0 accounts. If the group doesn't exist or is empty, no one # will be able to "su" to uid 0. # SU_WHEEL_ONLY no # # If compiled with cracklib support, sets the path to the dictionaries # CRACKLIB_DICTPATH /var/cache/cracklib/cracklib_dict # # Min/max values for automatic uid selection in useradd(8) # UID_MIN 1000 UID_MAX 60000 # System accounts SYS_UID_MIN 101 SYS_UID_MAX 999 # Extra per user uids SUB_UID_MIN 100000 SUB_UID_MAX 600100000 SUB_UID_COUNT 65536 # # Min/max values for automatic gid selection in groupadd(8) # GID_MIN 1000 GID_MAX 60000 # System accounts SYS_GID_MIN 101 SYS_GID_MAX 999 # Extra per user group ids SUB_GID_MIN 100000 SUB_GID_MAX 600100000 SUB_GID_COUNT 65536 # # Max number of login(1) retries if password is bad # LOGIN_RETRIES 5 # # Max time in seconds for login(1) # LOGIN_TIMEOUT 60 # # Maximum number of attempts to change password if rejected (too easy) # PASS_CHANGE_TRIES 5 # # Warn about weak passwords (but still allow them) if you are root. # PASS_ALWAYS_WARN yes # # Number of significant characters in the password for crypt(). # Default is 8, don't change unless your crypt() is better. # Ignored if MD5_CRYPT_ENAB set to "yes". # #PASS_MAX_LEN 8 # # Require password before chfn(1)/chsh(1) can make any changes. # CHFN_AUTH yes # # Which fields may be changed by regular users using chfn(1) - use # any combination of letters "frwh" (full name, room number, work # phone, home phone). If not defined, no changes are allowed. # For backward compatibility, "yes" = "rwh" and "no" = "frwh". # CHFN_RESTRICT rwh # # Password prompt (%s will be replaced by user name). # # XXX - it doesn't work correctly yet, for now leave it commented out # to use the default which is just "Password: ". #LOGIN_STRING "%s's Password: " # # Only works if compiled with MD5_CRYPT defined: # If set to "yes", new passwords will be encrypted using the MD5-based # algorithm compatible with the one used by recent releases of FreeBSD. # It supports passwords of unlimited length and longer salt strings. # Set to "no" if you need to copy encrypted passwords to other systems # which don't understand the new algorithm. Default is "no". # # Note: If you use PAM, it is recommended to use a value consistent with # the PAM modules configuration. # # This variable is deprecated. You should use ENCRYPT_METHOD instead. # #MD5_CRYPT_ENAB no # # Only works if compiled with ENCRYPTMETHOD_SELECT defined: # If set to MD5, MD5-based algorithm will be used for encrypting password # If set to SHA256, SHA256-based algorithm will be used for encrypting password # If set to SHA512, SHA512-based algorithm will be used for encrypting password # If set to DES, DES-based algorithm will be used for encrypting password (default) # Overrides the MD5_CRYPT_ENAB option # # Note: If you use PAM, it is recommended to use a value consistent with # the PAM modules configuration. # #ENCRYPT_METHOD DES # # Only works if ENCRYPT_METHOD is set to SHA256 or SHA512. # # Define the number of SHA rounds. # With a lot of rounds, it is more difficult to brute-force the password. # However, more CPU resources will be needed to authenticate users if # this value is increased. # # If not specified, the libc will choose the default number of rounds (5000). # The values must be within the 1000-999999999 range. # If only one of the MIN or MAX values is set, then this value will be used. # If MIN > MAX, the highest value will be used. # #SHA_CRYPT_MIN_ROUNDS 5000 #SHA_CRYPT_MAX_ROUNDS 5000 # # List of groups to add to the user's supplementary group set # when logging in from the console (as determined by the CONSOLE # setting). Default is none. # # Use with caution - it is possible for users to gain permanent # access to these groups, even when not logged in from the console. # How to do it is left as an exercise for the reader... # #CONSOLE_GROUPS floppy:audio:cdrom # # Should login be allowed if we can't cd to the home directory? # Default is no. # DEFAULT_HOME yes # # If this file exists and is readable, login environment will be # read from it. Every line should be in the form name=value. # ENVIRON_FILE /etc/environment # # If defined, this command is run when removing a user. # It should remove any at/cron/print jobs etc. owned by # the user to be removed (passed as the first argument). # #USERDEL_CMD /usr/sbin/userdel_local # # Enable setting of the umask group bits to be the same as owner bits # (examples: 022 -> 002, 077 -> 007) for non-root users, if the uid is # the same as gid, and username is the same as the primary group name. # # This also enables userdel(8) to remove user groups if no members exist. # USERGROUPS_ENAB yes # # If set to a non-zero number, the shadow utilities will make sure that # groups never have more than this number of users on one line. # This permits to support split groups (groups split into multiple lines, # with the same group ID, to avoid limitation of the line length in the # group file). # # 0 is the default value and disables this feature. # #MAX_MEMBERS_PER_GROUP 0 # # If useradd(8) should create home directories for users by default (non # system users only). # This option is overridden with the -M or -m flags on the useradd(8) # command-line. # #CREATE_HOME yes # # Force use shadow, even if shadow passwd & shadow group files are # missing. # #FORCE_SHADOW yes libeconf-0.3.8/tests/tst-logindefs1.c000066400000000000000000000035561370215501500174640ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: Open default login.defs from shadow and try out if we can read all entries */ int main(void) { econf_file *key_file = NULL; char **keys; size_t key_number; char *val; econf_err error; if ((error = econf_readFile (&key_file, TESTSDIR"tst-logindefs1-data/etc/login.defs", " \t", "#"))) { fprintf (stderr, "ERROR: couldn't read configuration file: %s\n", econf_errString(error)); return 1; } if ((error = econf_getStringValue (key_file, NULL, "USERGROUPS_ENAB", &val))) { fprintf (stderr, "Error reading USERGROUPS_ENAB: %s\n", econf_errString(error)); return 1; } else if (strlen(val) == 0) { fprintf (stderr, "USERGROUPS_ENAB returns nothing!\n"); return 1; } else if (strcmp (val, "yes") != 0) { fprintf (stderr, "USERGROUPS_ENAB returns wrong value: '%s'\n", val); return 1; } free (val); if ((error = econf_getStringValue (key_file, "", "UMASK", &val))) { fprintf (stderr, "Error reading UMASK: %s\n", econf_errString(error)); return 1; } else if (strlen(val) == 0) { fprintf (stderr, "UMASK returns nothing!\n"); return 1; } else if (strcmp (val, "022") != 0) { fprintf (stderr, "UMASK returns wrong value: '%s'\n", val); return 1; } free (val); error = econf_getKeys(key_file, NULL, &key_number, &keys); if (error) { fprintf (stderr, "Error getting all keys: %s\n", econf_errString(error)); return 1; } if (key_number == 0) { fprintf (stderr, "No keys found?\n"); return 1; } for (size_t i = 0; i < key_number; i++) { printf ("%zu: %s\n", i, keys[i]); } econf_free (keys); econf_free (key_file); return 0; } libeconf-0.3.8/tests/tst-logindefs2-data/000077500000000000000000000000001370215501500202175ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-logindefs2-data/logindefs.data000066400000000000000000000003431370215501500230240ustar00rootroot00000000000000# # this is /etc/login.defs sample # HELLO_WORLD "hello world!" STRING this_is_string # another comment NUMBER 123456 BOOLEAN yEs CRAZY1 = "this is crazy format" CRAZY2=fooBar CRAZY3 FoooBaaar EMPTY END "the is end" libeconf-0.3.8/tests/tst-logindefs2.c000066400000000000000000000105601370215501500174560ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include #include "libeconf.h" /* Test case: Open default logindefs.data from util-linux and try out if we can read all entries */ int main(void) { econf_file *key_file = NULL; char **keys; size_t key_number; econf_err error; if ((error = econf_readFile (&key_file, TESTSDIR"tst-logindefs2-data/logindefs.data", "= \t", "#"))) { fprintf (stderr, "ERROR: couldn't read configuration file: %s\n", econf_errString(error)); return 1; } if ((error = econf_getKeys(key_file, NULL, &key_number, &keys))) { fprintf (stderr, "Error getting all keys: %s\n", econf_errString(error)); econf_free(key_file); return 1; } if (key_number == 0) { fprintf (stderr, "No keys found?\n"); econf_free(key_file); return 1; } for (size_t i = 0; i < key_number; i++) { char *value = NULL; econf_getStringValue(key_file, NULL, keys[i], &value); printf ("%zu: %s: '%s'\n", i, keys[i], value); if (value != NULL) free (value); } int retval = 0; char *strval = NULL; econf_getStringValue (key_file, NULL, "STRING", &strval); if (strval == NULL || strcmp (strval, "this_is_string") != 0) { fprintf (stderr, "ERROR: %s, expected: %s, got: '%s'\n", "STRING", "this_is_string", strval?strval:"NULL"); retval = 1; } if (strval) free (strval); int intval = 0; econf_getIntValue (key_file, NULL, "NUMBER", &intval); if (intval == 0 || intval != 123456) { fprintf (stderr, "ERROR: %s, expected: %i, got: %i\n", "NUMBER", 123456, intval); retval = 1; } bool boolval = false; econf_getBoolValue (key_file, NULL, "BOOLEAN", &boolval); if (boolval != true) { fprintf (stderr, "ERROR: %s, expected: %i, got: %i\n", "BOOLEAN", true, boolval); retval = 1; } strval = NULL; econf_getStringValue (key_file, NULL, "CRAZY1", &strval); if (strval == NULL || strcmp (strval, "this is crazy format") != 0) { fprintf (stderr, "ERROR: %s, expected: '%s', got: '%s'\n", "CRAZY1", "this is crazy format", strval?strval:"NULL"); retval = 1; } if (strval) free (strval); strval = NULL; econf_getStringValue (key_file, NULL, "CRAZY2", &strval); if (strval == NULL || strcmp (strval, "fooBar") != 0) { fprintf (stderr, "ERROR: %s, expected: '%s', got: '%s'\n", "CRAZY1", "fooBar", strval?strval:"NULL"); retval = 1; } if (strval) free (strval); strval = NULL; econf_getStringValue (key_file, NULL, "CRAZY3", &strval); if (strval == NULL || strcmp (strval, "FoooBaaar") != 0) { fprintf (stderr, "ERROR: %s, expected: '%s', got: '%s'\n", "CRAZY3", "FoooBaaar", strval?strval:"NULL"); retval = 1; } if (strval) free (strval); strval = NULL; econf_getStringValue (key_file, NULL, "EMPTY", &strval); if (strval != NULL) { fprintf (stderr, "ERROR: %s, expected: 'NULL', got: '%s'\n", "EMPTY", strval?strval:"NULL"); retval = 1; } if (strval) free (strval); strval = NULL; econf_getStringValue (key_file, NULL, "END", &strval); if (strval == NULL || strcmp (strval, "the is end") != 0) { fprintf (stderr, "ERROR: %s, expected: '%s', got: '%s'\n", "END", "the is end", strval?strval:"NULL"); retval = 1; } if (strval) free (strval); strval = NULL; econf_getStringValue (key_file, NULL, "NOTEXIST", &strval); if (strval != NULL) { fprintf (stderr, "ERROR: %s, expected: '%s', got: '%s'\n", "NOTEXIST", "NULL", strval?strval:"NULL"); retval = 1; } if (strval) free (strval); strval = NULL; econf_getStringValue (key_file, NULL, "END", &strval); if (strval == NULL || strcmp (strval, "the is end") != 0) { fprintf (stderr, "ERROR: %s, expected: '%s', got: '%s'\n", "END", "the is end", strval?strval:"NULL"); retval = 1; } if (strval) free (strval); strval = NULL; econf_getStringValue (key_file, NULL, "NOTEXIST", &strval); if (strval != NULL) { fprintf (stderr, "ERROR: %s, expected: '%s', got: '%s'\n", "NOTEXIST", "NULL", strval?strval:"NULL"); retval = 1; } if (strval) free (strval); econf_free (keys); econf_free (key_file); return retval; } libeconf-0.3.8/tests/tst-merge1-data/000077500000000000000000000000001370215501500173435ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-merge1-data/usr/000077500000000000000000000000001370215501500201545ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-merge1-data/usr/etc/000077500000000000000000000000001370215501500207275ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-merge1-data/usr/etc/tst-merge1.conf000066400000000000000000000000341370215501500235630ustar00rootroot00000000000000[global] correct_key = true libeconf-0.3.8/tests/tst-merge1.c000066400000000000000000000024311370215501500166000ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include "libeconf.h" /* Test case: * Try to open two files, where one does not exist. * Call econf_mergeFiles with this. * Application should not crash. */ int main(void) { econf_file *key_file_1 = NULL, *key_file_2 = NULL, *key_file_m = NULL; econf_err error; error = econf_readFile (&key_file_1, TESTSDIR"tst-merge1-data/etc/tst-merge1.conf", "=", "#"); if (!error || key_file_1 != NULL) { fprintf (stderr, "ERROR: /etc should not contain a config file\n"); return 1; } error = econf_readFile (&key_file_2, TESTSDIR"tst-merge1-data/usr/etc/tst-merge1.conf", "=", "#"); if (error || key_file_2 == NULL) { fprintf (stderr, "ERROR: couldn't read /usr/etc configuration file: %s\n", econf_errString(error)); return 1; } error = econf_mergeFiles (&key_file_m, key_file_2, key_file_1); if (!error || key_file_m != NULL) { /* there was nothing to merge */ fprintf (stderr, "ERROR: econf_mergeFiles merged something when there was nothing to merge: %s\n", econf_errString(error)); return 1; } if (key_file_1) econf_free (key_file_1); if (key_file_2) econf_free (key_file_2); if (key_file_m) econf_free (key_file_m); return 0; } libeconf-0.3.8/tests/tst-merge2-data/000077500000000000000000000000001370215501500173445ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-merge2-data/etc/000077500000000000000000000000001370215501500201175ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-merge2-data/etc/tst-merge2.conf000066400000000000000000000000341370215501500227540ustar00rootroot00000000000000[global] correct_key = true libeconf-0.3.8/tests/tst-merge2.c000066400000000000000000000023141370215501500166010ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include "libeconf.h" /* Test case: * Try to open two files, where one does not exist. * Call econf_mergeFiles with this. * Application should not crash. */ int main(void) { econf_file *key_file_1 = NULL, *key_file_2 = NULL, *key_file_m = NULL; econf_err error; error = econf_readFile (&key_file_1, TESTSDIR"tst-merge2-data/etc/tst-merge2.conf", "=", "#"); if (error || key_file_1 == NULL) { fprintf (stderr, "ERROR: couldn't read /etc configuration file: %s\n", econf_errString(error)); return 1; } error = econf_readFile (&key_file_2, TESTSDIR"tst-merge2-data/usr/etc/tst-merge2.conf", "=", "#"); if (!error || key_file_2 != NULL) { fprintf (stderr, "ERROR: /usr/etc should not contain a config file\n"); return 1; } error = econf_mergeFiles (&key_file_m, key_file_2, key_file_1); if (key_file_m != NULL) { fprintf (stderr, "ERROR: econf_mergeFiles merged somethng when there was nothing to merge\n"); return 1; } if (key_file_1) econf_free (key_file_1); if (key_file_2) econf_free (key_file_2); if (key_file_m) econf_free (key_file_m); return 0; } libeconf-0.3.8/tests/tst-merge3-data/000077500000000000000000000000001370215501500173455ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-merge3-data/etc/000077500000000000000000000000001370215501500201205ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-merge3-data/etc/default/000077500000000000000000000000001370215501500215445ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-merge3-data/etc/default/su000066400000000000000000000003131370215501500221130ustar00rootroot00000000000000# /etc/default/su is an override of /etc/login.defs for su. # See /etc/login.defs and su(1) for more. # # List of supported variables: # ALWAYS_SET_PATH, ENV_PATH, ENV_ROOTPATH, ENV_SUPATH, FAIL_DELAY # libeconf-0.3.8/tests/tst-merge3-data/etc/login.defs000066400000000000000000000216241370215501500221000ustar00rootroot00000000000000# # /etc/login.defs - Configuration control definitions for the shadow package. # Some variables are used by login(1), su(1) and runuser(1) from util-linux # package as well pam pam_unix(8) from pam package. # # For more, see login.defs(5). Please note that SUSE supports only variables # listed here! Not listed variables from login.defs(5) have no effect. # # # Delay in seconds before being allowed another attempt after a login failure # Note: When PAM is used, some modules may enforce a minimum delay (e.g. # pam_unix(8) enforces a 2s delay) # FAIL_DELAY 3 # # Enable display of unknown usernames when login(1) failures are recorded. # LOG_UNKFAIL_ENAB no # # Enable "syslog" logging of newgrp(1) and sg(1) activity. # SYSLOG_SG_ENAB yes # # If defined, either full pathname of a file containing device names or # a ":" delimited list of device names. Root logins will be allowed only # from these devices. # CONSOLE /etc/securetty #CONSOLE console:tty01:tty02:tty03:tty04 # # If defined, all su(1) activity is logged to this file. # #SULOG_FILE /var/log/sulog # # If defined, ":" delimited list of "message of the day" files to # be displayed upon login. # MOTD_FILE /etc/motd #MOTD_FILE /etc/motd:/usr/lib/news/news-motd # # If defined, file which maps tty line to TERM environment parameter. # Each line of the file is in a format similar to "vt100 tty01". # #TTYTYPE_FILE /etc/ttytype # # If defined, file which inhibits all the usual chatter during the login # sequence. If a full pathname, then hushed mode will be enabled if the # user's name or shell are found in the file. If not a full pathname, then # hushed mode will be enabled if the file exists in the user's home directory. # #HUSHLOGIN_FILE .hushlogin HUSHLOGIN_FILE /etc/hushlogins # If this variable is set to "yes", hostname will be suppressed in the # login: prompt. #LOGIN_PLAIN_PROMPT no # # *REQUIRED* The default PATH settings, for superuser and normal users. # # (they are minimal, add the rest in the shell startup files) # # ENV_PATH: The default PATH settings for non-root. # # ENV_ROOTPATH: The default PATH settings for root # (used by login, su and runuser). # # ENV_SUPATH is an ENV_ROOTPATH override for su and runuser # (and falback for login). # ENV_PATH /usr/local/bin:/bin:/usr/bin ENV_ROOTPATH /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin #ENV_SUPATH /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin # If this variable is set to "yes" (default is "no"), su will always set # path. every su call will overwrite the PATH variable. # # Per default, only "su -" will set a new PATH. # # The recommended value is "yes". The default "no" behavior could have # a security implication in applications that use commands without path. # ALWAYS_SET_PATH yes # # Terminal permissions # # TTYGROUP Login tty will be assigned this group ownership. # TTYPERM Login tty will be set to this permission. # # If you have a write(1) program which is "setgid" to a special group # which owns the terminals, define TTYGROUP as the number of such group # and TTYPERM as 0620. Otherwise leave TTYGROUP commented out and # set TTYPERM to either 622 or 600. # TTYGROUP tty TTYPERM 0620 # Default initial "umask" value used by login(1) on non-PAM enabled systems. # Default "umask" value for pam_umask(8) on PAM enabled systems. # UMASK is also used by useradd(8) and newusers(8) to set the mode for new # home directories. # 022 is the default value, but 027, or even 077, could be considered # for increased privacy. There is no One True Answer here: each sysadmin # must make up their mind. UMASK 022 # # Password aging controls: # # PASS_MAX_DAYS Maximum number of days a password may be used. # PASS_MIN_DAYS Minimum number of days allowed between password changes. # PASS_WARN_AGE Number of days warning given before a password expires. # PASS_MAX_DAYS 99999 PASS_MIN_DAYS 0 PASS_WARN_AGE 7 # # Min/max values for automatic uid selection in useradd(8) # # SYS_UID_MIN to SYS_UID_MAX inclusive is the range for # UIDs for dynamically allocated administrative and system accounts. # UID_MIN to UID_MAX inclusive is the range of UIDs of dynamically # allocated user accounts. # UID_MIN 1000 UID_MAX 60000 # System accounts SYS_UID_MIN 100 SYS_UID_MAX 499 # Extra per user uids SUB_UID_MIN 100000 SUB_UID_MAX 600100000 SUB_UID_COUNT 65536 # # Min/max values for automatic gid selection in groupadd(8) # # SYS_GID_MIN to SYS_GID_MAX inclusive is the range for # GIDs for dynamically allocated administrative and system groups. # GID_MIN to GID_MAX inclusive is the range of GIDs of dynamically # allocated groups. # GID_MIN 1000 GID_MAX 60000 # System accounts SYS_GID_MIN 100 SYS_GID_MAX 499 # Extra per user group ids SUB_GID_MIN 100000 SUB_GID_MAX 600100000 SUB_GID_COUNT 65536 # # Max number of login(1) retries if password is bad # LOGIN_RETRIES 3 # # Max time in seconds for login(1) # LOGIN_TIMEOUT 60 # # Which fields may be changed by regular users using chfn(1) - use # any combination of letters "frwh" (full name, room number, work # phone, home phone). If not defined, no changes are allowed. # For backward compatibility, "yes" = "rwh" and "no" = "frwh". # CHFN_RESTRICT rwh # # This variable is deprecated. Use ENCRYPT_METHOD instead! # #MD5_CRYPT_ENAB DO_NOT_USE # # If set to MD5, MD5-based algorithm will be used for encrypting password # If set to SHA256, SHA256-based algorithm will be used for encrypting password # If set to SHA512, SHA512-based algorithm will be used for encrypting password # If set to DES, DES-based algorithm will be used for encrypting password (default) # Overrides the MD5_CRYPT_ENAB option # # ENCRYPT_METHOD_NIS is used by pam_unix_passwd.so. # # Note: If you use PAM, it is recommended to use a value consistent with # the PAM modules configuration. # ENCRYPT_METHOD SHA512 ENCRYPT_METHOD_NIS DES # # Number of rounds for salt. # Default values: # Minimum number of rounds. #SHA_CRYPT_MIN_ROUNDS 1000 # Maximum number of rounds. #SHA_CRYPT_MAX_ROUNDS 999999999 # # Only works if ENCRYPT_METHOD is set to SHA256 or SHA512. # # Define the number of SHA rounds. # With a lot of rounds, it is more difficult to brute-force the password. # However, more CPU resources will be needed to authenticate users if # this value is increased. # # If not specified, the libc will choose the default number of rounds (5000). # The values must be within the 1000-999999999 range. # If only one of the MIN or MAX values is set, then this value will be used. # If MIN > MAX, the highest value will be used. # # SHA_CRYPT_MIN_ROUNDS 5000 # SHA_CRYPT_MAX_ROUNDS 5000 # # Should login be allowed if we can't cd to the home directory? # Default is no. # DEFAULT_HOME yes # # If defined, this command is run when adding a user. # It should rebuild any NIS database etc. to add the # new created account. # USERADD_CMD /usr/sbin/useradd.local # # If defined, this command is run when removing a user. # It should remove any at/cron/print jobs etc. owned by # the user to be removed (passed as the first argument). # # See also USERDEL_PRECMD and USERDEL_POSTCMD below. # #USERDEL_CMD /usr/sbin/userdel_local # # If defined, this command is run before removing a user. # It should remove any at/cron/print jobs etc. owned by # the user to be removed. # USERDEL_PRECMD /usr/sbin/userdel-pre.local # # If defined, this command is run after removing a user. # It should rebuild any NIS database etc. to remove the # account from it. # USERDEL_POSTCMD /usr/sbin/userdel-post.local # # Enable setting of the umask group bits to be the same as owner bits # (examples: 022 -> 002, 077 -> 007) for non-root users, if the uid is # the same as gid, and username is the same as the primary group name. # # This also enables userdel(8) to remove user groups if no members exist. # USERGROUPS_ENAB no # # If set to a non-zero number, the shadow utilities will make sure that # groups never have more than this number of users on one line. # This permits to support split groups (groups split into multiple lines, # with the same group ID, to avoid limitation of the line length in the # group file). # # 0 is the default value and disables this feature. # #MAX_MEMBERS_PER_GROUP 0 # # If useradd(8) should create home directories for users by default (non # system users only). # This option is overridden with the -M or -m flags on the useradd(8) # command-line. # CREATE_HOME no # # Force use shadow, even if shadow passwd & shadow group files are # missing. # FORCE_SHADOW no # # User/group names must match the following regex expression. # The default is [A-Za-z_][A-Za-z0-9_.-]*[A-Za-z0-9_.$-]\?, # but be aware that the result could depend on the locale settings. # #CHARACTER_CLASS [A-Za-z_][A-Za-z0-9_.-]*[A-Za-z0-9_.$-]\? CHARACTER_CLASS [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_][ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.-]*[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.$-]\? libeconf-0.3.8/tests/tst-merge3.c000066400000000000000000000023301370215501500166000ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include "libeconf.h" /* Test case: * Try to open two files, where one only contains comments * Call econf_mergeFiles with this. * Application should not crash. */ int main(void) { econf_file *key_file_1 = NULL, *key_file_2 = NULL, *key_file_m = NULL; econf_err error; error = econf_readFile (&key_file_1, TESTSDIR"tst-merge3-data/etc/login.defs", " \t=", "#"); if (error || key_file_1 == NULL) { fprintf (stderr, "ERROR: couldn't read /etc/login.defs: %s\n", econf_errString(error)); return 1; } error = econf_readFile (&key_file_2, TESTSDIR"tst-merge3-data/etc/default/su", " \t=", "#"); if (error || key_file_2 == NULL) { fprintf (stderr, "ERROR: coudln't read /etc/default/su: %s\n", econf_errString(error)); return 1; } error = econf_mergeFiles (&key_file_m, key_file_2, key_file_1); if (error || key_file_m == NULL) { fprintf (stderr, "ERROR: error merging configuration files: %s\n", econf_errString(error)); return 1; } if (key_file_1) econf_free (key_file_1); if (key_file_2) econf_free (key_file_2); if (key_file_m) econf_free (key_file_m); return 0; } libeconf-0.3.8/tests/tst-merge4-data/000077500000000000000000000000001370215501500173465ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-merge4-data/data1.conf000066400000000000000000000000551370215501500212070ustar00rootroot00000000000000[global] KEY1=global [default] KEY1=default libeconf-0.3.8/tests/tst-merge4-data/data2.conf000066400000000000000000000000131370215501500212020ustar00rootroot00000000000000KEY1=data2 libeconf-0.3.8/tests/tst-merge4.c000066400000000000000000000042601370215501500166050ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: * Try to open two files, where one has group entries, the other not * Call econf_mergeFiles with this. * Application should not crash and return correct key values */ static bool check_string (econf_file *key_file, const char *group, const char *key, const char *value) { econf_err error; char *val_String; if ((error = econf_getStringValue(key_file, group, key, &val_String))) { fprintf (stderr, "ERROR: reading (%s,%s): %s\n", group, key, econf_errString(error)); return false; } /* NULL means empty string */ printf ("reading (%s,%s): got '%s', expected '%s'\n", group, key, value, val_String); if (strcmp(val_String, value?value:"") != 0) { fprintf (stderr, "ERROR: reading (%s,%s): expected '%s', got: '%s'\n", group, key, value, val_String); return false; } free(val_String); return true; } int main(void) { econf_file *key_file_1 = NULL, *key_file_2 = NULL, *key_file_m = NULL; econf_err error; int retval = 0; error = econf_readFile (&key_file_1, TESTSDIR"tst-merge4-data/data1.conf", "=", "#"); if (error || key_file_1 == NULL) { fprintf (stderr, "ERROR: couldn't read data1.conf: %s\n", econf_errString(error)); return 1; } error = econf_readFile (&key_file_2, TESTSDIR"tst-merge4-data/data2.conf", " \t=", "#"); if (error || key_file_2 == NULL) { fprintf (stderr, "ERROR: coudln't read data2.conf: %s\n", econf_errString(error)); return 1; } error = econf_mergeFiles (&key_file_m, key_file_2, key_file_1); if (error || key_file_m == NULL) { fprintf (stderr, "ERROR: error merging configuration files: %s\n", econf_errString(error)); return 1; } if (!check_string (key_file_m, "global", "KEY1", "global")) retval = 1; if (!check_string (key_file_m, "default", "KEY1", "default")) retval = 1; if (!check_string (key_file_m, NULL, "KEY1", "data2")) retval = 1; if (key_file_1) econf_free (key_file_1); if (key_file_2) econf_free (key_file_2); if (key_file_m) econf_free (key_file_m); return retval; } libeconf-0.3.8/tests/tst-merge5-data/000077500000000000000000000000001370215501500173475ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-merge5-data/data1.conf000066400000000000000000000000131370215501500212020ustar00rootroot00000000000000KEY1=data1 libeconf-0.3.8/tests/tst-merge5-data/data2.conf000066400000000000000000000000551370215501500212110ustar00rootroot00000000000000[global] KEY1=global [default] KEY1=default libeconf-0.3.8/tests/tst-merge5.c000066400000000000000000000042601370215501500166060ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: * Try to open two files, where one has group entries, the other not * Call econf_mergeFiles with this. * Application should not crash and return correct key values */ static bool check_string (econf_file *key_file, const char *group, const char *key, const char *value) { econf_err error; char *val_String; if ((error = econf_getStringValue(key_file, group, key, &val_String))) { fprintf (stderr, "ERROR: reading (%s,%s): %s\n", group, key, econf_errString(error)); return false; } /* NULL means empty string */ printf ("reading (%s,%s): got '%s', expected '%s'\n", group, key, value, val_String); if (strcmp(val_String, value?value:"") != 0) { fprintf (stderr, "ERROR: reading (%s,%s): expected '%s', got: '%s'\n", group, key, value, val_String); return false; } free(val_String); return true; } int main(void) { econf_file *key_file_1 = NULL, *key_file_2 = NULL, *key_file_m = NULL; econf_err error; int retval = 0; error = econf_readFile (&key_file_1, TESTSDIR"tst-merge5-data/data1.conf", "=", "#"); if (error || key_file_1 == NULL) { fprintf (stderr, "ERROR: couldn't read data1.conf: %s\n", econf_errString(error)); return 1; } error = econf_readFile (&key_file_2, TESTSDIR"tst-merge5-data/data2.conf", " \t=", "#"); if (error || key_file_2 == NULL) { fprintf (stderr, "ERROR: coudln't read data2.conf: %s\n", econf_errString(error)); return 1; } error = econf_mergeFiles (&key_file_m, key_file_2, key_file_1); if (error || key_file_m == NULL) { fprintf (stderr, "ERROR: error merging configuration files: %s\n", econf_errString(error)); return 1; } if (!check_string (key_file_m, "global", "KEY1", "global")) retval = 1; if (!check_string (key_file_m, "default", "KEY1", "default")) retval = 1; if (!check_string (key_file_m, NULL, "KEY1", "data1")) retval = 1; if (key_file_1) econf_free (key_file_1); if (key_file_2) econf_free (key_file_2); if (key_file_m) econf_free (key_file_m); return retval; } libeconf-0.3.8/tests/tst-parseconfig-data/000077500000000000000000000000001370215501500204635ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-parseconfig-data/empty-group.conf000066400000000000000000000000111370215501500236120ustar00rootroot00000000000000[global] libeconf-0.3.8/tests/tst-parseconfig1.c000066400000000000000000000007701370215501500200050ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: Open file with only empty group */ int main(void) { econf_file *key_file = NULL; econf_err error; if ((error = econf_readFile (&key_file, TESTSDIR"tst-parseconfig-data/empty-group.conf", "=", "#"))) { fprintf (stderr, "ERROR: couldn't read configuration file: %s\n", econf_errString(error)); return 1; } econf_free (key_file); return 0; } libeconf-0.3.8/tests/tst-quote1-data/000077500000000000000000000000001370215501500174015ustar00rootroot00000000000000libeconf-0.3.8/tests/tst-quote1-data/quote.conf000066400000000000000000000010141370215501500214010ustar00rootroot00000000000000[quote] unquoted = unquoted spaces_1 = spaces 1 spaces_2 = " spaces 2 " begin_quote = ""begin_quote" mid_quote = mid"quote end_quote = "end quote"" quoted_word = "a "quoted" word" quoted_word1 = "a 'quoted' word" quoted_string = ""a quoted string"" quoted_string1 = "'a quoted string'" unbal1 = "unbalanced unbal2 = unbalanced" unbal3 = "not "well" balanced unbal4 = not "well" balanced" quoted_delim = "a=b" quoted_delim1 = "=>b" unquoted_delim = a=b unquoted_delim1 = =>b unquoted_delim2=a=b unquoted_delim3==>b libeconf-0.3.8/tests/tst-quote1.c000066400000000000000000000045131370215501500166410ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include "libeconf.h" /* Test case: Read quoted strings from conf file */ static int print_error_get (const char *getgroup, const char *key, econf_err error) { fprintf (stderr, "ERROR: tried to get '%s' from '%s': %s\n", key, getgroup, econf_errString(error)); return 1; } static bool check_String (econf_file *key_file, const char *group, const char *key, const char *value) { econf_err error; char *val_String; if ((error = econf_getStringValue(key_file, group, key, &val_String))) { print_error_get (group, key, error); return false; } if ((value == NULL && val_String != NULL) || (value != NULL && val_String == NULL) || strcmp(val_String, value)) { fprintf (stderr, "ERROR: Expected String: '%s', Got: '%s'\n", value, val_String); return false; } free(val_String); return true; } int main(void) { econf_file *key_file = NULL; const char *group="quote"; econf_err error; int retval = 0; static const struct { const char *const key; const char *const val; } tests[] = { { "unquoted", "unquoted" }, { "spaces_1", "spaces 1" }, { "spaces_2", " spaces 2 " }, { "mid_quote", "mid\"quote" }, { "begin_quote", "\"begin_quote" }, { "end_quote", "end quote\"", }, { "quoted_word", "a \"quoted\" word", }, { "quoted_word1", "a 'quoted' word", }, { "quoted_string", "\"a quoted string\"", }, { "quoted_string1", "'a quoted string'", }, { "unbal1", "\"unbalanced", }, { "unbal2", "unbalanced\"", }, { "unbal3", "\"not \"well\" balanced", }, { "unbal4", "not \"well\" balanced\"", }, { "quoted_delim", "a=b", }, { "quoted_delim1", "=>b", }, { "unquoted_delim", "a=b", }, { "unquoted_delim1", "=>b", }, { "unquoted_delim2", "a=b", }, { "unquoted_delim3", "=>b", }, }; unsigned int i; if ((error = econf_readFile (&key_file, TESTSDIR"tst-quote1-data/quote.conf", "=", "#"))) { fprintf (stderr, "ERROR: couldn't read configuration file: %s\n", econf_errString(error)); return 1; } for (i = 0; i < sizeof(tests)/sizeof(*tests); i++) { if (!check_String(key_file, group, tests[i].key, tests[i].val)) retval = 1; } econf_free(key_file); return retval; } libeconf-0.3.8/tests/tst-setgetvalues1.c000066400000000000000000000112401370215501500202120ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include "libeconf.h" /* Test case: Create new file in memory, store all kind of types and read them again to verify, they where correctly stored. */ static void exit_with_error_set (const char *type, econf_err error) { fprintf (stderr, "ERROR: couldn't set type '%s': %s\n", type, econf_errString(error)); exit (1); } static void exit_with_error_get (const char *type, econf_err error) { fprintf (stderr, "ERROR: couldn't get type '%s': %s\n", type, econf_errString(error)); exit (1); } /* The econf_get*Value functions are identical except for return type, so let's create them via a macro. */ #define check_type(TYPE, FCT_TYPE, FCT_TYPE_STR, PR) \ static bool check_ ## FCT_TYPE (econf_file *key_file, TYPE value) \ { \ econf_err error; \ \ if ((error = econf_set ## FCT_TYPE ## Value(key_file, NULL, "KEY", value))) \ exit_with_error_set (FCT_TYPE_STR, error); \ TYPE val_ ## FCT_TYPE; \ if ((error = econf_get ## FCT_TYPE ## Value(key_file, NULL, "KEY", &val_ ## FCT_TYPE))) \ exit_with_error_get (FCT_TYPE_STR, error); \ if (val_ ## FCT_TYPE != value) \ { \ fprintf (stderr, "ERROR: Set "FCT_TYPE_STR": '%"PR"', Got: '%"PR"'\n", value, val_ ## FCT_TYPE); \ return false; \ } \ return true; \ } check_type(int32_t, Int, "Int", PRId32) check_type(uint32_t, UInt, "UInt", PRIu32) check_type(int64_t, Int64, "Int64", PRId64) check_type(uint64_t, UInt64, "UInt64", PRIu64) check_type(float, Float, "Float", "f") check_type(double, Double, "Double", "f") /* check_type(const char *, String, "String", "%s") */ static bool check_String (econf_file *key_file, const char *value) { econf_err error; if ((error = econf_setStringValue(key_file, NULL, "KEY", value))) exit_with_error_set ("String", error); char *val_String; if ((error = econf_getStringValue(key_file, NULL, "KEY", &val_String))) exit_with_error_get ("String", error); /* NULL means empty string */ if (strcmp(val_String, value?value:"") != 0) { fprintf (stderr, "ERROR: Set String: '%s', Got: '%s'\n", value, val_String); return false; } free(val_String); return true; } /* check_type(bool, Bool, "Bool", "%s") */ static bool check_Bool (econf_file *key_file, const char *value, bool expect) { econf_err error; if ((error = econf_setBoolValue(key_file, NULL, "KEY", value))) exit_with_error_set ("Bool", error); bool val_Bool; if ((error = econf_getBoolValue(key_file, NULL, "KEY", &val_Bool))) exit_with_error_get ("Bool", error); if (val_Bool != expect) { fprintf (stderr, "ERROR: Set Bool: '%s' (%i), Got: '%i'\n", value, expect, val_Bool); return false; } return true; } int main(void) { econf_file *key_file = NULL; econf_err error; int retval = 0; if ((error = econf_newKeyFile(&key_file, '=', '#'))) { fprintf (stderr, "ERROR: couldn't create new file: %s\n", econf_errString(error)); return 1; } /* test reading a key from an empty key_file */ int dummy; if ((error = econf_getIntValue(key_file, NULL, "KEY", &dummy)) != ECONF_NOKEY) exit_with_error_get ("int", error); if (!check_Int (key_file, INT32_MAX)) retval=1; if (!check_Int (key_file, INT32_MIN)) retval=1; if (!check_UInt (key_file, UINT32_MAX)) retval=1; if (!check_UInt (key_file, 0)) retval=1; if (!check_Int64 (key_file, INT64_MAX)) retval=1; if (!check_Int64 (key_file, INT64_MIN)) retval=1; if (!check_UInt64 (key_file, UINT64_MAX)) retval=1; if (!check_UInt64 (key_file, 0)) retval=1; if (!check_Float (key_file, FLT_MAX)) retval=1; if (!check_Float (key_file, FLT_MIN)) retval=1; if (!check_Double (key_file, DBL_MAX)) retval=1; if (!check_Double (key_file, DBL_MIN)) retval=1; if (!check_String (key_file, NULL)) retval=1; if (!check_String (key_file, "")) retval=1; if (!check_String (key_file, " ")) retval=1; if (!check_String (key_file, "This should become a long and complicated string, but up to now it is not = ! $ % € ß")) retval=1; if (!check_Bool (key_file, "True", true)) retval=1; if (!check_Bool (key_file, "true", true)) retval=1; if (!check_Bool (key_file, "Yes", true)) retval=1; if (!check_Bool (key_file, "yes", true)) retval=1; if (!check_Bool (key_file, "1", true)) retval=1; if (!check_Bool (key_file, "False", false)) retval=1; if (!check_Bool (key_file, "false", false)) retval=1; if (!check_Bool (key_file, "No", false)) retval=1; if (!check_Bool (key_file, "no", false)) retval=1; if (!check_Bool (key_file, "0", false)) retval=1; econf_free (key_file); return retval; }