summaryrefslogtreecommitdiff
path: root/src/paths.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/paths.h')
-rw-r--r--src/paths.h261
1 files changed, 261 insertions, 0 deletions
diff --git a/src/paths.h b/src/paths.h
new file mode 100644
index 0000000..8be56f8
--- /dev/null
+++ b/src/paths.h
@@ -0,0 +1,261 @@
+/**
+ * \file paths.h
+ * XDG Directory Specification implementation
+ */
+
+#ifndef PATHS_H
+#define PATHS_H
+
+/**
+ * Opaque type for paths
+ */
+typedef struct paths_t paths_t;
+
+/**
+ * Opaque type for a currently open file
+ */
+typedef struct paths_file_t paths_file_t;
+
+/**
+ * The different sources or directories if you will that are in the
+ * specification.
+ */
+typedef enum paths_source_t
+{
+ /** directory for data files */
+ PATHS_DATA,
+ /** directory for config files */
+ PATHS_CONFIG,
+ /** directory for cache files */
+ PATHS_CACHE,
+ /** directory for runtime files */
+ PATHS_RUNTIME,
+} paths_source_t;
+
+/** Do not block write calls */
+#define PATHS_NONBLOCK (0x01)
+/** Append on each write */
+#define PATHS_APPEND (0x02)
+/** Create file if needed */
+#define PATHS_CREATE (0x04)
+/** Truncate file when opening */
+#define PATHS_TRUNCATE (0x08)
+/** If PATHS_CREATE is set, give error if file already exists */
+#define PATHS_EXCLUSIVE (0x10)
+
+/**
+ * Create a new paths.
+ * Initializes the list of directories from enviroment variables.
+ * Returned object has a reference count of one.
+ * Threadsafe.
+ * Returns NULL in case of allocation errors.
+ * @return a new paths
+ */
+MALLOC paths_t* paths_new(void);
+
+/**
+ * Increase the reference count for paths.
+ * Threadsafe.
+ * @param paths paths object, may not be NULL
+ */
+NONULL void paths_ref(paths_t* paths);
+
+/**
+ * Decrease the reference count for paths and free if it reached zero.
+ * Threadsafe.
+ * @param paths paths object, may be NULL
+ */
+void paths_unref(paths_t* paths);
+
+/**
+ * Get single directory where user-specific files should be written.
+ * May only return NULL for PATHS_RUNTIME all other sources are guaranteed to
+ * return a non-NULL string. They may however return non-existant paths.
+ * PATHS_RUNTIME will return NULL if no such path was found as it has no
+ * default.
+ * If you wish paths to be created if missing, please use paths_write().
+ * Threadsafe.
+ * @param paths paths object, may not be NULL
+ * @param source requested directory
+ * @return absolute path to directory or NULL
+ */
+NONULL const char* paths_user_dir(paths_t* paths, paths_source_t source);
+
+/**
+ * Get preference ordered list of directories to search for files.
+ * All paths are absolute and NULL terminated. The list itself is NULL
+ * terminated and may never be empty. Path returned by paths_user_dir() for
+ * the same source is not included.
+ * Will return NULL for PATHS_CACHE and PATHS_RUNTIME as they are only
+ * user-specific writable directories.
+ * Threadsafe.
+ * @param paths paths object, may not be NULL
+ * @param source requested directory
+ * @return NULL terminated list of absolute paths to search or NULL
+ */
+NONULL const char** paths_search_dirs(paths_t* paths, paths_source_t source);
+
+/**
+ * Callback called with the result(s) from paths_find(). May be called from
+ * any thread. Return false to cancel the search, true to continue until all
+ * has been found. filename will be NULL when no more matches was found.
+ * The filename pointer is only valid until the callback has returned.
+ * @param userdata userdata given to paths_find()
+ * @param filenamme found file or NULL if no more results
+ * @return true to continue the search, false to not */
+typedef bool (* paths_find_callback_t)(void* userdata, const char* filename);
+
+/**
+ * Asynchronous search for matching files in directories for source.
+ * Returned in preference order, first paths_user_dir() and then
+ * paths_search_dirs().
+ * The callback is always called at least once.
+ * Match may use *, ?, [] and {} glob matches. It may also contain / characters
+ * to search in subdirectories
+ * Threadsafe.
+ * @param paths paths object, may not be NULL
+ * @param source requested directory
+ * @param match glob pattern to search with. may not be NULL
+ * @param find_callback callback to call when finding results, may not be NULL
+ * @param userdata argument to callback, may be NULL
+ */
+NONULL_ARGS(1, 3, 4)
+void paths_find(paths_t* paths, paths_source_t source, const char* match,
+ paths_find_callback_t find_callback, void* userdata);
+
+/**
+ * Synchronous setup to create file in directory.
+ * Returns NULL in case of error, see errno for details.
+ * Depending on source and convention, the actual file may not be created with
+ * the given name until paths_file_close().
+ * The file will eventually always end up in paths_user_dir() for directory.
+ * If any part of the target path is missing it will be created if possible.
+ * If flags contains PATHS_CREATE then the 5th argument mode_t mode must be
+ * given, just as for open().
+ * Threadsafe but what happens if two threads at the same time opens the same
+ * target file is up to the platforms locking mechanism.
+ * The returned paths_file_t is not threadsafe.
+ * @param paths paths object, may not be NULL
+ * @param source target directoru
+ * @param filename relative path of target file, may not be NULL
+ * @param flags flags
+ * @param ... mode if PATHS_CREATE is included in flags
+ * @return a file reference or NULL
+ */
+NONULL paths_file_t* paths_write(paths_t* paths, paths_source_t source,
+ const char* filename, unsigned int flags,
+ ...);
+
+/**
+ * Write data to file.
+ * Works just as libc write().
+ * Not threadsafe,
+ * the paths_file_t must only be accessed by one thread at a time.
+ * @param file target file, may not be NULL
+ * @param data data to write, may be NULL if size is zero
+ * @param size the maximum number of bytes to read from data
+ * @return number of bytes written to target
+ */
+NONULL_ARGS(1)
+ssize_t paths_file_write(paths_file_t* file, const void* data, size_t size);
+
+/**
+ * Close and finish saving file.
+ * If the file was saved successfully, the paths_file_t object is freed.
+ * If the save failed in any way, the object is not freed so you must call
+ * paths_file_abort() to finish up (or call paths_file_close() again and
+ * hope for better luck this time).
+ * Not threadsafe,
+ * the paths_file_t must only be accessed by one thread at a time.
+ * @param file target file, may not be NULL
+ * @return zero on success, non-zero in case of error
+ */
+NONULL int paths_file_close(paths_file_t* file);
+
+/**
+ * Abort saving the file. The target file is removed unless the original version
+ * before paths_write() could be restored.
+ * Not threadsafe,
+ * the paths_file_t must only be accessed by one thread at a time.
+ * @param file target file, may be NULL
+ */
+void paths_file_abort(paths_file_t* file);
+
+/**
+ * Get absolute path to directory where user-specific data files should be
+ * written. Returned directory may not exist.
+ * Threadsafe.
+ * @param paths paths object, may not be NULL
+ * @return absolute path to data directory
+ */
+static inline NONULL const char* paths_user_data(paths_t* paths)
+{
+ return paths_user_dir(paths, PATHS_DATA);
+}
+
+/**
+ * Get absolute path to directory where user-specific config files should be
+ * written. Returned directory may not exist.
+ * Threadsafe.
+ * @param paths paths object, may not be NULL
+ * @return absolute path to config directory
+ */
+static inline NONULL const char* paths_user_config(paths_t* paths)
+{
+ return paths_user_dir(paths, PATHS_CONFIG);
+}
+
+/**
+ * Get absolute path to directory where user-specific cache files should be
+ * written. Returned directory may not exist.
+ * Threadsafe.
+ * @param paths paths object, may not be NULL
+ * @return absolute path to cache directory
+ */
+static inline NONULL const char* paths_user_cache(paths_t* paths)
+{
+ return paths_user_dir(paths, PATHS_CACHE);
+}
+
+/**
+ * Get absolute path to directory where user-specific runtime files should be
+ * written.
+ * If not defined in enviroment or not valid NULL is returned.
+ * Threadsafe.
+ * @param paths paths object, may not be NULL
+ * @return absolute path to runtime directory or NULL
+ */
+static inline NONULL const char* paths_user_runtime(paths_t* paths)
+{
+ return paths_user_dir(paths, PATHS_RUNTIME);
+}
+
+/**
+ * Get preference ordered list of directories to search for data files.
+ * All paths are absolute and NULL terminated. The list itself is NULL
+ * terminated and may never be empty. Path returned by paths_user_data()
+ * is not included.
+ * Threadsafe.
+ * @param paths paths object, may not be NULL
+ * @return NULL terminated list of absolute paths to search
+ */
+static inline NONULL const char** paths_data(paths_t* paths)
+{
+ return paths_search_dirs(paths, PATHS_DATA);
+}
+
+/**
+ * Get preference ordered list of directories to search for config files.
+ * All paths are absolute and NULL terminated. The list itself is NULL
+ * terminated and may never be empty. Path returned by paths_user_config()
+ * is not included.
+ * Threadsafe.
+ * @param paths paths object, may not be NULL
+ * @return NULL terminated list of absolute paths to search
+ */
+static inline NONULL const char** paths_config(paths_t* paths)
+{
+ return paths_search_dirs(paths, PATHS_CONFIG);
+}
+
+#endif /* PATHS_H */