1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #if !defined(NO_GNU_SOURCE_THIS_TIME)
26 #define NO_GNU_SOURCE_THIS_TIME
27 #endif
28 #if !defined(_DARWIN_C_SOURCE)
29 #define _DARWIN_C_SOURCE
30 #endif
31
32 #include <libwebsockets.h>
33 #include "private-lib-core.h"
34 #include <string.h>
35 #include <stdio.h>
36
37 #if defined(LWS_WITH_LIBUV) && UV_VERSION_MAJOR > 0
38
39 int
lws_dir(const char * dirpath,void * user,lws_dir_callback_function cb)40 lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb)
41 {
42 struct lws_dir_entry lde;
43 uv_dirent_t dent;
44 uv_fs_t req;
45 int ret = 1, ir;
46 uv_loop_t loop;
47
48 ir = uv_loop_init(&loop);
49 if (ir) {
50 lwsl_err("%s: loop init failed %d\n", __func__, ir);
51 return 1;
52 }
53
54 ir = uv_fs_scandir(&loop, &req, dirpath, 0, NULL);
55 if (ir < 0) {
56 lwsl_err("Scandir on %s failed, errno %d\n", dirpath, LWS_ERRNO);
57 ret = 2;
58 goto bail;
59 }
60
61 while (uv_fs_scandir_next(&req, &dent) != UV_EOF) {
62 lde.name = dent.name;
63 lde.type = (int)dent.type;
64 if (cb(dirpath, user, &lde))
65 goto bail1;
66 }
67
68 ret = 0;
69
70 bail1:
71 uv_fs_req_cleanup(&req);
72 bail:
73 while (uv_loop_close(&loop))
74 ;
75
76 return ret;
77 }
78
79 #else
80
81 #if !defined(_WIN32) && !defined(LWS_PLAT_FREERTOS)
82
83 #include <dirent.h>
84
filter(const struct dirent * ent)85 static int filter(const struct dirent *ent)
86 {
87 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
88 return 0;
89
90 return 1;
91 }
92
93 int
lws_dir(const char * dirpath,void * user,lws_dir_callback_function cb)94 lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb)
95 {
96 struct lws_dir_entry lde;
97 struct dirent **namelist;
98 int n, i, ret = 1;
99
100 n = scandir((char *)dirpath, &namelist, filter, alphasort);
101 if (n < 0) {
102 lwsl_err("Scandir on '%s' failed, errno %d\n", dirpath, LWS_ERRNO);
103 return 1;
104 }
105
106 for (i = 0; i < n; i++) {
107 if (strchr(namelist[i]->d_name, '~'))
108 goto skip;
109 lde.name = namelist[i]->d_name;
110
111 /*
112 * some filesystems don't report this (ZFS) and tell that
113 * files are LDOT_UNKNOWN
114 */
115
116 #if defined(__sun)
117 struct stat s;
118 stat(namelist[i]->d_name, &s);
119 switch (s.st_mode) {
120 case S_IFBLK:
121 lde.type = LDOT_BLOCK;
122 break;
123 case S_IFCHR:
124 lde.type = LDOT_CHAR;
125 break;
126 case S_IFDIR:
127 lde.type = LDOT_DIR;
128 break;
129 case S_IFIFO:
130 lde.type = LDOT_FIFO;
131 break;
132 case S_IFLNK:
133 lde.type = LDOT_LINK;
134 break;
135 case S_IFREG:
136 lde.type = LDOT_FILE;
137 break;
138 default:
139 lde.type = LDOT_UNKNOWN;
140 break;
141 }
142 #else
143 switch (namelist[i]->d_type) {
144 case DT_BLK:
145 lde.type = LDOT_BLOCK;
146 break;
147 case DT_CHR:
148 lde.type = LDOT_CHAR;
149 break;
150 case DT_DIR:
151 lde.type = LDOT_DIR;
152 break;
153 case DT_FIFO:
154 lde.type = LDOT_FIFO;
155 break;
156 case DT_LNK:
157 lde.type = LDOT_LINK;
158 break;
159 case DT_REG:
160 lde.type = LDOT_FILE;
161 break;
162 case DT_SOCK:
163 lde.type = LDOTT_SOCKET;
164 break;
165 default:
166 lde.type = LDOT_UNKNOWN;
167 break;
168 }
169 #endif
170 if (cb(dirpath, user, &lde)) {
171 while (i++ < n)
172 free(namelist[i]);
173 goto bail;
174 }
175 skip:
176 free(namelist[i]);
177 }
178
179 ret = 0;
180
181 bail:
182 free(namelist);
183
184 return ret;
185 }
186
187 #else
188 #error "If you want lws_dir on windows, you need libuv"
189 #endif
190 #endif
191