nixio next
authorSteven Barth <steven@midlink.org>
Thu, 12 Feb 2009 19:48:06 +0000 (19:48 +0000)
committerSteven Barth <steven@midlink.org>
Thu, 12 Feb 2009 19:48:06 +0000 (19:48 +0000)
splice() still does not work correctly

12 files changed:
libs/nixio/Makefile
libs/nixio/lua/nixio/util.lua [new file with mode: 0644]
libs/nixio/src/address.c
libs/nixio/src/bind.c
libs/nixio/src/file.c [new file with mode: 0644]
libs/nixio/src/io.c
libs/nixio/src/nixio.c
libs/nixio/src/nixio.h
libs/nixio/src/poll.c
libs/nixio/src/socket.c
libs/nixio/src/sockopt.c
libs/nixio/src/splice.c [new file with mode: 0644]

index 6cc7254..53869bf 100644 (file)
@@ -5,7 +5,7 @@ include ../../build/gccconfig.mk
 %.o: %.c
        $(COMPILE) $(LUA_CFLAGS) $(FPIC) -c -o $@ $< 
 
-compile: src/nixio.o src/socket.o src/sockopt.o src/bind.o src/address.o src/poll.o src/io.o
+compile: src/nixio.o src/socket.o src/sockopt.o src/bind.o src/address.o src/poll.o src/io.o src/file.o src/splice.o
        $(LINK) $(SHLIB_FLAGS) -o src/nixio.so src/*.o
        mkdir -p dist$(LUA_LIBRARYDIR)
        cp src/nixio.so dist$(LUA_LIBRARYDIR)/nixio.so
diff --git a/libs/nixio/lua/nixio/util.lua b/libs/nixio/lua/nixio/util.lua
new file mode 100644 (file)
index 0000000..962ef9d
--- /dev/null
@@ -0,0 +1,70 @@
+--[[
+nixio - Linux I/O library for lua
+
+Copyright 2008 Steven Barth <steven@midlink.org>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+$Id$
+]]--
+
+local nixio = require "nixio"
+local setmetatable, assert = setmetatable, assert
+
+module "nixio.util"
+
+local BUFFERSIZE = 8096
+local socket = nixio.socket_meta
+
+function socket.sendall(self, data)
+       local sent, code, msg = self:send(data)
+
+       if not sent then
+               return sent, code, msg, data
+       end
+
+       while sent < #data do 
+               data = data:sub(sent + 1)
+               sent, code, msg = self:send(data)
+               
+               if not sent then
+                       return sent, code, msg, data
+               end
+       end
+       
+       return true
+end
+
+function socket.linesource(self, limit)
+       limit = limit or BUFFERSIZE
+       local buffer = ""
+       return function(flush)
+               local line, endp, _
+               
+               if flush then
+                       line = buffer
+                       buffer = ""
+                       return line
+               end
+
+               while not line do
+                       _, endp, line = buffer:find("^(.-)\r?\n")
+                       if line then
+                               buffer = buffer:sub(endp+1)
+                               return line
+                       elseif #buffer < limit then
+                               local newblock, code = self:recv(limit - #buffer)
+                               if not newblock then
+                                       return nil, code
+                               end
+                               buffer = buffer .. newblock
+                       else
+                               return nil, 0
+                       end
+               end
+       end
+end
\ No newline at end of file
index ae01c19..9ff063a 100644 (file)
  *  limitations under the License.
  */
 
-#include <lua.h>
-#include <lualib.h>
-#include <lauxlib.h>
+#include "nixio.h"
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
 #include <string.h>
 #include <netdb.h>
-#include "nixio.h"
+
 
 /**
  * getaddrinfo(host, family, port)
index 66337ee..678ae55 100644 (file)
@@ -16,9 +16,7 @@
  *  limitations under the License.
  */
 
