From 55c264d2a5a776545ecd69ad7b843e6e0d795ef7 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 6 Aug 2021 18:38:42 +1000 Subject: [PATCH] conf: store state in XDG_STATE_HOME Defaulting to $HOME/.local/state, this is the directory that state information is to be kept. As with the configuration loading, where a caller requests an absolute path, that path will be honored, we only fall back to XDG_STATE_HOME for relative paths. This adds a new PIPEWIRE_STATE_DIR environment variable to override this directory. --- src/pipewire/conf.c | 67 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/src/pipewire/conf.c b/src/pipewire/conf.c index c4fed6152..64951fac2 100644 --- a/src/pipewire/conf.c +++ b/src/pipewire/conf.c @@ -64,7 +64,7 @@ static int make_path(char *path, int size, const char *paths[]) return 0; } -static int get_read_path(char *path, size_t size, const char *prefix, const char *name) +static int get_config_path(char *path, size_t size, const char *prefix, const char *name) { const char *dir; char buffer[4096]; @@ -139,6 +139,63 @@ no_config: return 0; } +static int get_state_path(char *path, size_t size, const char *prefix, const char *name) +{ + const char *dir; + char buffer[4096]; + + if (name[0] == '/') { + const char *paths[] = { name, NULL }; + if (make_path(path, size, paths) == 0 && + access(path, R_OK) == 0) + return 1; + return -ENOENT; + } + + if (prefix && prefix[0] == '/') { + const char *paths[] = { prefix, name, NULL }; + if (make_path(path, size, paths) == 0 && + access(path, R_OK) == 0) + return 1; + return -ENOENT; + } + + if (prefix == NULL) { + prefix = name; + name = NULL; + } + + dir = getenv("PIPEWIRE_STATE_DIR"); + if (dir != NULL) { + const char *paths[] = { dir, prefix, name, NULL }; + if (make_path(path, size, paths) == 0 && + access(path, R_OK) == 0) + return 1; + } + + dir = getenv("XDG_STATE_HOME"); + if (dir != NULL) { + const char *paths[] = { dir, "pipewire", prefix, name, NULL }; + if (make_path(path, size, paths) == 0 && + access(path, R_OK) == 0) + return 1; + } + dir = getenv("HOME"); + if (dir == NULL) { + struct passwd pwd, *result = NULL; + if (getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer), &result) == 0) + dir = result ? result->pw_dir : NULL; + } + if (dir != NULL) { + const char *paths[] = { dir, ".config", "pipewire", prefix, name, NULL }; + if (make_path(path, size, paths) == 0 && + access(path, R_OK) == 0) + return 1; + } + + return 0; +} + static int ensure_path(char *path, int size, const char *paths[]) { int i, len, mode; @@ -185,7 +242,7 @@ static int open_write_dir(char *path, int size, const char *prefix) if (ensure_path(path, size, paths) == 0) goto found; } - dir = getenv("XDG_CONFIG_HOME"); + dir = getenv("XDG_STATE_HOME"); if (dir != NULL) { const char *paths[] = { dir, "pipewire", prefix, NULL }; if (ensure_path(path, size, paths) == 0) @@ -198,7 +255,7 @@ static int open_write_dir(char *path, int size, const char *prefix) dir = result ? result->pw_dir : NULL; } if (dir != NULL) { - const char *paths[] = { dir, ".config", "pipewire", prefix, NULL }; + const char *paths[] = { dir, ".local", "state", "pipewire", prefix, NULL }; if (ensure_path(path, size, paths) == 0) goto found; } @@ -286,7 +343,7 @@ int pw_conf_load_conf(const char *prefix, const char *name, struct pw_properties return -EINVAL; } - if (get_read_path(path, sizeof(path), prefix, name) == 0) { + if (get_config_path(path, sizeof(path), prefix, name) == 0) { pw_log_debug(NAME" %p: can't load config '%s': %m", conf, path); return -ENOENT; } @@ -304,7 +361,7 @@ int pw_conf_load_state(const char *prefix, const char *name, struct pw_propertie return -EINVAL; } - if (get_read_path(path, sizeof(path), prefix, name) == 0) { + if (get_state_path(path, sizeof(path), prefix, name) == 0) { pw_log_debug(NAME" %p: can't load config '%s': %m", conf, path); return -ENOENT; }