You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

191 lines
4.0 KiB

/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#if !defined(NO_GNU_SOURCE_THIS_TIME)
#define NO_GNU_SOURCE_THIS_TIME
#endif
#if !defined(_DARWIN_C_SOURCE)
#define _DARWIN_C_SOURCE
#endif
#include <libwebsockets.h>
#include "private-lib-core.h"
#include <string.h>
#include <stdio.h>
#if defined(LWS_WITH_LIBUV) && UV_VERSION_MAJOR > 0
int
lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb)
{
struct lws_dir_entry lde;
uv_dirent_t dent;
uv_fs_t req;
int ret = 1, ir;
uv_loop_t loop;
ir = uv_loop_init(&loop);
if (ir) {
lwsl_err("%s: loop init failed %d\n", __func__, ir);
return 1;
}
ir = uv_fs_scandir(&loop, &req, dirpath, 0, NULL);
if (ir < 0) {
lwsl_err("Scandir on %s failed, errno %d\n", dirpath, LWS_ERRNO);
ret = 2;
goto bail;
}
while (uv_fs_scandir_next(&req, &dent) != UV_EOF) {
lde.name = dent.name;
lde.type = (int)dent.type;
if (cb(dirpath, user, &lde))
goto bail1;
}
ret = 0;
bail1:
uv_fs_req_cleanup(&req);
bail:
while (uv_loop_close(&loop))
;
return ret;
}
#else
#if !defined(_WIN32) && !defined(LWS_PLAT_FREERTOS)
#include <dirent.h>
static int filter(const struct dirent *ent)
{
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
return 0;
return 1;
}
int
lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb)
{
struct lws_dir_entry lde;
struct dirent **namelist;
int n, i, ret = 1;
n = scandir((char *)dirpath, &namelist, filter, alphasort);
if (n < 0) {
lwsl_err("Scandir on '%s' failed, errno %d\n", dirpath, LWS_ERRNO);
return 1;
}
for (i = 0; i < n; i++) {
if (strchr(namelist[i]->d_name, '~'))
goto skip;
lde.name = namelist[i]->d_name;
/*
* some filesystems don't report this (ZFS) and tell that
* files are LDOT_UNKNOWN
*/
#if defined(__sun)
struct stat s;
stat(namelist[i]->d_name, &s);
switch (s.st_mode) {
case S_IFBLK:
lde.type = LDOT_BLOCK;
break;
case S_IFCHR:
lde.type = LDOT_CHAR;
break;
case S_IFDIR:
lde.type = LDOT_DIR;
break;
case S_IFIFO:
lde.type = LDOT_FIFO;
break;
case S_IFLNK:
lde.type = LDOT_LINK;
break;
case S_IFREG:
lde.type = LDOT_FILE;
break;
default:
lde.type = LDOT_UNKNOWN;
break;
}
#else
switch (namelist[i]->d_type) {
case DT_BLK:
lde.type = LDOT_BLOCK;
break;
case DT_CHR:
lde.type = LDOT_CHAR;
break;
case DT_DIR:
lde.type = LDOT_DIR;
break;
case DT_FIFO:
lde.type = LDOT_FIFO;
break;
case DT_LNK:
lde.type = LDOT_LINK;
break;
case DT_REG:
lde.type = LDOT_FILE;
break;
case DT_SOCK:
lde.type = LDOTT_SOCKET;
break;
default:
lde.type = LDOT_UNKNOWN;
break;
}
#endif
if (cb(dirpath, user, &lde)) {
while (i++ < n)
free(namelist[i]);
goto bail;
}
skip:
free(namelist[i]);
}
ret = 0;
bail:
free(namelist);
return ret;
}
#else
#error "If you want lws_dir on windows, you need libuv"
#endif
#endif