2 * nixio - Linux I/O library for lua
4 * Copyright (C) 2009 Steven Barth <steven@midlink.org>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
26 #include <sys/types.h>
30 /* Reads argument from given index and transforms it into a mode bitfield */
31 int nixio__check_mode(lua_State
*L
, int idx
, int def
) {
32 if (lua_isnoneornil(L
, idx
) && def
> 0) {
34 } else if (lua_isstring(L
, idx
) && lua_objlen(L
, idx
) == 9) {
36 const char *modestr
= lua_tostring(L
, idx
);
39 if (i
% 3 == 0) { /* read flags */
40 if (modestr
[i
] == 'r') {
42 } else if (modestr
[i
] != '-') {
45 } else if (i
% 3 == 1) { /* write flags */
46 if (modestr
[i
] == 'w') {
48 } else if (modestr
[i
] != '-') {
52 if (modestr
[i
] == 'x') {
54 } else if (modestr
[i
] == 's') {
56 } else if (modestr
[i
] == 'S') {
58 } else if (modestr
[i
] != '-') {
62 if (modestr
[i
] == 'x') {
64 } else if (modestr
[i
] == 's') {
66 } else if (modestr
[i
] == 'S') {
68 } else if (modestr
[i
] != '-') {
72 if (modestr
[i
] == 'x') {
74 } else if (modestr
[i
] == 't') {
76 } else if (modestr
[i
] == 'T') {
78 } else if (modestr
[i
] != '-') {
83 if (i
== 9) { /* successfully parsed */
86 } else if (lua_isnumber(L
, idx
)) {
87 int decmode
= lua_tointeger(L
, idx
);
88 int s
= (decmode
% 10000) / 1000;
89 int u
= (decmode
% 1000) / 100;
90 int g
= (decmode
% 100) / 10;
91 int o
= (decmode
% 10);
93 if (s
>=0 && s
<=7 && u
>=0 && u
<=7 && g
>=0 && g
<=7 && o
>=0 && o
<=7) {
94 return (s
<< 9) + (u
<< 6) + (g
<< 3) + o
;
98 return luaL_argerror(L
, idx
, "supported values: [0-7]?[0-7][0-7][0-7], "
99 "[-r][-w][-xsS][-r][-w][-xsS][-r][-w][-xtT]");
102 /* Transforms a mode into the modestring */
103 int nixio__mode_write(int mode
, char *modestr
) {
105 modestr
[0] = (mode
& 00400) ? 'r' : '-';
106 modestr
[1] = (mode
& 00200) ? 'w' : '-';
107 modestr
[2] = ((mode
& 04100) == 04100) ? 's' :
108 (mode
& 04000) ? 'S' : (mode
& 00100) ? 'x' : '-';
109 modestr
[3] = (mode
& 00040) ? 'r' : '-';
110 modestr
[4] = (mode
& 00020) ? 'w' : '-';
111 modestr
[5] = ((mode
& 02010) == 02010) ? 's' :
112 (mode
& 02000) ? 'S' : (mode
& 00010) ? 'x' : '-';
113 modestr
[6] = (mode
& 00004) ? 'r' : '-';
114 modestr
[7] = (mode
& 00002) ? 'w' : '-';
115 modestr
[8] = ((mode
& 01001) == 01001) ? 't' :
116 (mode
& 01000) ? 'T' : (mode
& 00001) ? 'x' : '-';
119 return (mode
& 00007) + ((mode
& 00070) >> 3) * 10 +
120 ((mode
& 00700) >> 6) * 100 + ((mode
& 07000) >> 9) * 1000;
123 static int nixio_access(lua_State
*L
) {
124 const char *path
= luaL_checkstring(L
, 1);
127 for (const char *s
= luaL_optstring(L
, 2, "f"); *s
; s
++) {
130 } else if (*s
== 'w') {
132 } else if (*s
== 'x') {
134 } else if (*s
!= 'f') {
135 return luaL_argerror(L
, 2, "supported values: [frwx]");
139 return nixio__pstatus(L
, !access(path
, mode
));
142 static int nixio_basename(lua_State
*L
) {
143 const char *path
= luaL_checkstring(L
, 1);
145 base
[PATH_MAX
-1] = 0;
147 strncpy(base
, path
, PATH_MAX
-1);
148 lua_pushstring(L
, basename(base
));
152 static int nixio_dirname(lua_State
*L
) {
153 const char *path
= luaL_checkstring(L
, 1);
155 base
[PATH_MAX
-1] = 0;
157 strncpy(base
, path
, PATH_MAX
-1);
158 lua_pushstring(L
, dirname(base
));
162 static int nixio_realpath(lua_State
*L
) {
163 const char *path
= luaL_checkstring(L
, 1);
166 if (!realpath(path
, real
)) {
167 return nixio__perror(L
);
169 lua_pushstring(L
, real
);
174 static int nixio_remove(lua_State
*L
) {
175 return nixio__pstatus(L
, !remove(luaL_checkstring(L
, 1)));
178 static int nixio_unlink(lua_State
*L
) {
179 return nixio__pstatus(L
, !unlink(luaL_checkstring(L
, 1)));
182 static int nixio_rename(lua_State
*L
) {
183 return nixio__pstatus(L
,
184 !rename(luaL_checkstring(L
, 1), luaL_checkstring(L
, 2)));
187 static int nixio_rmdir(lua_State
*L
) {
188 return nixio__pstatus(L
, !rmdir(luaL_checkstring(L
, 1)));
191 static int nixio_mkdir(lua_State
*L
) {
192 return nixio__pstatus(L
,
193 !mkdir(luaL_checkstring(L
, 1), nixio__check_mode(L
, 2, 0777)));
196 static int nixio_chmod(lua_State
*L
) {
197 return nixio__pstatus(L
,
198 !chmod(luaL_checkstring(L
, 1), nixio__check_mode(L
, 2, -1)));
201 static int nixio_dir__gc(lua_State
*L
) {
202 DIR **dirp
= lua_touserdata(L
, 1);
210 static int nixio_dir__iter(lua_State
*L
) {
211 DIR **dirp
= lua_touserdata(L
, lua_upvalueindex(1));
212 struct dirent
*entry
;
213 const char *n
= NULL
;
217 entry
= readdir(*dirp
);
218 n
= (entry
) ? entry
->d_name
: NULL
;
219 } while(n
&& n
[0] == '.' && (n
[1] == 0 || (n
[1] == '.' && n
[2] == 0)));
223 lua_pushstring(L
, n
);
235 static int nixio_dir(lua_State
*L
) {
236 const char *path
= luaL_optstring(L
, 1, ".");
237 DIR **dirp
= lua_newuserdata(L
, sizeof(DIR *));
239 *dirp
= opendir(path
);
241 return nixio__perror(L
);
243 luaL_getmetatable(L
, NIXIO_DIR_META
);
244 lua_setmetatable(L
, -2);
245 lua_pushcclosure(L
, nixio_dir__iter
, 1);
250 static int nixio_link(lua_State
*L
) {
251 return nixio__pstatus(L
,
252 !link(luaL_checkstring(L
, 1), luaL_checkstring(L
, 2)));
255 static int nixio_utimes(lua_State
*L
) {
256 const char *path
= luaL_checkstring(L
, 1);
257 if (lua_gettop(L
) < 2 || (lua_isnoneornil(L
, 2) && lua_isnoneornil(L
, 3))) {
258 return nixio__pstatus(L
, !utimes(path
, NULL
));
260 double atime
= nixio__checknumber(L
, 2);
261 double mtime
= nixio__optnumber(L
, 3, atime
);
262 struct timeval times
[2];
264 times
[0].tv_sec
= atime
;
265 times
[0].tv_usec
= 0;
266 times
[1].tv_sec
= mtime
;
267 times
[1].tv_usec
= 0;
269 return nixio__pstatus(L
, !utimes(path
, times
));
273 int nixio__push_stat(lua_State
*L
, nixio_stat_t
*buf
) {
274 lua_createtable(L
, 0, 15);
276 lua_pushinteger(L
, buf
->st_dev
);
277 lua_setfield(L
, -2, "dev");
279 lua_pushinteger(L
, buf
->st_ino
);
280 lua_setfield(L
, -2, "ino");
282 if (S_ISREG(buf
->st_mode
)) {
283 lua_pushliteral(L
, "reg");
284 } else if (S_ISDIR(buf
->st_mode
)) {
285 lua_pushliteral(L
, "dir");
286 } else if (S_ISCHR(buf
->st_mode
)) {
287 lua_pushliteral(L
, "chr");
288 } else if (S_ISBLK(buf
->st_mode
)) {
289 lua_pushliteral(L
, "blk");
290 } else if (S_ISFIFO(buf
->st_mode
)) {
291 lua_pushliteral(L
, "fifo");
292 } else if (S_ISLNK(buf
->st_mode
)) {
293 lua_pushliteral(L
, "lnk");
294 } else if (S_ISSOCK(buf
->st_mode
)) {
295 lua_pushliteral(L
, "sock");
297 lua_pushliteral(L
, "unknown");
299 lua_setfield(L
, -2, "type");
302 lua_pushinteger(L
, nixio__mode_write(buf
->st_mode
, modestr
));
303 lua_setfield(L
, -2, "modedec");
305 lua_pushlstring(L
, modestr
, 9);
306 lua_setfield(L
, -2, "modestr");
308 lua_pushinteger(L
, buf
->st_nlink
);
309 lua_setfield(L
, -2, "nlink");
311 lua_pushinteger(L
, buf
->st_uid
);
312 lua_setfield(L
, -2, "uid");
314 lua_pushinteger(L
, buf
->st_gid
);
315 lua_setfield(L
, -2, "gid");
317 lua_pushinteger(L
, buf
->st_rdev
);
318 lua_setfield(L
, -2, "rdev");
320 nixio__pushnumber(L
, buf
->st_size
);
321 lua_setfield(L
, -2, "size");
323 lua_pushinteger(L
, buf
->st_atime
);
324 lua_setfield(L
, -2, "atime");
326 lua_pushinteger(L
, buf
->st_mtime
);
327 lua_setfield(L
, -2, "mtime");
329 lua_pushinteger(L
, buf
->st_ctime
);
330 lua_setfield(L
, -2, "ctime");
333 lua_pushinteger(L
, buf
->st_blksize
);
334 lua_setfield(L
, -2, "blksize");
336 lua_pushinteger(L
, buf
->st_blocks
);
337 lua_setfield(L
, -2, "blocks");
343 static int nixio_stat(lua_State
*L
) {
345 if (stat(luaL_checkstring(L
, 1), &buf
)) {
346 return nixio__perror(L
);
348 nixio__push_stat(L
, &buf
);
349 if (lua_isstring(L
, 2)) {
350 lua_getfield(L
, -1, lua_tostring(L
, 2));
356 static int nixio_lstat(lua_State
*L
) {
358 if (stat(luaL_checkstring(L
, 1), &buf
)) {
359 return nixio__perror(L
);
361 nixio__push_stat(L
, &buf
);
362 if (lua_isstring(L
, 2)) {
363 lua_getfield(L
, -1, lua_tostring(L
, 2));
371 static int nixio_chown(lua_State
*L
) {
372 return nixio__pstatus(L
,
374 luaL_checkstring(L
, 1),
375 lua_isnoneornil(L
, 2) ? -1 : nixio__check_user(L
, 2),
376 lua_isnoneornil(L
, 3) ? -1 : nixio__check_group(L
, 3)
381 static int nixio_lchown(lua_State
*L
) {
382 return nixio__pstatus(L
,
384 luaL_checkstring(L
, 1),
385 lua_isnoneornil(L
, 2) ? -1 : nixio__check_user(L
, 2),
386 lua_isnoneornil(L
, 3) ? -1 : nixio__check_group(L
, 3)
391 static int nixio_mkfifo(lua_State
*L
) {
392 return nixio__pstatus(L
,
393 !mkfifo(luaL_checkstring(L
, 1), nixio__check_mode(L
, 2, -1)));
396 static int nixio_symlink(lua_State
*L
) {
397 return nixio__pstatus(L
,
398 !symlink(luaL_checkstring(L
, 1), luaL_checkstring(L
, 2)));
401 static int nixio_readlink(lua_State
*L
) {
403 ssize_t res
= readlink(luaL_checkstring(L
, 1), dest
, sizeof(dest
));
405 return nixio__perror(L
);
407 lua_pushlstring(L
, dest
, res
);
420 static int nixio_glob__iter(lua_State
*L
) {
421 nixio_glob_t
*globres
= lua_touserdata(L
, lua_upvalueindex(1));
422 if (!globres
->freed
&& globres
->pos
< globres
->gl
.gl_pathc
) {
423 lua_pushstring(L
, globres
->gl
.gl_pathv
[(globres
->pos
)++]);
425 if (!globres
->freed
) {
426 globfree(&globres
->gl
);
434 static int nixio_glob__gc(lua_State
*L
) {
435 nixio_glob_t
*globres
= lua_touserdata(L
, 1);
436 if (globres
&& !globres
->freed
) {
438 globfree(&globres
->gl
);
443 static int nixio_glob(lua_State
*L
) {
444 const char *pattern
= luaL_optstring(L
, 1, "*");
445 nixio_glob_t
*globres
= lua_newuserdata(L
, sizeof(nixio_glob_t
));
447 return luaL_error(L
, NIXIO_OOM
);
452 int globstat
= glob(pattern
, 0, NULL
, &globres
->gl
);
453 if (globstat
== GLOB_NOMATCH
) {
454 lua_pushcfunction(L
, nixio__nulliter
);
455 lua_pushinteger(L
, 0);
456 } else if (globstat
) {
457 return nixio__perror(L
);
459 luaL_getmetatable(L
, NIXIO_GLOB_META
);
460 lua_setmetatable(L
, -2);
461 lua_pushcclosure(L
, nixio_glob__iter
, 1);
462 lua_pushinteger(L
, globres
->gl
.gl_pathc
);
467 #include <sys/statvfs.h>
469 static int nixio__push_statvfs(lua_State
*L
, struct statvfs
*buf
) {
470 lua_createtable(L
, 0, 12);
472 nixio__pushnumber(L
, buf
->f_bavail
);
473 lua_setfield(L
, -2, "bavail");
475 nixio__pushnumber(L
, buf
->f_bfree
);
476 lua_setfield(L
, -2, "bfree");
478 nixio__pushnumber(L
, buf
->f_blocks
);
479 lua_setfield(L
, -2, "blocks");
481 nixio__pushnumber(L
, buf
->f_bsize
);
482 lua_setfield(L
, -2, "bsize");
484 nixio__pushnumber(L
, buf
->f_frsize
);
485 lua_setfield(L
, -2, "frsize");
487 nixio__pushnumber(L
, buf
->f_favail
);
488 lua_setfield(L
, -2, "favail");
490 nixio__pushnumber(L
, buf
->f_ffree
);
491 lua_setfield(L
, -2, "ffree");
493 nixio__pushnumber(L
, buf
->f_files
);
494 lua_setfield(L
, -2, "files");
496 nixio__pushnumber(L
, buf
->f_flag
);
497 lua_setfield(L
, -2, "flag");
499 nixio__pushnumber(L
, buf
->f_fsid
);
500 lua_setfield(L
, -2, "fsid");
502 nixio__pushnumber(L
, buf
->f_namemax
);
503 lua_setfield(L
, -2, "namemax");
508 static int nixio_statvfs(lua_State
*L
) {
510 if (statvfs(luaL_optstring(L
, 1, "."), &buf
)) {
511 return nixio__perror(L
);
513 return nixio__push_statvfs(L
, &buf
);
517 #endif /* !__WINNT__ */
522 static const luaL_reg R
[] = {
524 {"glob", nixio_glob
},
525 {"mkfifo", nixio_mkfifo
},
526 {"symlink", nixio_symlink
},
527 {"readlink", nixio_readlink
},
528 {"chown", nixio_chown
},
529 {"lchown", nixio_lchown
},
530 {"statvfs", nixio_statvfs
},
532 {"chmod", nixio_chmod
},
533 {"access", nixio_access
},
534 {"basename", nixio_basename
},
536 {"dirname", nixio_dirname
},
537 {"realpath", nixio_realpath
},
538 {"mkdir", nixio_mkdir
},
539 {"rmdir", nixio_rmdir
},
540 {"link", nixio_link
},
541 {"unlink", nixio_unlink
},
542 {"utimes", nixio_utimes
},
543 {"rename", nixio_rename
},
544 {"remove", nixio_remove
},
545 {"stat", nixio_stat
},
546 {"lstat", nixio_lstat
},
550 void nixio_open_fs(lua_State
*L
) {
552 luaL_register(L
, NULL
, R
);
553 lua_setfield(L
, -2, "fs");
555 luaL_newmetatable(L
, NIXIO_DIR_META
);
556 lua_pushcfunction(L
, nixio_dir__gc
);
557 lua_setfield(L
, -2, "__gc");
561 luaL_newmetatable(L
, NIXIO_GLOB_META
);
562 lua_pushcfunction(L
, nixio_glob__gc
);
563 lua_setfield(L
, -2, "__gc");