Index: nmap/nse_fs.cc =================================================================== --- nmap/nse_fs.cc (revision 17662) +++ nmap/nse_fs.cc (working copy) @@ -1,3 +1,23 @@ +/* LuaFileSystem library + * + * by Roberto Ierusalimschy, Andre Carregal and Tomas Guisasola + * as part of the Kepler Project. + * LuaFileSystem is currently maintained by Fabio Mascarenhas. + * + * LuaFileSystem is a Lua library developed to complement the set + * of functions related to file systems offered by the standard + * Lua distribution. + * LuaFileSystem offers a portable way to access the underlying + * directory structure and file attributes. + * + * LuaFileSystem is free software and uses the same license as Lua 5.1. + * + * the most recent copy can be found at + * http://www.keplerproject.org/luafilesystem/ + * + * Note: this is a modified version of the LuaFileSystem for the + * Nmap project http://nmap.org + **/ extern "C" { #include "lua.h" @@ -18,10 +38,26 @@ #include "nmap_error.h" #include "NmapOps.h" +#define DIR_METATABLE "dir" + #ifndef MAXPATHLEN -# define MAXPATHLEN 2048 +# define MAXPATHLEN 2048 #endif +#ifndef MAX_DIR_LENGTH +# define MAX_DIR_LENGTH 1024 +#endif + +typedef struct dir_data { + int closed; +#ifdef WIN32 + long hFile; + char pattern[MAX_DIR_LENGTH+1]; +#else + DIR *dir; +#endif +} dir_data; + extern NmapOps o; static bool filename_is_absolute(const char *file) { @@ -39,7 +75,7 @@ * The portability comes at the price of reduced * flexibility. */ -int nse_check_extension (const char* ext, const char* path) +static int nse_check_extension (const char* ext, const char* path) { int pathlen = strlen(path); int extlen = strlen(ext); @@ -75,8 +111,98 @@ return nse_fetchfile(path, path_len, file); } +/* +** Directory iterator +*/ +static int dir_iter (lua_State *L) { #ifdef WIN32 + struct _finddata_t c_file; +#else + struct dirent *entry; +#endif + dir_data *d = (dir_data *)luaL_checkudata(L, 1, DIR_METATABLE); + luaL_argcheck(L, !d->closed, 1, "closed directory"); +#ifdef WIN32 + if (d->hFile == 0L) { /* first entry */ + if ((d->hFile = _findfirst(d->pattern, &c_file)) == -1L) { + error("%s: No files in '%s\\*'", SCRIPT_ENGINE, dirname); + return 0; + } else { + lua_pushstring(L, c_file.name); + return 1; + } + } else { /* next entry */ + if (_findnext(d->hFile, &c_file) == -1L) { + /* no more entries => close directory */ + _findflose(d->hFile); + d->closed = 1; + return 0; + } else { + lua_pushstring(L, c_file.name); + return 1; + } + } +#else + if ((entry = readdir(d->dir)) != NULL) { + lua_pushstring(L, entry->d_name); + return 1; + } else { + /* no more entries => close directory */ + closedir(d->dir); + d->closed = 1; + return 0; + } +#endif +} +/* +** Closes directory iterators +*/ +static int dir_close (lua_State *L) { + dir_data *d = (dir_data *)lua_touserdata(L, 1); +#ifdef WIN32 + if (!d->closed && d->hFile) { + _findclose(d->hFile); + d->closed = 1; + } +#else + if (!d->closed && d->dir) { + closedir(d->dir); + d->closed = 1; + } +#endif + return 0; +} + +/* +** Factory of directory iterators +*/ +static int dir_iter_factory (lua_State *L) { + const char *dirname = luaL_checkstring(L, 1); + dir_data *d; + lua_pushcfunction(L, dir_iter); + d = (dir_data *)lua_newuserdata(L, sizeof(dir_data)); + d->closed = 0; +#ifdef WIN32 + d->hFile = 0L; + luaL_getmetatable(L, DIR_METATABLE); + lua_setmetatable(L, -2); + if (strlen(dirname) > MAX_DIR_LENGTH) + luaL_error(L, "%s: Path too long '%s'.", SCRIPT_ENGINE, dirname); + else + Snprintf(d->pattern, MAX_DIR_LENGTH, "%s/*", dirname); +#else + luaL_getmetatable(L, DIR_METATABLE); + lua_setmetatable(L, -2); + d->dir = opendir(dirname); + if (d->dir == NULL) + luaL_error(L, "%s: Could not open directory '%s'.", SCRIPT_ENGINE, dirname); +#endif + return 2; +} + +#ifdef WIN32 + int nse_scandir (lua_State *L) { HANDLE dir; WIN32_FIND_DATA entry; @@ -196,3 +322,32 @@ } #endif + +static int dir_create_meta (lua_State *L) { + luaL_newmetatable(L, DIR_METATABLE); + lua_pushstring(L, "__index"); + lua_newtable(L); + lua_pushstring(L, "next"); + lua_pushcfunction(L, dir_iter); + lua_settable(L, -3); + lua_pushstring (L, "close"); + lua_pushcfunction (L, dir_close); + lua_settable(L, -3); + lua_settable (L, -3); + lua_pushstring (L, "__gc"); + lua_pushcfunction (L, dir_close); + lua_settable (L, -3); + return 1; +} + +static const struct luaL_reg fslib[] = { +//{"attributes", file_info}, + {"dir", dir_iter_factory}, + {NULL, NULL}, +}; + +LUALIB_API int luaopen_fslib(lua_State *L) { + dir_create_meta(L); + luaL_register(L, NSE_FSLIBNAME, fslib); + return 1; +} Index: nmap/nse_main.cc =================================================================== --- nmap/nse_main.cc (revision 17662) +++ nmap/nse_main.cc (working copy) @@ -284,6 +284,7 @@ {NSE_NMAPLIBNAME, luaopen_nmap}, // nmap bindings {NSE_BINLIBNAME, luaopen_binlib}, {BITLIBNAME, luaopen_bit}, // bit library + {NSE_FSLIBNAME, luaopen_fslib}, // fs library #ifdef HAVE_OPENSSL {OPENSSLLIBNAME, luaopen_openssl}, // openssl bindings #endif Index: nmap/nse_fs.h =================================================================== --- nmap/nse_fs.h (revision 17662) +++ nmap/nse_fs.h (working copy) @@ -1,7 +1,7 @@ #ifndef NSE_FS #define NSE_FS -int nse_check_extension (const char* ext, const char* path); +#define NSE_FSLIBNAME "fs" int nse_fetchfile(char *path, size_t path_len, const char *file); @@ -9,6 +9,8 @@ int nse_scandir (lua_State *L); +LUALIB_API int luaopen_fslib(lua_State *L); + #define NSE_FILES 1 #define NSE_DIRS 2 Index: nmap/nse_main.lua =================================================================== --- nmap/nse_main.lua (revision 17662) +++ nmap/nse_main.lua (working copy) @@ -83,6 +83,7 @@ local sort = table.sort; local nmap = require "nmap"; +local fs = require "fs"; local cnse, rules = ...; -- The NSE C library and Script Rules @@ -469,10 +470,13 @@ print_debug(2, "Script %s was selected by name.", script.filename); files_loaded[path] = true; elseif t == "directory" then - for i, file in ipairs(cnse.dump_dir(path)) do - if not files_loaded[file] then - chosen_scripts[#chosen_scripts+1] = Script.new(file); - files_loaded[file] = true; + for file in fs.dir(path) do + if file ~= "." and file ~= ".." and find(file, "%.nse$") then + local f = path .."/".. file + if not files_loaded[f] then + chosen_scripts[#chosen_scripts+1] = Script.new(f); + files_loaded[f] = true; + end end end end