mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-11-04 13:30:08 -05:00
conf: load function (hook) - add OR support
While I was trying to work on XDG_CONFIG_HOME support, I though that it may be nice to support OR for the file specification. But then I found that we can already do this via the refer hook. I commit this change anyway, because the snd_config_hook_load() function is more clean now. The OR is implemented with three | characters like: "~/.asoundrc|||~/.asoundrc2|||/opt/some/other/path" (first file found wins) Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
4882da2c3e
commit
1fa7d670f8
1 changed files with 78 additions and 67 deletions
145
src/conf.c
145
src/conf.c
|
|
@ -3819,6 +3819,63 @@ static int config_file_open(snd_config_t *root, const char *filename)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int config_file_load(snd_config_t *root, const char *fn, int errors)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
struct dirent **namelist;
|
||||||
|
int err, n;
|
||||||
|
|
||||||
|
if (!errors && access(fn, R_OK) < 0)
|
||||||
|
return 1;
|
||||||
|
if (stat(fn, &st) < 0) {
|
||||||
|
SNDERR("cannot stat file/directory %s", fn);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!S_ISDIR(st.st_mode))
|
||||||
|
return config_file_open(root, fn);
|
||||||
|
#ifndef DOC_HIDDEN
|
||||||
|
#if defined(_GNU_SOURCE) && !defined(__NetBSD__) && !defined(__FreeBSD__) && !defined(__sun) && !defined(ANDROID)
|
||||||
|
#define SORTFUNC versionsort
|
||||||
|
#else
|
||||||
|
#define SORTFUNC alphasort
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
n = scandir(fn, &namelist, config_filename_filter, SORTFUNC);
|
||||||
|
if (n > 0) {
|
||||||
|
int j;
|
||||||
|
err = 0;
|
||||||
|
for (j = 0; j < n; ++j) {
|
||||||
|
if (err >= 0) {
|
||||||
|
int sl = strlen(fn) + strlen(namelist[j]->d_name) + 2;
|
||||||
|
char *filename = malloc(sl);
|
||||||
|
snprintf(filename, sl, "%s/%s", fn, namelist[j]->d_name);
|
||||||
|
filename[sl-1] = '\0';
|
||||||
|
|
||||||
|
err = config_file_open(root, filename);
|
||||||
|
free(filename);
|
||||||
|
}
|
||||||
|
free(namelist[j]);
|
||||||
|
}
|
||||||
|
free(namelist);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int config_file_load_user(snd_config_t *root, const char *fn, int errors)
|
||||||
|
{
|
||||||
|
char *fn2;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = snd_user_file(fn, &fn2);
|
||||||
|
if (err < 0)
|
||||||
|
return config_file_load(root, fn, errors);
|
||||||
|
err = config_file_load(root, fn2, errors);
|
||||||
|
free(fn2);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Loads and parses the given configurations files.
|
* \brief Loads and parses the given configurations files.
|
||||||
* \param[in] root Handle to the root configuration node.
|
* \param[in] root Handle to the root configuration node.
|
||||||
|
|
@ -3835,8 +3892,7 @@ int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t
|
||||||
{
|
{
|
||||||
snd_config_t *n;
|
snd_config_t *n;
|
||||||
snd_config_iterator_t i, next;
|
snd_config_iterator_t i, next;
|
||||||
struct finfo *fi = NULL;
|
int err, idx = 0, errors = 1, hit;
|
||||||
int err, idx = 0, fi_count = 0, errors = 1, hit;
|
|
||||||
|
|
||||||
assert(root && dst);
|
assert(root && dst);
|
||||||
if ((err = snd_config_search(config, "errors", &n)) >= 0) {
|
if ((err = snd_config_search(config, "errors", &n)) >= 0) {
|
||||||
|
|
@ -3863,20 +3919,6 @@ int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t
|
||||||
SNDERR("Invalid type for field filenames");
|
SNDERR("Invalid type for field filenames");
|
||||||
goto _err;
|
goto _err;
|
||||||
}
|
}
|
||||||
snd_config_for_each(i, next, n) {
|
|
||||||
snd_config_t *c = snd_config_iterator_entry(i);
|
|
||||||
const char *str;
|
|
||||||
if ((err = snd_config_get_string(c, &str)) < 0) {
|
|
||||||
SNDERR("Field %s is not a string", c->id);
|
|
||||||
goto _err;
|
|
||||||
}
|
|
||||||
fi_count++;
|
|
||||||
}
|
|
||||||
fi = calloc(fi_count, sizeof(*fi));
|
|
||||||
if (fi == NULL) {
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto _err;
|
|
||||||
}
|
|
||||||
do {
|
do {
|
||||||
hit = 0;
|
hit = 0;
|
||||||
snd_config_for_each(i, next, n) {
|
snd_config_for_each(i, next, n) {
|
||||||
|
|
@ -3890,67 +3932,36 @@ int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t
|
||||||
goto _err;
|
goto _err;
|
||||||
}
|
}
|
||||||
if (i == idx) {
|
if (i == idx) {
|
||||||
char *name;
|
char *name, *name2, *remain;
|
||||||
if ((err = snd_config_get_ascii(n, &name)) < 0)
|
if ((err = snd_config_get_ascii(n, &name)) < 0)
|
||||||
goto _err;
|
goto _err;
|
||||||
if ((err = snd_user_file(name, &fi[idx].name)) < 0)
|
name2 = name;
|
||||||
fi[idx].name = name;
|
remain = strstr(name, "|||");
|
||||||
else
|
while (1) {
|
||||||
free(name);
|
if (remain) {
|
||||||
|
*remain = '\0';
|
||||||
|
remain += 3;
|
||||||
|
}
|
||||||
|
printf("name2 = '%s', remain = '%s'\n", name2, remain);
|
||||||
|
err = config_file_load_user(root, name2, errors);
|
||||||
|
if (err < 0)
|
||||||
|
goto _err;
|
||||||
|
if (err == 0) /* first hit wins */
|
||||||
|
break;
|
||||||
|
if (!remain)
|
||||||
|
break;
|
||||||
|
name2 = remain;
|
||||||
|
remain = strstr(remain, "|||");
|
||||||
|
}
|
||||||
|
free(name);
|
||||||
idx++;
|
idx++;
|
||||||
hit = 1;
|
hit = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (hit);
|
} while (hit);
|
||||||
for (idx = 0; idx < fi_count; idx++) {
|
|
||||||
struct stat st;
|
|
||||||
if (!errors && access(fi[idx].name, R_OK) < 0)
|
|
||||||
continue;
|
|
||||||
if (stat(fi[idx].name, &st) < 0) {
|
|
||||||
SNDERR("cannot stat file/directory %s", fi[idx].name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (S_ISDIR(st.st_mode)) {
|
|
||||||
struct dirent **namelist;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
#ifndef DOC_HIDDEN
|
|
||||||
#if defined(_GNU_SOURCE) && !defined(__NetBSD__) && !defined(__FreeBSD__) && !defined(__sun) && !defined(ANDROID)
|
|
||||||
#define SORTFUNC versionsort
|
|
||||||
#else
|
|
||||||
#define SORTFUNC alphasort
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
n = scandir(fi[idx].name, &namelist, config_filename_filter, SORTFUNC);
|
|
||||||
if (n > 0) {
|
|
||||||
int j;
|
|
||||||
err = 0;
|
|
||||||
for (j = 0; j < n; ++j) {
|
|
||||||
if (err >= 0) {
|
|
||||||
int sl = strlen(fi[idx].name) + strlen(namelist[j]->d_name) + 2;
|
|
||||||
char *filename = malloc(sl);
|
|
||||||
snprintf(filename, sl, "%s/%s", fi[idx].name, namelist[j]->d_name);
|
|
||||||
filename[sl-1] = '\0';
|
|
||||||
|
|
||||||
err = config_file_open(root, filename);
|
|
||||||
free(filename);
|
|
||||||
}
|
|
||||||
free(namelist[j]);
|
|
||||||
}
|
|
||||||
free(namelist);
|
|
||||||
if (err < 0)
|
|
||||||
goto _err;
|
|
||||||
}
|
|
||||||
} else if ((err = config_file_open(root, fi[idx].name)) < 0)
|
|
||||||
goto _err;
|
|
||||||
}
|
|
||||||
*dst = NULL;
|
*dst = NULL;
|
||||||
err = 0;
|
err = 0;
|
||||||
_err:
|
_err:
|
||||||
if (fi)
|
|
||||||
for (idx = 0; idx < fi_count; idx++)
|
|
||||||
free(fi[idx].name);
|
|
||||||
free(fi);
|
|
||||||
snd_config_delete(n);
|
snd_config_delete(n);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue