diff options
Diffstat (limited to 'src/bindings.c')
-rw-r--r-- | src/bindings.c | 88 |
1 files changed, 88 insertions, 0 deletions
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; +} |