* 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
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include "wslua.h"
#include <errno.h>
#include <wsutil/file_util.h>
WSLUA_CLASS_DEFINE(Dir,FAIL_ON_NULL("Dir"));
WSLUA_CONSTRUCTOR Dir_make(lua_State* L) {
The created directory is set for permission mode 0755 (octal), meaning it is
read+write+execute by owner, but only read+execute by group members 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.
*/
#define WSLUA_ARG_Dir_make_NAME 1
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);
}
WSLUA_CONSTRUCTOR Dir_exists(lua_State* L) {
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.
*/
#define WSLUA_ARG_Dir_exists_NAME 1
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);
}
WSLUA_CONSTRUCTOR Dir_remove(lua_State* L) {
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()`.
*/
#define WSLUA_ARG_Dir_remove_NAME 1
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);
}
static int delete_directory(const char *directory) {
WS_DIR *dir;
WS_DIRENT *file;
char *filename;
int ret = 0;
if ((dir = ws_dir_open(directory, 0, NULL)) != NULL) {
while ((file = ws_dir_read_name(dir)) != NULL) {
filename = g_build_filename(directory, ws_dir_get_name(file), NULL);
if (test_for_directory(filename) != EISDIR) {
ret = ws_remove(filename);
} else {
ret = delete_directory (filename);
}
g_free(filename);
if (ret != 0) {
break;
}
}
ws_dir_close(dir);
}
if (ret == 0) {
ret = ws_remove(directory);
}
return ret;
}
WSLUA_CONSTRUCTOR Dir_remove_all(lua_State* L) {
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.
*/
#define WSLUA_ARG_Dir_remove_all_NAME 1
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);
}
WSLUA_CONSTRUCTOR Dir_open(lua_State* L) {
==== Example
[source,lua]
----
-- Print the contents of a directory
for filename in Dir.open('/path/to/dir') do
print(filename)
end
----
*/
#define WSLUA_ARG_Dir_open_PATHNAME 1
#define WSLUA_OPTARG_Dir_open_EXTENSION 2
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;
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, NULL);
dir->path = dirname_clean;
if (dir->dir == NULL) {
g_free(dir->path);
g_free(dir);
WSLUA_ARG_ERROR(Dir_open,PATHNAME,"could not open directory");
return 0;
}
dir->ext = g_strdup(extension);
pushDir(L,dir);
WSLUA_RETURN(1);
}
WSLUA_METAMETHOD Dir__call(lua_State* L) {
Gets the next file or subdirectory within the directory, or `nil` when done.
==== Example
[source,lua]
----
-- Open a directory and print the name of the first file or subdirectory
local dir = Dir.open('/path/to/dir')
local first = dir()
print(tostring(file))
----
*/
Dir dir = checkDir(L,1);
const char* file;
const char* 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;
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) {
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) {
#define WSLUA_OPTARG_Dir_personal_config_path_FILENAME 1
const char *fname = luaL_optstring(L, WSLUA_OPTARG_Dir_personal_config_path_FILENAME,"");
char* filename = get_persconffile_path(fname,false, lua_app_env_var_prefix);
lua_pushstring(L,filename);
g_free(filename);
WSLUA_RETURN(1);
}
WSLUA_CONSTRUCTOR Dir_global_config_path(lua_State* L) {
#define WSLUA_OPTARG_Dir_global_config_path_FILENAME 1
const char *fname = luaL_optstring(L, WSLUA_OPTARG_Dir_global_config_path_FILENAME,"");
char* filename;
filename = get_datafile_path(fname, lua_app_env_var_prefix);
lua_pushstring(L,filename);
g_free(filename);
WSLUA_RETURN(1);
}
WSLUA_CONSTRUCTOR Dir_personal_plugins_path(lua_State* L) {
lua_pushstring(L, get_plugins_pers_dir(lua_app_env_var_prefix));
WSLUA_RETURN(1);
}
WSLUA_CONSTRUCTOR Dir_global_plugins_path(lua_State* L) {
lua_pushstring(L, get_plugins_dir(lua_app_env_var_prefix));
WSLUA_RETURN(1);
}
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->ext);
g_free(dir->path);
g_free(dir);
return 0;
}
WSLUA_METAMETHOD Dir__tostring(lua_State* L) {
`(closed)` appended once `Dir:close()` has run). `path` is
the directory Dir.open() resolved to, so symlinks and
relative paths show as their canonical form. */
Dir dir = checkDir(L,1);
lua_pushfstring(L, "Dir: path=%s%s",
dir->path ? dir->path : "?",
dir->dir ? "" : " (closed)");
WSLUA_RETURN(1);
}
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),
WSLUA_CLASS_MTREG(Dir,tostring),
{ NULL, NULL }
};
int Dir_register(lua_State* L) {
WSLUA_REGISTER_CLASS(Dir);
return 0;
}
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/