summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSteven Barth <steven@midlink.org>2009-02-12 19:48:06 +0000
committerSteven Barth <steven@midlink.org>2009-02-12 19:48:06 +0000
commit5ff898e6248b668430f5f2e7d70de243f191eb04 (patch)
tree86d8807d89731c37c57981b5c0996138c77fdcf3
parent4327f9250e6d0f4a81ca949289d5e1444a360d4e (diff)
nixio next
splice() still does not work correctly
-rw-r--r--libs/nixio/Makefile2
-rw-r--r--libs/nixio/lua/nixio/util.lua70
-rw-r--r--libs/nixio/src/address.c6
-rw-r--r--libs/nixio/src/bind.c4
-rw-r--r--libs/nixio/src/file.c202
-rw-r--r--libs/nixio/src/io.c4
-rw-r--r--libs/nixio/src/nixio.c36
-rw-r--r--libs/nixio/src/nixio.h12
-rw-r--r--libs/nixio/src/poll.c4
-rw-r--r--libs/nixio/src/socket.c4
-rw-r--r--libs/nixio/src/sockopt.c6
-rw-r--r--libs/nixio/src/splice.c91
12 files changed, 405 insertions, 36 deletions
diff --git a/libs/nixio/Makefile b/libs/nixio/Makefile
index 6cc7254c8..53869bfba 100644
--- a/libs/nixio/Makefile
+++ b/libs/nixio/Makefile
@@ -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
index 000000000..962ef9d80
--- /dev/null
+++ b/libs/nixio/lua/nixio/util.lua
@@ -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
diff --git a/libs/nixio/src/address.c b/libs/nixio/src/address.c
index ae01c19ea..9ff063a33 100644
--- a/libs/nixio/src/address.c
+++ b/libs/nixio/src/address.c
@@ -16,15 +16,13 @@
* 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)
diff --git a/libs/nixio/src/bind.c b/libs/nixio/src/bind.c
index 66337eeb5..678ae5592 100644
--- a/libs/nixio/src/bind.c
+++ b/libs/nixio/src/bind.c
@@ -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
index 000000000..13a40c499
--- /dev/null
+++ b/libs/nixio/src/file.c
@@ -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);
+}
diff --git a/libs/nixio/src/io.c b/libs/nixio/src/io.c
index 30327b1c0..58054b2eb 100644
--- a/libs/nixio/src/io.c
+++ b/libs/nixio/src/io.c
@@ -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>
diff --git a/libs/nixio/src/nixio.c b/libs/nixio/src/nixio.c
index f152e05ea..327f65098 100644
--- a/libs/nixio/src/nixio.c
+++ b/libs/nixio/src/nixio.c
@@ -16,13 +16,10 @@
* 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);
diff --git a/libs/nixio/src/nixio.h b/libs/nixio/src/nixio.h
index 4b037b25e..e4bb6d6de 100644
--- a/libs/nixio/src/nixio.h
+++ b/libs/nixio/src/nixio.h
@@ -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 */
diff --git a/libs/nixio/src/poll.c b/libs/nixio/src/poll.c
index 7a397b96e..8fd585f22 100644
--- a/libs/nixio/src/poll.c
+++ b/libs/nixio/src/poll.c
@@ -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>
diff --git a/libs/nixio/src/socket.c b/libs/nixio/src/socket.c
index 9d4648671..f8fa3e649 100644
--- a/libs/nixio/src/socket.c
+++ b/libs/nixio/src/socket.c
@@ -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>
diff --git a/libs/nixio/src/sockopt.c b/libs/nixio/src/sockopt.c
index f1a326c75..c92254e88 100644
--- a/libs/nixio/src/sockopt.c
+++ b/libs/nixio/src/sockopt.c
@@ -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
index 000000000..37849751a
--- /dev/null
+++ b/libs/nixio/src/splice.c
@@ -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);
+}