More splicing stuff
[project/luci.git] / libs / nixio / src / file.c
index 13a40c4..de43ee4 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/file.h>
 
 
 static int nixio_file(lua_State *L) {
@@ -33,7 +34,11 @@ static int nixio_file(lua_State *L) {
                return nixio__perror(L);
        }
 
-       FILE **udata = lua_newuserdata(L, sizeof(FILE**));
+       FILE **udata = lua_newuserdata(L, sizeof(FILE*));
+       if (!udata) {
+               return luaL_error(L, "out of memory");
+       }
+
        *udata = file;
 
        luaL_getmetatable(L, NIXIO_FILE_META);
@@ -50,7 +55,11 @@ static int nixio_pipe(lua_State *L) {
        }
 
        luaL_getmetatable(L, NIXIO_FILE_META);
-       udata = lua_newuserdata(L, sizeof(FILE**));
+       udata = lua_newuserdata(L, sizeof(FILE*));
+       if (!udata) {
+               return luaL_error(L, "out of memory");
+       }
+
        if (!(*udata = fdopen(pipefd[0], "r"))) {
                return nixio__perror(L);
        }
@@ -69,50 +78,44 @@ static int nixio_pipe(lua_State *L) {
 }
 
 static int nixio_file_write(lua_State *L) {
-       FILE *fp = nixio__checkfile(L);
-       size_t len, written;
+       int fd = nixio__checkfd(L, 1);
+       size_t len;
+       ssize_t sent;
        const char *data = luaL_checklstring(L, 2, &len);
-       written = fwrite(data, sizeof(char), len, fp);
-       if (written < 0) {
-               return nixio__perror(L);
+
+       do {
+               sent = write(fd, data, len);
+       } while(sent == -1 && errno == EINTR);
+       if (sent >= 0) {
+               lua_pushinteger(L, sent);
+               return 1;
        } else {
-               return written;
+               return nixio__perror(L);
        }
 }
 
-
-/* Some code borrowed from Lua 5.1.4 liolib.c */
 static int nixio_file_read(lua_State *L) {
-       FILE *f = nixio__checkfile(L);
-       size_t n = (size_t)luaL_checkinteger(L, 2);
-       luaL_argcheck(L, 2, n >= 0, "invalid length");
-
-       if (n == 0) {
-               if (feof(f)) {
-                       return 0;
-               } else {
-                       lua_pushliteral(L, "");
-                       return 1;
-               }
-       }
+       int fd = nixio__checkfd(L, 1);
+       char buffer[NIXIO_BUFFERSIZE];
+       int req = luaL_checkinteger(L, 2);
+       int readc;
 
-       size_t rlen;  /* how much to read */
-       size_t nr;  /* number of chars actually read */
-       luaL_Buffer b;
-       luaL_buffinit(L, &b);
-       rlen = LUAL_BUFFERSIZE;  /* try to read that much each time */
+       /* We limit the readsize to NIXIO_BUFFERSIZE */
+       req = (req > NIXIO_BUFFERSIZE) ? NIXIO_BUFFERSIZE : req;
 
        do {
-               char *p = luaL_prepbuffer(&b);
-               if (rlen > n) rlen = n;  /* cannot read more than asked */
-                       nr = fread(p, sizeof(char), rlen, f);
-                       luaL_addsize(&b, nr);
-                       n -= nr;  /* still have to read `n' chars */
-       } while (n > 0 && nr == rlen);  /* until end of count or eof */
-       luaL_pushresult(&b);  /* close buffer */
-       return (n == 0 || lua_objlen(L, -1) > 0);
+               readc = read(fd, buffer, req);
+       } while (readc == -1 && errno == EINTR);
+
+       if (readc < 0) {
+               return nixio__perror(L);
+       } else {
+               lua_pushlstring(L, buffer, readc);
+               return 1;
+       }
 }
 
+
 static int nixio_file_seek(lua_State *L) {
        FILE *f = nixio__checkfile(L);
        off_t len = (off_t)luaL_checknumber(L, 2);
@@ -146,6 +149,29 @@ static int nixio_file_flush(lua_State *L) {
        return nixio__pstatus(L, !fflush(f));
 }
 
+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");
+               }
+       }
+
+       return nixio__pstatus(L, !flock(fd, flags));
+}
+
 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");
@@ -178,6 +204,7 @@ static const luaL_reg M[] = {
        {"tell",                nixio_file_tell},
        {"seek",                nixio_file_seek},
        {"flush",               nixio_file_flush},
+       {"lock",                nixio_file_lock},
        {"close",               nixio_file_close},
        {"__gc",                nixio_file__gc},
        {"__tostring",  nixio_file__tostring},
@@ -198,5 +225,5 @@ void nixio_open_file(lua_State *L) {
        luaL_register(L, NULL, M);
        lua_pushvalue(L, -1);
        lua_setfield(L, -2, "__index");
-       lua_pop(L, 1);
+       lua_setfield(L, -2, "meta_file");
 }