diff options
author | Emil Renner Berthing <esmil@mailme.dk> | 2012-12-12 18:45:18 +0100 |
---|---|---|
committer | Emil Renner Berthing <esmil@mailme.dk> | 2012-12-17 10:11:06 +0100 |
commit | b368aaec1ac413ec107bcd8d2eca202bda301725 (patch) | |
tree | b0a678321abddd914f728ace8e706ce976591156 | |
parent | f25118928aa35861b370a6529c651a28f5c8859b (diff) | |
download | lem-b368aaec1ac413ec107bcd8d2eca202bda301725.tar.gz lem-b368aaec1ac413ec107bcd8d2eca202bda301725.tar.xz lem-b368aaec1ac413ec107bcd8d2eca202bda301725.zip |
io: rework io.open()
-rw-r--r-- | lem/io/core.c | 138 | ||||
-rw-r--r-- | lem/io/stream.c | 161 |
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) { |