1From af34025ea52bdf8a33c2b6978953851e7cda95f4 Mon Sep 17 00:00:00 2001 2From: Jeffy Chen <jeffy.chen@rock-chips.com> 3Date: Wed, 7 Apr 2021 08:25:57 +0800 4Subject: [PATCH 47/93] config-parser: Support loading multiple configs 5 6Try loading .ini configs under "<config>.d/". 7 8Tested with: 9/etc/xdg/weston/weston.ini.d/99-pixman.ini 10[core] 11use-pixman=true 12 13Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 14--- 15 compositor/main.c | 5 +- 16 shared/config-parser.c | 146 ++++++++++++++++++++++++++++++++++------- 17 2 files changed, 127 insertions(+), 24 deletions(-) 18 19diff --git a/compositor/main.c b/compositor/main.c 20index 6ec89f3..7a1cc20 100644 21--- a/compositor/main.c 22+++ b/compositor/main.c 23@@ -1209,8 +1209,11 @@ load_configuration(struct weston_config **config, int32_t noconfig, 24 if (config_file) 25 file = config_file; 26 27- if (noconfig == 0) 28+ if (noconfig == 0) { 29+ setenv("WESTON_MAIN_PARSE", "1", 1); 30 *config = weston_config_parse(file); 31+ unsetenv("WESTON_MAIN_PARSE"); 32+ } 33 34 if (*config) { 35 full_path = weston_config_get_full_path(*config); 36diff --git a/shared/config-parser.c b/shared/config-parser.c 37index 30779ae..e474963 100644 38--- a/shared/config-parser.c 39+++ b/shared/config-parser.c 40@@ -31,6 +31,7 @@ 41 #include <stdlib.h> 42 #include <assert.h> 43 #include <ctype.h> 44+#include <dirent.h> 45 #include <limits.h> 46 #include <sys/types.h> 47 #include <sys/stat.h> 48@@ -70,6 +71,13 @@ open_config_file(struct weston_config *c, const char *name) 49 const char *p, *next; 50 int fd; 51 52+ if (!c) { 53+ if (name[0] != '/') 54+ return -1; 55+ 56+ return open(name, O_RDONLY | O_CLOEXEC); 57+ } 58+ 59 if (name[0] == '/') { 60 snprintf(c->path, sizeof c->path, "%s", name); 61 return open(name, O_RDONLY | O_CLOEXEC); 62@@ -337,6 +345,15 @@ config_add_section(struct weston_config *config, const char *name) 63 { 64 struct weston_config_section *section; 65 66+ /* squash single sessions */ 67+ if (strcmp(name, "launcher") && strcmp(name, "ivi-launcher") && 68+ strcmp(name, "output") && strcmp(name, "remote-output") && 69+ strcmp(name, "pipewire-output")) { 70+ section = weston_config_get_section(config, name, NULL, NULL); 71+ if (section) 72+ return section; 73+ } 74+ 75 section = zalloc(sizeof *section); 76 if (section == NULL) 77 return NULL; 78@@ -355,10 +372,33 @@ config_add_section(struct weston_config *config, const char *name) 79 80 static struct weston_config_entry * 81 section_add_entry(struct weston_config_section *section, 82- const char *key, const char *value) 83+ const char *key, const char *value, const char *file_name) 84 { 85 struct weston_config_entry *entry; 86 87+ /* hack for removing entry */ 88+ if (key[0] == '-') { 89+ key ++; 90+ value = NULL; 91+ } 92+ 93+ /* drop old entry */ 94+ entry = config_section_get_entry(section, key); 95+ if (entry) { 96+ if (getenv("WESTON_MAIN_PARSE")) { 97+ printf("%s: \"%s/%s\" from \"%s\" to \"%s\"\n", 98+ file_name ?: "unknown", section->name, 99+ entry->key, entry->value ?: "", value ?: ""); 100+ } 101+ wl_list_remove(&entry->link); 102+ free(entry->key); 103+ free(entry->value); 104+ free(entry); 105+ } 106+ 107+ if (!value || value[0] == '\0') 108+ return NULL; 109+ 110 entry = zalloc(sizeof *entry); 111 if (entry == NULL) 112 return NULL; 113@@ -382,14 +422,13 @@ section_add_entry(struct weston_config_section *section, 114 } 115 116 static bool 117-weston_config_parse_internal(struct weston_config *config, FILE *fp) 118+weston_config_parse_internal(struct weston_config *config, FILE *fp, 119+ const char *file_name) 120 { 121 struct weston_config_section *section = NULL; 122 char line[512], *p; 123 int i; 124 125- wl_list_init(&config->section_list); 126- 127 while (fgets(line, sizeof line, fp)) { 128 switch (line[0]) { 129 case '#': 130@@ -422,7 +461,7 @@ weston_config_parse_internal(struct weston_config *config, FILE *fp) 131 p[i - 1] = '\0'; 132 i--; 133 } 134- section_add_entry(section, line, p); 135+ section_add_entry(section, line, p, file_name); 136 continue; 137 } 138 } 139@@ -438,7 +477,8 @@ weston_config_parse_fp(FILE *file) 140 if (config == NULL) 141 return NULL; 142 143- if (!weston_config_parse_internal(config, file)) { 144+ wl_list_init(&config->section_list); 145+ if (!weston_config_parse_internal(config, file, NULL)) { 146 weston_config_destroy(config); 147 return NULL; 148 } 149@@ -446,48 +486,108 @@ weston_config_parse_fp(FILE *file) 150 return config; 151 } 152 153-WL_EXPORT struct weston_config * 154-weston_config_parse(const char *name) 155+static FILE * 156+weston_open_config_file(struct weston_config *config, const char *name) 157 { 158 FILE *fp; 159 struct stat filestat; 160- struct weston_config *config; 161 int fd; 162- bool ret; 163- 164- config = zalloc(sizeof *config); 165- if (config == NULL) 166- return NULL; 167 168 fd = open_config_file(config, name); 169- if (fd == -1) { 170- free(config); 171+ if (fd == -1) 172 return NULL; 173- } 174 175 if (fstat(fd, &filestat) < 0 || 176 !S_ISREG(filestat.st_mode)) { 177 close(fd); 178- free(config); 179 return NULL; 180 } 181 182 fp = fdopen(fd, "r"); 183 if (fp == NULL) { 184 close(fd); 185- free(config); 186 return NULL; 187 } 188 189- ret = weston_config_parse_internal(config, fp); 190+ return fp; 191+} 192 193- fclose(fp); 194+static int 195+accept_config_file(const struct dirent *entry) 196+{ 197+ const char *suffix = ".ini"; 198+ char *end = strstr(entry->d_name, suffix); 199+ return end && end[strlen(suffix)] == '\0'; 200+} 201 202- if (!ret) { 203- weston_config_destroy(config); 204+WL_EXPORT struct weston_config * 205+weston_config_parse(const char *name) 206+{ 207+ FILE *fp; 208+ struct weston_config *config; 209+ struct stat st; 210+ struct dirent **namelist; 211+ char path[sizeof(config->path) + 2]; 212+ bool ret; 213+ int n, i; 214+ 215+ config = zalloc(sizeof *config); 216+ if (config == NULL) 217 return NULL; 218+ 219+ wl_list_init(&config->section_list); 220+ 221+ fp = weston_open_config_file(config, name); 222+ if (fp) { 223+ ret = weston_config_parse_internal(config, fp, name); 224+ 225+ fclose(fp); 226+ 227+ if (!ret) { 228+ fprintf(stderr, "failed to parse %s\n", config->path); 229+ free(config); 230+ return NULL; 231+ } 232+ } 233+ 234+ strcpy(path, config->path); 235+ strcat(path, ".d"); 236+ if (stat(path, &st) < 0 || !S_ISDIR(st.st_mode)) 237+ return config; 238+ 239+ n = scandir(path, &namelist, accept_config_file, alphasort); 240+ if (n < 0) 241+ return config; 242+ 243+ for (i = 0; i < n; i++) { 244+ char *file = namelist[i]->d_name; 245+ char *sep = "/"; 246+ char fpath[strlen(path)+strlen(sep)+strlen(file) + 1]; 247+ strcpy(fpath, path); 248+ strcat(fpath, sep); 249+ strcat(fpath, file); 250+ free(namelist[i]); 251+ 252+ fp = weston_open_config_file(NULL, fpath); 253+ if (!fp) 254+ continue; 255+ 256+ ret = weston_config_parse_internal(config, fp, fpath); 257+ 258+ fclose(fp); 259+ 260+ if (!ret) { 261+ fprintf(stderr, "failed to parse '%s'\n", fpath); 262+ free(config); 263+ config = NULL; 264+ break; 265+ } 266 } 267 268+ for (; i < n; i++) 269+ free(namelist[i]); 270+ 271+ free(namelist); 272 return config; 273 } 274 275-- 2762.20.1 277 278