1From e9709cefd9dcdc8c96df5a135c8f039a037a1a72 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 13And strip leading spaces. 14 15Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 16--- 17 shared/config-parser.c | 129 +++++++++++++++++++++++++++++++++++------ 18 1 file changed, 110 insertions(+), 19 deletions(-) 19 20diff --git a/shared/config-parser.c b/shared/config-parser.c 21index 30779ae..8ad9ceb 100644 22--- a/shared/config-parser.c 23+++ b/shared/config-parser.c 24@@ -31,6 +31,7 @@ 25 #include <stdlib.h> 26 #include <assert.h> 27 #include <ctype.h> 28+#include <dirent.h> 29 #include <limits.h> 30 #include <sys/types.h> 31 #include <sys/stat.h> 32@@ -70,6 +71,13 @@ open_config_file(struct weston_config *c, const char *name) 33 const char *p, *next; 34 int fd; 35 36+ if (!c) { 37+ if (name[0] != '/') 38+ return -1; 39+ 40+ return open(name, O_RDONLY | O_CLOEXEC); 41+ } 42+ 43 if (name[0] == '/') { 44 snprintf(c->path, sizeof c->path, "%s", name); 45 return open(name, O_RDONLY | O_CLOEXEC); 46@@ -337,6 +345,15 @@ config_add_section(struct weston_config *config, const char *name) 47 { 48 struct weston_config_section *section; 49 50+ /* squash single sessions */ 51+ if (strcmp(name, "launcher") && strcmp(name, "ivi-launcher") && 52+ strcmp(name, "output") && strcmp(name, "remote-output") && 53+ strcmp(name, "pipewire-output")) { 54+ section = weston_config_get_section(config, name, NULL, NULL); 55+ if (section) 56+ return section; 57+ } 58+ 59 section = zalloc(sizeof *section); 60 if (section == NULL) 61 return NULL; 62@@ -359,6 +376,24 @@ section_add_entry(struct weston_config_section *section, 63 { 64 struct weston_config_entry *entry; 65 66+ /* hack for removing entry */ 67+ if (key[0] == '-') { 68+ key ++; 69+ value = NULL; 70+ } 71+ 72+ /* drop old entry */ 73+ entry = config_section_get_entry(section, key); 74+ if (entry) { 75+ wl_list_remove(&entry->link); 76+ free(entry->key); 77+ free(entry->value); 78+ free(entry); 79+ } 80+ 81+ if (!value || value[0] == '\0') 82+ return NULL; 83+ 84 entry = zalloc(sizeof *entry); 85 if (entry == NULL) 86 return NULL; 87@@ -388,8 +423,6 @@ weston_config_parse_internal(struct weston_config *config, FILE *fp) 88 char line[512], *p; 89 int i; 90 91- wl_list_init(&config->section_list); 92- 93 while (fgets(line, sizeof line, fp)) { 94 switch (line[0]) { 95 case '#': 96@@ -438,6 +471,7 @@ weston_config_parse_fp(FILE *file) 97 if (config == NULL) 98 return NULL; 99 100+ wl_list_init(&config->section_list); 101 if (!weston_config_parse_internal(config, file)) { 102 weston_config_destroy(config); 103 return NULL; 104@@ -446,48 +480,105 @@ weston_config_parse_fp(FILE *file) 105 return config; 106 } 107 108-WL_EXPORT struct weston_config * 109-weston_config_parse(const char *name) 110+static FILE * 111+weston_open_config_file(struct weston_config *config, const char *name) 112 { 113 FILE *fp; 114 struct stat filestat; 115- struct weston_config *config; 116 int fd; 117- bool ret; 118- 119- config = zalloc(sizeof *config); 120- if (config == NULL) 121- return NULL; 122 123 fd = open_config_file(config, name); 124- if (fd == -1) { 125- free(config); 126+ if (fd == -1) 127 return NULL; 128- } 129 130 if (fstat(fd, &filestat) < 0 || 131 !S_ISREG(filestat.st_mode)) { 132 close(fd); 133- free(config); 134 return NULL; 135 } 136 137 fp = fdopen(fd, "r"); 138 if (fp == NULL) { 139 close(fd); 140- free(config); 141 return NULL; 142 } 143 144- ret = weston_config_parse_internal(config, fp); 145+ return fp; 146+} 147 148- fclose(fp); 149+static int 150+accept_config_file(const struct dirent *entry) 151+{ 152+ const char *suffix = ".ini"; 153+ char *end = strstr(entry->d_name, suffix); 154+ return end && end[strlen(suffix)] == '\0'; 155+} 156 157- if (!ret) { 158- weston_config_destroy(config); 159+WL_EXPORT struct weston_config * 160+weston_config_parse(const char *name) 161+{ 162+ FILE *fp; 163+ struct weston_config *config; 164+ struct stat st; 165+ struct dirent **namelist; 166+ char path[sizeof(config->path) + 2]; 167+ bool ret; 168+ int n; 169+ 170+ config = zalloc(sizeof *config); 171+ if (config == NULL) 172 return NULL; 173+ 174+ wl_list_init(&config->section_list); 175+ 176+ fp = weston_open_config_file(config, name); 177+ if (fp) { 178+ ret = weston_config_parse_internal(config, fp); 179+ 180+ fclose(fp); 181+ 182+ if (!ret) { 183+ fprintf(stderr, "failed to parse %s\n", config->path); 184+ free(config); 185+ return NULL; 186+ } 187+ } 188+ 189+ strcpy(path, config->path); 190+ strcat(path, ".d"); 191+ if (stat(path, &st) < 0 || !S_ISDIR(st.st_mode)) 192+ return config; 193+ 194+ n = scandir(path, &namelist, accept_config_file, alphasort); 195+ if (n < 0) 196+ return config; 197+ 198+ while (n--) { 199+ char *file = namelist[n]->d_name; 200+ char *sep = "/"; 201+ char fpath[strlen(path)+strlen(sep)+strlen(file) + 1]; 202+ strcpy(fpath, path); 203+ strcat(fpath, sep); 204+ strcat(fpath, file); 205+ free(namelist[n]); 206+ 207+ fp = weston_open_config_file(NULL, fpath); 208+ if (!fp) 209+ continue; 210+ 211+ ret = weston_config_parse_internal(config, fp); 212+ 213+ fclose(fp); 214+ 215+ if (!ret) { 216+ fprintf(stderr, "failed to parse '%s'\n", fpath); 217+ free(namelist); 218+ free(config); 219+ return NULL; 220+ } 221 } 222 223+ free(namelist); 224 return config; 225 } 226 227-- 2282.20.1 229 230