ucm: top-level path - set directory from symlink

It is useful to read the top-level symlink and set the configuration
directory according this symlink for the relative paths.

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Jaroslav Kysela 2021-12-13 14:40:56 +01:00
parent 1454b5f118
commit d6adde0e32

View file

@ -31,6 +31,7 @@
*/ */
#include "ucm_local.h" #include "ucm_local.h"
#include <sys/stat.h>
#include <stdbool.h> #include <stdbool.h>
#include <dirent.h> #include <dirent.h>
#include <limits.h> #include <limits.h>
@ -2186,6 +2187,7 @@ static int parse_toplevel_path(snd_use_case_mgr_t *uc_mgr,
snd_config_t *n, *n2; snd_config_t *n, *n2;
const char *id; const char *id;
char *dir = NULL, *file = NULL, fn[PATH_MAX]; char *dir = NULL, *file = NULL, fn[PATH_MAX];
struct stat st;
long version; long version;
int err; int err;
@ -2260,23 +2262,51 @@ static int parse_toplevel_path(snd_use_case_mgr_t *uc_mgr,
} }
ucm_filename(fn, sizeof(fn), version, dir, file); ucm_filename(fn, sizeof(fn), version, dir, file);
if (access(fn, R_OK) == 0) { if (access(fn, R_OK) == 0 && lstat(fn, &st) == 0) {
if (replace_string(&uc_mgr->conf_dir_name, dir) == NULL) { if (st.st_mode & S_IFLNK) {
err = -ENOMEM; ssize_t r;
goto __error; char *link, *dir2, *p;
}
if (replace_string(&uc_mgr->conf_file_name, file) == NULL) { link = malloc(PATH_MAX);
err = -ENOMEM; if (link == NULL)
goto __error; goto __enomem;
r = readlink(fn, link, PATH_MAX - 1);
if (r <= 0) {
free(link);
goto __next;
}
link[r] = '\0';
p = strrchr(link, '/');
if (p) {
*p = '\0';
dir2 = malloc(PATH_MAX);
if (dir2 == NULL) {
free(link);
goto __enomem;
}
strncpy(dir2, dir, PATH_MAX - 1);
strncat(dir2, "/", PATH_MAX - 1);
strncat(dir2, link, PATH_MAX - 1);
fn[PATH_MAX - 1] = '\0';
free(dir);
dir = dir2;
}
free(link);
} }
if (replace_string(&uc_mgr->conf_dir_name, dir) == NULL)
goto __enomem;
if (replace_string(&uc_mgr->conf_file_name, file) == NULL)
goto __enomem;
strncpy(filename, fn, PATH_MAX); strncpy(filename, fn, PATH_MAX);
filename[PATH_MAX - 1] = '\0';
uc_mgr->conf_format = version; uc_mgr->conf_format = version;
goto __ok; goto __ok;
} }
__next: __next:
free(file); free(file);
free(dir); if (dir != fn)
free(dir);
dir = NULL; dir = NULL;
file = NULL; file = NULL;
} }
@ -2284,11 +2314,16 @@ __next:
err = -ENOENT; err = -ENOENT;
goto __error; goto __error;
__enomem:
err = -ENOMEM;
goto __error;
__ok: __ok:
err = 0; err = 0;
__error: __error:
free(file); free(file);
free(dir); if (dir != fn)
free(dir);
return err; return err;
} }