conf: allow masking od conf.d/ files

Read the .conf.d/ override files in the same order as the .conf files.
If we already have a .conf override file with the same name, it was one
with a higher priority and we ignore it.

This makes it possible to place a 10-rates.conf file in ~/.config that
will override a 10-rates.conf file in /etc and /usr/share.

Fixes #2629
This commit is contained in:
Wim Taymans 2022-08-08 16:05:46 +02:00
parent f8d26b96b4
commit e784e82b9a

View file

@ -190,6 +190,9 @@ static int get_config_dir(char *path, size_t size, const char *prefix, const cha
return -ENOENT;
}
if (pw_check_option("no-config", "true"))
goto no_config;
if ((res = get_envconf_path(path, size, prefix, name)) != 0) {
if ((*level)++ == 0)
return res;
@ -198,20 +201,18 @@ static int get_config_dir(char *path, size_t size, const char *prefix, const cha
if (*level == 0) {
(*level)++;
if ((res = get_confdata_path(path, size, prefix, name)) != 0)
if ((res = get_homeconf_path(path, size, prefix, name)) != 0)
return res;
}
if (pw_check_option("no-config", "true"))
return 0;
if (*level == 1) {
(*level)++;
if ((res = get_configdir_path(path, size, prefix, name)) != 0)
return res;
}
if (*level == 2) {
no_config:
(*level)++;
if ((res = get_homeconf_path(path, size, prefix, name)) != 0)
if ((res = get_confdata_path(path, size, prefix, name)) != 0)
return res;
}
return 0;
@ -428,13 +429,33 @@ error:
return -errno;
}
static bool check_override(struct pw_properties *conf, const char *name, int level)
{
const struct spa_dict_item *it;
spa_dict_for_each(it, &conf->dict) {
int lev, idx;
if (!spa_streq(name, it->value))
continue;
if (sscanf(it->key, "override.%d.%d.config.name", &lev, &idx) != 2)
continue;
if (lev < level)
return false;
}
return true;
}
static void add_override(struct pw_properties *conf, struct pw_properties *override,
const char *path, int level, int index)
const char *path, const char *name, int level, int index)
{
const struct spa_dict_item *it;
char key[1024];
snprintf(key, sizeof(key), "override.%d.%d.config.path", level, index);
pw_properties_set(conf, key, path);
snprintf(key, sizeof(key), "override.%d.%d.config.name", level, index);
pw_properties_set(conf, key, name);
spa_dict_for_each(it, &override->dict) {
snprintf(key, sizeof(key), "override.%d.%d.%s", level, index, it->key);
pw_properties_set(conf, key, it->value);
@ -493,10 +514,16 @@ int pw_conf_load_conf(const char *prefix, const char *name, struct pw_properties
return -errno;
for (i = 0; i < n; i++) {
snprintf(fname, sizeof(fname), "%s/%s", path, entries[i]->d_name);
if (conf_load(fname, override) >= 0)
add_override(conf, override, fname, level, i);
pw_properties_clear(override);
const char *name = entries[i]->d_name;
snprintf(fname, sizeof(fname), "%s/%s", path, name);
if (check_override(conf, name, level)) {
if (conf_load(fname, override) >= 0)
add_override(conf, override, fname, name, level, i);
pw_properties_clear(override);
} else {
pw_log_info("skip override %s with lower priority", fname);
}
free(entries[i]);
}
free(entries);
@ -941,7 +968,7 @@ int pw_conf_load_conf_for_context(struct pw_properties *props, struct pw_propert
conf_name = pw_properties_get(props, PW_KEY_CONFIG_OVERRIDE_NAME);
if (conf_name != NULL) {
struct pw_properties *override;
const char *path;
const char *path, *name;
override = pw_properties_new(NULL, NULL);
if (override == NULL) {
@ -957,7 +984,8 @@ int pw_conf_load_conf_for_context(struct pw_properties *props, struct pw_propert
return res;
}
path = pw_properties_get(override, "config.path");
add_override(conf, override, path, 0, 1);
name = pw_properties_get(override, "config.name");
add_override(conf, override, path, name, 0, 1);
pw_properties_free(override);
}