libeconf(3)

πŸ“¦
version 0.7.9 Β· 3 versions
, in debian trixie, fedora 43, fedora 44, opensuse-leap 16.0, ubuntu questing, ubuntu resolute

πŸ’– libeconf(3) πŸ’–

okay so bestie, this is the libeconf manual page β€” manual section 3, library vibes only. two header files, one iconic library, and a whole lot of config file lore. let's get into it. πŸ¦‹


✨ NAME ✨

  • include/libeconf.h β€” the public API for the econf library. the main character. πŸ‘‘
  • include/libeconf_ext.h β€” the public extended API for the econf library. the bonus content. ✨

🌸 DESCRIPTION 🌸

okay so libeconf? it's a highly flexible and configurable library that parses and manages key=value configuration files. no cap. it reads configuration file snippets from a bunch of different directories and then stitches together the final configuration file for the application out of all of them. it's giving very much "build-a-config". 🧚

The first file is the vendor provided configuration file, and it lives in /usr/_vendordir_/_project_. Optionally, /run/_project_ is also supported, for ephemeral overrides (iykyk β€” those ones don't stick around).

Defining the _project_ sub directory is optional. lowkey optional. πŸ™ˆ


There are two methods of overriding these vendor settings, and this is where it gets juicy:

  1. Copy the file from /usr/_vendordir_/_project_ to /etc/_project_ and modify the settings (see Example 1).
  2. Alternatively, you can create a directory named _file_._suffix_.d/ within /etc/_project_, with drop-in files in the form _name_._suffix_ (see Example 2).

These files contain only the changes of the specific settings the user is interested in β€” not the whole config, just the diff, bestie. πŸ’… There can be several such drop-in files, and they are processed in lexicographic order of their filename (yes, alphabetically, in order, no skipping).


The first method is useful when you want to override the complete configuration file with your own one β€” in that case the vendor supplied configuration is ignored. 🚫

So, if /etc/_project_/_example_._suffix_ exists, then /usr/_vendor_/_project_/_example_._suffix_ and /run/_project_/_example_._suffix_ will not be read. The disadvantage is that changes to the vendor configuration file β€” due e.g. an package update β€” are ignored, and the user has to manually merge them. 😭 that's the price of freedom, fr fr.

The other method will continue to use /usr/_vendor_/_project_/_example_._suffix_ as the base configuration file and merge all changes from /etc/_project_/_example_._suffix_.d/*._suffix_. So the user will automatically get improvements from the vendor, with the drawback that they could be incompatible with the user made changes. ⚠️

If there is a file with the same name in /usr/_vendor_/_project_/_example_._suffix_.d/ and in /etc/_project_/_example_._suffix_.d/*._suffix_., the file in /usr/_project_/_vendor_/_example_._suffix_.d/ will completely ignored. πŸ’€ (yes, really β€” the vendor one just loses.)

To disable a configuration file supplied by the vendor, the recommended way is to place a symlink to /dev/null in the configuration directory in /etc/_project_, with the same filename as the vendor configuration file. iconic trick, honestly. πŸŽ€


Optionally, schemes with only drop-ins and without a β€˜main’ configuration file will be supported too. In such schemes many drop-ins are loaded from a common directory in each hierarchy. For example, /usr/lib/<project>.d/*, /run/<project>.d/* and /etc/<project>.d/c.conf are all loaded and parsed in this scheme. 🌈


πŸŽ€ Example 1 πŸŽ€

If a /etc/_example_._suffix_ file exists:

  • /etc/_example_._suffix_
  • /usr/_vendor_/_project_/_example_._suffix_.d/*._suffix_
  • /run/_project_/_example_._suffix_.d/*._suffix_
  • /etc/_project_/_example_._suffix_.d/*._suffix_

πŸ¦‹ Example 2 πŸ¦‹

The list of files and directories read if no /etc/_example_._suffix_ file exists:

  • /usr/_vendor_/_project_/_example_._suffix_ if no /run/_project_/_example_._suffix_ exist
  • /usr/_vendor_/_project_/_example_._suffix_.d/*._suffix_
  • /run/_project_/_example_._suffix_.d/*._suffix_
  • /etc/_project_/_example_._suffix_.d/*._suffix_

⭐ UAPI Configuration Files Specification ⭐

The libeconf library fulfills all requirements defined by the Linux Userspace API (UAPI) Group chapter "Configuration Files Specification". πŸ“œ

See: https://uapi-group.org/specifications/specs/configuration_files_specification/


πŸ’œ Bindings πŸ’œ


✨ SYNOPSIS ✨

#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include 'libeconf.h'
#include 'libeconf_ext.h'

πŸŽ€ Typedefs

typedef enum econf_err econf_err
typedef struct econf_file econf_file
typedef struct econf_ext_value econf_ext_value

🌸 Enumerations

enum econf_err { ECONF_SUCCESS = 0, ECONF_ERROR = 1, ECONF_NOMEM = 2,
    ECONF_NOFILE = 3, ECONF_NOGROUP = 4, ECONF_NOKEY = 5, ECONF_EMPTYKEY
    = 6, ECONF_WRITEERROR = 7, ECONF_PARSE_ERROR = 8,
    ECONF_MISSING_BRACKET = 9, ECONF_MISSING_DELIMITER = 10,
    ECONF_EMPTY_SECTION_NAME = 11, ECONF_TEXT_AFTER_SECTION = 12,
    ECONF_FILE_LIST_IS_NULL = 13, ECONF_WRONG_BOOLEAN_VALUE = 14,
    ECONF_KEY_HAS_NULL_VALUE = 15, ECONF_WRONG_OWNER = 16,
    ECONF_WRONG_GROUP = 17, ECONF_WRONG_FILE_PERMISSION = 18,
    ECONF_WRONG_DIR_PERMISSION = 19, ECONF_ERROR_FILE_IS_SYM_LINK = 20,
    ECONF_PARSING_CALLBACK_FAILED = 21 }

libeconf error codes β€” bestie, these are your entire emotional support enum πŸ’…

πŸ¦‹ Functions

  • econf_err econf_readConfig (econf_file **key_file, const char *project, const char *usr_subdir, const char *config_name, const char *config_suffix, const char *delim, const char *comment) β€” literally the main character of this whole library 🫢 it evaluates key/values of a given configuration by reading and merging all needed/available files in three different directories (normally in /usr/etc, /run and /etc).
  • econf_err econf_readConfigWithCallback (econf_file **key_file, const char *project, const char *usr_subdir, const char *config_name, const char *config_suffix, const char *delim, const char *comment, bool (*callback)(const char *filename, const void *data), const void *callback_data) β€” does the same thing as econf_readConfig, no cap. The difference? you get to hand it a callback so you can, like, check every single parsed file. very your-vibe-your-rules ✨
  • econf_err econf_readFile (econf_file **result, const char *file_name, const char *delim, const char *comment) β€” processes the file of the given file_name and saves its contents into the key_file object. simple. iconic.
  • econf_err econf_readFileWithCallback (econf_file **result, const char *file_name, const char *delim, const char *comment, bool (*callback)(const char *filename, const void *data), const void *callback_data) β€” same energy as econf_readFile, but the user can additionally define a callback in order to check the parsed file πŸ‘‘
  • econf_err econf_mergeFiles (econf_file **merged_file, econf_file *usr_file, econf_file *etc_file) β€” merges the contents of two key_files objects. friendship bracelet energy fr fr πŸ’–
  • econf_err econf_newKeyFile (econf_file **result, char delimiter, char comment) β€” creates a brand new econf_file object. fresh out the box πŸŽ€
  • econf_err econf_newIniFile (econf_file **result) β€” creates a new econf_file object, but make it IniFile format 🌸
  • econf_err econf_writeFile (econf_file *key_file, const char *save_to_dir, const char *file_name) β€” writes the content of an econf_file struct to the specified location. put it in writing, periodt ✍️
  • char * econf_getPath (econf_file *kf) β€” evaluates the path name of the regarding configuration file.
  • econf_err econf_getGroups (econf_file *kf, size_t *length, char ***groups) β€” evaluates all group entries.
  • econf_err econf_getKeys (econf_file *kf, const char *group, size_t *length, char ***keys) β€” evaluates all keys.
  • econf_err econf_getIntValue (econf_file *kf, const char *group, const char *key, int32_t *result) β€” evaluates the int32 value for a given group/key.
  • econf_err econf_getInt64Value (econf_file *kf, const char *group, const char *key, int64_t *result) β€” evaluates the int64 value for a given group/key.
  • econf_err econf_getUIntValue (econf_file *kf, const char *group, const char *key, uint32_t *result) β€” evaluates the uint32 value for a given group/key.
  • econf_err econf_getUInt64Value (econf_file *kf, const char *group, const char *key, uint64_t *result) β€” evaluates the uint64 value for a given group/key.
  • econf_err econf_getFloatValue (econf_file *kf, const char *group, const char *key, float *result) β€” evaluates the float value for a given group/key.
  • econf_err econf_getDoubleValue (econf_file *kf, const char *group, const char *key, double *result) β€” evaluates the double value for a given group/key.
  • econf_err econf_getStringValue (econf_file *kf, const char *group, const char *key, char **result) β€” evaluates the string value for a given group/key.
  • econf_err econf_getBoolValue (econf_file *kf, const char *group, const char *key, bool *result) β€” evaluates the bool value for a given group/key.
  • econf_err econf_getIntValueDef (econf_file *kf, const char *group, const char *key, int32_t *result, int32_t def) β€” evaluates the int32 value for a given group/key, with a default fallback 🫢
  • econf_err econf_getInt64ValueDef (econf_file *kf, const char *group, const char *key, int64_t *result, int64_t def) β€” evaluates the int64 value for a given group/key, default included.
  • econf_err econf_getUIntValueDef (econf_file *kf, const char *group, const char *key, uint32_t *result, uint32_t def) β€” evaluates the uint32 value for a given group/key, plus a default.
  • econf_err econf_getUInt64ValueDef (econf_file *kf, const char *group, const char *key, uint64_t *result, uint64_t def) β€” evaluates the uint64 value for a given group/key, plus a default.
  • econf_err econf_getFloatValueDef (econf_file *kf, const char *group, const char *key, float *result, float def) β€” evaluates the float value for a given group/key, plus a default.
  • econf_err econf_getDoubleValueDef (econf_file *kf, const char *group, const char *key, double *result, double def) β€” evaluates the double value for a given group/key, plus a default.
  • econf_err econf_getStringValueDef (econf_file *kf, const char *group, const char *key, char **result, char *def) β€” evaluates the string value for a given group/key, plus a default.
  • econf_err econf_getBoolValueDef (econf_file *kf, const char *group, const char *key, bool *result, bool def) β€” evaluates the bool value for a given group/key, plus a default.
  • econf_err econf_setIntValue (econf_file *kf, const char *group, const char *key, int32_t value) β€” sets an int32 value for a given group/key.
  • econf_err econf_setInt64Value (econf_file *kf, const char *group, const char *key, int64_t value) β€” sets an int64 value for a given group/key.
  • econf_err econf_setUIntValue (econf_file *kf, const char *group, const char *key, uint32_t value) β€” sets a uint32 value for a given group/key.
  • econf_err econf_setUInt64Value (econf_file *kf, const char *group, const char *key, uint64_t value) β€” sets a uint64 value for a given group/key.
  • econf_err econf_setFloatValue (econf_file *kf, const char *group, const char *key, float value) β€” sets a float value for a given group/key.
  • econf_err econf_setDoubleValue (econf_file *kf, const char *group, const char *key, double value) β€” sets a double value for a given group/key.
  • econf_err econf_setStringValue (econf_file *kf, const char *group, const char *key, const char *value) β€” sets a string value for a given group/key.
  • econf_err econf_setBoolValue (econf_file *kf, const char *group, const char *key, const char *value) β€” sets a bool value for a given group/key.
  • const char * econf_errString (const econf_err error) β€” converts an econf_err type to a string. translating the vibe check into words πŸ’¬
  • void econf_errLocation (char **filename, uint64_t *line_nr) β€” info about where the error has happened. receipts, basically 🧾
  • void econf_freeArray (char **array) β€” frees an array of type char** created by econf_getGroups() or econf_getKeys(). cleanup era 🧹
  • void econf_freeFile (econf_file *key_file) β€” frees memory allocated by e.g. … (yes bestie, the sentence really does just trail off like that in the original, i'm not hiding anything from you πŸ’€)
  • char econf_comment_tag (econf_file *key_file) β€” returns the comment character tag of the given econf_file object.
  • char econf_delimiter_tag (econf_file *key_file) β€” returns the delimiter character of the given econf_file object.
  • void econf_set_comment_tag (econf_file *key_file, const char comment) β€” sets the comment character tag of the given econf_file object.
  • void econf_set_delimiter_tag (econf_file *key_file, const char delimiter) β€” sets the delimiter character of the given econf_file object.
  • econf_err econf_getExtValue (econf_file *kf, const char *group, const char *key, econf_ext_value **result) β€” evaluates more information for a given group/key. the deluxe version, the extra lore πŸ‘€
  • void econf_freeExtValue (econf_ext_value *to_free) β€” frees a complete econf_ext_value struct.
  • econf_err econf_set_conf_dirs (const char **dir_postfix_list) β€” sets a list of directory structures (with order) which describes the directories in which the files have to be parsed. you're literally picking the order, main character behaviour ✨

πŸ’– Detailed Description πŸ’–

Public API for the econf library.

Definition in file libeconf.h and libeconf_ext.h.


🌈 Typedef Documentation 🌈

typedef struct econf_file econf_file

Container which includes all information about the configuration file(s). it's giving ✨everything bagel✨ but for config data πŸ₯―

typedef struct econf_ext_value econf_ext_value

okay so this one is a whole lil bundle of lore, and every field matters:

  • char ** values β€” values of a given key in form of an string array.
  • char * file β€” path of the configuration file where this value has been read.
  • uint64_t line_number β€” line number of the configuration key/value.
  • char * comment_before_key β€” comment before the key/value entry.
  • char * comment_after_value β€” comment after the value entry.

like, it knows where it came from, what line it's on, and what was being whispered about it before and after. iconic, honestly πŸŽ€


⭐ Enumeration Type Documentation ⭐

enum econf_err

libeconf error codes

Enumerator

  • ECONF_SUCCESS β€” general purpose success code. slay! πŸŽ‰
  • ECONF_ERROR β€” generic Error.
  • ECONF_NOMEM β€” out of memory. 😭
  • ECONF_NOFILE β€” config file not found.
  • ECONF_NOGROUP β€” group not found.
  • ECONF_NOKEY β€” key not found.
  • ECONF_EMPTYKEY β€” key has empty value.
  • ECONF_WRITEERROR β€” error creating or writing to a file.
  • ECONF_PARSE_ERROR β€” general syntax error in input file.
  • ECONF_MISSING_BRACKET β€” missing closing section bracket.
  • ECONF_MISSING_DELIMITER β€” missing delimiter.
  • ECONF_EMPTY_SECTION_NAME β€” empty section name.
  • ECONF_TEXT_AFTER_SECTION β€” text after section.
  • ECONF_FILE_LIST_IS_NULL β€” parsed file list is NULL.
  • ECONF_WRONG_BOOLEAN_VALUE β€” wrong boolean value (1/0 true/false yes/no)
  • ECONF_KEY_HAS_NULL_VALUE β€” given key has NULL value.
  • ECONF_WRONG_OWNER β€” file has wrong owner.
  • ECONF_WRONG_GROUP β€” file has wrong group.
  • ECONF_WRONG_FILE_PERMISSION β€” file has wrong file permissions.
  • ECONF_WRONG_DIR_PERMISSION β€” file has wrong dir permissions.
  • ECONF_ERROR_FILE_IS_SYM_LINK β€” file is a sym link which is not permitted. 🚫
  • ECONF_PARSING_CALLBACK_FAILED β€” user defined parsing callback has failed. πŸ’€

✨ Function Documentation ✨


πŸ’« econf_readConfig()

econf_err econf_readConfig (econf_file ** key_file, const char *project,
    const char *usr_subdir, const char *config_name, const char
    *config_suffix, const char *delim, const char *comment)

Bestie, this one is the main character. It evaluates the key/values of a config by reading and merging all the needed/available files from different directories. And the order it does that in? Iconic and very specific, so pay attention bestie:

  • If /etc/$project/$config_name.$config_suffix does exist:
    • /etc/$project/$config_name.$config_suffix
    • $usr_subdir/$project/$config_name.$config_suffix.d/*.$config_suffix
    • /run/$project/$config_name.$config_suffix.d/*.$config_suffix
    • /etc/$project/$config_name.$config_suffix.d/*.$config_suffix
  • If /etc/$project/$config_name.$config_suffix does NOT exist:
    • If /run/$project/$config_name.$config_suffix does exist:
      • /run/$project/$config_name.$config_suffix
      • $usr_subdir/$project/$config_name.$config_suffix.d/*.$config_suffix
      • /run/$project/$config_name.$config_suffix.d/*.$config_suffix
      • /etc/$project/$config_name.$config_suffix.d/*.$config_suffix
    • If /run/$project/$config_name.$config_suffix does NOT exist:
      • $usr_subdir/$project/$config_name.$config_suffix
      • $usr_subdir/$project/$config_name.$config_suffix.d/*.$config_suffix
      • /run/$project/$config_name.$config_suffix.d/*.$config_suffix
      • /etc/$project/$config_name.$config_suffix.d/*.$config_suffix
  • If no main $config_name.$config_suffix file is defined, or it must not be parsed:
    • $usr_subdir/$project.d/*.$config_suffix
    • /run/$project.d/*.$config_suffix
    • /etc/$project.d/*.$config_suffix

🫢 Parameters

  • key_file β€” content of parsed file(s)
  • project β€” name of the project used as subdirectory, can be NULL
  • usr_subdir β€” absolute path of the first directory (often "/usr/lib")
  • config_name β€” basename of the configuration file. If it is NULL, drop-ins without a main configuration file will be parsed only.
  • config_suffix β€” suffix of the configuration file. Can also be NULL.
  • delim β€” delimiters of key/value e.g. '\t ='. If delim contains space characters AND none space characters, multiline values are not parseable.
  • comment β€” array of characters which define the start of a comment

πŸŽ€ Returns

econf_err ECONF_SUCCESS or error code

🌈 Example

Reading content in different cases in following order:

/etc/foo/example.conf does exist:

  • /etc/foo/example.conf
  • /usr/lib/foo/example.conf.d/ *.conf
  • /run/foo/example.conf.d/ *.conf
  • /etc/foo/example.conf.d/ *.conf

/etc/foo/example.conf does NOT exist:

  • /run/foo/example.conf does exist:
    • /run/foo/example.conf
    • /usr/lib/foo/example.conf.d/ *.conf
    • /run/foo/example.conf.d/ *.conf
    • /etc/foo/example.conf.d/ *.conf
  • /run/foo/example.conf does NOT exist:
    • /usr/lib/foo/example.conf
    • /usr/lib/foo/example.conf.d/ *.conf
    • /run/foo/example.conf.d/ *.conf
    • /etc/foo/example.conf.d/ *.conf
#include "libeconf.h"

econf_file *key_file = NULL;
econf_err error;

error = econf_readConfig (&key_file,
                          "foo",
                          "/usr/lib",
                          "example",
                          "conf",
                          "=", "#");

econf_free (key_file);

πŸ¦‹ econf_readConfigWithCallback()

econf_err econf_readConfigWithCallback (econf_file ** key_file, const char
    *project, const char *usr_subdir, const char *config_name, const char
    *config_suffix, const char *delim, const char *comment, bool
    (*callback)(const char *filename, const void *data), const void
    *callback_data)

Same energy as econf_readConfig β€” it evaluates key/values of a given configuration by reading and merging all needed/available files from different directories. Order is:

  • If /etc/$project/$config_name.$config_suffix does exist:
    • /etc/$project/$config_name.$config_suffix
    • $usr_subdir/$project/$config_name.$config_suffix.d/*.$config_suffix
    • /run/$project/$config_name.$config_suffix.d/*.$config_suffix
    • /etc/$project/$config_name.$config_suffix.d/*.$config_suffix
  • If /etc/$project/$config_name.$config_suffix does NOT exist:
    • If /run/$project/$config_name.$config_suffix does exist:
      • /run/$project/$config_name.$config_suffix
      • $usr_subdir/$project/$config_name.$config_suffix.d/*.$config_suffix
      • /run/$project/$config_name.$config_suffix.d/*.$config_suffix
      • /etc/$project/$config_name.$config_suffix.d/*.$config_suffix
    • If /run/$project/$config_name.$config_suffix does NOT exist:
      • $usr_subdir/$project/$config_name.$config_suffix
      • $usr_subdir/$project/$config_name.$config_suffix.d/*.$config_suffix
      • /run/$project/$config_name.$config_suffix.d/*.$config_suffix
      • /etc/$project/$config_name.$config_suffix.d/*.$config_suffix
  • If no main $config_name.$config_suffix file is defined, or it must not be parsed:
    • $usr_subdir/$project.d/*.$config_suffix
    • /run/$project.d/*.$config_suffix
    • /etc/$project.d/*.$config_suffix

For each parsed file the user defined function will be called in order, e.g. to check the correct file permissions. πŸ’…

🫢 Parameters

  • key_file β€” content of parsed file(s)
  • project β€” name of the project used as subdirectory, can be NULL
  • usr_subdir β€” absolute path of the first directory (often "/usr/lib")
  • config_name β€” basename of the configuration file. If it is NULL, drop-ins without a main configuration file will be parsed only.
  • config_suffix β€” suffix of the configuration file. Can also be NULL.
  • delim β€” delimiters of key/value e.g. '\t ='. If delim contains space characters AND none space characters, multiline values are not parseable.
  • comment β€” array of characters which define the start of a comment
  • callback β€” function which will be called for each file. This user defined function has the pathname as parameter and returns true if this file can be parsed. If not, the parsing of all files will be aborted and ECONF_PARSING_CALLBACK_FAILED will be returned.
  • callback_data β€” pointer which will be given to the callback function.

πŸŽ€ Returns

econf_err ECONF_SUCCESS or error code

🌈 Example

Reading content in different cases in following order:

/etc/foo/example.conf does exist:

  • /etc/foo/example.conf
  • /usr/lib/foo/example.conf.d/ *.conf
  • /run/foo/example.conf.d/ *.conf
  • /etc/foo/example.conf.d/ *.conf

/etc/foo/example.conf does NOT exist:

  • /run/foo/example.conf does exist:
    • /run/foo/example.conf
    • /usr/lib/foo/example.conf.d/ *.conf
    • /run/foo/example.conf.d/ *.conf
    • /etc/foo/example.conf.d/ *.conf
  • /run/foo/example.conf does NOT exist:
    • /usr/lib/foo/example.conf
    • /usr/lib/foo/example.conf.d/ *.conf
    • /run/foo/example.conf.d/ *.conf
    • /etc/foo/example.conf.d/ *.conf
#include "libeconf.h"

bool checkFile(const char *filename, const void *data) {
  /* checking code which returns true or false */
  return true;
}

