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; return -ENOENT;
} }
if (pw_check_option("no-config", "true"))
goto no_config;
if ((res = get_envconf_path(path, size, prefix, name)) != 0) { if ((res = get_envconf_path(path, size, prefix, name)) != 0) {
if ((*level)++ == 0) if ((*level)++ == 0)
return res; return res;
@ -198,20 +201,18 @@ static int get_config_dir(char *path, size_t size, const char *prefix, const cha
if (*level == 0) { if (*level == 0) {
(*level)++; (*level)++;
if ((res = get_confdata_path(path, size, prefix, name)) != 0) if ((res = get_homeconf_path(path, size, prefix, name)) != 0)
return res; return res;
} }
if (pw_check_option("no-config", "true"))
return 0;
if (*level == 1) { if (*level == 1) {
(*level)++; (*level)++;
if ((res = get_configdir_path(path, size, prefix, name)) != 0) if ((res = get_configdir_path(path, size, prefix, name)) != 0)
return res; return res;
} }
if (*level == 2) { if (*level == 2) {
no_config:
(*level)++; (*level)++;
if ((res = get_homeconf_path(path, size, prefix, name)) != 0) if ((res = get_confdata_path(path, size, prefix, name)) != 0)
return res; return res;
} }
return 0; return 0;
@ -428,13 +429,33 @@ error:
return -errno; 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, 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; const struct spa_dict_item *it;
char key[1024]; char key[1024];
snprintf(key, sizeof(key), "override.%d.%d.config.path", level, index); snprintf(key, sizeof(key), "override.%d.%d.config.path", level, index);
pw_properties_set(conf, key, path); 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) { spa_dict_for_each(it, &override->dict) {
snprintf(key, sizeof(key), "override.%d.%d.%s", level, index, it->key); snprintf(key, sizeof(key), "override.%d.%d.%s", level, index, it->key);
pw_properties_set(conf, key, it->value); 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; return -errno;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
snprintf(fname, sizeof(fname), "%s/%s", path, entries[i]->d_name); const char *name = entries[i]->d_name;
if (conf_load(fname, override) >= 0)
add_override(conf, override, fname, level, i); snprintf(fname, sizeof(fname), "%s/%s", path, name);
pw_properties_clear(override); 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[i]);
} }
free(entries); 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); conf_name = pw_properties_get(props, PW_KEY_CONFIG_OVERRIDE_NAME);
if (conf_name != NULL) { if (conf_name != NULL) {
struct pw_properties *override; struct pw_properties *override;
const char *path; const char *path, *name;
override = pw_properties_new(NULL, NULL); override = pw_properties_new(NULL, NULL);
if (override == NULL) { if (override == NULL) {
@ -957,7 +984,8 @@ int pw_conf_load_conf_for_context(struct pw_properties *props, struct pw_propert
return res; return res;
} }
path = pw_properties_get(override, "config.path"); 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); pw_properties_free(override);
} }