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