econf_file *key_file = NULL;
econf_err error;

error = econf_readConfigWithCallback (&key_file,
                                      "foo",
                                      "/usr/lib",
                                      "example",
                                      "conf",
                                      "=", "#",
                                      checkFile,
                                      NULL);

econf_free (key_file);

πŸ“ econf_readFile()

econf_err econf_readFile (econf_file ** result, const char * file_name,
    const char * delim, const char * comment)

Process the file of the given file_name and save its contents into the key_file object. Slay. ✨

🫢 Parameters

  • result β€” content of parsed file
  • file_name β€” absolute path of parsed file
  • delim β€” delimiters of key/value e.g. '\t ='
  • comment β€” array of characters which define the start of a comment

πŸŽ€ Returns

econf_err ECONF_SUCCESS or error code

🌈 Usage

#include "libeconf.h"

econf_file *key_file = NULL;
econf_err error;

error = econf_readFile (&key_file, "/etc/test.conf", "=", "#");

econf_free (key_file);
Default behaviour if entries have the same name in one file: The first hit will be returned. Further entries will be ignored. This can be changed by setting the environment variable JOIN_SAME_ENTRIES (see econf_set_opt). In that case entries with the same name will be joined to one single entry.

🧚 econf_readFileWithCallback()

econf_err econf_readFileWithCallback (econf_file ** result, const char *
    file_name, const char * delim, const char * comment, bool
    (*callback)(const char *filename, const void *data), const void
    *callback_data)

