xref: /aosp_15_r20/external/libwebsockets/lib/misc/dir.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker  * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker  * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker  *
13*1c60b9acSAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker  *
16*1c60b9acSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker  * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker  */
24*1c60b9acSAndroid Build Coastguard Worker 
25*1c60b9acSAndroid Build Coastguard Worker #if !defined(NO_GNU_SOURCE_THIS_TIME)
26*1c60b9acSAndroid Build Coastguard Worker #define NO_GNU_SOURCE_THIS_TIME
27*1c60b9acSAndroid Build Coastguard Worker #endif
28*1c60b9acSAndroid Build Coastguard Worker #if !defined(_DARWIN_C_SOURCE)
29*1c60b9acSAndroid Build Coastguard Worker #define _DARWIN_C_SOURCE
30*1c60b9acSAndroid Build Coastguard Worker #endif
31*1c60b9acSAndroid Build Coastguard Worker 
32*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
33*1c60b9acSAndroid Build Coastguard Worker #include <string.h>
34*1c60b9acSAndroid Build Coastguard Worker #include <stdio.h>
35*1c60b9acSAndroid Build Coastguard Worker 
36*1c60b9acSAndroid Build Coastguard Worker #include <sys/stat.h>
37*1c60b9acSAndroid Build Coastguard Worker #if defined(WIN32)
38*1c60b9acSAndroid Build Coastguard Worker #include <direct.h>
39*1c60b9acSAndroid Build Coastguard Worker #define read _read
40*1c60b9acSAndroid Build Coastguard Worker #define open _open
41*1c60b9acSAndroid Build Coastguard Worker #define close _close
42*1c60b9acSAndroid Build Coastguard Worker #define write _write
43*1c60b9acSAndroid Build Coastguard Worker #define mkdir(x,y) _mkdir(x)
44*1c60b9acSAndroid Build Coastguard Worker #define rmdir _rmdir
45*1c60b9acSAndroid Build Coastguard Worker #define unlink _unlink
46*1c60b9acSAndroid Build Coastguard Worker #define HAVE_STRUCT_TIMESPEC
47*1c60b9acSAndroid Build Coastguard Worker #if defined(pid_t)
48*1c60b9acSAndroid Build Coastguard Worker #undef pid_t
49*1c60b9acSAndroid Build Coastguard Worker #endif
50*1c60b9acSAndroid Build Coastguard Worker #endif /* win32 */
51*1c60b9acSAndroid Build Coastguard Worker 
52*1c60b9acSAndroid Build Coastguard Worker #define COMBO_SIZEOF 512
53*1c60b9acSAndroid Build Coastguard Worker 
54*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_PLAT_FREERTOS)
55*1c60b9acSAndroid Build Coastguard Worker 
56*1c60b9acSAndroid Build Coastguard Worker #if defined(WIN32)
57*1c60b9acSAndroid Build Coastguard Worker #include "../../win32port/dirent/dirent-win32.h"
58*1c60b9acSAndroid Build Coastguard Worker #else
59*1c60b9acSAndroid Build Coastguard Worker #include <dirent.h>
60*1c60b9acSAndroid Build Coastguard Worker #endif
61*1c60b9acSAndroid Build Coastguard Worker 
filter(const struct dirent * ent)62*1c60b9acSAndroid Build Coastguard Worker static int filter(const struct dirent *ent)
63*1c60b9acSAndroid Build Coastguard Worker {
64*1c60b9acSAndroid Build Coastguard Worker 	if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
65*1c60b9acSAndroid Build Coastguard Worker 		return 0;
66*1c60b9acSAndroid Build Coastguard Worker 
67*1c60b9acSAndroid Build Coastguard Worker 	return 1;
68*1c60b9acSAndroid Build Coastguard Worker }
69*1c60b9acSAndroid Build Coastguard Worker 
70*1c60b9acSAndroid Build Coastguard Worker 
71*1c60b9acSAndroid Build Coastguard Worker #if !defined(WIN32)
72*1c60b9acSAndroid Build Coastguard Worker static char csep = '/';
73*1c60b9acSAndroid Build Coastguard Worker #else
74*1c60b9acSAndroid Build Coastguard Worker static char csep = '\\';
75*1c60b9acSAndroid Build Coastguard Worker #endif
76*1c60b9acSAndroid Build Coastguard Worker 
77*1c60b9acSAndroid Build Coastguard Worker static void
lws_dir_via_stat(char * combo,size_t l,const char * path,struct lws_dir_entry * lde)78*1c60b9acSAndroid Build Coastguard Worker lws_dir_via_stat(char *combo, size_t l, const char *path, struct lws_dir_entry *lde)
79*1c60b9acSAndroid Build Coastguard Worker {
80*1c60b9acSAndroid Build Coastguard Worker         struct stat s;
81*1c60b9acSAndroid Build Coastguard Worker 
82*1c60b9acSAndroid Build Coastguard Worker         lws_strncpy(combo + l, path, COMBO_SIZEOF - l);
83*1c60b9acSAndroid Build Coastguard Worker 
84*1c60b9acSAndroid Build Coastguard Worker         lde->type = LDOT_UNKNOWN;
85*1c60b9acSAndroid Build Coastguard Worker 
86*1c60b9acSAndroid Build Coastguard Worker         if (!stat(combo, &s)) {
87*1c60b9acSAndroid Build Coastguard Worker 		switch (s.st_mode & S_IFMT) {
88*1c60b9acSAndroid Build Coastguard Worker 		case S_IFBLK:
89*1c60b9acSAndroid Build Coastguard Worker 			lde->type = LDOT_BLOCK;
90*1c60b9acSAndroid Build Coastguard Worker 			break;
91*1c60b9acSAndroid Build Coastguard Worker 		case S_IFCHR:
92*1c60b9acSAndroid Build Coastguard Worker 			lde->type = LDOT_CHAR;
93*1c60b9acSAndroid Build Coastguard Worker 			break;
94*1c60b9acSAndroid Build Coastguard Worker 		case S_IFDIR:
95*1c60b9acSAndroid Build Coastguard Worker 			lde->type = LDOT_DIR;
96*1c60b9acSAndroid Build Coastguard Worker 			break;
97*1c60b9acSAndroid Build Coastguard Worker 		case S_IFIFO:
98*1c60b9acSAndroid Build Coastguard Worker 			lde->type = LDOT_FIFO;
99*1c60b9acSAndroid Build Coastguard Worker 			break;
100*1c60b9acSAndroid Build Coastguard Worker #if !defined(WIN32)
101*1c60b9acSAndroid Build Coastguard Worker 		case S_IFLNK:
102*1c60b9acSAndroid Build Coastguard Worker 			lde->type = LDOT_LINK;
103*1c60b9acSAndroid Build Coastguard Worker 			break;
104*1c60b9acSAndroid Build Coastguard Worker #endif
105*1c60b9acSAndroid Build Coastguard Worker 		case S_IFREG:
106*1c60b9acSAndroid Build Coastguard Worker 			lde->type = LDOT_FILE;
107*1c60b9acSAndroid Build Coastguard Worker 			break;
108*1c60b9acSAndroid Build Coastguard Worker 		default:
109*1c60b9acSAndroid Build Coastguard Worker 			break;
110*1c60b9acSAndroid Build Coastguard Worker 		}
111*1c60b9acSAndroid Build Coastguard Worker         }
112*1c60b9acSAndroid Build Coastguard Worker }
113*1c60b9acSAndroid Build Coastguard Worker 
114*1c60b9acSAndroid Build Coastguard Worker int
lws_dir(const char * dirpath,void * user,lws_dir_callback_function cb)115*1c60b9acSAndroid Build Coastguard Worker lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb)
116*1c60b9acSAndroid Build Coastguard Worker {
117*1c60b9acSAndroid Build Coastguard Worker 	struct lws_dir_entry lde;
118*1c60b9acSAndroid Build Coastguard Worker 	struct dirent **namelist;
119*1c60b9acSAndroid Build Coastguard Worker 	int n, i, ret = 1;
120*1c60b9acSAndroid Build Coastguard Worker 	char combo[COMBO_SIZEOF];
121*1c60b9acSAndroid Build Coastguard Worker 	size_t l;
122*1c60b9acSAndroid Build Coastguard Worker 
123*1c60b9acSAndroid Build Coastguard Worker 	l = (size_t)(ssize_t)lws_snprintf(combo, COMBO_SIZEOF - 2, "%s", dirpath);
124*1c60b9acSAndroid Build Coastguard Worker 	combo[l++] = csep;
125*1c60b9acSAndroid Build Coastguard Worker 	combo[l] = '\0';
126*1c60b9acSAndroid Build Coastguard Worker 
127*1c60b9acSAndroid Build Coastguard Worker 	n = scandir((char *)dirpath, &namelist, filter, alphasort);
128*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0) {
129*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("Scandir on '%s' failed, errno %d\n", dirpath, LWS_ERRNO);
130*1c60b9acSAndroid Build Coastguard Worker 		return 1;
131*1c60b9acSAndroid Build Coastguard Worker 	}
132*1c60b9acSAndroid Build Coastguard Worker 
133*1c60b9acSAndroid Build Coastguard Worker 	for (i = 0; i < n; i++) {
134*1c60b9acSAndroid Build Coastguard Worker #if !defined(__sun)
135*1c60b9acSAndroid Build Coastguard Worker 		unsigned int type = namelist[i]->d_type;
136*1c60b9acSAndroid Build Coastguard Worker #endif
137*1c60b9acSAndroid Build Coastguard Worker 		if (strchr(namelist[i]->d_name, '~'))
138*1c60b9acSAndroid Build Coastguard Worker 			goto skip;
139*1c60b9acSAndroid Build Coastguard Worker 		lde.name = namelist[i]->d_name;
140*1c60b9acSAndroid Build Coastguard Worker 
141*1c60b9acSAndroid Build Coastguard Worker 		/*
142*1c60b9acSAndroid Build Coastguard Worker 		 * some filesystems don't report this (ZFS) and tell that
143*1c60b9acSAndroid Build Coastguard Worker 		 * files are LDOT_UNKNOWN
144*1c60b9acSAndroid Build Coastguard Worker 		 */
145*1c60b9acSAndroid Build Coastguard Worker 
146*1c60b9acSAndroid Build Coastguard Worker #if defined(__sun)
147*1c60b9acSAndroid Build Coastguard Worker 		lws_dir_via_stat(combo, l, namelist[i]->d_name, &lde);
148*1c60b9acSAndroid Build Coastguard Worker #else
149*1c60b9acSAndroid Build Coastguard Worker 		/*
150*1c60b9acSAndroid Build Coastguard Worker 		 * XFS on Linux doesn't fill in d_type at all, always zero.
151*1c60b9acSAndroid Build Coastguard Worker 		 */
152*1c60b9acSAndroid Build Coastguard Worker 
153*1c60b9acSAndroid Build Coastguard Worker 		if (DT_BLK != DT_UNKNOWN && type == DT_BLK)
154*1c60b9acSAndroid Build Coastguard Worker 			lde.type = LDOT_BLOCK;
155*1c60b9acSAndroid Build Coastguard Worker 		else if (DT_CHR != DT_UNKNOWN && type == DT_CHR)
156*1c60b9acSAndroid Build Coastguard Worker 			lde.type = LDOT_CHAR;
157*1c60b9acSAndroid Build Coastguard Worker 		else if (DT_DIR != DT_UNKNOWN && type == DT_DIR)
158*1c60b9acSAndroid Build Coastguard Worker 			lde.type = LDOT_DIR;
159*1c60b9acSAndroid Build Coastguard Worker 		else if (DT_FIFO != DT_UNKNOWN && type == DT_FIFO)
160*1c60b9acSAndroid Build Coastguard Worker 			lde.type = LDOT_FIFO;
161*1c60b9acSAndroid Build Coastguard Worker 		else if (DT_LNK != DT_UNKNOWN && type == DT_LNK)
162*1c60b9acSAndroid Build Coastguard Worker 			lde.type = LDOT_LINK;
163*1c60b9acSAndroid Build Coastguard Worker 		else if (DT_REG != DT_UNKNOWN && type == DT_REG)
164*1c60b9acSAndroid Build Coastguard Worker 			lde.type = LDOT_FILE;
165*1c60b9acSAndroid Build Coastguard Worker 		else if (DT_SOCK != DT_UNKNOWN && type == DT_SOCK)
166*1c60b9acSAndroid Build Coastguard Worker 			lde.type = LDOTT_SOCKET;
167*1c60b9acSAndroid Build Coastguard Worker 		else {
168*1c60b9acSAndroid Build Coastguard Worker 			lde.type = LDOT_UNKNOWN;
169*1c60b9acSAndroid Build Coastguard Worker 			lws_dir_via_stat(combo, l, namelist[i]->d_name, &lde);
170*1c60b9acSAndroid Build Coastguard Worker 		}
171*1c60b9acSAndroid Build Coastguard Worker #endif
172*1c60b9acSAndroid Build Coastguard Worker 		if (cb(dirpath, user, &lde)) {
173*1c60b9acSAndroid Build Coastguard Worker 			while (i < n)
174*1c60b9acSAndroid Build Coastguard Worker 				free(namelist[i++]);
175*1c60b9acSAndroid Build Coastguard Worker 			ret = 0; /* told to stop by cb */
176*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
177*1c60b9acSAndroid Build Coastguard Worker 		}
178*1c60b9acSAndroid Build Coastguard Worker skip:
179*1c60b9acSAndroid Build Coastguard Worker 		free(namelist[i]);
180*1c60b9acSAndroid Build Coastguard Worker 	}
181*1c60b9acSAndroid Build Coastguard Worker 
182*1c60b9acSAndroid Build Coastguard Worker bail:
183*1c60b9acSAndroid Build Coastguard Worker 	free(namelist);
184*1c60b9acSAndroid Build Coastguard Worker 
185*1c60b9acSAndroid Build Coastguard Worker 	return ret;
186*1c60b9acSAndroid Build Coastguard Worker }
187*1c60b9acSAndroid Build Coastguard Worker 
188*1c60b9acSAndroid Build Coastguard Worker /*
189*1c60b9acSAndroid Build Coastguard Worker  * Check filename against one globby filter
190*1c60b9acSAndroid Build Coastguard Worker  *
191*1c60b9acSAndroid Build Coastguard Worker  * We can support things like "*.rpm"
192*1c60b9acSAndroid Build Coastguard Worker  */
193*1c60b9acSAndroid Build Coastguard Worker 
194*1c60b9acSAndroid Build Coastguard Worker static int
lws_dir_glob_check(const char * nm,const char * filt)195*1c60b9acSAndroid Build Coastguard Worker lws_dir_glob_check(const char *nm, const char *filt)
196*1c60b9acSAndroid Build Coastguard Worker {
197*1c60b9acSAndroid Build Coastguard Worker 	while (*nm) {
198*1c60b9acSAndroid Build Coastguard Worker 		if (*filt == '*') {
199*1c60b9acSAndroid Build Coastguard Worker 			if (!strcmp(nm, filt + 1))
200*1c60b9acSAndroid Build Coastguard Worker 				return 1;
201*1c60b9acSAndroid Build Coastguard Worker 		} else {
202*1c60b9acSAndroid Build Coastguard Worker 			if (*nm != *filt)
203*1c60b9acSAndroid Build Coastguard Worker 				return 0;
204*1c60b9acSAndroid Build Coastguard Worker 			filt++;
205*1c60b9acSAndroid Build Coastguard Worker 		}
206*1c60b9acSAndroid Build Coastguard Worker 		nm++;
207*1c60b9acSAndroid Build Coastguard Worker 	}
208*1c60b9acSAndroid Build Coastguard Worker 
209*1c60b9acSAndroid Build Coastguard Worker 	return 0;
210*1c60b9acSAndroid Build Coastguard Worker }
211*1c60b9acSAndroid Build Coastguard Worker 
212*1c60b9acSAndroid Build Coastguard Worker /*
213*1c60b9acSAndroid Build Coastguard Worker  * We get passed a single filter string, like "*.txt" or "mydir/\*.rpm" or so.
214*1c60b9acSAndroid Build Coastguard Worker  */
215*1c60b9acSAndroid Build Coastguard Worker 
216*1c60b9acSAndroid Build Coastguard Worker int
lws_dir_glob_cb(const char * dirpath,void * user,struct lws_dir_entry * lde)217*1c60b9acSAndroid Build Coastguard Worker lws_dir_glob_cb(const char *dirpath, void *user, struct lws_dir_entry *lde)
218*1c60b9acSAndroid Build Coastguard Worker {
219*1c60b9acSAndroid Build Coastguard Worker 	lws_dir_glob_t *filter = (lws_dir_glob_t*)user;
220*1c60b9acSAndroid Build Coastguard Worker 	char path[384];
221*1c60b9acSAndroid Build Coastguard Worker 
222*1c60b9acSAndroid Build Coastguard Worker 	if (!strcmp(lde->name, ".") || !strcmp(lde->name, ".."))
223*1c60b9acSAndroid Build Coastguard Worker 		return 0;
224*1c60b9acSAndroid Build Coastguard Worker 
225*1c60b9acSAndroid Build Coastguard Worker 	if (lde->type == LDOT_DIR)
226*1c60b9acSAndroid Build Coastguard Worker 		return 0;
227*1c60b9acSAndroid Build Coastguard Worker 
228*1c60b9acSAndroid Build Coastguard Worker 	if (lws_dir_glob_check(lde->name, filter->filter)) {
229*1c60b9acSAndroid Build Coastguard Worker 		lws_snprintf(path, sizeof(path), "%s%c%s", dirpath, csep,
230*1c60b9acSAndroid Build Coastguard Worker 							   lde->name);
231*1c60b9acSAndroid Build Coastguard Worker 		filter->cb(filter->user, path);
232*1c60b9acSAndroid Build Coastguard Worker 	}
233*1c60b9acSAndroid Build Coastguard Worker 
234*1c60b9acSAndroid Build Coastguard Worker 	return 0;
235*1c60b9acSAndroid Build Coastguard Worker }
236*1c60b9acSAndroid Build Coastguard Worker 
237*1c60b9acSAndroid Build Coastguard Worker int
lws_dir_rm_rf_cb(const char * dirpath,void * user,struct lws_dir_entry * lde)238*1c60b9acSAndroid Build Coastguard Worker lws_dir_rm_rf_cb(const char *dirpath, void *user, struct lws_dir_entry *lde)
239*1c60b9acSAndroid Build Coastguard Worker {
240*1c60b9acSAndroid Build Coastguard Worker 	char path[384];
241*1c60b9acSAndroid Build Coastguard Worker 
242*1c60b9acSAndroid Build Coastguard Worker 	if (!strcmp(lde->name, ".") || !strcmp(lde->name, ".."))
243*1c60b9acSAndroid Build Coastguard Worker 		return 0;
244*1c60b9acSAndroid Build Coastguard Worker 
245*1c60b9acSAndroid Build Coastguard Worker 	lws_snprintf(path, sizeof(path), "%s%c%s", dirpath, csep, lde->name);
246*1c60b9acSAndroid Build Coastguard Worker 
247*1c60b9acSAndroid Build Coastguard Worker 	if (lde->type == LDOT_DIR) {
248*1c60b9acSAndroid Build Coastguard Worker #if !defined(WIN32) && !defined(_WIN32) && !defined(__COVERITY__)
249*1c60b9acSAndroid Build Coastguard Worker 		char dummy[8];
250*1c60b9acSAndroid Build Coastguard Worker 		/*
251*1c60b9acSAndroid Build Coastguard Worker 		 * hm... eg, recursive dir symlinks can show up a LDOT_DIR
252*1c60b9acSAndroid Build Coastguard Worker 		 * here.  If it's a symlink, don't recurse into it.
253*1c60b9acSAndroid Build Coastguard Worker 		 *
254*1c60b9acSAndroid Build Coastguard Worker 		 * Notice we immediately discard dummy without looking in it.
255*1c60b9acSAndroid Build Coastguard Worker 		 * There is no way to get into trouble from its lack of NUL
256*1c60b9acSAndroid Build Coastguard Worker 		 * termination in dummy[].  We just wanted to know if it was
257*1c60b9acSAndroid Build Coastguard Worker 		 * a symlink at all.
258*1c60b9acSAndroid Build Coastguard Worker 		 *
259*1c60b9acSAndroid Build Coastguard Worker 		 * Hide this from Coverity since it flags any use of readlink()
260*1c60b9acSAndroid Build Coastguard Worker 		 * even if safe.
261*1c60b9acSAndroid Build Coastguard Worker 		 */
262*1c60b9acSAndroid Build Coastguard Worker 		if (readlink(path, dummy, sizeof(dummy)) < 0)
263*1c60b9acSAndroid Build Coastguard Worker #endif
264*1c60b9acSAndroid Build Coastguard Worker 			lws_dir(path, NULL, lws_dir_rm_rf_cb);
265*1c60b9acSAndroid Build Coastguard Worker 
266*1c60b9acSAndroid Build Coastguard Worker 		if (rmdir(path))
267*1c60b9acSAndroid Build Coastguard Worker 			lwsl_warn("%s: rmdir %s failed %d\n", __func__, path, errno);
268*1c60b9acSAndroid Build Coastguard Worker 	} else {
269*1c60b9acSAndroid Build Coastguard Worker 		if (unlink(path)) {
270*1c60b9acSAndroid Build Coastguard Worker #if defined(WIN32)
271*1c60b9acSAndroid Build Coastguard Worker 			SetFileAttributesA(path, FILE_ATTRIBUTE_NORMAL);
272*1c60b9acSAndroid Build Coastguard Worker 			if (unlink(path))
273*1c60b9acSAndroid Build Coastguard Worker #else
274*1c60b9acSAndroid Build Coastguard Worker 			if (rmdir(path))
275*1c60b9acSAndroid Build Coastguard Worker #endif
276*1c60b9acSAndroid Build Coastguard Worker 			lwsl_warn("%s: unlink %s failed %d (type %d)\n",
277*1c60b9acSAndroid Build Coastguard Worker 					__func__, path, errno, lde->type);
278*1c60b9acSAndroid Build Coastguard Worker 		}
279*1c60b9acSAndroid Build Coastguard Worker 	}
280*1c60b9acSAndroid Build Coastguard Worker 
281*1c60b9acSAndroid Build Coastguard Worker 	return 0;
282*1c60b9acSAndroid Build Coastguard Worker }
283*1c60b9acSAndroid Build Coastguard Worker 
284*1c60b9acSAndroid Build Coastguard Worker 
285*1c60b9acSAndroid Build Coastguard Worker #endif
286*1c60b9acSAndroid Build Coastguard Worker 
287*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_PLUGINS_API)
288*1c60b9acSAndroid Build Coastguard Worker 
289*1c60b9acSAndroid Build Coastguard Worker struct lws_plugins_args {
290*1c60b9acSAndroid Build Coastguard Worker 	struct lws_plugin	**pplugin;
291*1c60b9acSAndroid Build Coastguard Worker 	const char		*_class;
292*1c60b9acSAndroid Build Coastguard Worker 	const char		*filter;
293*1c60b9acSAndroid Build Coastguard Worker 	each_plugin_cb_t	each;
294*1c60b9acSAndroid Build Coastguard Worker 	void			*each_user;
295*1c60b9acSAndroid Build Coastguard Worker };
296*1c60b9acSAndroid Build Coastguard Worker 
297*1c60b9acSAndroid Build Coastguard Worker static int
lws_plugins_dir_cb(const char * dirpath,void * user,struct lws_dir_entry * lde)298*1c60b9acSAndroid Build Coastguard Worker lws_plugins_dir_cb(const char *dirpath, void *user, struct lws_dir_entry *lde)
299*1c60b9acSAndroid Build Coastguard Worker {
300*1c60b9acSAndroid Build Coastguard Worker 	struct lws_plugins_args *pa = (struct lws_plugins_args *)user;
301*1c60b9acSAndroid Build Coastguard Worker 	char path[256], base[64], *q = base;
302*1c60b9acSAndroid Build Coastguard Worker 	const lws_plugin_header_t *pl;
303*1c60b9acSAndroid Build Coastguard Worker 	const char *p;
304*1c60b9acSAndroid Build Coastguard Worker 
305*1c60b9acSAndroid Build Coastguard Worker 	if (strlen(lde->name) < 7)
306*1c60b9acSAndroid Build Coastguard Worker 		return 0; /* keep going */
307*1c60b9acSAndroid Build Coastguard Worker 
308*1c60b9acSAndroid Build Coastguard Worker 	/*
309*1c60b9acSAndroid Build Coastguard Worker 	 * The actual plugin names for protocol plugins look like
310*1c60b9acSAndroid Build Coastguard Worker 	 * "libprotocol_lws_ssh_base.so" and for event libs
311*1c60b9acSAndroid Build Coastguard Worker 	 * "libwebsockets-evlib_ev.so"... to recover the base name of
312*1c60b9acSAndroid Build Coastguard Worker 	 * "lws_ssh_base" and "evlib_ev" we strip from the left to after the
313*1c60b9acSAndroid Build Coastguard Worker 	 * first _ or -, and then truncate at the first .
314*1c60b9acSAndroid Build Coastguard Worker 	 */
315*1c60b9acSAndroid Build Coastguard Worker 
316*1c60b9acSAndroid Build Coastguard Worker 	p = lde->name;
317*1c60b9acSAndroid Build Coastguard Worker 	while (*p && *p != '_' && *p != '-')
318*1c60b9acSAndroid Build Coastguard Worker 		p++;
319*1c60b9acSAndroid Build Coastguard Worker 	if (!*p)
320*1c60b9acSAndroid Build Coastguard Worker 		return 0;
321*1c60b9acSAndroid Build Coastguard Worker 	p++;
322*1c60b9acSAndroid Build Coastguard Worker 	while (*p && *p != '.' && lws_ptr_diff(q, base) < (int)sizeof(base) - 1)
323*1c60b9acSAndroid Build Coastguard Worker 		*q++ = *p++;
324*1c60b9acSAndroid Build Coastguard Worker 	*q = '\0';
325*1c60b9acSAndroid Build Coastguard Worker 
326*1c60b9acSAndroid Build Coastguard Worker 	/* if he's given a filter, only match if base matches it */
327*1c60b9acSAndroid Build Coastguard Worker 	if (pa->filter && strcmp(base, pa->filter))
328*1c60b9acSAndroid Build Coastguard Worker 		return 0; /* keep going */
329*1c60b9acSAndroid Build Coastguard Worker 
330*1c60b9acSAndroid Build Coastguard Worker 	lws_snprintf(path, sizeof(path) - 1, "%s/%s", dirpath, lde->name);
331*1c60b9acSAndroid Build Coastguard Worker 
332*1c60b9acSAndroid Build Coastguard Worker 	pl = lws_plat_dlopen(pa->pplugin, path, base, pa->_class,
333*1c60b9acSAndroid Build Coastguard Worker 			     pa->each, pa->each_user);
334*1c60b9acSAndroid Build Coastguard Worker 
335*1c60b9acSAndroid Build Coastguard Worker 	/*
336*1c60b9acSAndroid Build Coastguard Worker 	 * If we were looking for a specific plugin, finding it should make
337*1c60b9acSAndroid Build Coastguard Worker 	 * us stop looking (eg, to account for directory precedence of the
338*1c60b9acSAndroid Build Coastguard Worker 	 * same plugin).  If scanning for plugins in a dir, we always keep
339*1c60b9acSAndroid Build Coastguard Worker 	 * going.
340*1c60b9acSAndroid Build Coastguard Worker 	 */
341*1c60b9acSAndroid Build Coastguard Worker 
342*1c60b9acSAndroid Build Coastguard Worker 	return pa->filter && pl;
343*1c60b9acSAndroid Build Coastguard Worker }
344*1c60b9acSAndroid Build Coastguard Worker 
345*1c60b9acSAndroid Build Coastguard Worker int
lws_plugins_init(struct lws_plugin ** pplugin,const char * const * d,const char * _class,const char * filter,each_plugin_cb_t each,void * each_user)346*1c60b9acSAndroid Build Coastguard Worker lws_plugins_init(struct lws_plugin **pplugin, const char * const *d,
347*1c60b9acSAndroid Build Coastguard Worker 		 const char *_class, const char *filter,
348*1c60b9acSAndroid Build Coastguard Worker 		 each_plugin_cb_t each, void *each_user)
349*1c60b9acSAndroid Build Coastguard Worker {
350*1c60b9acSAndroid Build Coastguard Worker 	struct lws_plugins_args pa;
351*1c60b9acSAndroid Build Coastguard Worker 	char *ld_env;
352*1c60b9acSAndroid Build Coastguard Worker 	int ret = 1;
353*1c60b9acSAndroid Build Coastguard Worker 
354*1c60b9acSAndroid Build Coastguard Worker 	pa.pplugin = pplugin;
355*1c60b9acSAndroid Build Coastguard Worker 	pa._class = _class;
356*1c60b9acSAndroid Build Coastguard Worker 	pa.each = each;
357*1c60b9acSAndroid Build Coastguard Worker 	pa.each_user = each_user;
358*1c60b9acSAndroid Build Coastguard Worker 	pa.filter = filter;
359*1c60b9acSAndroid Build Coastguard Worker 
360*1c60b9acSAndroid Build Coastguard Worker 	/*
361*1c60b9acSAndroid Build Coastguard Worker 	 * Check LD_LIBRARY_PATH override path first if present
362*1c60b9acSAndroid Build Coastguard Worker 	 */
363*1c60b9acSAndroid Build Coastguard Worker 
364*1c60b9acSAndroid Build Coastguard Worker 	ld_env = getenv("LD_LIBRARY_PATH");
365*1c60b9acSAndroid Build Coastguard Worker 	if (ld_env) {
366*1c60b9acSAndroid Build Coastguard Worker 		char temp[128];
367*1c60b9acSAndroid Build Coastguard Worker 		struct lws_tokenize ts;
368*1c60b9acSAndroid Build Coastguard Worker 
369*1c60b9acSAndroid Build Coastguard Worker 		memset(&ts, 0, sizeof(ts));
370*1c60b9acSAndroid Build Coastguard Worker 		ts.start = ld_env;
371*1c60b9acSAndroid Build Coastguard Worker 		ts.len = strlen(ld_env);
372*1c60b9acSAndroid Build Coastguard Worker 		ts.flags = LWS_TOKENIZE_F_SLASH_NONTERM |
373*1c60b9acSAndroid Build Coastguard Worker 			   LWS_TOKENIZE_F_DOT_NONTERM |
374*1c60b9acSAndroid Build Coastguard Worker 			   LWS_TOKENIZE_F_MINUS_NONTERM |
375*1c60b9acSAndroid Build Coastguard Worker 			   LWS_TOKENIZE_F_NO_INTEGERS |
376*1c60b9acSAndroid Build Coastguard Worker 			   LWS_TOKENIZE_F_NO_FLOATS;
377*1c60b9acSAndroid Build Coastguard Worker 
378*1c60b9acSAndroid Build Coastguard Worker 		do {
379*1c60b9acSAndroid Build Coastguard Worker 			ts.e = (int8_t)lws_tokenize(&ts);
380*1c60b9acSAndroid Build Coastguard Worker 			if (ts.e != LWS_TOKZE_TOKEN)
381*1c60b9acSAndroid Build Coastguard Worker 				continue;
382*1c60b9acSAndroid Build Coastguard Worker 
383*1c60b9acSAndroid Build Coastguard Worker 			lws_strnncpy(temp, ts.token,
384*1c60b9acSAndroid Build Coastguard Worker 				     ts.token_len,
385*1c60b9acSAndroid Build Coastguard Worker 				     sizeof(temp));
386*1c60b9acSAndroid Build Coastguard Worker 
387*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: trying %s\n", __func__, temp);
388*1c60b9acSAndroid Build Coastguard Worker 			if (!lws_dir(temp, &pa, lws_plugins_dir_cb))
389*1c60b9acSAndroid Build Coastguard Worker 				ret = 0;
390*1c60b9acSAndroid Build Coastguard Worker 
391*1c60b9acSAndroid Build Coastguard Worker 		} while (ts.e > 0);
392*1c60b9acSAndroid Build Coastguard Worker 	}
393*1c60b9acSAndroid Build Coastguard Worker 
394*1c60b9acSAndroid Build Coastguard Worker 	while (d && *d) {
395*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: trying %s\n", __func__, *d);
396*1c60b9acSAndroid Build Coastguard Worker 		if (!lws_dir(*d, &pa, lws_plugins_dir_cb))
397*1c60b9acSAndroid Build Coastguard Worker 			ret = 0;
398*1c60b9acSAndroid Build Coastguard Worker 
399*1c60b9acSAndroid Build Coastguard Worker 		d++;
400*1c60b9acSAndroid Build Coastguard Worker 	}
401*1c60b9acSAndroid Build Coastguard Worker 
402*1c60b9acSAndroid Build Coastguard Worker 	return ret;
403*1c60b9acSAndroid Build Coastguard Worker }
404*1c60b9acSAndroid Build Coastguard Worker 
405*1c60b9acSAndroid Build Coastguard Worker int
lws_plugins_destroy(struct lws_plugin ** pplugin,each_plugin_cb_t each,void * each_user)406*1c60b9acSAndroid Build Coastguard Worker lws_plugins_destroy(struct lws_plugin **pplugin, each_plugin_cb_t each,
407*1c60b9acSAndroid Build Coastguard Worker 		    void *each_user)
408*1c60b9acSAndroid Build Coastguard Worker {
409*1c60b9acSAndroid Build Coastguard Worker 	struct lws_plugin *p = *pplugin, *p1;
410*1c60b9acSAndroid Build Coastguard Worker 
411*1c60b9acSAndroid Build Coastguard Worker 	while (p) {
412*1c60b9acSAndroid Build Coastguard Worker 		if (each)
413*1c60b9acSAndroid Build Coastguard Worker 			each(p, each_user);
414*1c60b9acSAndroid Build Coastguard Worker 		lws_plat_destroy_dl(p);
415*1c60b9acSAndroid Build Coastguard Worker 		p1 = p->list;
416*1c60b9acSAndroid Build Coastguard Worker 		p->list = NULL;
417*1c60b9acSAndroid Build Coastguard Worker 		lws_free(p);
418*1c60b9acSAndroid Build Coastguard Worker 		p = p1;
419*1c60b9acSAndroid Build Coastguard Worker 	}
420*1c60b9acSAndroid Build Coastguard Worker 
421*1c60b9acSAndroid Build Coastguard Worker 	*pplugin = NULL;
422*1c60b9acSAndroid Build Coastguard Worker 
423*1c60b9acSAndroid Build Coastguard Worker 	return 0;
424*1c60b9acSAndroid Build Coastguard Worker }
425*1c60b9acSAndroid Build Coastguard Worker #endif
426