From 12476abdab83f765da8173e73b172ecf4749f6b9 Mon Sep 17 00:00:00 2001 From: katherine Date: Sat, 7 Dec 2019 15:16:24 -0700 Subject: initial commit --- README.md | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 README.md (limited to 'README.md') diff --git a/README.md b/README.md new file mode 100644 index 0000000..4173770 --- /dev/null +++ b/README.md @@ -0,0 +1,199 @@ +simple-xdg-bdirs +================ + +[simple-xdg-bdirs.h](simple-xdg-bdirs.h) is a single header file which +implements calculating file paths according to the +[XDG Base Directory Specification][1]. + +brief summary +------------- + +the XDG Base Directory Specification is a popular specification which defines +predictable locations for programs to store their config, runtime, cache, and +data files. these locations are calculated based on specially named environment +variables, with certain directories defined as default fallbacks. + +this single-header library provides a couple of simple functions to calculate +those locations at runtime, as well as functions to build file paths against +them. + +example +------- + +the following example file is available as [example.c](doc/example.c), which +you can compile and play with yourself. + +```C +#include +#include + +#include "../simple-xdg-bdirs.h" + +/* a simple example which attempts to read a value from a configuration file + * and write it back to a cache file */ +int main(int argc, char *argv[]) +{ + char *s, *wdir, **rdirs, **cur; + + /* alloc a null-terminated array of directories in which to search for + * configuration files */ + rdirs = simple_xdg_bdirs_read_dirs(SIMPLE_XDG_BDIRS_CONFIG); + + /* in case of error, errno is set, so perror works */ + if (rdirs == NULL) { + perror(NULL); + return 1; + } + + /* search in the config directories for the given relative path. if not + * found in the first, the second will be checked as a fallback etc */ + s = simple_xdg_bdirs_fullpath_read("xdg_bdirs_test/config.conf", rdirs); + + /* element strings of rdirs must also be freed */ + for (cur = rdirs; *cur != NULL; cur++) + free(*cur); + free(rdirs); + + /* check for errors again */ + if (s == NULL) { + perror(NULL); + return 1; + } + + /* print the fullpath of the file that was found */ + puts(s); + free(s); + + /* locate the directory into which runtime files should be written + * (things like sockets or lock files) */ + wdir = simple_xdg_bdirs_write_dir(SIMPLE_XDG_BDIRS_RUNTIME); + + if (wdir == NULL) { + perror(NULL); + return 1; + } + + /* a convenience function that builds a fullpath from a relative path and + * write directory */ + s = simple_xdg_bdirs_fullpath_write("xdg_bdirs_test.lock", wdir); + + free(wdir); + + if (s == NULL) { + perror(NULL); + return 1; + } + + puts(s); + free(s); + + return 0; +} +``` + +basically, each function returns either a string or `NULL`, in which case +`errno` will also be set. simple! + +interface +--------- + +```C +enum simple_xdg_bdirs_ftype { + SIMPLE_XDG_BDIRS_DATA, + SIMPLE_XDG_BDIRS_CONFIG, + SIMPLE_XDG_BDIRS_CACHE, + SIMPLE_XDG_BDIRS_RUNTIME, +}; +``` + +one of these types is passed to each of the functions below, denoting the +category of file to which the functions actions ought to correspond. + +- `SIMPLE_XDG_BDIRS_DATA` is used for persistent data created by a program +- `SIMPLE_XDG_BDIRS_CONFIG` is used for a program's configuration files +- `SIMPLE_XDG_BDIRS_CACHE` is used for transient data which may be deleted + without warning by the system +- `SIMPLE_XDG_BDIRS_RUNTIME` is used for "runtime files", such as lock files + or sockets + + +```C +static char* +simple_xdg_bdirs_write_dir(enum simple_xdg_bdirs_ftype type) +``` + +this function finds and returns a single string that is the path of a +directory into which all files of type `type` ought to be written. + +because the location of this directory is determined at runtime, and in +particular because it relies on the state of the filesystem and environment +variables, it is possible that no good candidate directory will be found, in +which case `NULL` will be returned. + +if a string is returned, it is guaranteed to always have a trailing '/', +meaning that a relative path can be appended directly without fear of +unintended results, like '/etx/xdgherbstluftwm' + +errors: +- `ENOENT`: no candidate dir found +- `EINVAL`: bad argument +- `EOVERFLOW`: extremely-large string encountered (unlikely) +- `ENOMEM`: malloc err + + +```C +static char** +simple_xdg_bdirs_read_dirs(enum simple_xdg_bdirs_ftype type) +``` + +this function finds and returns a null-terminated array of strings that are +the paths, in order, where one ought to search for files of type `type` when +reading. + +because some filetypes have only a single, environment-determined read dir, +it's possible that none will be found, in which case `NULL` will be +returned. + +returned strings are guaranteed to always have a trailing '/', meaning that +a relative path can be appended directly without fear of unintended results, +like '/etx/xdgherbstluftwm' + +errors: +- `ENOENT`: no candidate dirs found +- `EINVAL`: bad argument +- `EOVERFLOW`: extremely-large string encountered (unlikely) +- `ENOMEM`: malloc err + + +```C +static char* +simple_xdg_bdirs_fullpath_read(const char *rel_path, char **read_dirs) +``` + +take a relative path and set of directories returned from +`simple_xdg_bdirs_read_dirs` and return either a full path to an existing +file or, on error, NULL + +errors +- `ENOENT`: target file not found or readable +- `EINVAL`: bad argument +- `EOVERFLOW`: extremely-large string encountered (unlikely) +- `ENOMEM`: malloc err + + +```C +static char* +simple_xdg_bdirs_fullpath_write(const char *rel_path, char *write_dir) +``` + +take a relative path and a write directory returned from +`simple_xdg_bdirs_write_dir` and return either a full path to the targeted +write path or, on error, NULL + +errors +- `ENOENT`: write_dir is not found or not write accessible +- `EINVAL`: bad argument +- `EOVERFLOW`: extremely-large string encountered (unlikely) +- `ENOMEM`: malloc err + +[1]: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html -- cgit v1.2.3