-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathluadir.c
More file actions
80 lines (63 loc) · 1.93 KB
/
luadir.c
File metadata and controls
80 lines (63 loc) · 1.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/* luaDIR API:
* export function, which return iterator by directory
* WARNING: not support non-ASCII paths
*
* name, isdir = dir(path)
* - path directory path
* > name current file/dir name
* > isdir name is directory
*/
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <lua54/lauxlib.h>
#include <lua54/lua.h>
#define LD_DIR_MT "luadir.dir"
typedef struct {
DIR* ptr;
const char* path;
} dir_t;
static int ld_iter(lua_State* L);
static int ld_dir(lua_State* L) {
const char* path = luaL_checkstring(L, 1);
luaL_argcheck(L, path != NULL, 1, "path cannot be empty");
dir_t* dir = lua_newuserdatauv(L, sizeof *dir, 0);
if ((dir->ptr = opendir(path)) == NULL)
luaL_error(L, "cannot open folder: %s", path);
dir->path = path;
(void)readdir(dir->ptr); // skip .
(void)readdir(dir->ptr); // skip ..
luaL_getmetatable(L, LD_DIR_MT);
lua_setmetatable(L, -2);
lua_pushcclosure(L, ld_iter, 1);
return 1;
}
static int ld_iter(lua_State* L) {
static char full_path[1024];
dir_t* dir = luaL_checkudata(L, lua_upvalueindex(1), LD_DIR_MT);
luaL_argcheck(L, dir != NULL, 1, "dir cannot be nil");
struct dirent* de;
if ((de = readdir(dir->ptr)) == NULL) return 0;
if (snprintf(full_path, sizeof full_path,
"%s/%s", dir->path, de->d_name) < 0)
luaL_error(L, "full path is very long");
struct stat st;
if (stat(full_path, &st)) return 0;
lua_pushstring(L, de->d_name);
lua_pushboolean(L, S_ISDIR(st.st_mode));
return 2;
}
static int ld_gc(lua_State* L) {
dir_t* dir = luaL_checkudata(L, 1, LD_DIR_MT);
if (dir->ptr) closedir(dir->ptr);
return 0;
}
LUA_API int luaopen_luadir(lua_State* L) {
luaL_newmetatable(L, LD_DIR_MT);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, ld_gc);
lua_setfield(L, -2, "__gc");
lua_pushcfunction(L, ld_dir);
return 1;
}