Add various functions for Lua directory handling and path info

This adds new functions to get plugins path info, find out if a directory
exists, make a new one, remove one, etc. It also creates a file environment
for user-supplied Lua scripts, to prevent global variable contamination as
well as supply the script-specific file name.  Some other minor cleanup was
done as I found them.

A new testsuite was added to test the existing and new directory functions.

Change-Id: I19bd587b5e8a73d89b8521af73670e023314fb33
Reviewed-on: https://code.wireshark.org/review/832
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Hadriel Kaplan 2014-03-26 02:24:51 -04:00 committed by Anders Broman
parent da1af6e549
commit 8c2bb80574
16 changed files with 688 additions and 197 deletions

View File

@ -310,6 +310,7 @@ set(WSLUA_MODULES
${CMAKE_SOURCE_DIR}/epan/wslua/wslua_tree.c
${CMAKE_SOURCE_DIR}/epan/wslua/wslua_tvb.c
${CMAKE_SOURCE_DIR}/epan/wslua/wslua_file.c
${CMAKE_SOURCE_DIR}/epan/wslua/wslua_dir.c
${CMAKE_SOURCE_DIR}/epan/wslua/wslua_util.c
${CMAKE_SOURCE_DIR}/epan/wslua/wslua_struct.c
)

View File

@ -255,4 +255,5 @@ WSLUA_MODULES = \
../epan/wslua/wslua_tree.c \
../epan/wslua/wslua_tvb.c \
../epan/wslua/wslua_file.c \
../epan/wslua/wslua_dir.c \
../epan/wslua/wslua_util.c

View File

@ -347,6 +347,7 @@ WSLua Reference Manual
<!ENTITY WsLuaTree SYSTEM "wsluarm_src/wslua_tree.xml">
<!ENTITY WsLuaTvb SYSTEM "wsluarm_src/wslua_tvb.xml">
<!ENTITY WsLuaFile SYSTEM "wsluarm_src/wslua_file.xml">
<!ENTITY WsLuaDir SYSTEM "wsluarm_src/wslua_dir.xml">
<!ENTITY WsLuaUtility SYSTEM "wsluarm_src/wslua_util.xml">
<!ENTITY WsLuaInt64 SYSTEM "wsluarm_src/wslua_int64.xml">
<!ENTITY WsLuaStruct SYSTEM "wsluarm_src/wslua_struct.xml">

View File

@ -169,6 +169,7 @@ register_menu("Test/Packets", menuable_tap, MENU_TOOLS_UNSORTED)</programlisting
&WsLuaTree;
&WsLuaTvb;
&WsLuaFile;
&WsLuaDir;
&WsLuaUtility;
&WsLuaInt64;
&WsLuaStruct;

View File

