summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmil Renner Berthing <esmil@mailme.dk>2012-12-12 18:45:18 +0100
committerEmil Renner Berthing <esmil@mailme.dk>2012-12-17 10:11:06 +0100
commitb368aaec1ac413ec107bcd8d2eca202bda301725 (patch)
treeb0a678321abddd914f728ace8e706ce976591156
parentf25118928aa35861b370a6529c651a28f5c8859b (diff)
downloadlem-b368aaec1ac413ec107bcd8d2eca202bda301725.tar.gz
lem-b368aaec1ac413ec107bcd8d2eca202bda301725.tar.xz
lem-b368aaec1ac413ec107bcd8d2eca202bda301725.zip
io: rework io.open()
-rw-r--r--lem/io/core.c138
-rw-r--r--lem/io/stream.c161
2 files changed, 137 insertions, 162 deletions
diff --git a/lem/io/core.c b/lem/io/core.c
index 5f964be..33be6e0 100644
--- a/lem/io/core.c
+++ b/lem/io/core.c
@@ -93,6 +93,142 @@ module_index(lua_State *T)
return 1;
}
+struct open {
+ struct lem_async a;
+ const char *path;
+ int fd;
+ int flags;
+};
+
+static void
+io_open_work(struct lem_async *a)
+{
+ struct open *o = (struct open *)a;
+ int fd;
+ struct stat st;
+
+ fd = open(o->path, o->flags | O_NONBLOCK,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (fd < 0) {
+ o->flags = -errno;
+ return;
+ }
+
+ if (fstat(fd, &st)) {
+ o->flags = -errno;
+ close(fd);
+ return;
+ }
+
+ o->fd = fd;
+ lem_debug("st.st_mode & S_IFMT = %o", st.st_mode & S_IFMT);
+ switch (st.st_mode & S_IFMT) {
+ case S_IFREG:
+ case S_IFBLK:
+ o->flags = 0;
+ break;
+
+ case S_IFSOCK:
+ case S_IFCHR:
+ case S_IFIFO:
+ o->flags = 1;
+ break;
+
+ default:
+ o->flags = -EINVAL;
+ break;
+ }
+}
+
+static void
+io_open_reap(struct lem_async *a)
+{
+ struct open *o = (struct open *)a;
+ lua_State *T = o->a.T;
+ int fd = o->fd;
+ int ret = o->flags;
+
+ lem_debug("ret = %d", ret);
+ free(o);
+
+ switch (ret) {
+ case 0: file_new(T, fd, 2); break;
+ case 1: stream_new(T, fd, 3); break;
+ default:
+ lua_pushnil(T);
+ lua_pushstring(T, strerror(-ret));
+ lem_queue(T, 2);
+ return;
+ }
+
+ lem_queue(T, 1);
+}
+
+static int
+io_mode_to_flags(const char *mode)
+{
+ int omode;
+ int oflags;
+
+ switch (*mode++) {
+ case 'r':
+ omode = O_RDONLY;
+ oflags = 0;
+ break;
+ case 'w':
+ omode = O_WRONLY;
+ oflags = O_CREAT | O_TRUNC;
+ break;
+ case 'a':
+ omode = O_WRONLY;
+ oflags = O_CREAT | O_APPEND;
+ break;
+ default:
+ return -1;
+ }
+
+next:
+ switch (*mode++) {
+ case '\0':
+ break;
+ case '+':
+ omode = O_RDWR;
+ goto next;
+ case 'b':
+ /* this does nothing on *nix, but
+ * don't treat it as an error */
+ goto next;
+ case 'x':
+ oflags |= O_EXCL;
+ goto next;
+ default:
+ return -1;
+ }
+
+ return omode | oflags;
+}
+
+static int
+io_open(lua_State *T)
+{
+ const char *path = luaL_checkstring(T, 1);
+ int flags = io_mode_to_flags(luaL_optstring(T, 2, "r"));
+ struct open *o;
+
+ if (flags < 0)
+ return luaL_error(T, "invalid mode string");
+
+ o = lem_xmalloc(sizeof(struct open));
+ o->path = path;
+ o->flags = flags;
+ lem_async_do(&o->a, T, io_open_work, io_open_reap);
+
+ lua_settop(T, 1);
+ lua_pushvalue(T, lua_upvalueindex(1));
+ lua_pushvalue(T, lua_upvalueindex(2));
+ return lua_yield(T, 3);
+}
+
int
luaopen_lem_io_core(lua_State *L)
{
@@ -213,7 +349,7 @@ luaopen_lem_io_core(lua_State *L)
/* insert open function */
lua_getfield(L, -1, "File"); /* upvalue 1 = File */
lua_getfield(L, -2, "Stream"); /* upvalue 2 = Stream */
- lua_pushcclosure(L, stream_open, 2);
+ lua_pushcclosure(L, io_open, 2);
lua_setfield(L, -2, "open");
/* insert popen function */
lua_getfield(L, -1, "Stream"); /* upvalue 1 = Stream */
diff --git a/lem/io/stream.c b/lem/io/stream.c
index 9c36484..a34856b 100644
--- a/lem/io/stream.c
+++ b/lem/io/stream.c
@@ -451,167 +451,6 @@ stream_sendfile(lua_State *T)
return lua_yield(T, 3);
}
-struct open {
- struct lem_async a;
- const char *path;
- int fd;
- int flags;
- int type;
-};
-
-static void
-stream_open_work(struct lem_async *a)
-{
- struct open *o = (struct open *)a;
- int fd;
- struct stat st;
-
- fd = open(o->path, o->flags | O_NONBLOCK,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
- if (fd < 0)
- goto error;
-
- if (fstat(fd, &st))
- goto error;
-
- o->fd = fd;
- lem_debug("st.st_mode & S_IFMT = %o", st.st_mode & S_IFMT);
- switch (st.st_mode & S_IFMT) {
- case S_IFSOCK:
- case S_IFCHR:
- case S_IFIFO:
- o->type = 1;
- break;
-
- case S_IFREG:
- case S_IFBLK:
- o->type = 0;
- break;
-
- default:
- o->type = -1;
- }
-
- return;
-
-error:
- o->fd = -errno;
-}
-
-static void
-stream_open_reap(struct lem_async *a)
-{
- struct open *o = (struct open *)a;
- lua_State *T = o->a.T;
- int fd = o->fd;
- int ret = o->type;
-
- lem_debug("o->type = %d", ret);
- free(o);
-
- if (fd < 0) {
- lua_pushnil(T);
- lua_pushstring(T, strerror(-o->fd));
- /*
- switch (-o->fd) {
- case ENOENT:
- lua_pushliteral(T, "not found");
- break;
- case EACCES:
- lua_pushliteral(T, "permission denied");
- break;
- default:
- lua_pushstring(T, strerror(errno));
- }
- */
- lem_queue(T, 2);
- return;
- }
-
- if (ret < 0) {
- lua_pushnil(T);
- lua_pushliteral(T, "invalid type");
- lem_queue(T, 2);
- return;
- }
-
- if (ret == 0)
- file_new(T, fd, lua_upvalueindex(3));
- else
- stream_new(T, fd, lua_upvalueindex(1));
-
- lem_queue(T, 1);
-}
-
-static int
-mode_to_flags(const char *mode)
-{
- int omode;
- int oflags;
-
- switch (*mode++) {
- case 'r':
- omode = O_RDONLY;
- oflags = 0;
- break;
- case 'w':
- omode = O_WRONLY;
- oflags = O_CREAT | O_TRUNC;
- break;
- case 'a':
- omode = O_WRONLY;
- oflags = O_CREAT | O_APPEND;
- break;
- default:
- return -1;
- }
-
-next:
- switch (*mode++) {
- case '\0':
- break;
- case '+':
- omode = O_RDWR;
- goto next;
- case 'b':
- /* this does nothing on *nix, but
- * don't treat it as an error */
- goto next;
- case 'x':
- oflags |= O_EXCL;
- goto next;
- default:
- return -1;
- }
-
- return omode | oflags;
-}
-
-static int
-stream_open(lua_State *T)
-{
- const char *path = luaL_checkstring(T, 1);
- int flags = mode_to_flags(luaL_optstring(T, 2, "r"));
- struct open *o;
- int args;
-
- if (flags < 0)
- return luaL_error(T, "invalid mode string");
-
- o = lem_xmalloc(sizeof(struct open));
- o->path = path;
- o->flags = flags;
-
- lem_async_do(&o->a, T, stream_open_work, stream_open_reap);
-
- args = lua_gettop(T);
- if (args > 2) {
- lua_settop(T, 2);
- args = 2;
- }
- return lua_yield(T, args);
-}
-
static int
stream_popen(lua_State *T)
{