[mod_magnet] lighty.c.readdir

lighty.c.readdir           dir walk

Note: the "lighty.c.*" namespace is EXPERIMENTAL / UNSTABLE
In the future, these may be removed, altered, or moved to a different
namespace.
personal/stbuehler/tests-path
Glenn Strauss 2021-08-13 08:21:09 -04:00
parent ed94ae88e8
commit 3ddf457560
1 changed files with 70 additions and 1 deletions

View File

@ -22,6 +22,7 @@
#include "stat_cache.h"
#include "status_counter.h"
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
@ -240,6 +241,72 @@ static int magnet_pairs(lua_State *L) {
}
#endif
/* XXX: mystery why dir walk (readdir) is not already part of lua io liolib.c */
#ifndef _D_EXACT_NAMLEN
#ifdef _DIRENT_HAVE_D_NAMLEN
#define _D_EXACT_NAMLEN(d) ((d)->d_namlen)
#else
#define _D_EXACT_NAMLEN(d) (strlen ((d)->d_name))
#endif
#endif
static int magnet_readdir_iter(lua_State *L) {
DIR ** const d = (DIR **)lua_touserdata(L, lua_upvalueindex(1));
if (NULL == *d) return 0;
/* readdir() and skip over "." and ".." */
struct dirent *de;
const char *n;
do {
de = readdir(*d);
} while (de && (n = de->d_name)[0] == '.'
&& (n[1] == '\0' || (n[1] == '.' && n[2] == '\0')));
if (de) {
lua_pushlstring(L, de->d_name, _D_EXACT_NAMLEN(de));
return 1;
}
else { /* EOF */
closedir(*d);
*d = NULL;
return 0;
}
}
static int magnet_readdir_gc(lua_State *L) {
/*DIR ** const d = ((DIR **)luaL_checkudata(L, 1, "lighty.DIR"));*/
DIR ** const d = lua_touserdata(L, 1);
if (*d) closedir(*d);
return 0;
}
static void magnet_readdir_metatable(lua_State * const L) {
if (luaL_newmetatable(L, "lighty.DIR")) { /* (sp += 1) */
lua_pushcclosure(L, magnet_readdir_gc, 0); /* (sp += 1) */
lua_setfield(L, -2, "__gc"); /* (sp -= 1) */
lua_pushboolean(L, 0); /* (sp += 1) */
lua_setfield(L, -2, "__metatable"); /* protect metatable (sp -= 1) */
}
}
static int magnet_readdir(lua_State *L) {
const char * const s = luaL_checkstring(L, 1);
DIR * const d = opendir(s);
if (d) {
DIR ** const dp = (DIR **)lua_newuserdata(L, sizeof(DIR *));
*dp = d;
magnet_readdir_metatable(L);
lua_setmetatable(L, -2);
lua_pushcclosure(L, magnet_readdir_iter, 1);
}
else
lua_pushnil(L);
return 1;
}
static int magnet_newindex_readonly(lua_State *L) {
lua_pushliteral(L, "lua table is read-only");
return lua_error(L);
@ -1878,7 +1945,8 @@ static void magnet_init_lighty_table(lua_State * const L) {
magnet_mainenv_metatable(L); /* init table for mem locality (sp += 1) */
magnet_stat_metatable(L); /* init table for mem locality (sp += 1) */
lua_pop(L, 2); /* pop mainenv,stat metatables (sp -= 2) */
magnet_readdir_metatable(L); /* init table for mem locality (sp += 1) */
lua_pop(L, 3); /* pop init'd metatables (sp -= 3) */
/* lighty table
*
@ -2044,6 +2112,7 @@ static void magnet_init_lighty_table(lua_State * const L) {
,{ "urlenc_normalize", magnet_urlenc_normalize }/* url-enc normalization */
,{ "fspath_simplify", magnet_fspath_simplify } /* simplify fspath */
,{ "cookie_tokens", magnet_cookie_tokens } /* parse cookie tokens */
,{ "readdir", magnet_readdir } /* dir walk */
,{ NULL, NULL }
};