Process the file of the given file_name and save its contents into the key_file object. The user defined function will be called in order, e.g. to check the correct file permissions. πŸ‘‘

🫢 Parameters

  • result β€” content of parsed file
  • file_name β€” absolute path of parsed file
  • delim β€” delimiters of key/value e.g. '\t ='
  • comment β€” array of characters which define the start of a comment
  • callback β€” function which will be called for the given filename. This user defined function has the pathname as parameter and returns true if this file can be parsed. If not, the parsing will be aborted and ECONF_PARSING_CALLBACK_FAILED will be returned.
  • callback_data β€” pointer which will be given to the callback function.

πŸŽ€ Returns

econf_err ECONF_SUCCESS or error code

🌈 Usage

#include "libeconf.h"
bool checkFile(const char *filename, const void *data) {
  /* checking code which returns true or false */
  return true;
}

econf_file *key_file = NULL;
econf_err error;

error = econf_readFileWithCallback (&key_file, "/etc/test.conf", "=", "#", checkFile, NULL);
econf_free (key_file);
Default behaviour if entries have the same name in one file: The first hit will be returned. Further entries will be ignored. This can be changed by setting the environment variable JOIN_SAME_ENTRIES (see econf_set_opt). In that case entries with the same name will be joined to one single entry.

πŸ’œ econf_mergeFiles()

