#include <stdio.h>
#include <string.h>
#include <unistd.h>
+#include <sys/file.h>
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);
}
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);
}
}
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);
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");
{"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},
luaL_register(L, NULL, M);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
- lua_pop(L, 1);
+ lua_setfield(L, -2, "meta_file");
}