commit e01979620025666633250b3e2d545fe59c629f73 Author: Vladimír Čunát Date: Fri Nov 13 14:16:32 2020 +0100 fix map() command on 32-bit platforms; regressed in 5.2.0 LuaJIT FFI was using opendir() (etc.) variants with 32-bit inodes but the C parts was using them as 64-bit inode variants. Consequently the `struct dirent` layout didn't match and we were getting filenames shifted by eight bytes. Now the whole dir-listing lua function is written in C. diff --git a/.luacheckrc b/.luacheckrc index 0cf0b884..67bc18f6 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -20,6 +20,7 @@ new_read_globals = { 'user', 'verbose', 'worker', + 'kluautil_list_dir', -- Sandbox declarations 'kB', 'MB', diff --git a/NEWS b/NEWS index 2eae3082..9d8cde99 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ Knot Resolver X.Y.X (yyyy-mm-dd) ================================ +Bugfixes +-------- +- fix map() command on 32-bit platforms; regressed in 5.2.0 (!1093) + Knot Resolver 5.2.0 (2020-11-11) ================================ diff --git a/daemon/bindings/impl.c b/daemon/bindings/impl.c index d10f4525..d9ad0774 100644 --- a/daemon/bindings/impl.c +++ b/daemon/bindings/impl.c @@ -2,6 +2,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +#include #include #include #include @@ -29,6 +30,29 @@ const char * lua_table_checkindices(lua_State *L, const char *keys[]) return NULL; } +/** Return table listing filenames in a given directory (ls -A). */ +static int kluautil_list_dir(lua_State *L) +{ + lua_newtable(L); // empty table even on errors + + const char *path = lua_tolstring(L, 1, NULL); + if (!path) return 1; + DIR *dir = opendir(path); + if (!dir) return 1; + + struct dirent *entry; + int lua_i = 1; + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) { + lua_pushstring(L, entry->d_name); + lua_rawseti(L, -2, lua_i++); + } + } + + closedir(dir); + return 1; +} + /* Each of these just creates the correspondingly named lua table of functions. */ int kr_bindings_cache (lua_State *L); /* ./cache.c */ @@ -44,6 +68,9 @@ void kr_bindings_register(lua_State *L) kr_bindings_modules(L); kr_bindings_net(L); kr_bindings_worker(L); + + /* Finally some lua utils *written in C*, not really a binding. */ + lua_register(L, "kluautil_list_dir", kluautil_list_dir); } void lua_error_p(lua_State *L, const char *fmt, ...) diff --git a/daemon/lua/kluautil.lua b/daemon/lua/kluautil.lua index 57912e7b..e73e952c 100644 --- a/daemon/lua/kluautil.lua +++ b/daemon/lua/kluautil.lua @@ -1,6 +1,5 @@ -- SPDX-License-Identifier: GPL-3.0-or-later -local ffi = require('ffi') local kluautil = {} -- Get length of table @@ -28,14 +27,6 @@ function kluautil.kr_table_unpack(tab) return unpack(tab, 1, tab.n) end -ffi.cdef([[ - typedef struct __dirstream DIR; - DIR *opendir(const char *name); - struct dirent *readdir(DIR *dirp); - int closedir(DIR *dirp); - char *strerror(int errnum); -]]) - -- Fetch over HTTPS function kluautil.kr_https_fetch(url, out_file, ca_file) local http_ok, http_request = pcall(require, 'http.request') @@ -88,26 +79,6 @@ function kluautil.kr_https_fetch(url, out_file, ca_file) return true end --- List directory -function kluautil.list_dir (path) - local results = {} - local dir = ffi.C.opendir(path) - if dir == nil then - return results - end - - local entry = ffi.C.readdir(dir) - while entry ~= nil do - local entry_name = ffi.string(ffi.C.kr_dirent_name(entry)) - if entry_name ~= '.' and entry_name ~= '..' then - table.insert(results, entry_name) - end - entry = ffi.C.readdir(dir) - end - - ffi.C.closedir(dir) - - return results -end +kluautil.list_dir = kluautil_list_dir return kluautil