/* diriter ... -- entry */ static int ex_dir(lua_State *L) { const char *pathname; DIR **pd; struct dirent *d; switch (lua_type(L, 1)) { default: return luaL_typerror(L, 1, "pathname"); case LUA_TSTRING: pathname = lua_tostring(L, 1); lua_pushcfunction(L, ex_dir); /* pathname ... iter */ pd = lua_newuserdata(L, sizeof *pd);/* pathname ... iter state */ *pd = opendir(pathname); if (!*pd) return push_error(L); luaL_getmetatable(L, DIR_HANDLE); /* pathname ... iter state M */ lua_setmetatable(L, -2); /* pathname ... iter state */ lua_pushvalue(L, 1); /* pathname ... iter state pathname */ diriter_setpathname(L, -2); /* pathname ... iter state */ return 2; case LUA_TUSERDATA: pd = luaL_checkudata(L, 1, DIR_HANDLE); do d = readdir(*pd); while (d && isdotfile(d->d_name)); if (!d) { diriter_close(L); return push_error(L); } new_dirent(L); /* diriter ... entry */ diriter_getpathname(L, 1); /* diriter ... entry dir */ lua_pushstring(L, d->d_name); /* diriter ... entry dir name */ lua_pushvalue(L, -1); /* diriter ... entry dir name name */ lua_setfield(L, -4, "name"); /* diriter ... entry dir name */ lua_concat(L, 2); /* diriter ... entry fullpath */ lua_replace(L, 1); /* fullpath ... entry */ lua_replace(L, 2); /* fullpath entry ... */ return ex_dirent(L); } /*NOTREACHED*/ }
/* pathname/file [entry] -- entry */ static int ex_dirent(lua_State *L) { struct stat st; switch (lua_type(L, 1)) { default: return luaL_typerror(L, 1, "file or pathname"); case LUA_TSTRING: { const char *name = lua_tostring(L, 1); if (-1 == stat(name, &st)) return push_error(L); } break; case LUA_TUSERDATA: { FILE *f = check_file(L, 1, NULL); if (-1 == fstat(fileno(f), &st)) return push_error(L); } break; } if (lua_type(L, 2) != LUA_TTABLE) { lua_settop(L, 1); new_dirent(L); } else { lua_settop(L, 2); } if (S_ISDIR(st.st_mode)) lua_pushliteral(L, "directory"); else lua_pushliteral(L, "file"); lua_setfield(L, 2, "type"); lua_pushnumber(L, st.st_size); lua_setfield(L, 2, "size"); return 1; }
/* pathname/file [entry] -- entry */ static int ex_dirent(lua_State *L) { int isdir; lua_Number size; DWORD attr; switch (lua_type(L, 1)) { default: return luaL_typerror(L, 1, "file or pathname"); case LUA_TSTRING: { const char *name = lua_tostring(L, 1); attr = GetFileAttributes(name); if (attr == (DWORD)-1) return push_error(L); isdir = attr & FILE_ATTRIBUTE_DIRECTORY; if (isdir) size = 0; else size = get_file_size(name); } break; case LUA_TUSERDATA: { FILE *f = check_file(L, 1, NULL); BY_HANDLE_FILE_INFORMATION info; if (!GetFileInformationByHandle(file_handle(f), &info)) return push_error(L); attr = info.dwFileAttributes; isdir = attr & FILE_ATTRIBUTE_DIRECTORY; size = qword_to_number(info.nFileSizeHigh, info.nFileSizeLow); } break; } if (lua_type(L, 2) != LUA_TTABLE) { lua_settop(L, 1); new_dirent(L); } else { lua_settop(L, 2); } if (isdir) lua_pushliteral(L, "directory"); else lua_pushliteral(L, "file"); lua_setfield(L, 2, "type"); lua_pushnumber(L, size); lua_setfield(L, 2, "size"); return 1; }