From 7db6401dfb0604e92946ac4f7c76d541498e6ebb Mon Sep 17 00:00:00 2001 From: sanine Date: Mon, 3 Jan 2022 16:49:58 -0600 Subject: add scan_directory() --- src/argent.c | 3 +- src/bindings.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/bindings.h | 4 +++ 3 files changed, 94 insertions(+), 1 deletion(-) 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 #include #include +#include +#include +#include #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 -- cgit v1.2.1