nixio:
[project/luci.git] / libs / nixio / src / file.c
index de43ee487d561511161e75fddea6ed97361361cc..5229b4988b448f79ca96ee78bf680d4a02c098ab 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
-#include <sys/file.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 
-static int nixio_file(lua_State *L) {
+static int nixio_open(lua_State *L) {
        const char *filename = luaL_checklstring(L, 1, NULL);
-       const char *mode = luaL_optlstring(L, 2, "r", NULL);
+       int flags = luaL_optint(L, 2, O_RDONLY);
+       int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+       int fd;
 
-       FILE *file = fopen(filename, mode);
-       if (!file) {
+       do {
+               fd = open(filename, flags, mode);
+       } while (fd == -1 && errno == EINTR);
+       if (fd == -1) {
                return nixio__perror(L);
        }
 
-       FILE **udata = lua_newuserdata(L, sizeof(FILE*));
+       int *udata = lua_newuserdata(L, sizeof(int));
        if (!udata) {
                return luaL_error(L, "out of memory");
        }
 
-       *udata = file;
+       *udata = fd;
 
        luaL_getmetatable(L, NIXIO_FILE_META);
        lua_setmetatable(L, -2);
@@ -47,30 +53,81 @@ static int nixio_file(lua_State *L) {
        return 1;
 }
 
+static int nixio_open_flags(lua_State *L) {
+       int mode = 0;
+       const int j = lua_gettop(L);
+       for (int i=1; i<=j; i++) {
+               const char *flag = luaL_checkstring(L, i);
+               if (!strcmp(flag, "append")) {
+                       mode |= O_APPEND;
+               } else if (!strcmp(flag, "creat")) {
+                       mode |= O_CREAT;
+               } else if (!strcmp(flag, "excl")) {
+                       mode |= O_EXCL;
+               } else if (!strcmp(flag, "nonblock") || !strcmp(flag, "ndelay")) {
+                       mode |= O_NONBLOCK;
+               } else if (!strcmp(flag, "sync")) {
+                       mode |= O_SYNC;
+               } else if (!strcmp(flag, "trunc")) {
+                       mode |= O_TRUNC;
+               } else if (!strcmp(flag, "rdonly")) {
+                       mode |= O_RDONLY;
+               } else if (!strcmp(flag, "wronly")) {
+                       mode |= O_WRONLY;
+               } else if (!strcmp(flag, "rdwr")) {
+                       mode |= O_RDWR;
+               } else {
+                       return luaL_argerror(L, i, "supported values: append, creat, "
+                                       "excl, nonblock, ndelay, sync, trunc");
+               }
+       }
+       lua_pushinteger(L, mode);
+       return 1;
+}
+
+static int nixio_dup(lua_State *L) {
+       int oldfd = nixio__checkfd(L, 1);
+       int newfd = (lua_gettop(L) > 1) ? nixio__checkfd(L, 2) : -1;
+       int stat  = (newfd == -1) ? dup(oldfd) : dup2(oldfd, newfd);
+
+       if (stat == -1) {
+               return nixio__perror(L);
+       } else {
+               int *udata = lua_newuserdata(L, sizeof(int));
+               if (!udata) {
+                       return luaL_error(L, "out of memory");
+               }
+
+               *udata = stat;
+               luaL_getmetatable(L, NIXIO_FILE_META);
+               lua_setmetatable(L, -2);
+               return 1;
+       }
+}
+
 static int nixio_pipe(lua_State *L) {
-       int pipefd[2];
-       FILE **udata;
+       int pipefd[2], *udata;
        if (pipe(pipefd)) {
                return nixio__perror(L);
        }
 
        luaL_getmetatable(L, NIXIO_FILE_META);
-       udata = lua_newuserdata(L, sizeof(FILE*));
+       udata = lua_newuserdata(L, sizeof(int));
        if (!udata) {
                return luaL_error(L, "out of memory");
        }
 
-       if (!(*udata = fdopen(pipefd[0], "r"))) {
-               return nixio__perror(L);
-       }
+       *udata = pipefd[0];
        lua_pushvalue(L, -2);
        lua_setmetatable(L, -2);
 
 
-       udata = lua_newuserdata(L, sizeof(FILE**));
-       if (!(*udata = fdopen(pipefd[1], "w"))) {
-               return nixio__perror(L);
+       udata = lua_newuserdata(L, sizeof(int));
+       if (!udata) {
+               return luaL_error(L, "out of memory");
        }
+
+       *udata = pipefd[1];
        lua_pushvalue(L, -3);
        lua_setmetatable(L, -2);
 
@@ -117,7 +174,7 @@ static int nixio_file_read(lua_State *L) {
 
 
 static int nixio_file_seek(lua_State *L) {
-       FILE *f = nixio__checkfile(L);
+       int fd = nixio__checkfd(L, 1);
        off_t len = (off_t)luaL_checknumber(L, 2);
        int whence;
        const char *whstr = luaL_optlstring(L, 3, "set", NULL);
@@ -130,61 +187,78 @@ static int nixio_file_seek(lua_State *L) {
        } else {
                return luaL_argerror(L, 3, "supported values: set, cur, end");
        }
-       return nixio__pstatus(L, !fseeko(f, len, whence));
+       len = lseek(fd, len, whence);
+       if (len == -1) {
+               return nixio__perror(L);
+       } else {
+               lua_pushnumber(L, len);
+               return 1;
+       }
 }
 
 static int nixio_file_tell(lua_State *L) {
-       FILE *f = nixio__checkfile(L);
-       off_t pos = ftello(f);
+       int fd = nixio__checkfd(L, 1);
+       off_t pos = lseek(fd, 0, SEEK_CUR);
        if (pos < 0) {
                return nixio__perror(L);
        } else {
-               lua_pushnumber(L, (lua_Number)pos);
+               lua_pushnumber(L, pos);
                return 1;
        }
 }
 
-static int nixio_file_flush(lua_State *L) {
-       FILE *f = nixio__checkfile(L);
-       return nixio__pstatus(L, !fflush(f));
+static int nixio_file_sync(lua_State *L) {
+       int fd = nixio__checkfd(L, 1);
+       int meta = lua_toboolean(L, 2);
+       return nixio__pstatus(L, (meta) ? !fsync(fd) : !fdatasync(fd));
 }
 
 static int nixio_file_lock(lua_State *L) {
-       int fd = fileno(nixio__checkfile(L));
-
-       const int j = lua_gettop(L);
-       int flags = 0;
-       for (int i=2; i<=j; i++) {
-               const char *flag = luaL_checkstring(L, i);
-               if (!strcmp(flag, "sh")) {
-                       flags |= LOCK_SH;
-               } else if (!strcmp(flag, "ex")) {
-                       flags |= LOCK_EX;
-               } else if (!strcmp(flag, "un")) {
-                       flags |= LOCK_UN;
-               } else if (!strcmp(flag, "nb")) {
-                       flags |= LOCK_NB;
-               } else {
-                       return luaL_argerror(L, i, "supported values: sh, ex, un, nb");
-               }
+       int fd = nixio__checkfd(L, 1);
+       const char *flag = luaL_checkstring(L, 2);
+       off_t len = (off_t)luaL_optnumber(L, 3, 0);
+       int stat;
+
+       int cmd = 0;
+       if (!strcmp(flag, "lock")) {
+               cmd = F_LOCK;
+       } else if (!strcmp(flag, "tlock")) {
+               cmd = F_TLOCK;
+       } else if (!strcmp(flag, "ulock")) {
+               cmd = F_ULOCK;
+       } else if (!strcmp(flag, "test")) {
+               cmd = F_TEST;
+       } else {
+               return luaL_argerror(L, 2,
+                               "supported values: lock, tlock, ulock, test");
        }
 
-       return nixio__pstatus(L, !flock(fd, flags));
+       do {
+               stat = lockf(fd, cmd, len);
+       } while (stat == -1 && errno == EINTR);
+
+       return nixio__pstatus(L, !stat);
 }
 
 static int nixio_file_close(lua_State *L) {
-       FILE **fpp = (FILE**)luaL_checkudata(L, 1, NIXIO_FILE_META);
-       luaL_argcheck(L, *fpp, 1, "invalid file object");
-       int res = fclose(*fpp);
-       *fpp = NULL;
+       int *fdp = luaL_checkudata(L, 1, NIXIO_FILE_META);
+       luaL_argcheck(L, *fdp != -1, 1, "invalid file object");
+       int res;
+       do {
+               res = close(*fdp);
+       } while (res == -1 && errno == EINTR);
+       *fdp = -1;
        return nixio__pstatus(L, !res);
 }
 
 static int nixio_file__gc(lua_State *L) {
-       FILE **fpp = (FILE**)luaL_checkudata(L, 1, NIXIO_FILE_META);
-       if (*fpp) {
-               fclose(*fpp);
-               *fpp = NULL;
+       int *fdp = luaL_checkudata(L, 1, NIXIO_FILE_META);
+       int res;
+       if (*fdp != -1) {
+               do {
+                       res = close(*fdp);
+               } while (res == -1 && errno == EINTR);
+               *fdp = -1;
        }
        return 0;
 }
@@ -203,7 +277,7 @@ static const luaL_reg M[] = {
        {"read",                nixio_file_read},
        {"tell",                nixio_file_tell},
        {"seek",                nixio_file_seek},
-       {"flush",               nixio_file_flush},
+       {"sync",                nixio_file_sync},
        {"lock",                nixio_file_lock},
        {"close",               nixio_file_close},
        {"__gc",                nixio_file__gc},
@@ -213,7 +287,9 @@ static const luaL_reg M[] = {
 
 /* module table */
 static const luaL_reg R[] = {
-       {"open",                nixio_file},
+       {"dup",                 nixio_dup},
+       {"open",                nixio_open},
+       {"open_flags",  nixio_open_flags},
        {"pipe",                nixio_pipe},
        {NULL,                  NULL}
 };