-#include <lua.h>
-#include <lualib.h>
-#include <lauxlib.h>
+#include "nixio.h"
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
diff --git a/libs/nixio/src/file.c b/libs/nixio/src/file.c
new file mode 100644 (file)
index 0000000..13a40c4
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * nixio - Linux I/O library for lua
+ *
+ *   Copyright (C) 2009 Steven Barth <steven@midlink.org>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include "nixio.h"
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static int nixio_file(lua_State *L) {
+       const char *filename = luaL_checklstring(L, 1, NULL);
+       const char *mode = luaL_optlstring(L, 2, "r", NULL);
+
+       FILE *file = fopen(filename, mode);
+       if (!file) {
+               return nixio__perror(L);
+       }
+
+       FILE **udata = lua_newuserdata(L, sizeof(FILE**));
+       *udata = file;
+
+       luaL_getmetatable(L, NIXIO_FILE_META);
+       lua_setmetatable(L, -2);
+
+       return 1;
+}
+
+static int nixio_pipe(lua_State *L) {
+       int pipefd[2];
+       FILE **udata;
+       if (pipe(pipefd)) {
+               return nixio__perror(L);
+       }
+
+       luaL_getmetatable(L, NIXIO_FILE_META);
+       udata = lua_newuserdata(L, sizeof(FILE**));
+       if (!(*udata = fdopen(pipefd[0], "r"))) {
+               return nixio__perror(L);
+       }
+       lua_pushvalue(L, -2);
+       lua_setmetatable(L, -2);
+
+
+       udata = lua_newuserdata(L, sizeof(FILE**));
+       if (!(*udata = fdopen(pipefd[1], "w"))) {
+               return nixio__perror(L);
+       }
+       lua_pushvalue(L, -3);
+       lua_setmetatable(L, -2);
+
+       return 2;
+}
+
+static int nixio_file_write(lua_State *L) {
+       FILE *fp = nixio__checkfile(L);
+       size_t len, written;
+       const char *data = luaL_checklstring(L, 2, &len);
+       written = fwrite(data, sizeof(char), len, fp);
+       if (written < 0) {
+               return nixio__perror(L);
+       } else {
+               return written;
+       }
+}
+
+
+/* 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;
+               }
+       }
+
+       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 */
+
+       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);
+}
+
+static int nixio_file_seek(lua_State *L) {
+       FILE *f = nixio__checkfile(L);
+       off_t len = (off_t)luaL_checknumber(L, 2);
+       int whence;
+       const char *whstr = luaL_optlstring(L, 3, "set", NULL);
+       if (!strcmp(whstr, "set")) {
+               whence = SEEK_SET;
+       } else if (!strcmp(whstr, "cur")) {
+               whence = SEEK_CUR;
+       } else if (!strcmp(whstr, "end")) {
+               whence = SEEK_END;
+       } else {
+               return luaL_argerror(L, 3, "supported values: set, cur, end");
+       }
+       return nixio__pstatus(L, !fseeko(f, len, whence));
+}
+
+static int nixio_file_tell(lua_State *L) {
+       FILE *f = nixio__checkfile(L);
+       off_t pos = ftello(f);
+       if (pos < 0) {
+               return nixio__perror(L);
+       } else {
+               lua_pushnumber(L, (lua_Number)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_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;
+       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;
+       }
+       return 0;
+}
+
+/**
+ * string representation
+ */
+static int nixio_file__tostring(lua_State *L) {
+       lua_pushfstring(L, "nixio file %d", nixio__tofd(L, 1));
+       return 1;
+}
+
+/* method table */
+static const luaL_reg M[] = {
+       {"write",               nixio_file_write},
+       {"read",                nixio_file_read},
+       {"tell",                nixio_file_tell},
+       {"seek",                nixio_file_seek},
+       {"flush",               nixio_file_flush},
+       {"close",               nixio_file_close},
+       {"__gc",                nixio_file__gc},
+       {"__tostring",  nixio_file__tostring},
+       {NULL,                  NULL}
+};
+
+/* module table */
+static const luaL_reg R[] = {
+       {"open",                nixio_file},
+       {"pipe",                nixio_pipe},
+       {NULL,                  NULL}
+};
+
+void nixio_open_file(lua_State *L) {
+       luaL_register(L, NULL, R);
+
+       luaL_newmetatable(L, NIXIO_FILE_META);
+       luaL_register(L, NULL, M);
+       lua_pushvalue(L, -1);
+       lua_setfield(L, -2, "__index");
+       lua_pop(L, 1);
+}
index 30327b1..58054b2 100644 (file)
@@ -16,9 +16,7 @@
  *  limitations under the License.
  */
 
-#include <lua.h>
-#include <lualib.h>
-#include <lauxlib.h>
+#include "nixio.h"
 #include <errno.h>
 #include <stdlib.h>
 #include <stdio.h>
index f152e05..327f650 100644 (file)
  *  limitations under the License.
  */
 
-#include <lua.h>
-#include <lualib.h>
-#include <lauxlib.h>
+#include "nixio.h"
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
-#include "nixio.h"
 
 #define VERSION 0.1
 
@@ -52,6 +49,12 @@ nixio_sock* nixio__checksock(lua_State *L) {
     return sock;
 }
 
+FILE* nixio__checkfile(lua_State *L) {
+       FILE **fpp = (FILE**)luaL_checkudata(L, 1, NIXIO_FILE_META);
+       luaL_argcheck(L, *fpp, 1, "invalid file object");
+       return *fpp;
+}
+
 /* read fd from nixio_sock object */
 int nixio__checksockfd(lua_State *L) {
        return nixio__checksock(L)->fd;
@@ -67,15 +70,16 @@ int nixio__checkfd(lua_State *L, int ud) {
 int nixio__tofd(lua_State *L, int ud) {
        void *udata = lua_touserdata(L, ud);
        int fd = -1;
-       if (udata && lua_getmetatable(L, ud)) {
+       if (lua_getmetatable(L, ud)) {
                luaL_getmetatable(L, NIXIO_META);
+               luaL_getmetatable(L, NIXIO_FILE_META);
                luaL_getmetatable(L, LUA_FILEHANDLE);
-               if (lua_rawequal(L, -2, -3)) {
+               if (lua_rawequal(L, -3, -4)) {
                        fd = ((nixio_sock*)udata)->fd;
-               } else if (lua_rawequal(L, -1, -3)) {
-                       fd = fileno(*((FILE **)udata));
+               } else if (lua_rawequal(L, -2, -4) || lua_rawequal(L, -1, -4)) {
+                       fd = (*((FILE **)udata)) ? fileno(*((FILE **)udata)) : -1;
                }
-               lua_pop(L, 3);
+               lua_pop(L, 4);
        }
        return fd;
 }
@@ -90,24 +94,26 @@ LUALIB_API int luaopen_nixio(lua_State *L) {
        /* create metatable */
        luaL_newmetatable(L, NIXIO_META);
 
-       /* method table */
-       lua_newtable(L);
+       /* metatable.__index = metatable */
        lua_pushvalue(L, -1);
-
-       /* metatable.__index = M */
-       lua_setfield(L, -3, "__index");
-       lua_remove(L, -2);
+       lua_setfield(L, -2, "__index");
 
        /* register module */
        luaL_register(L, "nixio", R);
 
+       /* register metatable as socket_meta */
+       lua_pushvalue(L, -2);
+       lua_setfield(L, -2, "socket_meta");
+
        /* register methods */
+       nixio_open_file(L);
        nixio_open_socket(L);
        nixio_open_sockopt(L);
        nixio_open_bind(L);
        nixio_open_address(L);
        nixio_open_poll(L);
        nixio_open_io(L);
+       nixio_open_splice(L);
 
        /* module version */
        lua_pushnumber(L, VERSION);
index 4b037b2..e4bb6d6 100644 (file)
@@ -2,7 +2,16 @@
 #define NIXIO_H_
 
 #define NIXIO_META "nixio.socket"
+#define NIXIO_FILE_META "nixio.file"
 #define NIXIO_BUFFERSIZE 8096
+#define _FILE_OFFSET_BITS 64
+
+/* uClibc: broken as always */
+#define _LARGEFILE_SOURCE
+
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
 
 struct nixio_socket {
        int fd;
@@ -19,14 +28,17 @@ nixio_sock* nixio__checksock(lua_State *L);
 int nixio__checksockfd(lua_State *L);
 int nixio__checkfd(lua_State *L, int ud);
 int nixio__tofd(lua_State *L, int ud);
+FILE* nixio__checkfile(lua_State *L);
 
 /* Module functions */
+void nixio_open_file(lua_State *L);
 void nixio_open_socket(lua_State *L);
 void nixio_open_sockopt(lua_State *L);
 void nixio_open_bind(lua_State *L);
 void nixio_open_address(lua_State *L);
 void nixio_open_poll(lua_State *L);
 void nixio_open_io(lua_State *L);
+void nixio_open_splice(lua_State *L);
 
 /* Method functions */
 
index 7a397b9..8fd585f 100644 (file)
@@ -16,9 +16,7 @@
  *  limitations under the License.
  */
 
-#include <lua.h>
-#include <lualib.h>
-#include <lauxlib.h>
+#include "nixio.h"
 #include <poll.h>
 #include <time.h>
 #include <errno.h>
index 9d46486..f8fa3e6 100644 (file)
@@ -16,9 +16,7 @@
  *  limitations under the License.
  */
 
-#include <lua.h>
-#include <lualib.h>
-#include <lauxlib.h>
+#include "nixio.h"
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <unistd.h>
index f1a326c..c92254e 100644 (file)
@@ -16,9 +16,7 @@
  *  limitations under the License.
  */
 
-#include <lua.h>
-#include <lualib.h>
-#include <lauxlib.h>
+#include "nixio.h"
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
@@ -181,7 +179,7 @@ void nixio_open_sockopt(lua_State *L) {
        luaL_register(L, NULL, M);
        lua_pop(L, 1);
 
-       luaL_getmetatable(L, LUA_FILEHANDLE);
+       luaL_getmetatable(L, NIXIO_FILE_META);
        lua_pushcfunction(L, nixio_sock_setblocking);
        lua_setfield(L, -2, "setblocking");
        lua_pop(L, 1);
diff --git a/libs/nixio/src/splice.c b/libs/nixio/src/splice.c
new file mode 100644 (file)
index 0000000..3784975
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * nixio - Linux I/O library for lua
+ *
+ *   Copyright (C) 2009 Steven Barth <steven@midlink.org>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#define _GNU_SOURCE
+
+#include "nixio.h"
+#include <fcntl.h>
+
+/* guess what sucks... */
+#ifdef __UCLIBC__
+#include <unistd.h>
+#include <sys/syscall.h>
+ssize_t splice(int __fdin, __off64_t *__offin, int __fdout,
+        __off64_t *__offout, size_t __len, unsigned int __flags) {
+       return syscall(__NR_splice, __fdin, __offin, __fdout, __offout, __len, __flags);
+}
+#endif
+
+
+/**
+ * Checks whether a flag is set in the table and translates it into a bitmap
+ */
+static void nixio_splice_flags__w(lua_State *L, int *m, int f, const char *t) {
+       lua_pushstring(L, t);
+       lua_rawget(L, -2);
+       if (lua_toboolean(L, -1)) {
+               *m |= f;
+       }
+       lua_pop(L, 1);
+}
+
+/**
+ * Translate integer to poll flags and vice versa
+ */
+static int nixio_splice_flags(lua_State *L) {
+       int flags = 0;
+
+       luaL_checktype(L, 1, LUA_TTABLE);
+       lua_settop(L, 1);
+       nixio_splice_flags__w(L, &flags, SPLICE_F_MOVE, "move");
+       nixio_splice_flags__w(L, &flags, SPLICE_F_NONBLOCK, "nonblock");
+       nixio_splice_flags__w(L, &flags, SPLICE_F_MORE, "more");
+       lua_pushinteger(L, flags);
+
+       return 1;
+}
+
+static int nixio_splice(lua_State *L) {
+       int fd_in = nixio__checkfd(L, 1);
+       int fd_out = nixio__checkfd(L, 2);
+       size_t len = luaL_checkinteger(L, 3);
+       int flags = luaL_optinteger(L, 4, 0);
+
+
+       long spliced = splice(fd_in, NULL, fd_out, NULL, len, flags);
+
+       if (spliced < 0) {
+               return nixio__perror(L);
+       }
+
+       lua_pushnumber(L, spliced);
+       return 1;
+}
+
+
+
+/* module table */
+static const luaL_reg R[] = {
+       {"splice",                      nixio_splice},
+       {"splice_flags",        nixio_splice_flags},
+       {NULL,                  NULL}
+};
+
+void nixio_open_splice(lua_State *L) {
+       luaL_register(L, NULL, R);
+}