1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

lws_dir: add rm -rf and glob filter callbacks

Bring over two general-purpose callbacks for lws_dir from Sai
This commit is contained in:
Andy Green 2020-05-01 12:56:20 +01:00
parent cb0ea63ef1
commit cced12822b
2 changed files with 143 additions and 44 deletions

View file

@ -577,6 +577,53 @@ lws_dir_callback_function(const char *dirpath, void *user,
*/
LWS_VISIBLE LWS_EXTERN int
lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb);
/**
* lws_dir_rm_rf_cb() - callback for lws_dir that performs recursive rm -rf
*
* \param dirpath: directory we are at in lws_dir
* \param user: ignored
* \param lde: lws_dir info on the file or directory we are at
*
* This is a readymade rm -rf callback for use with lws_dir. It recursively
* removes everything below the starting dir and then the starting dir itself.
* Works on linux, OSX and Windows at least.
*/
LWS_VISIBLE LWS_EXTERN int
lws_dir_rm_rf_cb(const char *dirpath, void *user, struct lws_dir_entry *lde);
/*
* We pass every file in the base dir through a filter, and call back on the
* ones that match. Directories are ignored.
*
* The original path filter string may look like, eg, "sai-*.deb" or "*.txt"
*/
typedef int (*lws_dir_glob_cb_t)(void *data, const char *path);
typedef struct lws_dir_glob {
const char *filter;
lws_dir_glob_cb_t cb;
void *user;
} lws_dir_glob_t;
/**
* lws_dir_glob_cb() - callback for lws_dir that performs filename globbing
*
* \param dirpath: directory we are at in lws_dir
* \param user: pointer to your prepared lws_dir_glob_cb_t
* \param lde: lws_dir info on the file or directory we are at
*
* \p user is prepared with an `lws_dir_glob_t` containing a callback for paths
* that pass the filtering, a user pointer to pass to that callback, and a
* glob string like "*.txt". It may not contain directories, the lws_dir musr
* be started at the correct dir.
*
* Only the base path passed to lws_dir is scanned, it does not look in subdirs.
*/
LWS_VISIBLE LWS_EXTERN int
lws_dir_glob_cb(const char *dirpath, void *user, struct lws_dir_entry *lde);
#endif
/**

View file

@ -34,52 +34,24 @@
#include <string.h>
#include <stdio.h>
#include <sys/stat.h>
#if defined(WIN32)
#include <direct.h>
#define read _read
#define open _open
#define close _close
#define write _write
#define mkdir(x,y) _mkdir(x)
#define rmdir _rmdir
#define unlink _unlink
#define HAVE_STRUCT_TIMESPEC
#if defined(pid_t)
#undef pid_t
#endif
#endif /* win32 */
#define COMBO_SIZEOF 256
#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(LWS_PLAT_FREERTOS)
#if defined(WIN32)
@ -232,5 +204,85 @@ bail:
return ret;
}
/*
* Check filename against one globby filter
*
* We can support things like "*.rpm"
*/
static int
lws_dir_glob_check(const char *nm, const char *filt)
{
while (*nm) {
if (*filt == '*') {
if (!strcmp(nm, filt + 1))
return 1;
} else {
if (*nm != *filt)
return 0;
filt++;
}
nm++;
}
return 0;
}
/*
* We get passed a single filter string, like "*.txt" or "mydir/\*.rpm" or so.
*/
int
lws_dir_glob_cb(const char *dirpath, void *user, struct lws_dir_entry *lde)
{
lws_dir_glob_t *filter = (lws_dir_glob_t*)user;
char path[384];
if (!strcmp(lde->name, ".") || !strcmp(lde->name, ".."))
return 0;
if (lde->type == LDOT_DIR)
return 0;
if (lws_dir_glob_check(lde->name, filter->filter)) {
lws_snprintf(path, sizeof(path), "%s%c%s", dirpath, csep,
lde->name);
filter->cb(filter->user, path);
}
return 0;
}
int
lws_dir_rm_rf_cb(const char *dirpath, void *user, struct lws_dir_entry *lde)
{
char path[384];
if (!strcmp(lde->name, ".") || !strcmp(lde->name, ".."))
return 0;
lws_snprintf(path, sizeof(path), "%s%c%s", dirpath, csep, lde->name);
if (lde->type == LDOT_DIR) {
lws_dir(path, NULL, lws_dir_rm_rf_cb);
if (rmdir(path))
lwsl_warn("%s: rmdir %s failed %d\n", __func__, path, errno);
} else {
if (unlink(path)) {
#if defined(WIN32)
SetFileAttributesA(path, FILE_ATTRIBUTE_NORMAL);
if (unlink(path))
#else
if (rmdir(path))
#endif
lwsl_warn("%s: unlink %s failed %d (type %d)\n",
__func__, path, errno, lde->type);
}
}
return 0;
}
#endif