%.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
--- /dev/null
+--[[
+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
* 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)
* 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>
--- /dev/null
+/*
+ * 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);
+}
* 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>
* 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
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;
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;
}
/* 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);
#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;
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 */
* 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>
* 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>
* 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>
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);
--- /dev/null
+/*
+ * 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);
+}