mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-11-04 13:30:08 -05:00
conf: Search included files under user specified configuration directories
Users can include file by giving a relative path or just a file name via alsaconf syntax <xxx>. ALSA conf will search the file in top configuration directory and additional configuration directories defined by users via alsaconf syntax <searchdir:xxx>. ALSA conf will search and open an included file in the following order of priority: 1. directly open the file by its name; 2. search for the file name in top config direcotry "/usr/share/alsa/"; 3. search for the file name in additional configuration directories specified by users, via alsaconf syntax <searchdir:relative-path/to/user/share/alsa>; These directories will be searched in the same order as their definition. The configuration directories defined by a file will only be used to search the files included by this file. Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
adb9866b70
commit
c169438682
1 changed files with 158 additions and 1 deletions
159
src/conf.c
159
src/conf.c
|
|
@ -456,6 +456,18 @@ struct filedesc {
|
||||||
snd_input_t *in;
|
snd_input_t *in;
|
||||||
unsigned int line, column;
|
unsigned int line, column;
|
||||||
struct filedesc *next;
|
struct filedesc *next;
|
||||||
|
|
||||||
|
/* list of the include paths (configuration directories),
|
||||||
|
* defined by <searchdir:relative-path/to/top-alsa-conf-dir>,
|
||||||
|
* for searching its included files.
|
||||||
|
*/
|
||||||
|
struct list_head include_paths;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* path to search included files */
|
||||||
|
struct include_path {
|
||||||
|
char *dir;
|
||||||
|
struct list_head list;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LOCAL_ERROR (-0x68000000)
|
#define LOCAL_ERROR (-0x68000000)
|
||||||
|
|
@ -501,6 +513,108 @@ static inline void snd_config_unlock(void) { }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a diretory to the paths to search included files.
|
||||||
|
* param fd - File object that owns these paths to search files included by it.
|
||||||
|
* param dir - Path of the directory to add. Allocated externally and need to
|
||||||
|
* be freed manually later.
|
||||||
|
* return - Zero if successful, otherwise a negative error code.
|
||||||
|
*
|
||||||
|
* The direcotry should be a subdiretory of top configuration directory
|
||||||
|
* "/usr/share/alsa/".
|
||||||
|
*/
|
||||||
|
static int add_include_path(struct filedesc *fd, char *dir)
|
||||||
|
{
|
||||||
|
struct include_path *path;
|
||||||
|
|
||||||
|
path = calloc(1, sizeof(*path));
|
||||||
|
if (!path)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
path->dir = dir;
|
||||||
|
list_add_tail(&path->list, &fd->include_paths);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free all include paths of a file descriptor.
|
||||||
|
* param fd - File object that owns these paths to search files included by it.
|
||||||
|
*/
|
||||||
|
static void free_include_paths(struct filedesc *fd)
|
||||||
|
{
|
||||||
|
struct list_head *pos, *npos, *base;
|
||||||
|
struct include_path *path;
|
||||||
|
|
||||||
|
base = &fd->include_paths;
|
||||||
|
list_for_each_safe(pos, npos, base) {
|
||||||
|
path = list_entry(pos, struct include_path, list);
|
||||||
|
list_del(&path->list);
|
||||||
|
if (path->dir)
|
||||||
|
free(path->dir);
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Search and open a file, and creates a new input object reading from the file.
|
||||||
|
* param inputp - The functions puts the pointer to the new input object
|
||||||
|
* at the address specified by \p inputp.
|
||||||
|
* param file - Name of the configuration file.
|
||||||
|
* param include_paths - Optional, addtional directories to search the file.
|
||||||
|
* return - Zero if successful, otherwise a negative error code.
|
||||||
|
*
|
||||||
|
* This function will search and open the file in the following order
|
||||||
|
* of priority:
|
||||||
|
* 1. directly open the file by its name;
|
||||||
|
* 2. search for the file name in top configuration directory
|
||||||
|
* "/usr/share/alsa/";
|
||||||
|
* 3. search for the file name in in additional configuration directories
|
||||||
|
* specified by users, via alsaconf syntax
|
||||||
|
* <searchdir:relative-path/to/user/share/alsa>;
|
||||||
|
* These directories should be subdirectories of /usr/share/alsa.
|
||||||
|
*/
|
||||||
|
static int input_stdio_open(snd_input_t **inputp, const char *file,
|
||||||
|
struct list_head *include_paths)
|
||||||
|
{
|
||||||
|
struct list_head *pos, *base;
|
||||||
|
struct include_path *path;
|
||||||
|
char full_path[PATH_MAX + 1];
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
err = snd_input_stdio_open(inputp, file, "r");
|
||||||
|
if (err == 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (file[0] == '/') /* not search file with absolute path */
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/* search file in top configuration directory /usr/share/alsa */
|
||||||
|
snprintf(full_path, PATH_MAX, "%s/%s", ALSA_CONFIG_DIR, file);
|
||||||
|
err = snd_input_stdio_open(inputp, full_path, "r");
|
||||||
|
if (err == 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* search file in user specified include paths. These directories
|
||||||
|
* are subdirectories of /usr/share/alsa.
|
||||||
|
*/
|
||||||
|
if (include_paths) {
|
||||||
|
base = include_paths;
|
||||||
|
list_for_each(pos, base) {
|
||||||
|
path = list_entry(pos, struct include_path, list);
|
||||||
|
if (!path->dir)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
snprintf(full_path, PATH_MAX, "%s/%s", path->dir, file);
|
||||||
|
err = snd_input_stdio_open(inputp, full_path, "r");
|
||||||
|
if (err == 0)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int safe_strtoll(const char *str, long long *val)
|
static int safe_strtoll(const char *str, long long *val)
|
||||||
{
|
{
|
||||||
long long v;
|
long long v;
|
||||||
|
|
@ -629,10 +743,44 @@ static int get_char_skip_comments(input_t *input)
|
||||||
char *str;
|
char *str;
|
||||||
snd_input_t *in;
|
snd_input_t *in;
|
||||||
struct filedesc *fd;
|
struct filedesc *fd;
|
||||||
|
DIR *dirp;
|
||||||
int err = get_delimstring(&str, '>', input);
|
int err = get_delimstring(&str, '>', input);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
if (!strncmp(str, "searchdir:", 10)) {
|
||||||
|
/* directory to search included files */
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
|
tmp = malloc(strlen(ALSA_CONFIG_DIR) + 1
|
||||||
|
+ strlen(str + 10) + 1);
|
||||||
|
if (tmp == NULL) {
|
||||||
|
free(str);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
sprintf(tmp, ALSA_CONFIG_DIR "/%s", str + 10);
|
||||||
|
free(str);
|
||||||
|
str = tmp;
|
||||||
|
|
||||||
|
dirp = opendir(str);
|
||||||
|
if (!dirp) {
|
||||||
|
SNDERR("Invalid search dir %s", str);
|
||||||
|
free(str);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
closedir(dirp);
|
||||||
|
|
||||||
|
err = add_include_path(input->current, str);
|
||||||
|
if (err < 0) {
|
||||||
|
SNDERR("Cannot add search dir %s", str);
|
||||||
|
free(str);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!strncmp(str, "confdir:", 8)) {
|
if (!strncmp(str, "confdir:", 8)) {
|
||||||
|
/* file in the specified directory */
|
||||||
char *tmp = malloc(strlen(ALSA_CONFIG_DIR) + 1 + strlen(str + 8) + 1);
|
char *tmp = malloc(strlen(ALSA_CONFIG_DIR) + 1 + strlen(str + 8) + 1);
|
||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
free(str);
|
free(str);
|
||||||
|
|
@ -641,8 +789,12 @@ static int get_char_skip_comments(input_t *input)
|
||||||
sprintf(tmp, ALSA_CONFIG_DIR "/%s", str + 8);
|
sprintf(tmp, ALSA_CONFIG_DIR "/%s", str + 8);
|
||||||
free(str);
|
free(str);
|
||||||
str = tmp;
|
str = tmp;
|
||||||
}
|
|
||||||
err = snd_input_stdio_open(&in, str, "r");
|
err = snd_input_stdio_open(&in, str, "r");
|
||||||
|
} else { /* absolute or relative file path */
|
||||||
|
err = input_stdio_open(&in, str,
|
||||||
|
&input->current->include_paths);
|
||||||
|
}
|
||||||
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
SNDERR("Cannot access file %s", str);
|
SNDERR("Cannot access file %s", str);
|
||||||
free(str);
|
free(str);
|
||||||
|
|
@ -658,6 +810,7 @@ static int get_char_skip_comments(input_t *input)
|
||||||
fd->next = input->current;
|
fd->next = input->current;
|
||||||
fd->line = 1;
|
fd->line = 1;
|
||||||
fd->column = 0;
|
fd->column = 0;
|
||||||
|
INIT_LIST_HEAD(&fd->include_paths);
|
||||||
input->current = fd;
|
input->current = fd;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -1668,6 +1821,7 @@ static int snd_config_load1(snd_config_t *config, snd_input_t *in, int override)
|
||||||
fd->line = 1;
|
fd->line = 1;
|
||||||
fd->column = 0;
|
fd->column = 0;
|
||||||
fd->next = NULL;
|
fd->next = NULL;
|
||||||
|
INIT_LIST_HEAD(&fd->include_paths);
|
||||||
input.current = fd;
|
input.current = fd;
|
||||||
input.unget = 0;
|
input.unget = 0;
|
||||||
err = parse_defs(config, &input, 0, override);
|
err = parse_defs(config, &input, 0, override);
|
||||||
|
|
@ -1708,9 +1862,12 @@ static int snd_config_load1(snd_config_t *config, snd_input_t *in, int override)
|
||||||
fd_next = fd->next;
|
fd_next = fd->next;
|
||||||
snd_input_close(fd->in);
|
snd_input_close(fd->in);
|
||||||
free(fd->name);
|
free(fd->name);
|
||||||
|
free_include_paths(fd);
|
||||||
free(fd);
|
free(fd);
|
||||||
fd = fd_next;
|
fd = fd_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free_include_paths(fd);
|
||||||
free(fd);
|
free(fd);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue