summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/argent.c3
-rw-r--r--src/bindings.c88
-rw-r--r--src/bindings.h4
3 files changed, 94 insertions, 1 deletions
diff --git a/src/argent.c b/src/argent.c
index b83f851..c4738d4 100644
--- a/src/argent.c
+++ b/src/argent.c
@@ -33,7 +33,8 @@ int main(int argc, char **argv)
argent_log(DEBUG, "create argent table");
hs_create_table
(L,
- hs_str_cfunc("markdown", markdown)
+ hs_str_cfunc("markdown", markdown),
+ hs_str_cfunc("scanDirectory", scan_directory)
);
lua_setglobal(L, "argent");
diff --git a/src/bindings.c b/src/bindings.c
index b02911b..2988685 100644
--- a/src/bindings.c
+++ b/src/bindings.c
@@ -1,6 +1,9 @@
#include <stdlib.h>
#include <string.h>
#include <lua.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
#include "honeysuckle.h"
#include "md4c-html.h"
@@ -76,3 +79,88 @@ int markdown(lua_State *L)
argent_log(DEBUG, "finish markdown parsing");
return 1;
}
+
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+static void throw_directory_error(lua_State *L, char *dir_name);
+static struct dirent *read_dir(lua_State *L, DIR *directory);
+
+int scan_directory(lua_State *L)
+{
+ argent_log(DEBUG, "begin scan_directory()");
+ char *dir_name;
+ hs_parse_args(L, hs_str(dir_name));
+
+ DIR *directory = opendir(dir_name);
+ if (directory == NULL)
+ throw_directory_error(L, dir_name);
+
+ lua_newtable(L);
+ int directory_table = lua_gettop(L);
+ int directory_index = 1;
+ lua_newtable(L);
+ int file_table = lua_gettop(L);
+ int file_index = 1;
+
+ struct dirent *entry;
+ while ((entry = read_dir(L, directory)) != NULL) {
+ lua_pushstring(L, entry->d_name);
+ if (entry->d_type == DT_DIR) {
+ lua_rawseti(L, directory_table, directory_index);
+ directory_index += 1;
+ }
+ else {
+ lua_rawseti(L, file_table, file_index);
+ file_index += 1;
+ }
+ }
+
+ closedir(directory);
+ argent_log(DEBUG, "end scan_directory()");
+
+ return 2;
+}
+
+
+static void throw_directory_error(lua_State *L, char *dir_name)
+{
+ argent_log(ERROR, "failed to open directory: %d\n", errno);
+ switch(errno) {
+ case EACCES:
+ hs_throw_error(L, "read %s: permission denied", dir_name);
+ break;
+
+ case EMFILE:
+ hs_throw_error(L, "read %s: this process has too many open files", dir_name);
+ break;
+
+ case ENFILE:
+ hs_throw_error(L, "read %s: this file system cannot support any more open files", dir_name);
+ break;
+
+ case ENOMEM:
+ hs_throw_error(L, "read %s: Not enough memory", dir_name);
+ break;
+
+ default:
+ hs_throw_error(L, "read %s: unknown error", dir_name);
+ break;
+ }
+}
+
+
+static struct dirent *read_dir(lua_State *L, DIR *directory)
+{
+ // can't tell if a NULL was EOF or error without this
+ errno = 0;
+ struct dirent *entry = readdir(directory);
+
+ if (entry == NULL && errno != 0) {
+ argent_log(ERROR, "attempted to read invalid dirstream");
+ closedir(directory);
+ hs_throw_error(L, "attempted to read invalid dirstream");
+ }
+
+ return entry;
+}
diff --git a/src/bindings.h b/src/bindings.h
index 3ee3a1a..853f0c0 100644
--- a/src/bindings.h
+++ b/src/bindings.h
@@ -5,4 +5,8 @@
int markdown(lua_State *L);
+// return two arrays, one containing filenames for all directories in the dir
+// and the other containing filenames for all regular files
+int scan_directory(lua_State *L);
+
#endif