io.write returns number of written bytes on error
This commit is contained in:
18
liolib.c
18
liolib.c
@@ -662,11 +662,12 @@ static int io_readline (lua_State *L) {
|
|||||||
|
|
||||||
static int g_write (lua_State *L, FILE *f, int arg) {
|
static int g_write (lua_State *L, FILE *f, int arg) {
|
||||||
int nargs = lua_gettop(L) - arg;
|
int nargs = lua_gettop(L) - arg;
|
||||||
int status = 1;
|
size_t totalbytes = 0; /* total number of bytes written */
|
||||||
errno = 0;
|
errno = 0;
|
||||||
for (; nargs--; arg++) {
|
for (; nargs--; arg++) { /* for each argument */
|
||||||
char buff[LUA_N2SBUFFSZ];
|
char buff[LUA_N2SBUFFSZ];
|
||||||
const char *s;
|
const char *s;
|
||||||
|
size_t numbytes; /* bytes written in one call to 'fwrite' */
|
||||||
size_t len = lua_numbertocstring(L, arg, buff); /* try as a number */
|
size_t len = lua_numbertocstring(L, arg, buff); /* try as a number */
|
||||||
if (len > 0) { /* did conversion work (value was a number)? */
|
if (len > 0) { /* did conversion work (value was a number)? */
|
||||||
s = buff;
|
s = buff;
|
||||||
@@ -674,12 +675,15 @@ static int g_write (lua_State *L, FILE *f, int arg) {
|
|||||||
}
|
}
|
||||||
else /* must be a string */
|
else /* must be a string */
|
||||||
s = luaL_checklstring(L, arg, &len);
|
s = luaL_checklstring(L, arg, &len);
|
||||||
status = status && (fwrite(s, sizeof(char), len, f) == len);
|
numbytes = fwrite(s, sizeof(char), len, f);
|
||||||
|
totalbytes += numbytes;
|
||||||
|
if (numbytes < len) { /* write error? */
|
||||||
|
int n = luaL_fileresult(L, 0, NULL);
|
||||||
|
lua_pushinteger(L, cast_st2S(totalbytes));
|
||||||
|
return n + 1; /* return fail, error msg., error code, and counter */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (l_likely(status))
|
return 1; /* no errors; file handle already on stack top */
|
||||||
return 1; /* file handle already on stack top */
|
|
||||||
else
|
|
||||||
return luaL_fileresult(L, status, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
20
ltests.c
20
ltests.c
@@ -2106,6 +2106,25 @@ static int coresume (lua_State *L) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(LUA_USE_POSIX)
|
||||||
|
|
||||||
|
#define nonblock NULL
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
static int nonblock (lua_State *L) {
|
||||||
|
FILE *f = cast(luaL_Stream*, luaL_checkudata(L, 1, LUA_FILEHANDLE))->f;
|
||||||
|
int fd = fileno(f);
|
||||||
|
int flags = fcntl(fd, F_GETFL, 0);
|
||||||
|
flags |= O_NONBLOCK;
|
||||||
|
fcntl(fd, F_SETFL, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* }====================================================== */
|
/* }====================================================== */
|
||||||
|
|
||||||
|
|
||||||
@@ -2159,6 +2178,7 @@ static const struct luaL_Reg tests_funcs[] = {
|
|||||||
{"upvalue", upvalue},
|
{"upvalue", upvalue},
|
||||||
{"externKstr", externKstr},
|
{"externKstr", externKstr},
|
||||||
{"externstr", externstr},
|
{"externstr", externstr},
|
||||||
|
{"nonblock", nonblock},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8699,6 +8699,9 @@ Writes the value of each of its arguments to @id{file}.
|
|||||||
The arguments must be strings or numbers.
|
The arguments must be strings or numbers.
|
||||||
|
|
||||||
In case of success, this function returns @id{file}.
|
In case of success, this function returns @id{file}.
|
||||||
|
Otherwise, it returns four values:
|
||||||
|
@fail, the error message, the error code,
|
||||||
|
and the number of bytes it was able to write.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -696,6 +696,37 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if T and T.nonblock then
|
||||||
|
print("testing failed write")
|
||||||
|
|
||||||
|
-- unable to write anything to /dev/full
|
||||||
|
local f = io.open("/dev/full", "w")
|
||||||
|
assert(f:setvbuf("no"))
|
||||||
|
local _, _, err, count = f:write("abcd")
|
||||||
|
assert(err > 0 and count == 0)
|
||||||
|
assert(f:close())
|
||||||
|
|
||||||
|
-- receiver will read a "few" bytes (enough to empty a large buffer)
|
||||||
|
local receiver = [[
|
||||||
|
lua -e 'assert(io.stdin:setvbuf("no")); assert(#io.read(1e4) == 1e4)' ]]
|
||||||
|
|
||||||
|
local f = io.popen(receiver, "w")
|
||||||
|
assert(f:setvbuf("no"))
|
||||||
|
T.nonblock(f)
|
||||||
|
|
||||||
|
-- able to write a few bytes
|
||||||
|
assert(f:write(string.rep("a", 1e2)))
|
||||||
|
|
||||||
|
-- Unable to write more bytes than the pipe buffer supports.
|
||||||
|
-- (In Linux, the pipe buffer size is 64K (2^16). Posix requires at
|
||||||
|
-- least 512 bytes.)
|
||||||
|
local _, _, err, count = f:write("abcd", string.rep("a", 2^17))
|
||||||
|
assert(err > 0 and count >= 512 and count < 2^17)
|
||||||
|
|
||||||
|
assert(f:close())
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
if not _soft then
|
if not _soft then
|
||||||
print("testing large files (> BUFSIZ)")
|
print("testing large files (> BUFSIZ)")
|
||||||
io.output(file)
|
io.output(file)
|
||||||
|
|||||||
Reference in New Issue
Block a user