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 struct wgt *wgt_create()
76 struct wgt *wgt = malloc(sizeof * wgt);
88 void wgt_disconnect(struct wgt *wgt)
96 void wgt_locales_reset(struct wgt *wgt)
100 free(wgt->locales[--wgt->nrlocales]);
103 void wgt_addref(struct wgt *wgt)
109 void wgt_unref(struct wgt *wgt)
112 if (!--wgt->refcount) {
114 wgt_locales_reset(wgt);
120 int wgt_connectat(struct wgt *wgt, int dirfd, const char *pathname)
128 rfd = openat(rfd, pathname, O_PATH|O_DIRECTORY);
132 if (wgt->rootfd >= 0)
138 int wgt_connect(struct wgt *wgt, const char *pathname)
140 return wgt_connectat(wgt, AT_FDCWD, pathname);
143 int wgt_is_connected(struct wgt *wgt)
146 return wgt->rootfd != -1;
149 int wgt_has(struct wgt *wgt, const char *filename)
152 assert(wgt_is_connected(wgt));
153 if (!validsubpath(filename)) {
157 return 0 == faccessat(wgt->rootfd, filename, F_OK, 0);
160 int wgt_open_read(struct wgt *wgt, const char *filename)
163 assert(wgt_is_connected(wgt));
164 if (!validsubpath(filename)) {
168 return openat(wgt->rootfd, filename, O_RDONLY);
171 static int locadd(struct wgt *wgt, const char *locstr, int length)
176 item = strndup(locstr, length);
178 for (i = 0 ; item[i] ; i++)
179 item[i] = tolower(item[i]);
180 for (i = 0 ; i < wgt->nrlocales ; i++)
181 if (!strcmp(item, wgt->locales[i])) {
186 ptr = realloc(wgt->locales, (1 + wgt->nrlocales) * sizeof(wgt->locales[0]));
189 wgt->locales[wgt->nrlocales++] = item;
198 int wgt_locales_add(struct wgt *wgt, const char *locstr)
200 const char *stop, *next;
203 stop = strchrnul(locstr, ',');
204 next = stop + !!*stop;
205 while (locstr != stop) {
206 if (locadd(wgt, locstr, stop - locstr))
208 do { stop--; } while(stop > locstr && *stop != '-');
215 int wgt_locales_score(struct wgt *wgt, const char *lang)
221 for (i = 0 ; i < wgt->nrlocales ; i++)
222 if (!strcasecmp(lang, wgt->locales[i]))
228 static const char *localize(struct wgt *wgt, const char *filename, char path[PATH_MAX])
232 if (!validsubpath(filename)) {
236 for (i = 0 ; i < wgt->nrlocales ; i++) {
237 if (snprintf(path, PATH_MAX, "locales/%s/%s", wgt->locales[i], filename) >= PATH_MAX) {
241 if (0 == faccessat(wgt->rootfd, path, F_OK, 0))
244 if (0 == faccessat(wgt->rootfd, filename, F_OK, 0))
250 char *wgt_locales_locate(struct wgt *wgt, const char *filename)
257 assert(wgt_is_connected(wgt));
258 loc = localize(wgt, filename, path);
262 result = strdup(loc);
270 int wgt_locales_open_read(struct wgt *wgt, const char *filename)
276 assert(wgt_is_connected(wgt));
277 loc = localize(wgt, filename, path);
281 return openat(wgt->rootfd, loc, O_RDONLY);