mirror of https://github.com/lua/lua
More disciplined use of 'errno'
Set errno to zero before calling any function where we may use its errno, and check errno for zero before using it (as functions may not set it even in error). The code assumes that no function will put garbage on errno (although ISO C allows that): If any function during an operation set errno, and the operation result in an error, assume that errno has something to say.
This commit is contained in:
parent
94b503d95e
commit
bb7bb5944c
16
lauxlib.c
16
lauxlib.c
|
@ -249,11 +249,13 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
|
|||
return 1;
|
||||
}
|
||||
else {
|
||||
const char *msg;
|
||||
luaL_pushfail(L);
|
||||
msg = (en != 0) ? strerror(en) : "(no extra info)";
|
||||
if (fname)
|
||||
lua_pushfstring(L, "%s: %s", fname, strerror(en));
|
||||
lua_pushfstring(L, "%s: %s", fname, msg);
|
||||
else
|
||||
lua_pushstring(L, strerror(en));
|
||||
lua_pushstring(L, msg);
|
||||
lua_pushinteger(L, en);
|
||||
return 3;
|
||||
}
|
||||
|
@ -750,9 +752,12 @@ static const char *getF (lua_State *L, void *ud, size_t *size) {
|
|||
|
||||
|
||||
static int errfile (lua_State *L, const char *what, int fnameindex) {
|
||||
const char *serr = strerror(errno);
|
||||
int err = errno;
|
||||
const char *filename = lua_tostring(L, fnameindex) + 1;
|
||||
lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
|
||||
if (err != 0)
|
||||
lua_pushfstring(L, "cannot %s %s: %s", what, filename, strerror(err));
|
||||
else
|
||||
lua_pushfstring(L, "cannot %s %s", what, filename);
|
||||
lua_remove(L, fnameindex);
|
||||
return LUA_ERRFILE;
|
||||
}
|
||||
|
@ -805,6 +810,7 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
|
|||
}
|
||||
else {
|
||||
lua_pushfstring(L, "@%s", filename);
|
||||
errno = 0;
|
||||
lf.f = fopen(filename, "r");
|
||||
if (lf.f == NULL) return errfile(L, "open", fnameindex);
|
||||
}
|
||||
|
@ -814,6 +820,7 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
|
|||
if (c == LUA_SIGNATURE[0]) { /* binary file? */
|
||||
lf.n = 0; /* remove possible newline */
|
||||
if (filename) { /* "real" file? */
|
||||
errno = 0;
|
||||
lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
|
||||
if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
|
||||
skipcomment(lf.f, &c); /* re-read initial portion */
|
||||
|
@ -823,6 +830,7 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
|
|||
lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */
|
||||
status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode);
|
||||
readstatus = ferror(lf.f);
|
||||
errno = 0; /* no useful error number until here */
|
||||
if (filename) fclose(lf.f); /* close file (even in case of errors) */
|
||||
if (readstatus) {
|
||||
lua_settop(L, fnameindex); /* ignore results from 'lua_load' */
|
||||
|
|
25
liolib.c
25
liolib.c
|
@ -245,8 +245,8 @@ static int f_gc (lua_State *L) {
|
|||
*/
|
||||
static int io_fclose (lua_State *L) {
|
||||
LStream *p = tolstream(L);
|
||||
int res = fclose(p->f);
|
||||
return luaL_fileresult(L, (res == 0), NULL);
|
||||
errno = 0;
|
||||
return luaL_fileresult(L, (fclose(p->f) == 0), NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -272,6 +272,7 @@ static int io_open (lua_State *L) {
|
|||
LStream *p = newfile(L);
|
||||
const char *md = mode; /* to traverse/check mode */
|
||||
luaL_argcheck(L, l_checkmode(md), 2, "invalid mode");
|
||||
errno = 0;
|
||||
p->f = fopen(filename, mode);
|
||||
return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
|
||||
}
|
||||
|
@ -292,6 +293,7 @@ static int io_popen (lua_State *L) {
|
|||
const char *mode = luaL_optstring(L, 2, "r");
|
||||
LStream *p = newprefile(L);
|
||||
luaL_argcheck(L, l_checkmodep(mode), 2, "invalid mode");
|
||||
errno = 0;
|
||||
p->f = l_popen(L, filename, mode);
|
||||
p->closef = &io_pclose;
|
||||
return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
|
||||
|
@ -300,6 +302,7 @@ static int io_popen (lua_State *L) {
|
|||
|
||||
static int io_tmpfile (lua_State *L) {
|
||||
LStream *p = newfile(L);
|
||||
errno = 0;
|
||||
p->f = tmpfile();
|
||||
return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
|
||||
}
|
||||
|
@ -567,6 +570,7 @@ static int g_read (lua_State *L, FILE *f, int first) {
|
|||
int nargs = lua_gettop(L) - 1;
|
||||
int n, success;
|
||||
clearerr(f);
|
||||
errno = 0;
|
||||
if (nargs == 0) { /* no arguments? */
|
||||
success = read_line(L, f, 1);
|
||||
n = first + 1; /* to return 1 result */
|
||||
|
@ -660,6 +664,7 @@ static int io_readline (lua_State *L) {
|
|||
static int g_write (lua_State *L, FILE *f, int arg) {
|
||||
int nargs = lua_gettop(L) - arg;
|
||||
int status = 1;
|
||||
errno = 0;
|
||||
for (; nargs--; arg++) {
|
||||
if (lua_type(L, arg) == LUA_TNUMBER) {
|
||||
/* optimization: could be done exactly as for strings */
|
||||
|
@ -678,7 +683,8 @@ static int g_write (lua_State *L, FILE *f, int arg) {
|
|||
}
|
||||
if (l_likely(status))
|
||||
return 1; /* file handle already on stack top */
|
||||
else return luaL_fileresult(L, status, NULL);
|
||||
else
|
||||
return luaL_fileresult(L, status, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -703,6 +709,7 @@ static int f_seek (lua_State *L) {
|
|||
l_seeknum offset = (l_seeknum)p3;
|
||||
luaL_argcheck(L, (lua_Integer)offset == p3, 3,
|
||||
"not an integer in proper range");
|
||||
errno = 0;
|
||||
op = l_fseek(f, offset, mode[op]);
|
||||
if (l_unlikely(op))
|
||||
return luaL_fileresult(L, 0, NULL); /* error */
|
||||
|
@ -719,19 +726,25 @@ static int f_setvbuf (lua_State *L) {
|
|||
FILE *f = tofile(L);
|
||||
int op = luaL_checkoption(L, 2, NULL, modenames);
|
||||
lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
|
||||
int res = setvbuf(f, NULL, mode[op], (size_t)sz);
|
||||
int res;
|
||||
errno = 0;
|
||||
res = setvbuf(f, NULL, mode[op], (size_t)sz);
|
||||
return luaL_fileresult(L, res == 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int io_flush (lua_State *L) {
|
||||
return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
|
||||
FILE *f = getiofile(L, IO_OUTPUT);
|
||||
errno = 0;
|
||||
return luaL_fileresult(L, fflush(f) == 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int f_flush (lua_State *L) {
|
||||
return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
|
||||
FILE *f = tofile(L);
|
||||
errno = 0;
|
||||
return luaL_fileresult(L, fflush(f) == 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
|
2
loslib.c
2
loslib.c
|
@ -155,6 +155,7 @@ static int os_execute (lua_State *L) {
|
|||
|
||||
static int os_remove (lua_State *L) {
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
errno = 0;
|
||||
return luaL_fileresult(L, remove(filename) == 0, filename);
|
||||
}
|
||||
|
||||
|
@ -162,6 +163,7 @@ static int os_remove (lua_State *L) {
|
|||
static int os_rename (lua_State *L) {
|
||||
const char *fromname = luaL_checkstring(L, 1);
|
||||
const char *toname = luaL_checkstring(L, 2);
|
||||
errno = 0;
|
||||
return luaL_fileresult(L, rename(fromname, toname) == 0, NULL);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue