#include #include #include #include #define ldirlib_c #include "lua.h" #include "lauxlib.h" #include "lualib.h" /* forward declaration for the iterator function */ static int dir_iter (lua_State *L); static int l_dir (lua_State *L) { const char *path = luaL_checkstring(L, 1); /* create a userdatum to store a DIR address */ DIR **d = (DIR **)lua_newuserdata(L, sizeof(DIR *)); /* set its metatable */ luaL_getmetatable(L, "LuaBook.dir"); lua_setmetatable(L, -2); /* try to open the given directory */ *d = opendir(path); if (*d == NULL) /* error opening the directory? */ luaL_error(L, "cannot open %s: %s", path, strerror(errno)); /* creates and returns the iterator function (its sole upvalue, the directory userdatum, is already on the stack top */ lua_pushcclosure(L, dir_iter, 1); return 1; } static int dir_iter (lua_State *L) { DIR *d = *(DIR **)lua_touserdata(L, lua_upvalueindex(1)); struct dirent *entry; #ifdef _WIN32 struct _stat file_stat; #else struct stat file_stat; #endif if ((entry = readdir(d)) != NULL) { lua_newtable(L); lua_pushstring(L, "name"); lua_pushstring(L, entry->d_name); lua_settable(L, -3); #ifdef _WIN32 _stat(entry->d_name, &file_stat); #else stat(entry->d_name, &file_stat); #endif lua_pushstring(L, "type"); lua_pushnumber(L, (S_IFREG & file_stat.st_mode) ? 2 : ((S_IFDIR & file_stat.st_mode) ? 1 : 0)); lua_settable(L, -3); return 1; } else return 0; /* no more values to return */ } static int dir_gc (lua_State *L) { DIR *d = *(DIR **)lua_touserdata(L, 1); if (d) closedir(d); return 0; } static const luaL_reg dirlib[] = { {NULL, NULL} }; int luaopen_dir (lua_State *L) { luaL_openlib(L, LUA_DIRLIBNAME, dirlib, 0); luaL_newmetatable(L, "LuaBook.dir"); /* set its __gc field */ lua_pushstring(L, "__gc"); lua_pushcfunction(L, dir_gc); lua_settable(L, -3); /* register the `dir' function */ lua_pushcfunction(L, l_dir); lua_setglobal(L, "dir"); lua_pushnumber(L, 1); lua_setglobal(L, "FLAG_DIR"); lua_pushnumber(L, 2); lua_setglobal(L, "FLAG_FILE"); return 0; }