4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
39 static int validsubpath(const char *subpath)
42 if (subpath[i] == '/')
45 switch(subpath[i++]) {
49 if (subpath[i] == '/') {
53 if (subpath[i++] == '.') {
58 if (subpath[i++] == '/') {
64 while(subpath[i] && subpath[i] != '/')
74 static const char *normalsubpath(const char *subpath)
76 while(*subpath == '/')
78 return validsubpath(subpath) ? subpath : NULL;
81 struct wgt *wgt_create()
83 struct wgt *wgt = malloc(sizeof * wgt);
95 void wgt_disconnect(struct wgt *wgt)
103 void wgt_locales_reset(struct wgt *wgt)
106 while(wgt->nrlocales)
107 free(wgt->locales[--wgt->nrlocales]);
110 void wgt_addref(struct wgt *wgt)
116 void wgt_unref(struct wgt *wgt)
119 if (!--wgt->refcount) {
121 wgt_locales_reset(wgt);
127 int wgt_connectat(struct wgt *wgt, int dirfd, const char *pathname)
135 rfd = openat(rfd, pathname, O_PATH|O_DIRECTORY);
139 if (wgt->rootfd >= 0)
145 int wgt_connect(struct wgt *wgt, const char *pathname)
147 return wgt_connectat(wgt, AT_FDCWD, pathname);
150 int wgt_is_connected(struct wgt *wgt)
153 return wgt->rootfd != -1;
156 int wgt_has(struct wgt *wgt, const char *filename)
159 assert(wgt_is_connected(wgt));
161 filename = normalsubpath(filename);
166 return 0 == faccessat(wgt->rootfd, filename, F_OK, 0);
169 int wgt_open_read(struct wgt *wgt, const char *filename)
172 assert(wgt_is_connected(wgt));
173 filename = normalsubpath(filename);
178 return openat(wgt->rootfd, filename, O_RDONLY);
181 static int locadd(struct wgt *wgt, const char *locstr, int length)
186 item = strndup(locstr, length);
188 for (i = 0 ; item[i] ; i++)
189 item[i] = tolower(item[i]);
190 for (i = 0 ; i < wgt->nrlocales ; i++)
191 if (!strcmp(item, wgt->locales[i])) {
196 ptr = realloc(wgt->locales, (1 + wgt->nrlocales) * sizeof(wgt->locales[0]));
199 wgt->locales[wgt->nrlocales++] = item;
208 int wgt_locales_add(struct wgt *wgt, const char *locstr)
210 const char *stop, *next;
213 stop = strchrnul(locstr, ',');
214 next = stop + !!*stop;
215 while (locstr != stop) {
216 if (locadd(wgt, locstr, stop - locstr))
218 do { stop--; } while(stop > locstr && *stop != '-');
225 int wgt_locales_score(struct wgt *wgt, const char *lang)
231 for (i = 0 ; i < wgt->nrlocales ; i++)
232 if (!strcasecmp(lang, wgt->locales[i]))
238 static const char *localize(struct wgt *wgt, const char *filename, char path[PATH_MAX])
242 filename = normalsubpath(filename);
247 for (i = 0 ; i < wgt->nrlocales ; i++) {
248 if (snprintf(path, PATH_MAX, "locales/%s/%s", wgt->locales[i], filename) >= PATH_MAX) {
252 if (0 == faccessat(wgt->rootfd, path, F_OK, 0))
255 if (0 == faccessat(wgt->rootfd, filename, F_OK, 0))
261 char *wgt_locales_locate(struct wgt *wgt, const char *filename)
268 assert(wgt_is_connected(wgt));
269 loc = localize(wgt, filename, path);
273 result = strdup(loc);
281 int wgt_locales_open_read(struct wgt *wgt, const char *filename)
287 assert(wgt_is_connected(wgt));
288 loc = localize(wgt, filename, path);
292 return openat(wgt->rootfd, loc, O_RDONLY);