3 ** tek.os.posix - tek POSIX library
4 ** Written by Timm S. Mueller <tmueller at neoscientists.org>
5 ** See copyright notice in COPYRIGHT
10 #include <sys/types.h>
22 #define DIRCLASSNAME "dir*"
26 setfield(lua_State *L, const char *attr, const char *key, lua_Integer n)
28 if (attr == NULL || strcmp(attr, key) == 0)
29 lua_pushinteger(L, n);
31 lua_setfield(L, -2, key);
36 setstat(lua_State *L, int result, struct stat *s, const char *attr)
41 lua_pushstring(L, strerror(errno));
48 setfield(L, attr, "dev", s->st_dev);
49 setfield(L, attr, "ino", s->st_ino);
51 if (attr == NULL || strcmp(attr, "mode") == 0)
53 if (S_ISREG(s->st_mode))
54 lua_pushstring(L, "file");
55 else if (S_ISDIR(s->st_mode))
56 lua_pushstring(L, "directory");
57 else if (S_ISLNK(s->st_mode))
58 lua_pushstring(L, "link");
59 else if (S_ISSOCK(s->st_mode))
60 lua_pushstring(L, "socket");
61 else if (S_ISFIFO(s->st_mode))
62 lua_pushstring(L, "named pipe");
63 else if (S_ISCHR(s->st_mode))
64 lua_pushstring(L, "char device");
65 else if (S_ISBLK(s->st_mode))
66 lua_pushstring(L, "block device");
68 lua_pushstring(L, "other");
70 lua_setfield(L, -2, "mode");
73 setfield(L, attr, "nlink", s->st_nlink);
74 setfield(L, attr, "uid", s->st_uid);
75 setfield(L, attr, "gid", s->st_gid);
76 setfield(L, attr, "rdev", s->st_rdev);
77 setfield(L, attr, "access", s->st_atime);
78 setfield(L, attr, "modifications", s->st_mtime);
79 setfield(L, attr, "change", s->st_ctime);
80 setfield(L, attr, "size", s->st_size);
81 setfield(L, attr, "blocks", s->st_blocks);
82 setfield(L, attr, "blksize", s->st_blksize);
89 posix_stat(lua_State *L)
91 const char *path = luaL_checkstring(L, 1);
92 const char *attr = luaL_optstring(L, 2, NULL);
94 return setstat(L, stat(path, &s), &s, attr);
99 posix_lstat(lua_State *L)
101 const char *path = luaL_checkstring(L, 1);
102 const char *attr = luaL_optstring(L, 2, NULL);
104 return setstat(L, lstat(path, &s), &s, attr);
109 posix_opendir(lua_State *L)
111 const char *path = luaL_checkstring(L, 1);
112 DIR **pdir = lua_newuserdata(L, sizeof(void *));
114 lua_pushvalue(L, lua_upvalueindex(2)); /* class metatable */
115 /* attach metatable to the userdata object */
116 lua_setmetatable(L, -2); /* s: udata */
117 /* create class instance */
118 *pdir = opendir(path);
122 lua_pushstring(L, strerror(errno));
130 getinstptr(lua_State *L, int narg, const char *classname)
132 DIR **pinst = luaL_checkudata(L, narg, classname);
133 if (*pinst) return pinst;
134 luaL_argerror(L, narg, "Closed handle");
140 posix_closedir(lua_State *L)
142 DIR **pdir = getinstptr(L, 1, DIRCLASSNAME);
150 posix_readdir(lua_State *L)
152 DIR *dir = *getinstptr(L, 1, DIRCLASSNAME);
153 struct dirent *de = readdir(dir);
155 lua_pushstring(L, de->d_name);
163 posix_readlink(lua_State *L)
165 const char *path = luaL_checkstring(L, 1);
166 char buf[PATH_MAX + 1];
167 ssize_t len = readlink(path, buf, sizeof(buf) - 1);
171 lua_pushstring(L, strerror(errno));
175 lua_pushstring(L, buf);
181 posix_mkdir(lua_State *L)
183 const char *path = luaL_checkstring(L, 1);
184 if (mkdir(path, 0775) == 0)
186 lua_pushboolean(L, 1);
190 lua_pushstring(L, strerror(errno));
196 posix_symlink(lua_State *L)
198 const char *oldpath = luaL_checkstring(L, 1);
199 const char *newpath = luaL_checkstring(L, 2);
200 if (symlink(oldpath, newpath) == 0)
202 lua_pushboolean(L, 1);
206 lua_pushstring(L, strerror(errno));
212 resolvepath(const char *src, char *dest)
214 int len = strlen(src);
215 const char *sp = src + len;
217 int dc = 0, slc = 0, eac = 0, wc = 0;
251 /* resolve one eatcount */
253 /* now wait for next path part */
261 while (dc == 2 || dc == 1)
273 /* unresolved eatcount */
277 /* resolve remaining slash */
284 for (i = 0; i < len / 2; ++i)
287 dest[i] = dest[len - i - 1];
288 dest[len - i - 1] = t;
296 posix_abspath(lua_State *L)
298 const char *path = luaL_checkstring(L, 1);
302 char *srcpath, *dstpath;
316 char *newpwd = realloc(pwd, pwdsize);
321 if (!getcwd(pwd, pwdsize))
329 lua_pushstring(L, strerror(errno));
336 srcpath = malloc(len1 + 1 + len2 + 1);
337 dstpath = malloc(len1 + 1 + len2 + 1);
339 if (srcpath && dstpath)
343 strcpy(srcpath, pwd);
346 strcpy(srcpath + len1 + 1, path);
347 res = resolvepath(srcpath, dstpath);
352 lua_pushstring(L, dstpath);
359 lua_pushstring(L, "Not a valid path");
369 luaL_error(L, "Out of memory");
375 posix_nanosleep(lua_State *L)
378 lua_Number d = luaL_checknumber(L, 1);
380 req.tv_sec = (time_t) d;
381 req.tv_nsec = (long) ((d - req.tv_sec) * 1000000000);
383 if (nanosleep(&req, NULL) == 0)
385 lua_pushboolean(L, 1);
390 lua_pushstring(L, strerror(errno));
395 static const luaL_Reg lib[] =
397 { "stat", posix_stat },
398 { "lstat", posix_lstat },
399 { "opendir", posix_opendir },
400 { "closedir", posix_closedir },
401 { "readdir", posix_readdir },
402 { "mkdir", posix_mkdir },
403 { "readlink", posix_readlink },
404 { "symlink", posix_symlink },
405 { "abspath", posix_abspath },
406 { "nanosleep", posix_nanosleep },
411 static const luaL_Reg methods[] =
413 {"read", posix_readdir },
414 {"close", posix_closedir },
415 {"__gc", posix_closedir },
421 addclass(lua_State *L, const char *libname, const char *classname,
422 luaL_Reg *functions, luaL_Reg *methods, void *userdata)
424 luaL_newmetatable(L, classname); /* classtab */
425 lua_pushliteral(L, "__index"); /* classtab, "__index" */
427 /* insert self: classtab.__index = classtab */
428 lua_pushvalue(L, -2); /* classtab, "__index", classtab */
429 lua_rawset(L, -3); /* classtab */
431 /* insert methods. consume 1 userdata. do not create a new tab */
432 lua_pushlightuserdata(L, userdata); /* classtab, userdata */
433 luaL_openlib(L, NULL, methods, 1); /* classtab */
435 /* first upvalue: userdata */
436 lua_pushlightuserdata(L, userdata); /* classtab, userdata */
438 /* duplicate table argument to be used as second upvalue for cclosure */
439 lua_pushvalue(L, -2); /* classtab, userdata, classtab */
441 /* insert functions */
442 luaL_openlib(L, libname, functions, 2); /* classtab, libtab */
449 int luaopen_tek_os_posix(lua_State *L)
451 addclass(L, "tek.os.posix", DIRCLASSNAME,
452 (luaL_Reg *) lib, (luaL_Reg *) methods, NULL);