econf_err econf_mergeFiles (econf_file ** merged_file, econf_file *
    usr_file, econf_file * etc_file)

Merge the contents of two key_files objects. Entries in etc_file will be preferred. πŸ’… Comment and delimiter tag will be taken from usr_file. This can be changed by calling the functions econf_set_comment_tag and econf_set_delimiter_tag. πŸŽ€

🫢 Parameters

  • merged_file β€” merged data
  • usr_file β€” First data block which has to be merged.
  • etc_file β€” Second data block which has to be merged.

πŸŽ€ Returns

econf_err ECONF_SUCCESS or error code

okay so here's the usage vibe when you're putting it all together:

       Usage:

       #include "libeconf.h"

       econf_file *key_file_1 = NULL, *key_file_2 = NULL, *key_file_ret = NULL
       econf_err error;

       error = econf_readFile (&key_file1, "/usr/etc/test.conf", "=", "#");
       error = econf_readFile (&key_file2, /etc/test.conf", "=", "#");
       error = econf_mergeFiles (&key_file_ret, key_file_1, key_file_2);

       econf_free (key_file_ret);
       econf_free (key_file_1);
       econf_free (key_file_2);

econf_newKeyFile

   econf_err econf_newKeyFile (econf_file ** result, char delimiter, char
       comment)

Bestie, this one creates a brand new econf_file object. It's giving main character energy ✨.

Parameters:

  • result β€” pointer to the allocated econf_file object. That's where it lives.
  • delimiter β€” delimiter of key/value, e.g. '='.
  • comment β€” character which defines the start of a comment.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_newIniFile

   econf_err econf_newIniFile (econf_file ** result)

Okay so this makes a new econf_file object in IniFile format. So the delimiter will be '=' and comments start with '#'. Periodt. πŸ’…

Parameters:

  • result β€” pointer to the allocated econf_file object.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_writeFile

   econf_err econf_writeFile (econf_file * key_file, const char * save_to_dir,
       const char * file_name)

This one writes the content of an econf_file struct to a specified location. No cap. 🫢

Parameters:

  • key_file β€” data which has to be written.
  • save_to_dir β€” directory into which the file has to be written.
  • file_name β€” filename (with suffix).

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getPath

   char* econf_getPath (econf_file * kf)

Evaluating path name β€” it's giving detective vibes πŸ”.

Parameters:

  • kf β€” given/parsed data.

Returns:

  • Absolute path name or an empty string if kf is a result of already merged data (e.G. returned by econf_readDirs).

econf_getGroups

   econf_err econf_getGroups (econf_file * kf, size_t * length, char ***
       groups)

Evaluating all group entries β€” collect them all like PokΓ©mon ✨.

Parameters:

  • kf β€” given/parsed data.
  • length β€” length of the returned group array.
  • groups β€” string array of evaluated groups.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getKeys

   econf_err econf_getKeys (econf_file * kf, const char * group, size_t *
       length, char *** keys)

Evaluating all keys β€” the way that this function just gathers them πŸ’….

Parameters:

  • kf β€” given/parsed data.
  • group β€” group name for which the keys have to be evaluated or NULL for keys, which do not belong to a group.
  • length β€” length of the returned key array.
  • keys β€” string array of evaluated keys.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getIntValue

   econf_err econf_getIntValue (econf_file * kf, const char * group, const char
       * key, int32_t * result)

Evaluating int32 value for given group/key. Lowkey useful.

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value is requested.
  • result β€” determined value.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getInt64Value

   econf_err econf_getInt64Value (econf_file * kf, const char * group, const
       char * key, int64_t * result)

Evaluating int64 value for given group/key. Highkey same energy.

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value is requested.
  • result β€” determined value.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getUIntValue

   econf_err econf_getUIntValue (econf_file * kf, const char * group, const
       char * key, uint32_t * result)

Evaluating uint32 value for given group/key. Slay.

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value is requested.
  • result β€” determined value.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getUInt64Value

   econf_err econf_getUInt64Value (econf_file * kf, const char * group, const
       char * key, uint64_t * result)

Evaluating uint64 value for given group/key. Iconic.

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value is requested.
  • result β€” determined value.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getFloatValue

   econf_err econf_getFloatValue (econf_file * kf, const char * group, const
       char * key, float * result)

Evaluating float value for given group/key. It's giving precision πŸ’….

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value is requested.
  • result β€” determined value.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getDoubleValue

   econf_err econf_getDoubleValue (econf_file * kf, const char * group, const
       char * key, double * result)

Evaluating double value for given group/key. Double the trouble, double the slay ✨.

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value is requested.
  • result β€” determined value.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getStringValue

   econf_err econf_getStringValue (econf_file * kf, const char * group, const
       char * key, char ** result)

Evaluating string value for given group/key. The moment we've all been waiting for.

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value is requested.
  • result β€” a newly allocated string or NULL in error case.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getBoolValue

   econf_err econf_getBoolValue (econf_file * kf, const char * group, const
       char * key, bool * result)

Evaluating bool value for given group/key. True or false, bestie.

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value is requested.
  • result β€” determined value.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getIntValueDef

   econf_err econf_getIntValueDef (econf_file * kf, const char * group, const
       char * key, int32_t * result, int32_t def)

Evaluating int32 value for given group/key. If key is not found, the default value is returned and error is ECONF_NOKEY. No cap.

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value is requested.
  • result β€” determined value.
  • def β€” default value if the value has not been found.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getInt64ValueDef

   econf_err econf_getInt64ValueDef (econf_file * kf, const char * group, const
       char * key, int64_t * result, int64_t def)

Evaluating int64 value for given group/key. If key is not found, the default value is returned and error is ECONF_NOKEY. Periodt.

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value is requested.
  • result β€” determined value.
  • def β€” default value if the value has not been found.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getUIntValueDef

   econf_err econf_getUIntValueDef (econf_file * kf, const char * group, const
       char * key, uint32_t * result, uint32_t def)

Evaluating uint32 value for given group/key. If key is not found, the default value is returned and error is ECONF_NOKEY. Lowkey clutch.

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value is requested.
  • result β€” determined value.
  • def β€” default value if the value has not been found.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getUInt64ValueDef

   econf_err econf_getUInt64ValueDef (econf_file * kf, const char * group,
       const char * key, uint64_t * result, uint64_t def)

Evaluating uint64 value for given group/key. If key is not found, the default value is returned and error is ECONF_NOKEY. Slay.

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value is requested.
  • result β€” determined value.
  • def β€” default value if the value has not been found.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getFloatValueDef

   econf_err econf_getFloatValueDef (econf_file * kf, const char * group, const
       char * key, float * result, float def)

Evaluating float value for given group/key. If key is not found, the default value is returned and error is ECONF_NOKEY. It's giving fallback realness.

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value is requested.
  • result β€” determined value.
  • def β€” default value if the value has not been found.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getDoubleValueDef

   econf_err econf_getDoubleValueDef (econf_file * kf, const char * group,
       const char * key, double * result, double def)

Evaluating double value for given group/key. If key is not found, the default value is returned and error is ECONF_NOKEY. Double the fallback, double the vibe.

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value is requested.
  • result β€” determined value.
  • def β€” default value if the value has not been found.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getStringValueDef

   econf_err econf_getStringValueDef (econf_file * kf, const char * group,
       const char * key, char ** result, char * def)

Evaluating string value for given group/key. If key is not found, the default value is returned and error is ECONF_NOKEY. The way that this handles strings is iconic.

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value is requested.
  • result β€” returns a newly allocated string, even if 'default' is returned.
  • def β€” default value if the value has not been found.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_getBoolValueDef

   econf_err econf_getBoolValueDef (econf_file * kf, const char * group, const
       char * key, bool * result, bool def)

Evaluating bool value for given group/key. If key is not found, the default value is returned and error is ECONF_NOKEY. True story.

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value is requested.
  • result β€” determined value.
  • def β€” default value if the value has not been found.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_setIntValue

   econf_err econf_setIntValue (econf_file * kf, const char * group, const char
       * key, int32_t value)

Set int32 value for given group/key. Setting the vibe, no cap.

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value has to be set.
  • value β€” value which has to be set.

Returns:

  • econf_err β€” ECONF_SUCCESS or error code.

econf_setInt64Value

   econf_err econf_setInt64Value (econf_file * kf, const char * group, const char
       * key, int64_t value)

Set int64 value for given group/key. Big numbers, big energy.

Parameters:

  • kf β€” given/parsed data.
  • group β€” desired group or NULL if there is no group defined.
  • key β€” key for which the value has to be set.
  • value β€” value which has to be set.

econf_err econf_setUIntValue (econf_file * kf, const char * group, const char * key, uint32_t value) πŸŽ€

bestie. this one sets a uint32 value for the group/key you point it at. tiny number, big energy. ✨

Parameters:

  • kf β€” the given/parsed data, aka your whole config situation
  • group β€” the group you want, or NULL if there is no group defined
  • key β€” the key for which the value has to be set
  • value β€” the value which has to be set

Returns: econf_err β€” ECONF_SUCCESS or an error code


econf_err econf_setUInt64Value (econf_file * kf, const char * group, const char * key, uint64_t value) πŸ’–

same vibe as above but the number is uint64, so it's the bigger sister. more digits, more slay. πŸ”₯

Parameters:

  • kf β€” the given/parsed data
  • group β€” the group you want, or NULL if there is no group defined
  • key β€” the key for which the value has to be set
  • value β€” the value which has to be set

Returns: econf_err β€” ECONF_SUCCESS or an error code


econf_err econf_setFloatValue (econf_file * kf, const char * group, const char * key, float value) 🌸

sets a float value for the group/key. yes, decimals. yes, she's precise. πŸ’…

Parameters:

  • kf β€” the given/parsed data
  • group β€” the group you want, or NULL if there is no group defined
  • key β€” the key for which the value has to be set
  • value β€” the value which has to be set

Returns: econf_err β€” ECONF_SUCCESS or an error code


econf_err econf_setDoubleValue (econf_file * kf, const char * group, const char * key, double value) ✨

and now the double version. more precision, same group/key energy. ngl she ate. πŸ¦‹

Parameters:

  • kf β€” the given/parsed data
  • group β€” the group you want, or NULL if there is no group defined
  • key β€” the key for which the value has to be set
  • value β€” the value which has to be set

Returns: econf_err β€” ECONF_SUCCESS or an error code


econf_err econf_setStringValue (econf_file * kf, const char * group, const char * key, const char * value) πŸ’¬

sets a string value for the given group/key. the classic. the moment. the icon. πŸ‘‘

Parameters:

  • kf β€” the given/parsed data
  • group β€” the group you want, or NULL if there is no group defined
  • key β€” the key for which the value has to be set
  • value β€” the value which has to be set

Returns: econf_err β€” ECONF_SUCCESS or an error code


econf_err econf_setBoolValue (econf_file * kf, const char * group, const char * key, const char * value) πŸ“

sets a bool value for the given group/key. note the plot twist: the value here is a const char *, not an actual bool. that's just how she is. πŸ’€

Parameters:

  • kf β€” the given/parsed data
  • group β€” the group you want, or NULL if there is no group defined
  • key β€” the key for which the value has to be set
  • value β€” the value which has to be set

Returns: econf_err β€” ECONF_SUCCESS or an error code


const char* econf_errString (const econf_err error) 🫢

converts an econf_err type into a string, fr fr. error code in, words out. translator behavior. 🌈

Parameters:

  • error β€” error enum

Returns: human readable string


void econf_errLocation (char ** filename, uint64_t * line_nr) πŸ”

the receipts!! gives you info about where the error has happened. detective mode activated. πŸ•΅οΈ

Parameters:

  • filename β€” path of the last scanned file
  • line_nr β€” number of the last handled line

void econf_freeArray (char ** array) 🧹

frees an array of type char** that was created by econf_getGroups() or econf_getKeys(). clean up after yourself bestie, the memory is not gonna free itself. 😭

Parameters:

  • array β€” array of strings

Returns: void


void econf_freeFile (econf_file * key_file) πŸ—‘οΈ

frees memory allocated by e.g. econf_readFile(), econf_readDirs(),... you know the drill.

Parameters:

  • key_file β€” allocated data

Returns: void


char econf_comment_tag (econf_file * key_file) πŸŽ€

returns the comment character tag of the given econf_file object. this tag will be taken while writing comments to file. she's telling you how she comments. πŸ’œ

Parameters:

  • key_file β€” econf_file object

Returns: char comment character tag


char econf_delimiter_tag (econf_file * key_file) βž—

returns the delimiter character of the given econf_file object. this delimiter will be taken while writing the data to file.

Parameters:

  • key_file β€” econf_file object

Returns: char delimiter of key/value


void econf_set_comment_tag (econf_file * key_file, const char comment) πŸ’…

sets the comment character tag of the given econf_file object. this tag will be taken while writing comments to file. you're literally choosing her comment aesthetic.

Parameters:

  • key_file β€” econf_file object
  • comment β€” comment tag

void econf_set_delimiter_tag (econf_file * key_file, const char delimiter) βœ‚οΈ

sets the delimiter character of the given econf_file object. this delimiter will be taken while writing the data to file.

Parameters:

  • key_file β€” econf_file object
  • delimiter β€” delimiter of key/value

econf_err econf_getExtValue (econf_file * kf, const char * group, const char * key, econf_ext_value ** result) πŸ”₯

evaluating more information for the given group/key. extra lore, if you will. the extended cut. 🎬

Parameters:

  • kf β€” the given/parsed data
  • group β€” the group you want, or NULL if there is no group defined
  • key β€” the key for which the value is requested
  • result β€” a newly allocated struct or NULL in error case

Returns: econf_err β€” ECONF_SUCCESS or an error code


void econf_freeExtValue (econf_ext_value * to_free) 🧼

frees a complete econf_ext_value struct. the whole thing, no crumbs left. 🍽️

Parameters:

  • to_free β€” struct which has to be freed

Returns: void


econf_err econf_set_conf_dirs (const char **dir_postfix_list) πŸ“

sets a list of directory structures (with order) which describes the directories in which the files have to be parsed. order matters, it's giving main character sequencing. ⭐

Parameters:

  • dir_postfix_list β€” list of directory structures. E.G. with the given list: {"/conf.d/", ".d/", "/", NULL} files in the following directories will be parsed: <default_dirs>/<project_name>.<suffix>.d/ <default_dirs>/<project_name>/conf.d/, <default_dirs>/<project_name>.d/, <default_dirs>/<project_name>/. The entry <default_dirs>/<project_name>.<suffix>.d/ will be added automatically.

Returns: econf_err β€” ECONF_SUCCESS or an error code


🌈 SEE ALSO 🌈

  • econftool

and that's a wrap on libeconf(3), bestie!! πŸŽ€βœ¨ this was Version 0.4.7, dated Thu Apr 8 2021, and honestly? iconic behavior. go forth and parse, you absolute legend. πŸ’–πŸ¦‹πŸŒΈπŸ‘‘