diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-10-16 17:41:35 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-10-16 17:41:35 -0300 |
commit | ec748fcb0a6913a814f106218e9fde3a73ffc014 (patch) | |
tree | ba0355be86136353a49dd6271e3d757600dc813c /liolib.c | |
parent | c196348717dfda116726145220e5d1311547980e (diff) | |
download | lua-ec748fcb0a6913a814f106218e9fde3a73ffc014.tar.gz lua-ec748fcb0a6913a814f106218e9fde3a73ffc014.tar.bz2 lua-ec748fcb0a6913a814f106218e9fde3a73ffc014.zip |
correct handling of opened files in presence of memory allocation
errors
Diffstat (limited to 'liolib.c')
-rw-r--r-- | liolib.c | 56 |
1 files changed, 31 insertions, 25 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: liolib.c,v 2.19 2002/09/19 20:12:47 roberto Exp roberto $ | 2 | ** $Id: liolib.c,v 2.20 2002/10/11 20:40:32 roberto Exp roberto $ |
3 | ** Standard I/O (and system) library | 3 | ** Standard I/O (and system) library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -68,18 +68,25 @@ static FILE *tofile (lua_State *L, int findex) { | |||
68 | } | 68 | } |
69 | 69 | ||
70 | 70 | ||
71 | static void newfile (lua_State *L, FILE *f) { | 71 | /* |
72 | lua_boxpointer(L, f); | 72 | ** When creating file handles, always creates a `closed' file handle |
73 | ** before opening the actual file; so, if there is a memory error, the | ||
74 | ** file is not left opened. | ||
75 | */ | ||
76 | static FILE **newfile (lua_State *L) { | ||
77 | FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); | ||
78 | *pf = NULL; /* file handle is currently `closed' */ | ||
73 | lua_pushliteral(L, FILEHANDLE); | 79 | lua_pushliteral(L, FILEHANDLE); |
74 | lua_rawget(L, LUA_REGISTRYINDEX); | 80 | lua_rawget(L, LUA_REGISTRYINDEX); |
75 | lua_setmetatable(L, -2); | 81 | lua_setmetatable(L, -2); |
82 | return pf; | ||
76 | } | 83 | } |
77 | 84 | ||
78 | 85 | ||
79 | static void registerfile (lua_State *L, FILE *f, const char *name, | 86 | static void registerfile (lua_State *L, FILE *f, const char *name, |
80 | const char *impname) { | 87 | const char *impname) { |
81 | lua_pushstring(L, name); | 88 | lua_pushstring(L, name); |
82 | newfile(L, f); | 89 | *newfile(L) = f; |
83 | if (impname) { | 90 | if (impname) { |
84 | lua_pushstring(L, impname); | 91 | lua_pushstring(L, impname); |
85 | lua_pushvalue(L, -2); | 92 | lua_pushvalue(L, -2); |
@@ -89,16 +96,6 @@ static void registerfile (lua_State *L, FILE *f, const char *name, | |||
89 | } | 96 | } |
90 | 97 | ||
91 | 98 | ||
92 | static int setnewfile (lua_State *L, FILE *f) { | ||
93 | if (f == NULL) | ||
94 | return pushresult(L, 0); | ||
95 | else { | ||
96 | newfile(L, f); | ||
97 | return 1; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | |||
102 | static int aux_close (lua_State *L) { | 99 | static int aux_close (lua_State *L) { |
103 | FILE *f = tofile(L, 1); | 100 | FILE *f = tofile(L, 1); |
104 | if (f == stdin || f == stdout || f == stderr) | 101 | if (f == stdin || f == stdout || f == stderr) |
@@ -126,8 +123,11 @@ static int io_gc (lua_State *L) { | |||
126 | 123 | ||
127 | 124 | ||
128 | static int io_open (lua_State *L) { | 125 | static int io_open (lua_State *L) { |
129 | FILE *f = fopen(luaL_check_string(L, 1), luaL_opt_string(L, 2, "r")); | 126 | const char *filename = luaL_check_string(L, 1); |
130 | return setnewfile(L, f); | 127 | const char *mode = luaL_opt_string(L, 2, "r"); |
128 | FILE **pf = newfile(L); | ||
129 | *pf = fopen(filename, mode); | ||
130 | return (*pf == NULL) ? pushresult(L, 0) : 1; | ||
131 | } | 131 | } |
132 | 132 | ||
133 | 133 | ||
@@ -136,14 +136,19 @@ static int io_popen (lua_State *L) { | |||
136 | luaL_error(L, "`popen' not supported"); | 136 | luaL_error(L, "`popen' not supported"); |
137 | return 0; | 137 | return 0; |
138 | #else | 138 | #else |
139 | FILE *f = popen(luaL_check_string(L, 1), luaL_opt_string(L, 2, "r")); | 139 | const char *filename = luaL_check_string(L, 1); |
140 | return setnewfile(L, f); | 140 | const char *mode = luaL_opt_string(L, 2, "r"); |
141 | FILE **pf = newfile(L); | ||
142 | *pf = popen(filename, mode); | ||
143 | return (*pf == NULL) ? pushresult(L, 0) : 1; | ||
141 | #endif | 144 | #endif |
142 | } | 145 | } |
143 | 146 | ||
144 | 147 | ||
145 | static int io_tmpfile (lua_State *L) { | 148 | static int io_tmpfile (lua_State *L) { |
146 | return setnewfile(L, tmpfile()); | 149 | FILE **pf = newfile(L); |
150 | *pf = tmpfile(); | ||
151 | return (*pf == NULL) ? pushresult(L, 0) : 1; | ||
147 | } | 152 | } |
148 | 153 | ||
149 | 154 | ||
@@ -168,9 +173,9 @@ static int g_iofile (lua_State *L, const char *name, const char *mode) { | |||
168 | const char *filename = lua_tostring(L, 1); | 173 | const char *filename = lua_tostring(L, 1); |
169 | lua_pushstring(L, name); | 174 | lua_pushstring(L, name); |
170 | if (filename) { | 175 | if (filename) { |
171 | FILE *f = fopen(filename, mode); | 176 | FILE **pf = newfile(L); |
172 | luaL_arg_check(L, f, 1, strerror(errno)); | 177 | *pf = fopen(filename, mode); |
173 | newfile(L, f); | 178 | luaL_arg_check(L, *pf, 1, strerror(errno)); |
174 | } | 179 | } |
175 | else { | 180 | else { |
176 | tofile(L, 1); /* check that it's a valid file handle */ | 181 | tofile(L, 1); /* check that it's a valid file handle */ |
@@ -218,9 +223,10 @@ static int io_lines (lua_State *L) { | |||
218 | return f_lines(L); | 223 | return f_lines(L); |
219 | } | 224 | } |
220 | else { | 225 | else { |
221 | FILE *f = fopen(luaL_check_string(L, 1), "r"); | 226 | const char *filename = luaL_check_string(L, 1); |
222 | luaL_arg_check(L, f, 1, strerror(errno)); | 227 | FILE **pf = newfile(L); |
223 | newfile(L, f); | 228 | *pf = fopen(filename, "r"); |
229 | luaL_arg_check(L, *pf, 1, strerror(errno)); | ||
224 | aux_lines(L, lua_gettop(L), 1); | 230 | aux_lines(L, lua_gettop(L), 1); |
225 | return 1; | 231 | return 1; |
226 | } | 232 | } |