@ -35,6 +35,7 @@ set(WSLUA_MODULES
${CMAKE_CURRENT_SOURCE_DIR}/wslua/wslua_pinfo.c
${CMAKE_CURRENT_SOURCE_DIR}/wslua/wslua_listener.c
${CMAKE_CURRENT_SOURCE_DIR}/wslua/wslua_gui.c
${CMAKE_CURRENT_SOURCE_DIR}/wslua/wslua_dir.c
${CMAKE_CURRENT_SOURCE_DIR}/wslua/wslua_util.c
${CMAKE_CURRENT_SOURCE_DIR}/wslua/wslua_field.c
${CMAKE_CURRENT_SOURCE_DIR}/wslua/wslua_file.c

View File

@ -41,6 +41,7 @@ wslua_modules = \
$(srcdir)/wslua_pinfo.c \
$(srcdir)/wslua_listener.c \
$(srcdir)/wslua_gui.c \
$(srcdir)/wslua_dir.c \
$(srcdir)/wslua_util.c \
$(srcdir)/wslua_field.c \
$(srcdir)/wslua_file.c \
@ -144,4 +145,5 @@ checkapi:
wslua_tree.c \
wslua_tree.c \
wslua_tvb.c \
wslua_dir.c \
wslua_util.c

View File

@ -26,6 +26,7 @@ MODULES = \
wslua_pinfo.c \
wslua_listener.c \
wslua_gui.c \
wslua_dir.c \
wslua_util.c \
wslua_field.c \
wslua_file.c \
@ -48,6 +49,7 @@ OBJECTS= \
wslua_pinfo.obj \
wslua_listener.obj \
wslua_gui.obj \
wslua_dir.obj \
wslua_util.obj \
wslua_field.obj \
wslua_file.obj \

View File

@ -411,10 +411,42 @@ static int lua_script_push_args(const int script_num) {
return count;
}
#define FILE_NAME_KEY "__FILE__"
#define DIR_NAME_KEY "__DIR__"
/* assumes a loaded chunk's function is on top of stack */
static void set_file_environment(const gchar* filename, const gchar* dirname) {
lua_newtable(L); /* environment for script (index 3) */
lua_pushstring(L, filename); /* tell the script about its filename */
lua_setfield(L, -2, FILE_NAME_KEY); /* make it accessible at __FILE__ */
lua_pushstring(L, dirname); /* tell the script about its dirname */
lua_setfield(L, -2, DIR_NAME_KEY); /* make it accessible at __DIR__ */
lua_newtable(L); /* metatable */
#if LUA_VERSION_NUM >= 502
lua_pushglobaltable(L);
#else
lua_pushvalue(L, LUA_GLOBALSINDEX);
#endif
lua_setfield(L, -2, "__index"); /* __index points to global environment */
lua_setmetatable(L, -2); /* pop metatable, set it as metatable of environment */
#if LUA_VERSION_NUM >= 502
lua_setupvalue(L, -2, 1); /* pop environment and assign it to upvalue 1 */
#else
lua_setfenv(L, -2); /* pop environment and set it as the func's environment */
#endif
}
/* If file_count > 0 then it's a command-line-added user script, and the count
* represents which user script it is (first=1, second=2, etc.).
* If dirname != NULL, then it's a user script and the dirname will get put in a file environment
* If dirname == NULL then it's a wireshark script and no file environment is created
*/
static gboolean lua_load_script(const gchar* filename, const int file_count) {
static gboolean lua_load_script(const gchar* filename, const gchar* dirname, const int file_count) {
FILE* file;
int error;
int numargs = 0;
@ -433,8 +465,12 @@ static gboolean lua_load_script(const gchar* filename, const int file_count) {
#else
error = lua_load(L,getF,file,filename);
#endif
switch (error) {
case 0:
if (dirname) {
set_file_environment(filename, dirname);
}
if (file_count > 0) {
numargs = lua_script_push_args(file_count);
}
@ -471,7 +507,9 @@ static int wslua_panic(lua_State* LS) {
return 0; /* keep gcc happy */
}
static int lua_load_plugins(const char *dirname, register_cb cb, gpointer client_data, gboolean count_only) {
static int lua_load_plugins(const char *dirname, register_cb cb, gpointer client_data,
gboolean count_only, const gboolean is_user)
{
WS_DIR *dir; /* scanned directory */
WS_DIRENT *file; /* current file */
gchar *filename, *dot;
@ -487,7 +525,7 @@ static int lua_load_plugins(const char *dirname, register_cb cb, gpointer client
filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dirname, name);
if (test_for_directory(filename) == EISDIR) {
plugins_counter += lua_load_plugins(filename, cb, client_data, count_only);
plugins_counter += lua_load_plugins(filename, cb, client_data, count_only, is_user);
g_free(filename);
continue;
}
@ -509,7 +547,7 @@ static int lua_load_plugins(const char *dirname, register_cb cb, gpointer client
if (!count_only) {
if (cb)
(*cb)(RA_LUA_PLUGINS, name, client_data);
if (lua_load_script(filename,0)) {
if (lua_load_script(filename, is_user ? dirname : NULL, 0)) {
wslua_add_plugin(g_strdup(name), g_strdup(""), g_strdup(filename));
}
}
@ -528,7 +566,7 @@ int wslua_count_plugins(void) {
int plugins_counter;
/* count global scripts */
plugins_counter = lua_load_plugins(get_plugin_dir(), NULL, NULL, TRUE);
plugins_counter = lua_load_plugins(get_plugin_dir(), NULL, NULL, TRUE, FALSE);
/* count users init.lua */
filename = get_persconffile_path("init.lua", FALSE);
@ -539,7 +577,7 @@ int wslua_count_plugins(void) {
/* count user scripts */
filename = get_plugins_pers_dir();
plugins_counter += lua_load_plugins(filename, NULL, NULL, TRUE);
plugins_counter += lua_load_plugins(filename, NULL, NULL, TRUE, TRUE);
g_free(filename);
/* count scripts from command line */
@ -734,7 +772,7 @@ int wslua_init(register_cb cb, gpointer client_data) {
}
if (( file_exists(filename))) {
lua_load_script(filename,0);
lua_load_script(filename, NULL, 0);
}
g_free(filename);
@ -752,7 +790,7 @@ int wslua_init(register_cb cb, gpointer client_data) {
lua_pop(L,1); /* pop the getglobal result */
/* load global scripts */
lua_load_plugins(get_plugin_dir(), cb, client_data, FALSE);
lua_load_plugins(get_plugin_dir(), cb, client_data, FALSE, FALSE);
/* check whether we should run other scripts even if running superuser */
lua_getglobal(L,"run_user_scripts_when_superuser");
@ -769,21 +807,26 @@ int wslua_init(register_cb cb, gpointer client_data) {
if ((file_exists(filename))) {
if (cb)
(*cb)(RA_LUA_PLUGINS, get_basename(filename), client_data);
lua_load_script(filename,0);
lua_load_script(filename, NULL, 0);
}
g_free(filename);
/* load user scripts */
filename = get_plugins_pers_dir();
lua_load_plugins(filename, cb, client_data, FALSE);
lua_load_plugins(filename, cb, client_data, FALSE, TRUE);
g_free(filename);
/* load scripts from command line */
while((script_filename = ex_opt_get_next("lua_script"))) {
char* dirname = g_strdup(script_filename);
char* dname = get_dirname(dirname);
if (cb)
(*cb)(RA_LUA_PLUGINS, get_basename(script_filename), client_data);
lua_load_script(script_filename,file_count);
lua_load_script(script_filename, dname ? dname : "", file_count);
file_count++;
g_free(dirname);
}
}

View File

@ -94,8 +94,13 @@ end
-- other useful constants
GUI_ENABLED = gui_enabled()
DATA_DIR = datafile_path()
USER_DIR = persconffile_path()
DATA_DIR = Dir.global_config_path()
USER_DIR = Dir.personal_config_path()
-- deprecated function names
datafile_path = Dir.global_config_path
persconffile_path = Dir.personal_config_path
dofile(DATA_DIR.."console.lua")
--dofile(DATA_DIR.."dtd_gen.lua")

View File

@ -714,6 +714,8 @@ extern int wslua_set_tap_enums(lua_State* L);
extern int wslua_is_field_available(lua_State* L, const char* field_abbr);
extern char* wslua_get_actual_filename(const char* fname);
extern int wslua_bin2hex(lua_State* L, const guint8* data, const guint len, const gboolean lowercase, const gchar* sep);
extern int wslua_hex2bin(lua_State* L, const char* data, const guint len, const gchar* sep);
extern int luaopen_rex_glib(lua_State *L);

383
epan/wslua/wslua_dir.c Normal file
View File

@ -0,0 +1,383 @@
/*
* wslua_dir.c
*
* (c) 2014, Hadriel Kaplan <hadrielk at yahoo dot com>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
/* WSLUA_MODULE Dir Directory handling functions */
#include "wslua.h"
#include <wsutil/file_util.h>
WSLUA_CLASS_DEFINE(Dir,FAIL_ON_NULL("Dir"),NOP); /* A Directory object, as well as associated functions. */
WSLUA_CONSTRUCTOR Dir_make(lua_State* L) {
/* Creates a directory.
The created directory is set for permission mode 0755 (octal), meaning it is
read+write+execute by owner, but only read+execute by group and others.
IF the directory was created successfully, a boolean `true` is returned.
If the directory cannot be made because it already exists, `false` is returned.
If the directory cannot be made because an error occurred, `nil` is returned.
@since 1.11.3
*/
#define WSLUA_ARG_Dir_make_NAME 1 /* The name of the directory, possibly including path. */
const char *dir_path = luaL_checkstring(L, WSLUA_ARG_Dir_make_NAME);
ws_statb64 s_buf;
int ret;
if (ws_stat64(dir_path, &s_buf) != 0 && errno == ENOENT) {
ret = ws_mkdir(dir_path, 0755);
if (ret == -1) {
lua_pushnil(L);
} else {
lua_pushboolean(L, 1);
}
} else {
lua_pushboolean(L, 0);
}
WSLUA_RETURN(1); /* Boolean `true` on success, `false` if already exists, `nil` on error. */
}
WSLUA_CONSTRUCTOR Dir_exists(lua_State* L) {
/* Returns true if the given directory name exists.
If the directory exists, a boolean `true` is returned.
If the path is a file instead, `false` is returned.
If the path does not exist or an error occurred, `nil` is returned.
@since 1.11.3
*/
#define WSLUA_ARG_Dir_exists_NAME 1 /* The name of the directory, possibly including path. */
const char *dir_path = luaL_checkstring(L, WSLUA_ARG_Dir_exists_NAME);
int ret;
if ((ret = test_for_directory (dir_path)) == EISDIR) {
lua_pushboolean(L, 1);
} else {
if (ret == 0) {
lua_pushboolean(L, 0);
} else {
lua_pushnil(L);
}
}
WSLUA_RETURN(1); /* Boolean `true` if the directory exists, `false` if it's a file, `nil` on error/not-exist. */
}
WSLUA_CONSTRUCTOR Dir_remove(lua_State* L) {
/* Removes an empty directory.
If the directory was removed successfully, a boolean `true` is returned.
If the directory cannot be removed because it does not exist, `false` is returned.
If the directory cannot be removed because an error occurred, `nil` is returned.
This function only removes empty directories. To remove a directory regardless,
use `Dir.remove_all()`.
@since 1.11.3
*/
#define WSLUA_ARG_Dir_remove_NAME 1 /* The name of the directory, possibly including path. */
const char *dir_path = luaL_checkstring(L, WSLUA_ARG_Dir_remove_NAME);
int ret;
if (test_for_directory (dir_path) == EISDIR) {
ret = ws_remove(dir_path);
if (ret != 0) {
lua_pushnil(L);
} else {
lua_pushboolean(L, 1);
}
} else {
lua_pushboolean(L, 0);
}
WSLUA_RETURN(1); /* Boolean `true` on success, `false` if does not exist, `nil` on error. */
}
static int delete_directory(const char *directory) {
WS_DIR *dir;
WS_DIRENT *file;
gchar *filename;
int ret = 0;
/* delete all contents of directory */
if ((dir = ws_dir_open(directory, 0, NULL)) != NULL) {
while ((file = ws_dir_read_name(dir)) != NULL) {
filename = g_strdup_printf ("%s%s%s", directory, G_DIR_SEPARATOR_S,
ws_dir_get_name(file));
if (test_for_directory(filename) != EISDIR) {
ret = ws_remove(filename);
} else {
/* recurse */
ret = delete_directory (filename);
}
if (ret != 0) {
break;
}
g_free (filename);
}
ws_dir_close(dir);
}
if (ret == 0) {
ret = ws_remove(directory);
}
return ret;
}
WSLUA_CONSTRUCTOR Dir_remove_all(lua_State* L) {
/* Removes an empty or non-empty directory.
If the directory was removed successfully, a boolean `true` is returned.
If the directory cannot be removed because it does not exist, `false` is returned.
If the directory cannot be removed because an error occurred, `nil` is returned.
@since 1.11.3
*/
#define WSLUA_ARG_Dir_remove_all_NAME 1 /* The name of the directory, possibly including path. */
const char *dir_path = luaL_checkstring(L, WSLUA_ARG_Dir_remove_all_NAME);
int ret;
if (test_for_directory (dir_path) == EISDIR) {
ret = delete_directory(dir_path);
if (ret != 0) {
lua_pushnil(L);
} else {
lua_pushboolean(L, 1);
}
} else {
lua_pushboolean(L, 0);
}
WSLUA_RETURN(1); /* Boolean `true` on success, `false` if does not exist, `nil` on error. */
}
WSLUA_CONSTRUCTOR Dir_open(lua_State* L) {
/* Opens a directory and returns a `Dir` object representing the files in the directory.
@code for filename in Dir.open(path) do ... end @endcode
*/
#define WSLUA_ARG_Dir_open_PATHNAME 1 /* The pathname of the directory. */
#define WSLUA_OPTARG_Dir_open_EXTENSION 2 /* If given, only files with this extension will be returned. */
const char* dirname = luaL_checkstring(L,WSLUA_ARG_Dir_open_PATHNAME);
const char* extension = luaL_optstring(L,WSLUA_OPTARG_Dir_open_EXTENSION,NULL);
Dir dir;
char* dirname_clean;
if (!dirname) {
WSLUA_ARG_ERROR(Dir_open,PATHNAME,"must be a string");
return 0;
}
dirname_clean = wslua_get_actual_filename(dirname);
if (!dirname_clean) {
WSLUA_ARG_ERROR(Dir_open,PATHNAME,"directory does not exist");
return 0;
}
if (!test_for_directory(dirname_clean)) {
g_free(dirname_clean);
WSLUA_ARG_ERROR(Dir_open,PATHNAME, "must be a directory");
return 0;
}
dir = (Dir)g_malloc(sizeof(struct _wslua_dir));
dir->dir = g_dir_open(dirname_clean, 0, dir->dummy);
g_free(dirname_clean);
dir->ext = extension ? g_strdup(extension) : NULL;
dir->dummy = (GError **)g_malloc(sizeof(GError *));
*(dir->dummy) = NULL;
if (dir->dir == NULL) {
g_free(dir->dummy);
g_free(dir);
WSLUA_ARG_ERROR(Dir_open,PATHNAME,"could not open directory");
return 0;
}
pushDir(L,dir);
WSLUA_RETURN(1); /* the `Dir` object. */
}
WSLUA_METAMETHOD Dir__call(lua_State* L) {
/* At every invocation will return one file (nil when done). */
Dir dir = checkDir(L,1);
const gchar* file;
const gchar* filename;
const char* ext;
if (!dir->dir) {
return 0;
}
if ( ! ( file = g_dir_read_name(dir->dir ) )) {
g_dir_close(dir->dir);
dir->dir = NULL;
return 0;
}
if ( ! dir->ext ) {
lua_pushstring(L,file);
return 1;
}
do {
filename = file;
/* XXX strstr returns ptr to first match,
this fails ext=".xxx" filename="aaa.xxxz.xxx" */
if ( ( ext = strstr(filename,dir->ext)) && g_str_equal(ext,dir->ext) ) {
lua_pushstring(L,filename);
return 1;
}
} while(( file = g_dir_read_name(dir->dir) ));
g_dir_close(dir->dir);
dir->dir = NULL;
return 0;
}
WSLUA_METHOD Dir_close(lua_State* L) {
/* Closes the directory. */
Dir dir = checkDir(L,1);
if (dir->dir) {
g_dir_close(dir->dir);
dir->dir = NULL;
}
return 0;
}
WSLUA_CONSTRUCTOR Dir_personal_config_path(lua_State* L) {
/* Gets the personal configuration directory path, with filename if supplied.
@since 1.11.3
*/
#define WSLUA_OPTARG_personal_config_path_FILENAME 1 /* A filename. */
const char *fname = luaL_optstring(L, WSLUA_OPTARG_personal_config_path_FILENAME,"");
char* filename = get_persconffile_path(fname,FALSE);
lua_pushstring(L,filename);
g_free(filename);
WSLUA_RETURN(1); /* The full pathname for a file in the personal configuration directory. */
}
WSLUA_CONSTRUCTOR Dir_global_config_path(lua_State* L) {
/* Gets the global configuration directory path, with filename if supplied.
@since 1.11.3
*/
#define WSLUA_OPTARG_global_config_path_FILENAME 1 /* A filename */
const char *fname = luaL_optstring(L, WSLUA_OPTARG_global_config_path_FILENAME,"");
char* filename;
if (running_in_build_directory()) {
/* Running in build directory, set datafile_path to wslua source directory */
filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "epan" G_DIR_SEPARATOR_S "wslua"
G_DIR_SEPARATOR_S "%s", get_datafile_dir(), fname);
} else {
filename = get_datafile_path(fname);
}
lua_pushstring(L,filename);
g_free(filename);
WSLUA_RETURN(1); /* The full pathname for a file in wireshark's configuration directory. */
}
WSLUA_CONSTRUCTOR Dir_personal_plugins_path(lua_State* L) {
/* Gets the personal plugins directory path.
@since 1.11.3
*/
char* filename = get_plugins_pers_dir();
lua_pushstring(L,filename);
g_free(filename);
WSLUA_RETURN(1); /* The pathname for the personal plugins directory. */
}
WSLUA_CONSTRUCTOR Dir_global_plugins_path(lua_State* L) {
/* Gets the global plugins directory path.
@since 1.11.3
*/
lua_pushstring(L, get_plugin_dir());
WSLUA_RETURN(1); /* The pathname for the global plugins directory. */
}
/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
static int Dir__gc(lua_State* L) {
Dir dir = toDir(L,1);
if(!dir) return 0;
if (dir->dir) {
g_dir_close(dir->dir);
}
g_free(dir->dummy);
if (dir->ext) g_free(dir->ext);
g_free(dir);
return 0;
}
WSLUA_METHODS Dir_methods[] = {
WSLUA_CLASS_FNREG(Dir,make),
WSLUA_CLASS_FNREG(Dir,exists),
WSLUA_CLASS_FNREG(Dir,remove),
WSLUA_CLASS_FNREG(Dir,remove_all),
WSLUA_CLASS_FNREG(Dir,open),
WSLUA_CLASS_FNREG(Dir,close),
WSLUA_CLASS_FNREG(Dir,personal_config_path),
WSLUA_CLASS_FNREG(Dir,global_config_path),
WSLUA_CLASS_FNREG(Dir,personal_plugins_path),
WSLUA_CLASS_FNREG(Dir,global_plugins_path),
{ NULL, NULL }
};
WSLUA_META Dir_meta[] = {
WSLUA_CLASS_MTREG(Dir,call),
{ NULL, NULL }
};
int Dir_register(lua_State* L) {
WSLUA_REGISTER_CLASS(Dir);
return 0;
}

View File

@ -938,7 +938,7 @@ WSLUA_ATTRIBUTES CaptureInfo_attributes[] = {
};
WSLUA_META CaptureInfo_meta[] = {
{"__tostring", CaptureInfo__tostring},
WSLUA_CLASS_MTREG(CaptureInfo,tostring),
{ NULL, NULL }
};
@ -1138,7 +1138,7 @@ WSLUA_ATTRIBUTES CaptureInfoConst_attributes[] = {
};
WSLUA_META CaptureInfoConst_meta[] = {
{"__tostring", CaptureInfoConst__tostring},
WSLUA_CLASS_MTREG(CaptureInfoConst,tostring),
{ NULL, NULL }
};
@ -1353,12 +1353,12 @@ WSLUA_ATTRIBUTES FrameInfo_attributes[] = {
};
WSLUA_METHODS FrameInfo_methods[] = {
{"read_data", FrameInfo_read_data},
WSLUA_CLASS_FNREG(FrameInfo,read_data),
{ NULL, NULL }
};
WSLUA_META FrameInfo_meta[] = {
{"__tostring", FrameInfo__tostring},
WSLUA_CLASS_MTREG(FrameInfo,tostring),
{ NULL, NULL }
};
@ -1495,12 +1495,12 @@ WSLUA_ATTRIBUTES FrameInfoConst_attributes[] = {
};
WSLUA_METHODS FrameInfoConst_methods[] = {
{"write_data", FrameInfoConst_write_data},
WSLUA_CLASS_FNREG(FrameInfoConst,write_data),
{ NULL, NULL }
};
WSLUA_META FrameInfoConst_meta[] = {
{"__tostring", FrameInfoConst__tostring},
WSLUA_CLASS_MTREG(FrameInfoConst,tostring),
{ NULL, NULL }
};
@ -2420,12 +2420,12 @@ WSLUA_ATTRIBUTES FileHandler_attributes[] = {
};
WSLUA_METHODS FileHandler_methods[] = {
{"new", FileHandler_new},
WSLUA_CLASS_FNREG(FileHandler,new),
{ NULL, NULL }
};
WSLUA_META FileHandler_meta[] = {
{"__tostring", FileHandler__tostring},
WSLUA_CLASS_MTREG(FileHandler,tostring),
{ NULL, NULL }
};

View File

@ -557,7 +557,7 @@ static int Int64__gc(lua_State* L _U_) {
return 0;
}
static const luaL_Reg Int64_methods[] = {
WSLUA_METHODS Int64_methods[] = {
WSLUA_CLASS_FNREG(Int64,new),
WSLUA_CLASS_FNREG(Int64,max),
WSLUA_CLASS_FNREG(Int64,min),
@ -581,7 +581,7 @@ static const luaL_Reg Int64_methods[] = {
{ NULL, NULL }
};
static const luaL_Reg Int64_meta[] = {
WSLUA_META Int64_meta[] = {
WSLUA_CLASS_MTREG(Int64,tostring),
WSLUA_CLASS_MTREG(Int64,call),
WSLUA_CLASS_MTREG(wslua,concat),
@ -1076,7 +1076,7 @@ static int UInt64__gc(lua_State* L _U_) {
return 0;
}
static const luaL_Reg UInt64_methods[] = {
WSLUA_METHODS UInt64_methods[] = {
WSLUA_CLASS_FNREG(UInt64,new),
WSLUA_CLASS_FNREG(UInt64,max),
WSLUA_CLASS_FNREG(UInt64,min),
@ -1100,7 +1100,7 @@ static const luaL_Reg UInt64_methods[] = {
{ NULL, NULL }
};
static const luaL_Reg UInt64_meta[] = {
WSLUA_META UInt64_meta[] = {
WSLUA_CLASS_MTREG(UInt64,tostring),
WSLUA_CLASS_MTREG(UInt64,call),
WSLUA_CLASS_MTREG(wslua,concat),

View File

@ -127,7 +127,7 @@ WSLUA_FUNCTION wslua_debug( lua_State* L ) { /* Will add a log entry with debug
/* The returned filename is g_malloc()'d so the caller must free it */
/* except when NULL is returned if file doesn't exist */
static char* wslua_get_actual_filename(const char* fname) {
char* wslua_get_actual_filename(const char* fname) {
char fname_clean[256];
char* f;
char* filename;
@ -228,176 +228,6 @@ WSLUA_FUNCTION wslua_dofile(lua_State* L) {
}
WSLUA_FUNCTION wslua_persconffile_path(lua_State* L) {
#define WSLUA_OPTARG_persconffile_path_FILENAME 1 /* A filename. */
const char *fname = luaL_optstring(L, WSLUA_OPTARG_persconffile_path_FILENAME,"");
char* filename = get_persconffile_path(fname,FALSE);
lua_pushstring(L,filename);
g_free(filename);
WSLUA_RETURN(1); /* The full pathname for a file in the personal configuration directory. */
}
WSLUA_FUNCTION wslua_datafile_path(lua_State* L) {
#define WSLUA_OPTARG_datafile_path_FILENAME 1 /* A filename */
const char *fname = luaL_optstring(L, WSLUA_OPTARG_datafile_path_FILENAME,"");
char* filename;
if (running_in_build_directory()) {
/* Running in build directory, set datafile_path to wslua source directory */
filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "epan" G_DIR_SEPARATOR_S "wslua"
G_DIR_SEPARATOR_S "%s", get_datafile_dir(), fname);
} else {
filename = get_datafile_path(fname);
}
lua_pushstring(L,filename);
g_free(filename);
WSLUA_RETURN(1); /* The full pathname for a file in wireshark's configuration directory. */
}
WSLUA_CLASS_DEFINE(Dir,FAIL_ON_NULL("Dir"),NOP); /* A Directory */
WSLUA_CONSTRUCTOR Dir_open(lua_State* L) {
/* Opens a directory and returns a `Dir` object representing the files in the directory.
@code for filename in Dir.open(path) do ... end @endcode
*/
#define WSLUA_ARG_Dir_open_PATHNAME 1 /* The pathname of the directory. */
#define WSLUA_OPTARG_Dir_open_EXTENSION 2 /* If given, only files with this extension will be returned. */
const char* dirname = luaL_checkstring(L,WSLUA_ARG_Dir_open_PATHNAME);
const char* extension = luaL_optstring(L,WSLUA_OPTARG_Dir_open_EXTENSION,NULL);
Dir dir;
char* dirname_clean;
if (!dirname) {
WSLUA_ARG_ERROR(Dir_open,PATHNAME,"must be a string");
return 0;
}
dirname_clean = wslua_get_actual_filename(dirname);
if (!dirname_clean) {
WSLUA_ARG_ERROR(Dir_open,PATHNAME,"directory does not exist");
return 0;
}
if (!test_for_directory(dirname_clean)) {
g_free(dirname_clean);
WSLUA_ARG_ERROR(Dir_open,PATHNAME, "must be a directory");
return 0;
}
dir = (Dir)g_malloc(sizeof(struct _wslua_dir));
dir->dir = g_dir_open(dirname_clean, 0, dir->dummy);
g_free(dirname_clean);
dir->ext = extension ? g_strdup(extension) : NULL;
dir->dummy = (GError **)g_malloc(sizeof(GError *));
*(dir->dummy) = NULL;
if (dir->dir == NULL) {
g_free(dir->dummy);
g_free(dir);
WSLUA_ARG_ERROR(Dir_open,PATHNAME,"could not open directory");
return 0;
}
pushDir(L,dir);
WSLUA_RETURN(1); /* the `Dir` object. */
}
WSLUA_METAMETHOD Dir__call(lua_State* L) {
/* At every invocation will return one file (nil when done). */
Dir dir = checkDir(L,1);
const gchar* file;
const gchar* filename;
const char* ext;
if (!dir->dir) {
return 0;
}
if ( ! ( file = g_dir_read_name(dir->dir ) )) {
g_dir_close(dir->dir);
dir->dir = NULL;
return 0;
}
if ( ! dir->ext ) {
lua_pushstring(L,file);
return 1;
}
do {
filename = file;
/* XXX strstr returns ptr to first match,
this fails ext=".xxx" filename="aaa.xxxz.xxx" */
if ( ( ext = strstr(filename,dir->ext)) && g_str_equal(ext,dir->ext) ) {
lua_pushstring(L,filename);
return 1;
}
} while(( file = g_dir_read_name(dir->dir) ));
g_dir_close(dir->dir);
dir->dir = NULL;
return 0;
}
WSLUA_METHOD Dir_close(lua_State* L) {
/* Closes the directory. */
Dir dir = checkDir(L,1);
if (dir->dir) {
g_dir_close(dir->dir);
dir->dir = NULL;
}
return 0;
}
/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
static int Dir__gc(lua_State* L) {
Dir dir = toDir(L,1);
if(!dir) return 0;
if (dir->dir) {
g_dir_close(dir->dir);
}
g_free(dir->dummy);
if (dir->ext) g_free(dir->ext);
g_free(dir);
return 0;
}
static const luaL_Reg Dir_methods[] = {
{"open", Dir_open},
{"close", Dir_close},
{ NULL, NULL }
};
static const luaL_Reg Dir_meta[] = {
{"__call", Dir__call},
{ NULL, NULL }
};
int Dir_register(lua_State* L) {
WSLUA_REGISTER_CLASS(Dir);
return 0;
}
typedef struct _statcmd_t {
lua_State* L;
int func_ref;
@ -434,7 +264,7 @@ static void statcmd_init(const char *opt_arg, void* userdata) {
}
WSLUA_FUNCTION wslua_register_stat_cmd_arg(lua_State* L) {
/* Register a function to handle a -z option */
/* Register a function to handle a `-z` option */
#define WSLUA_ARG_register_stat_cmd_arg_ARGUMENT 1 /* Argument */
#define WSLUA_OPTARG_register_stat_cmd_arg_ACTION 2 /* Action */
const char* arg = luaL_checkstring(L,WSLUA_ARG_register_stat_cmd_arg_ARGUMENT);

202
test/lua/dir.lua Normal file
View File

@ -0,0 +1,202 @@
-- test script for wslua Dir functions
------------- helper funcs ------------
local total_tests = 0
local function testing(name)
print("---- Testing "..name.." ---- ")
end
local function test(name, ...)
total_tests = total_tests + 1
io.stdout:write("test "..name.."-"..total_tests.."...")
if (...) == true then
io.stdout:write("passed\n")
return true
else
io.stdout:write("failed!\n")
error(name.." test failed!")
end
end
-- the following are so we can use pcall (which needs a function to call)
local function callDirFuncBase(name, t)
t.result = Dir[name]()
return true
end
local function callDirFunc(name, val, t)
t.result = Dir[name](val)
return true
end
local function makeFile(filename)
local f = io.open(filename, "w")
if not f then
error ("failed to make file"..filename.." in directory\n"..
"make sure to delete 'temp' directory before running again")
end
f:write("fooobarrloo")
f:close()
return true
end
--------------------------
-- for our called function results
local t = {}
testing("Dir basics")
test("global", _G.Dir ~= nil)
test("global", type(Dir.make) == 'function')
test("global", type(Dir.remove) == 'function')
test("global", type(Dir.remove_all) == 'function')
test("global", type(Dir.open) == 'function')
test("global", type(Dir.close) == 'function')
test("global", type(Dir.exists) == 'function')
test("global", type(Dir.personal_config_path) == 'function')
test("global", type(Dir.global_config_path) == 'function')
test("global", type(Dir.personal_plugins_path) == 'function')
test("global", type(Dir.global_plugins_path) == 'function')
testing("Dir paths/filenames")
test("Dir.__FILE__", __FILE__ ~= nil)
test("Dir.__DIR__", __DIR__ ~= nil)
test("Dir.exists", pcall(callDirFunc, "exists", "temp", t))
test("Dir.personal_config_path", pcall(callDirFuncBase, "personal_config_path", t))
test("Dir.global_config_path", pcall(callDirFuncBase, "global_config_path", t))
test("Dir.personal_plugins_path", pcall(callDirFuncBase, "personal_plugins_path", t))
test("Dir.global_plugins_path", pcall(callDirFuncBase, "global_plugins_path", t))
print("\nFor your information, I got the following info:\n")
print("__FILE__ = '" .. __FILE__ .. "'")
print("__DIR__ = '" .. __DIR__ .. "'")
print("personal_config_path = '" .. Dir.personal_config_path() .. "'")
print("global_config_path = '" .. Dir.global_config_path() .. "'")
print("personal_plugins_path = '" .. Dir.personal_plugins_path() .. "'")
print("global_plugins_path = '" .. Dir.global_plugins_path() .. "'")
print("\n")
testing("Directory manipulation")
test("Dir.exists", pcall(callDirFunc, "exists", "temp", t))
if t.result == true or t.result == false then
error("this testsuite requires there be no 'temp' directory or file; please remove it")
end
testing("Dir.make")
test("Dir.make", pcall(callDirFunc, "make", "temp", t) and t.result == true)
test("Dir.exists", pcall(callDirFunc, "exists", "temp", t) and t.result == true)
-- make the same dir, should give false
test("Dir.make", pcall(callDirFunc, "make", "temp", t) and t.result == false)
testing("Dir.remove")
test("Dir.remove", pcall(callDirFunc, "remove", "temp", t) and t.result == true)
test("Dir.exists", pcall(callDirFunc, "exists", "temp", t) and t.result == nil)
test("Dir.remove", pcall(callDirFunc, "remove", "temp", t) and t.result == false)
Dir.make("temp")
makeFile("temp/file.txt")
-- will return nil because temp has a file
test("Dir.remove", pcall(callDirFunc, "remove", "temp", t) and t.result == nil)
testing("Dir.remove_all")
test("Dir.remove_all", pcall(callDirFunc, "remove_all", "temp", t) and t.result == true)
test("Dir.remove_all", pcall(callDirFunc, "remove_all", "temp", t) and t.result == false)
Dir.make("temp")
makeFile("temp/file1.txt")
makeFile("temp/file2.txt")
makeFile("temp/file3.txt")
test("Dir.remove_all", pcall(callDirFunc, "remove_all", "temp", t) and t.result == true)
test("Dir.remove_all", pcall(callDirFunc, "remove_all", "temp", t) and t.result == false)
testing("Dir.open")
Dir.make("temp")
makeFile("temp/file1.txt")
makeFile("temp/file2.txt")
makeFile("temp/file3.txt")
test("Dir.open", pcall(callDirFunc, "open", "temp", t))
test("Dir.open", type(t.result) == 'userdata')
test("Dir.open", typeof(t.result) == 'Dir')
io.stdout:write("calling Dir object...")
local dir = t.result
local file = dir()
io.stdout:write("passed\n")
test("Dir.call", file == "file1.txt")
file = dir()
test("Dir.call", file == "file2.txt")
file = dir()
test("Dir.call", file == "file3.txt")
file = dir()
test("Dir.call", file == nil)
file = dir()
test("Dir.call", file == nil)
testing("Dir.close")
test("Dir.close", pcall(callDirFunc, "close", dir, t))
test("Dir.close", pcall(callDirFunc, "close", dir, t))
testing("Negative testing 1")
-- now try breaking it
test("Dir.open", pcall(callDirFunc, "open", "temp", t))
dir = t.result
-- call dir() now
file = dir()
test("Dir.call", file == "file1.txt")
Dir.remove_all("temp")
-- call it again
file = dir()
test("Dir.call", file == "file2.txt")
test("Dir.close", pcall(callDirFunc, "close", dir, t))
testing("Negative testing 2")
-- do it again, but this time don't do dir() until after removing the files
Dir.make("temp")
makeFile("temp/file1.txt")
makeFile("temp/file2.txt")
makeFile("temp/file3.txt")
test("Dir.open", pcall(callDirFunc, "open", "temp", t))
dir = t.result
Dir.remove_all("temp")
-- now do it
file = dir()
test("Dir.call", file == nil)
test("Dir.close", pcall(callDirFunc, "close", dir, t))
-- negative tests
testing("Negative testing 3")
-- invalid args
test("Dir.make", not pcall(callDirFunc, "make", {}, t))
test("Dir.make", not pcall(callDirFunc, "make", nil, t))
test("Dir.remove", not pcall(callDirFunc, "remove", {}, t))
test("Dir.remove", not pcall(callDirFunc, "remove", nil, t))
test("Dir.remove_all", not pcall(callDirFunc, "remove_all", {}, t))
test("Dir.remove_all", not pcall(callDirFunc, "remove_all", nil, t))
test("Dir.open", not pcall(callDirFunc, "open", {}, t))
test("Dir.open", not pcall(callDirFunc, "open", nil, t))
test("Dir.close", not pcall(callDirFunc, "close", "dir", t))
test("Dir.close", not pcall(callDirFunc, "close", nil, t))
print("\n-----------------------------\n")
print("All tests passed!\n\n")

View File

@ -22,6 +22,22 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
wslua_step_dir_test() {
if [ $HAVE_LUA -ne 0 ]; then
test_step_skipped
return
fi
# Tshark catches lua script failures, so we have to parse the output.
$TSHARK -r $CAPTURE_DIR/empty.pcap -X lua_script:$TESTS_DIR/lua/dir.lua > testout.txt 2>&1
if grep -q "All tests passed!" testout.txt; then
test_step_ok
else
cat testout.txt
test_step_failed "didn't find pass marker"
fi
}
wslua_step_dissector_test() {
if [ $HAVE_LUA -ne 0 ]; then
test_step_skipped
@ -358,6 +374,7 @@ wslua_cleanup_step() {
wslua_suite() {
test_step_set_pre wslua_cleanup_step
test_step_set_post wslua_cleanup_step
test_step_add "wslua dir" wslua_step_dir_test
test_step_add "wslua dissector" wslua_step_dissector_test
test_step_add "wslua field/fieldinfo" wslua_step_field_test
test_step_add "wslua file" wslua_step_file_test