From d9340154accd593984fa0d2101fe5f3b63f4c3a2 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 25 Nov 2002 13:05:39 -0200 Subject: [PATCH] `__tostring' for files + small bug (could do invalid read inside a userdata when it was not a file) --- liolib.c | 55 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/liolib.c b/liolib.c index 0ee9f94f..79855608 100644 --- a/liolib.c +++ b/liolib.c @@ -1,5 +1,5 @@ /* -** $Id: liolib.c,v 2.23 2002/11/14 15:41:38 roberto Exp roberto $ +** $Id: liolib.c,v 2.24 2002/11/18 16:53:19 roberto Exp roberto $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ @@ -54,23 +54,26 @@ static int pushresult (lua_State *L, int i, const char *filename) { } -static FILE *tofile (lua_State *L, int findex) { +static FILE **topfile (lua_State *L, int findex) { FILE **f = (FILE **)lua_touserdata(L, findex); - if (f && *f && lua_getmetatable(L, findex) && - lua_rawequal(L, -1, lua_upvalueindex(1))) { - lua_pop(L, 1); - return *f; + if (f == NULL || !lua_getmetatable(L, findex) || + !lua_rawequal(L, -1, lua_upvalueindex(1))) { + luaL_argerror(L, findex, "bad file"); } - if (findex > 0) { - if (f && *f == NULL) - luaL_error(L, "attempt to use a closed file"); - else - luaL_argerror(L, findex, "bad file"); - } - return NULL; + lua_pop(L, 1); + return f; } +static FILE *tofile (lua_State *L, int findex) { + FILE **f = topfile(L, findex); + if (*f == NULL) + luaL_error(L, "attempt to use a closed file"); + return *f; +} + + + /* ** When creating file handles, always creates a `closed' file handle ** before opening the actual file; so, if there is a memory error, the @@ -126,13 +129,25 @@ static int io_close (lua_State *L) { static int io_gc (lua_State *L) { - FILE **f = (FILE **)lua_touserdata(L, 1); - if (!(f && *f == NULL)) /* ignore closed files */ + FILE **f = topfile(L, 1); + if (*f != NULL) /* ignore closed files */ aux_close(L); return 0; } +static int io_tostring (lua_State *L) { + char buff[32]; + FILE **f = topfile(L, 1); + if (*f == NULL) + strcpy(buff, "closed"); + else + sprintf(buff, "%p", lua_touserdata(L, 1)); + lua_pushfstring(L, "file (%s)", buff); + return 1; +} + + static int io_open (lua_State *L) { const char *filename = luaL_checkstring(L, 1); const char *mode = luaL_optstring(L, 2, "r"); @@ -164,13 +179,9 @@ static int io_tmpfile (lua_State *L) { static FILE *getiofile (lua_State *L, const char *name) { - FILE *f; lua_pushstring(L, name); lua_rawget(L, lua_upvalueindex(1)); - f = tofile(L, -1); - if (f == NULL) - luaL_error(L, "%s is closed", name); - return f; + return tofile(L, -1); } @@ -478,6 +489,10 @@ static void createmeta (lua_State *L) { lua_pushvalue(L, -2); /* push metatable (will be upvalue for `gc' method) */ lua_pushcclosure(L, io_gc, 1); lua_rawset(L, -3); /* metatable.__gc = io_gc */ + lua_pushliteral(L, "__tostring"); + lua_pushvalue(L, -2); /* push metatable */ + lua_pushcclosure(L, io_tostring, 1); + lua_rawset(L, -3); /* file methods */ lua_pushliteral(L, "__index"); lua_pushvalue(L, -2); /* push metatable */