aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHadriel Kaplan <hadrielk@yahoo.com>2014-03-26 02:24:51 -0400
committerAnders Broman <a.broman58@gmail.com>2014-03-26 07:37:34 +0000
commit8c2bb805742c918b933923947a533d098774da75 (patch)
treeb3859068c4fdd09bd26ab01168835a042715644b
parentda1af6e549856c8e213dadc1ec37a41a50246e1d (diff)
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>
-rw-r--r--docbook/CMakeLists.txt1
-rw-r--r--docbook/Makefile.common1
-rw-r--r--docbook/user-guide.xml1
-rw-r--r--docbook/wsluarm.xml1
-rw-r--r--epan/wslua/CMakeLists.txt1
-rw-r--r--epan/wslua/Makefile.am2
-rw-r--r--epan/wslua/Makefile.nmake2
-rw-r--r--epan/wslua/init_wslua.c65
-rw-r--r--epan/wslua/template-init.lua9
-rw-r--r--epan/wslua/wslua.h2
-rw-r--r--epan/wslua/wslua_dir.c383
-rw-r--r--epan/wslua/wslua_file.c16
-rw-r--r--epan/wslua/wslua_int64.c8
-rw-r--r--epan/wslua/wslua_util.c174
-rw-r--r--test/lua/dir.lua202
-rwxr-xr-xtest/suite-wslua.sh17
16 files changed, 688 insertions, 197 deletions
diff --git a/docbook/CMakeLists.txt b/docbook/CMakeLists.txt
index e03076f5aa..2fb6818720 100644
--- a/docbook/CMakeLists.txt
+++ b/docbook/CMakeLists.txt
@@ -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
)
diff --git a/docbook/Makefile.common b/docbook/Makefile.common
index d0056cc3e3..23b5eae27d 100644
--- a/docbook/Makefile.common
+++ b/docbook/Makefile.common
@@ -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
diff --git a/docbook/user-guide.xml b/docbook/user-guide.xml
index 5d5e2548c6..b2555e3bca 100644
--- a/docbook/user-guide.xml
+++ b/docbook/user-guide.xml
@@ -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">
diff --git a/docbook/wsluarm.xml b/docbook/wsluarm.xml
index fdcae10a1f..2e22d4e280 100644
--- a/docbook/wsluarm.xml
+++ b/docbook/wsluarm.xml
@@ -169,6 +169,7 @@ register_menu("Test/Packets", menuable_tap, MENU_TOOLS_UNSORTED)</programlisting
&WsLuaTree;
&WsLuaTvb;
&WsLuaFile;
+ &WsLuaDir;
&WsLuaUtility;
&WsLuaInt64;
&WsLuaStruct;
diff --git a/epan/wslua/CMakeLists.txt b/epan/wslua/CMakeLists.txt
index ca5dfa3fb9..a9c676ef6b 100644
--- a/epan/wslua/CMakeLists.txt
+++ b/epan/wslua/CMakeLists.txt
@@ -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
diff --git a/epan/wslua/Makefile.am b/epan/wslua/Makefile.am
index 96c455e2dc..27dd367e6f 100644
--- a/epan/wslua/Makefile.am
+++ b/epan/wslua/Makefile.am
@@ -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
diff --git a/epan/wslua/Makefile.nmake b/epan/wslua/Makefile.nmake
index dc672efe47..b8b96cdf5c 100644
--- a/epan/wslua/Makefile.nmake
+++ b/epan/wslua/Makefile.nmake
@@ -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 \
diff --git a/epan/wslua/init_wslua.c b/epan/wslua/init_wslua.c
index 4ce2780520..fb1e2e15c7 100644
--- a/epan/wslua/init_wslua.c
+++ b/epan/wslua/init_wslua.c
@@ -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);
}
}
diff --git a/epan/wslua/template-init.lua b/epan/wslua/template-init.lua
index 0a9ad0d00d..2f99159b07 100644
--- a/epan/wslua/template-init.lua
+++ b/epan/wslua/template-init.lua
@@ -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")
diff --git a/epan/wslua/wslua.h b/epan/wslua/wslua.h
index d8a2606239..1ec3087233 100644
--- a/epan/wslua/wslua.h
+++ b/epan/wslua/wslua.h
@@ -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);
diff --git a/epan/wslua/wslua_dir.c b/epan/wslua/wslua_dir.c
new file mode 100644
index 0000000000..d39484df48
--- /dev/null
+++ b/epan/wslua/wslua_dir.c
@@ -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;
+}
diff --git a/epan/wslua/wslua_file.c b/epan/wslua/wslua_file.c
index 6149a8e043..15a7990778 100644
--- a/epan/wslua/wslua_file.c
+++ b/epan/wslua/wslua_file.c
@@ -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 }
};
diff --git a/epan/wslua/wslua_int64.c b/epan/wslua/wslua_int64.c
index ace9280659..d222eee85c 100644
--- a/epan/wslua/wslua_int64.c
+++ b/epan/wslua/wslua_int64.c
@@ -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),
diff --git a/epan/wslua/wslua_util.c b/epan/wslua/wslua_util.c
index c9098aa980..77d264cc58 100644
--- a/epan/wslua/wslua_util.c
+++ b/epan/wslua/wslua_util.c
@@ -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);
diff --git a/test/lua/dir.lua b/test/lua/dir.lua
new file mode 100644
index 0000000000..88ecbe2ce9
--- /dev/null
+++ b/test/lua/dir.lua
@@ -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")
diff --git a/test/suite-wslua.sh b/test/suite-wslua.sh
index d6c2244746..d4eaa60489 100755
--- a/test/suite-wslua.sh
+++ b/test/suite-wslua.sh
@@ -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