mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	conf-parser: add support for .d directories
This allows a configuration scheme where after loading configuration from "somefile", the parser loads configuration from files in directory "somefile.d". This feature needs to be enabled on a per-file basis, though, and this patch doesn't yet enable the feature for any files.
This commit is contained in:
		
							parent
							
								
									d97460045c
								
							
						
					
					
						commit
						1d7ce90139
					
				
					 6 changed files with 52 additions and 8 deletions
				
			
		| 
						 | 
					@ -617,7 +617,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
 | 
				
			||||||
    ci.default_channel_map_set = ci.default_sample_spec_set = false;
 | 
					    ci.default_channel_map_set = ci.default_sample_spec_set = false;
 | 
				
			||||||
    ci.conf = c;
 | 
					    ci.conf = c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    r = f ? pa_config_parse(c->config_file, f, table, NULL, NULL) : 0;
 | 
					    r = f ? pa_config_parse(c->config_file, f, table, NULL, false, NULL) : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (r >= 0) {
 | 
					    if (r >= 0) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2594,7 +2594,7 @@ pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn = pa_maybe_prefix_path(fname, paths_dir);
 | 
					    fn = pa_maybe_prefix_path(fname, paths_dir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    r = pa_config_parse(fn, NULL, items, p->proplist, p);
 | 
					    r = pa_config_parse(fn, NULL, items, p->proplist, false, p);
 | 
				
			||||||
    pa_xfree(fn);
 | 
					    pa_xfree(fn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (r < 0)
 | 
					    if (r < 0)
 | 
				
			||||||
| 
						 | 
					@ -4411,7 +4411,7 @@ pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel
 | 
				
			||||||
                              pa_run_from_build_tree() ? PA_SRCDIR "/modules/alsa/mixer/profile-sets/" :
 | 
					                              pa_run_from_build_tree() ? PA_SRCDIR "/modules/alsa/mixer/profile-sets/" :
 | 
				
			||||||
                              PA_ALSA_PROFILE_SETS_DIR);
 | 
					                              PA_ALSA_PROFILE_SETS_DIR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    r = pa_config_parse(fn, NULL, items, NULL, ps);
 | 
					    r = pa_config_parse(fn, NULL, items, NULL, false, ps);
 | 
				
			||||||
    pa_xfree(fn);
 | 
					    pa_xfree(fn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (r < 0)
 | 
					    if (r < 0)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -204,7 +204,7 @@ static void update_rule(struct rule *r) {
 | 
				
			||||||
    table[0].data = &r->application_name;
 | 
					    table[0].data = &r->application_name;
 | 
				
			||||||
    table[1].data = &r->icon_name;
 | 
					    table[1].data = &r->icon_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (pa_config_parse(fn, NULL, table, NULL, r) < 0)
 | 
					    if (pa_config_parse(fn, NULL, table, NULL, false, r) < 0)
 | 
				
			||||||
        pa_log_warn("Failed to parse .desktop file %s.", fn);
 | 
					        pa_log_warn("Failed to parse .desktop file %s.", fn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_xfree(fn);
 | 
					    pa_xfree(fn);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,7 +149,7 @@ void pa_client_conf_load(pa_client_conf *c, bool load_from_x11, bool load_from_e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    f = pa_open_config_file(DEFAULT_CLIENT_CONFIG_FILE, DEFAULT_CLIENT_CONFIG_FILE_USER, ENV_CLIENT_CONFIG_FILE, &fn);
 | 
					    f = pa_open_config_file(DEFAULT_CLIENT_CONFIG_FILE, DEFAULT_CLIENT_CONFIG_FILE_USER, ENV_CLIENT_CONFIG_FILE, &fn);
 | 
				
			||||||
    if (f) {
 | 
					    if (f) {
 | 
				
			||||||
        pa_config_parse(fn, f, table, NULL, NULL);
 | 
					        pa_config_parse(fn, f, table, NULL, false, NULL);
 | 
				
			||||||
        pa_xfree(fn);
 | 
					        pa_xfree(fn);
 | 
				
			||||||
        fclose(f);
 | 
					        fclose(f);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,7 @@
 | 
				
			||||||
#include <config.h>
 | 
					#include <config.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <dirent.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
| 
						 | 
					@ -103,7 +104,7 @@ static int parse_line(pa_config_parser_state *state) {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        r = pa_config_parse(fn, NULL, state->item_table, state->proplist, state->userdata);
 | 
					        r = pa_config_parse(fn, NULL, state->item_table, state->proplist, false, state->userdata);
 | 
				
			||||||
        pa_xfree(path);
 | 
					        pa_xfree(path);
 | 
				
			||||||
        return r;
 | 
					        return r;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -152,8 +153,13 @@ static int parse_line(pa_config_parser_state *state) {
 | 
				
			||||||
        return normal_assignment(state);
 | 
					        return normal_assignment(state);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int conf_filter(const struct dirent *entry) {
 | 
				
			||||||
 | 
					    return pa_endswith(entry->d_name, ".conf");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Go through the file and parse each line */
 | 
					/* Go through the file and parse each line */
 | 
				
			||||||
int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, pa_proplist *proplist, void *userdata) {
 | 
					int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, pa_proplist *proplist, bool use_dot_d,
 | 
				
			||||||
 | 
					                    void *userdata) {
 | 
				
			||||||
    int r = -1;
 | 
					    int r = -1;
 | 
				
			||||||
    bool do_close = !f;
 | 
					    bool do_close = !f;
 | 
				
			||||||
    pa_config_parser_state state;
 | 
					    pa_config_parser_state state;
 | 
				
			||||||
| 
						 | 
					@ -211,6 +217,38 @@ finish:
 | 
				
			||||||
    if (do_close && f)
 | 
					    if (do_close && f)
 | 
				
			||||||
        fclose(f);
 | 
					        fclose(f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (use_dot_d) {
 | 
				
			||||||
 | 
					        char *dir_name;
 | 
				
			||||||
 | 
					        int n;
 | 
				
			||||||
 | 
					        struct dirent **entries = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dir_name = pa_sprintf_malloc("%s.d", filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        n = scandir(dir_name, &entries, conf_filter, alphasort);
 | 
				
			||||||
 | 
					        if (n >= 0) {
 | 
				
			||||||
 | 
					            int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (i = 0; i < n; i++) {
 | 
				
			||||||
 | 
					                char *filename2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                filename2 = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", dir_name, entries[i]->d_name);
 | 
				
			||||||
 | 
					                pa_config_parse(filename2, NULL, t, proplist, false, userdata);
 | 
				
			||||||
 | 
					                pa_xfree(filename2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                free(entries[i]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            free(entries);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            if (errno == ENOENT)
 | 
				
			||||||
 | 
					                pa_log_debug("%s does not exist, ignoring.", dir_name);
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                pa_log_warn("scandir(\"%s\") failed: %s", dir_name, pa_cstrerror(errno));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        pa_xfree(dir_name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return r;
 | 
					    return r;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,6 +59,11 @@ struct pa_config_parser_state {
 | 
				
			||||||
 * pa_config_items in *t that is terminated by an item where lvalue is
 | 
					 * pa_config_items in *t that is terminated by an item where lvalue is
 | 
				
			||||||
 * NULL.
 | 
					 * NULL.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * If use_dot_d is true, then after parsing the file named by the filename
 | 
				
			||||||
 | 
					 * argument, the function will parse all files ending with ".conf" in
 | 
				
			||||||
 | 
					 * alphabetical order from a directory whose name is filename + ".d", if such
 | 
				
			||||||
 | 
					 * directory exists.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 * Some configuration files may contain a Properties section, which
 | 
					 * Some configuration files may contain a Properties section, which
 | 
				
			||||||
 * is a bit special. Normally all accepted lvalues must be predefined
 | 
					 * is a bit special. Normally all accepted lvalues must be predefined
 | 
				
			||||||
 * in the pa_config_item table, but in the Properties section the
 | 
					 * in the pa_config_item table, but in the Properties section the
 | 
				
			||||||
| 
						 | 
					@ -68,7 +73,8 @@ struct pa_config_parser_state {
 | 
				
			||||||
 * properties, and those properties will be merged into the given
 | 
					 * properties, and those properties will be merged into the given
 | 
				
			||||||
 * proplist. If proplist is NULL, then sections named "Properties"
 | 
					 * proplist. If proplist is NULL, then sections named "Properties"
 | 
				
			||||||
 * are not allowed at all in the configuration file. */
 | 
					 * are not allowed at all in the configuration file. */
 | 
				
			||||||
int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, pa_proplist *proplist, void *userdata);
 | 
					int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, pa_proplist *proplist, bool use_dot_d,
 | 
				
			||||||
 | 
					                    void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Generic parsers for integers, size_t, booleans and strings */
 | 
					/* Generic parsers for integers, size_t, booleans and strings */
 | 
				
			||||||
int pa_config_parse_int(pa_config_parser_state *state);
 | 
					int pa_config_parse_int(pa_config_parser_state *state);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue