regen pidl all: rm epan/dissectors/pidl/*-stamp; pushd epan/dissectors/pidl/ && make...
[wireshark-sm.git] / epan / wslua / wslua_dir.c
blob4049d780e16e1425ea72e2f0a2cdf0681877709a
1 /*
2 * wslua_dir.c
4 * (c) 2014, Hadriel Kaplan <hadrielk at yahoo dot com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "config.h"
15 /* WSLUA_MODULE Dir Directory Handling Functions */
17 #include "wslua.h"
18 #include <errno.h>
19 #include <wsutil/file_util.h>
21 WSLUA_CLASS_DEFINE(Dir,FAIL_ON_NULL("Dir")); /* A Directory object, as well as associated functions. */
23 WSLUA_CONSTRUCTOR Dir_make(lua_State* L) {
24 /* Creates a directory.
26 The created directory is set for permission mode 0755 (octal), meaning it is
27 read+write+execute by owner, but only read+execute by group members and others.
29 If the directory was created successfully, a boolean `true` is returned.
30 If the directory cannot be made because it already exists, `false` is returned.
31 If the directory cannot be made because an error occurred, `nil` is returned.
33 #define WSLUA_ARG_Dir_make_NAME 1 /* The name of the directory, possibly including path. */
35 const char *dir_path = luaL_checkstring(L, WSLUA_ARG_Dir_make_NAME);
36 ws_statb64 s_buf;
37 int ret;
39 if (ws_stat64(dir_path, &s_buf) != 0 && errno == ENOENT) {
40 ret = ws_mkdir(dir_path, 0755);
41 if (ret == -1) {
42 lua_pushnil(L);
43 } else {
44 lua_pushboolean(L, 1);
46 } else {
47 lua_pushboolean(L, 0);
50 WSLUA_RETURN(1); /* Boolean `true` on success, `false` if the directory already exists, `nil` on error. */
53 WSLUA_CONSTRUCTOR Dir_exists(lua_State* L) {
54 /* Returns true if the given directory name exists.
56 If the directory exists, a boolean `true` is returned.
57 If the path is a file instead, `false` is returned.
58 If the path does not exist or an error occurred, `nil` is returned.
60 #define WSLUA_ARG_Dir_exists_NAME 1 /* The name of the directory, possibly including path. */
62 const char *dir_path = luaL_checkstring(L, WSLUA_ARG_Dir_exists_NAME);
63 int ret;
65 if ((ret = test_for_directory (dir_path)) == EISDIR) {
66 lua_pushboolean(L, 1);
67 } else {
68 if (ret == 0) {
69 lua_pushboolean(L, 0);
70 } else {
71 lua_pushnil(L);
75 WSLUA_RETURN(1); /* Boolean `true` if the directory exists, `false` if it's a file, `nil` on error or not-exist. */
78 WSLUA_CONSTRUCTOR Dir_remove(lua_State* L) {
79 /* Removes an empty directory.
81 If the directory was removed successfully, a boolean `true` is returned.
82 If the directory cannot be removed because it does not exist, `false` is returned.
83 If the directory cannot be removed because an error occurred, `nil` is returned.
85 This function only removes empty directories. To remove a directory regardless,
86 use `Dir.remove_all()`.
88 #define WSLUA_ARG_Dir_remove_NAME 1 /* The name of the directory, possibly including path. */
90 const char *dir_path = luaL_checkstring(L, WSLUA_ARG_Dir_remove_NAME);
91 int ret;
93 if (test_for_directory (dir_path) == EISDIR) {
94 ret = ws_remove(dir_path);
95 if (ret != 0) {
96 lua_pushnil(L);
97 } else {
98 lua_pushboolean(L, 1);
100 } else {
101 lua_pushboolean(L, 0);
104 WSLUA_RETURN(1); /* Boolean `true` on success, `false` if does not exist, `nil` on error. */
107 static int delete_directory(const char *directory) {
108 WS_DIR *dir;
109 WS_DIRENT *file;
110 char *filename;
111 int ret = 0;
113 /* delete all contents of directory */
114 if ((dir = ws_dir_open(directory, 0, NULL)) != NULL) {
115 while ((file = ws_dir_read_name(dir)) != NULL) {
116 filename = g_build_filename(directory, ws_dir_get_name(file), NULL);
117 if (test_for_directory(filename) != EISDIR) {
118 ret = ws_remove(filename);
119 } else {
120 /* recurse */
121 ret = delete_directory (filename);
123 g_free(filename);
124 if (ret != 0) {
125 break;
128 ws_dir_close(dir);
131 if (ret == 0) {
132 ret = ws_remove(directory);
135 return ret;
139 WSLUA_CONSTRUCTOR Dir_remove_all(lua_State* L) {
140 /* Removes an empty or non-empty directory.
142 If the directory was removed successfully, a boolean `true` is returned.
143 If the directory cannot be removed because it does not exist, `false` is returned.
144 If the directory cannot be removed because an error occurred, `nil` is returned.
146 #define WSLUA_ARG_Dir_remove_all_NAME 1 /* The name of the directory, possibly including path. */
148 const char *dir_path = luaL_checkstring(L, WSLUA_ARG_Dir_remove_all_NAME);
149 int ret;
151 if (test_for_directory (dir_path) == EISDIR) {
152 ret = delete_directory(dir_path);
153 if (ret != 0) {
154 lua_pushnil(L);
155 } else {
156 lua_pushboolean(L, 1);
158 } else {
159 lua_pushboolean(L, 0);
162 WSLUA_RETURN(1); /* Boolean `true` on success, `false` if does not exist, `nil` on error. */
165 WSLUA_CONSTRUCTOR Dir_open(lua_State* L) {
166 /* Opens a directory and returns a <<lua_class_Dir,`Dir`>> object representing the files in the directory.
168 ==== Example
170 [source,lua]
171 ----
172 -- Print the contents of a directory
173 for filename in Dir.open('/path/to/dir') do
174 print(filename)
176 ----
178 #define WSLUA_ARG_Dir_open_PATHNAME 1 /* The pathname of the directory. */
179 #define WSLUA_OPTARG_Dir_open_EXTENSION 2 /* If given, only files with this extension will be returned. */
181 const char* dirname = luaL_checkstring(L,WSLUA_ARG_Dir_open_PATHNAME);
182 const char* extension = luaL_optstring(L,WSLUA_OPTARG_Dir_open_EXTENSION,NULL);
183 Dir dir;
184 char* dirname_clean;
186 dirname_clean = wslua_get_actual_filename(dirname);
187 if (!dirname_clean) {
188 WSLUA_ARG_ERROR(Dir_open,PATHNAME,"directory does not exist");
189 return 0;
192 if (!test_for_directory(dirname_clean)) {
193 g_free(dirname_clean);
194 WSLUA_ARG_ERROR(Dir_open,PATHNAME, "must be a directory");
195 return 0;
198 dir = (Dir)g_malloc(sizeof(struct _wslua_dir));
199 dir->dir = g_dir_open(dirname_clean, 0, NULL);
200 g_free(dirname_clean);
202 if (dir->dir == NULL) {
203 g_free(dir);
205 WSLUA_ARG_ERROR(Dir_open,PATHNAME,"could not open directory");
206 return 0;
209 dir->ext = g_strdup(extension);
211 pushDir(L,dir);
212 WSLUA_RETURN(1); /* The <<lua_class_Dir,`Dir`>> object. */
215 WSLUA_METAMETHOD Dir__call(lua_State* L) {
217 Gets the next file or subdirectory within the directory, or `nil` when done.
219 ==== Example
221 [source,lua]
222 ----
223 -- Open a directory and print the name of the first file or subdirectory
224 local dir = Dir.open('/path/to/dir')
225 local first = dir()
226 print(tostring(file))
227 ----
230 Dir dir = checkDir(L,1);
231 const char* file;
232 const char* filename;
233 const char* ext;
235 if (!dir->dir) {
236 return 0;
239 if ( ! ( file = g_dir_read_name(dir->dir ) )) {
240 g_dir_close(dir->dir);
241 dir->dir = NULL;
242 return 0;
246 if ( ! dir->ext ) {
247 lua_pushstring(L,file);
248 return 1;
251 do {
252 filename = file;
254 /* XXX strstr returns ptr to first match,
255 this fails ext=".xxx" filename="aaa.xxxz.xxx" */
256 if ( ( ext = strstr(filename,dir->ext)) && g_str_equal(ext,dir->ext) ) {
257 lua_pushstring(L,filename);
258 return 1;
260 } while(( file = g_dir_read_name(dir->dir) ));
262 g_dir_close(dir->dir);
263 dir->dir = NULL;
264 return 0;
267 WSLUA_METHOD Dir_close(lua_State* L) {
268 /* Closes the directory. Called automatically during garbage collection of a <<lua_class_Dir,`Dir`>> object. */
269 Dir dir = checkDir(L,1);
271 if (dir->dir) {
272 g_dir_close(dir->dir);
273 dir->dir = NULL;
276 return 0;
279 WSLUA_CONSTRUCTOR Dir_personal_config_path(lua_State* L) {
280 /* Gets the https://www.wireshark.org/docs/wsug_html_chunked/ChAppFilesConfigurationSection.html[personal configuration] directory path, with filename if supplied. */
281 #define WSLUA_OPTARG_Dir_personal_config_path_FILENAME 1 /* A filename. */
282 const char *fname = luaL_optstring(L, WSLUA_OPTARG_Dir_personal_config_path_FILENAME,"");
283 char* filename = get_persconffile_path(fname,false);
285 lua_pushstring(L,filename);
286 g_free(filename);
287 WSLUA_RETURN(1); /* The full pathname for a file in the personal configuration directory. */
290 WSLUA_CONSTRUCTOR Dir_global_config_path(lua_State* L) {
291 /* Gets the https://www.wireshark.org/docs/wsug_html_chunked/ChAppFilesConfigurationSection.html[global configuration] directory path, with filename if supplied. */
292 #define WSLUA_OPTARG_Dir_global_config_path_FILENAME 1 /* A filename */
293 const char *fname = luaL_optstring(L, WSLUA_OPTARG_Dir_global_config_path_FILENAME,"");
294 char* filename;
296 filename = get_datafile_path(fname);
297 lua_pushstring(L,filename);
298 g_free(filename);
299 WSLUA_RETURN(1); /* The full pathname for a file in Wireshark's configuration directory. */
302 WSLUA_CONSTRUCTOR Dir_personal_plugins_path(lua_State* L) {
303 /* Gets the personal plugins directory path. */
304 lua_pushstring(L, get_plugins_pers_dir());
305 WSLUA_RETURN(1); /* The pathname of the https://www.wireshark.org/docs/wsug_html_chunked/ChPluginFolders.html[personal plugins] directory. */
308 WSLUA_CONSTRUCTOR Dir_global_plugins_path(lua_State* L) {
309 /* Gets the global plugins directory path. */
310 lua_pushstring(L, get_plugins_dir());
311 WSLUA_RETURN(1); /* The pathname of the https://www.wireshark.org/docs/wsug_html_chunked/ChPluginFolders.html[global plugins] directory. */
314 /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
315 static int Dir__gc(lua_State* L) {
316 Dir dir = toDir(L,1);
318 if(!dir) return 0;
320 if (dir->dir) {
321 g_dir_close(dir->dir);
324 g_free(dir->ext);
325 g_free(dir);
327 return 0;
330 WSLUA_METHODS Dir_methods[] = {
331 WSLUA_CLASS_FNREG(Dir,make),
332 WSLUA_CLASS_FNREG(Dir,exists),
333 WSLUA_CLASS_FNREG(Dir,remove),
334 WSLUA_CLASS_FNREG(Dir,remove_all),
335 WSLUA_CLASS_FNREG(Dir,open),
336 WSLUA_CLASS_FNREG(Dir,close),
337 WSLUA_CLASS_FNREG(Dir,personal_config_path),
338 WSLUA_CLASS_FNREG(Dir,global_config_path),
339 WSLUA_CLASS_FNREG(Dir,personal_plugins_path),
340 WSLUA_CLASS_FNREG(Dir,global_plugins_path),
341 { NULL, NULL }
344 WSLUA_META Dir_meta[] = {
345 WSLUA_CLASS_MTREG(Dir,call),
346 { NULL, NULL }
349 int Dir_register(lua_State* L) {
350 WSLUA_REGISTER_CLASS(Dir);
351 return 0;
355 * Editor modelines - https://www.wireshark.org/tools/modelines.html
357 * Local variables:
358 * c-basic-offset: 4
359 * tab-width: 8
360 * indent-tabs-mode: nil
361 * End:
363 * vi: set shiftwidth=4 tabstop=8 expandtab:
364 * :indentSize=4:tabSize=8:noTabs=true: