diff options
-rw-r--r-- | liolib.c | 18 | ||||
-rw-r--r-- | ltests.c | 20 | ||||
-rw-r--r-- | manual/manual.of | 3 | ||||
-rw-r--r-- | testes/files.lua | 31 |
4 files changed, 65 insertions, 7 deletions
@@ -662,11 +662,12 @@ static int io_readline (lua_State *L) { | |||
662 | 662 | ||
663 | static int g_write (lua_State *L, FILE *f, int arg) { | 663 | static int g_write (lua_State *L, FILE *f, int arg) { |
664 | int nargs = lua_gettop(L) - arg; | 664 | int nargs = lua_gettop(L) - arg; |
665 | int status = 1; | 665 | size_t totalbytes = 0; /* total number of bytes written */ |
666 | errno = 0; | 666 | errno = 0; |
667 | for (; nargs--; arg++) { | 667 | for (; nargs--; arg++) { /* for each argument */ |
668 | char buff[LUA_N2SBUFFSZ]; | 668 | char buff[LUA_N2SBUFFSZ]; |
669 | const char *s; | 669 | const char *s; |
670 | size_t numbytes; /* bytes written in one call to 'fwrite' */ | ||
670 | size_t len = lua_numbertocstring(L, arg, buff); /* try as a number */ | 671 | size_t len = lua_numbertocstring(L, arg, buff); /* try as a number */ |
671 | if (len > 0) { /* did conversion work (value was a number)? */ | 672 | if (len > 0) { /* did conversion work (value was a number)? */ |
672 | s = buff; | 673 | s = buff; |
@@ -674,12 +675,15 @@ static int g_write (lua_State *L, FILE *f, int arg) { | |||
674 | } | 675 | } |
675 | else /* must be a string */ | 676 | else /* must be a string */ |
676 | s = luaL_checklstring(L, arg, &len); | 677 | s = luaL_checklstring(L, arg, &len); |
677 | status = status && (fwrite(s, sizeof(char), len, f) == len); | 678 | numbytes = fwrite(s, sizeof(char), len, f); |
679 | totalbytes += numbytes; | ||
680 | if (numbytes < len) { /* write error? */ | ||
681 | int n = luaL_fileresult(L, 0, NULL); | ||
682 | lua_pushinteger(L, cast_st2S(totalbytes)); | ||
683 | return n + 1; /* return fail, error msg., error code, and counter */ | ||
684 | } | ||
678 | } | 685 | } |
679 | if (l_likely(status)) | 686 | return 1; /* no errors; file handle already on stack top */ |
680 | return 1; /* file handle already on stack top */ | ||
681 | else | ||
682 | return luaL_fileresult(L, status, NULL); | ||
683 | } | 687 | } |
684 | 688 | ||
685 | 689 | ||
@@ -2106,6 +2106,25 @@ static int coresume (lua_State *L) { | |||
2106 | } | 2106 | } |
2107 | } | 2107 | } |
2108 | 2108 | ||
2109 | #if !defined(LUA_USE_POSIX) | ||
2110 | |||
2111 | #define nonblock NULL | ||
2112 | |||
2113 | #else | ||
2114 | |||
2115 | #include <unistd.h> | ||
2116 | #include <fcntl.h> | ||
2117 | |||
2118 | static int nonblock (lua_State *L) { | ||
2119 | FILE *f = cast(luaL_Stream*, luaL_checkudata(L, 1, LUA_FILEHANDLE))->f; | ||
2120 | int fd = fileno(f); | ||
2121 | int flags = fcntl(fd, F_GETFL, 0); | ||
2122 | flags |= O_NONBLOCK; | ||
2123 | fcntl(fd, F_SETFL, flags); | ||
2124 | return 0; | ||
2125 | } | ||
2126 | #endif | ||
2127 | |||
2109 | /* }====================================================== */ | 2128 | /* }====================================================== */ |
2110 | 2129 | ||
2111 | 2130 | ||
@@ -2159,6 +2178,7 @@ static const struct luaL_Reg tests_funcs[] = { | |||
2159 | {"upvalue", upvalue}, | 2178 | {"upvalue", upvalue}, |
2160 | {"externKstr", externKstr}, | 2179 | {"externKstr", externKstr}, |
2161 | {"externstr", externstr}, | 2180 | {"externstr", externstr}, |
2181 | {"nonblock", nonblock}, | ||
2162 | {NULL, NULL} | 2182 | {NULL, NULL} |
2163 | }; | 2183 | }; |
2164 | 2184 | ||
diff --git a/manual/manual.of b/manual/manual.of index c1a9c138..7cd0d4db 100644 --- a/manual/manual.of +++ b/manual/manual.of | |||
@@ -8699,6 +8699,9 @@ Writes the value of each of its arguments to @id{file}. | |||
8699 | The arguments must be strings or numbers. | 8699 | The arguments must be strings or numbers. |
8700 | 8700 | ||
8701 | In case of success, this function returns @id{file}. | 8701 | In case of success, this function returns @id{file}. |
8702 | Otherwise, it returns four values: | ||
8703 | @fail, the error message, the error code, | ||
8704 | and the number of bytes it was able to write. | ||
8702 | 8705 | ||
8703 | } | 8706 | } |
8704 | 8707 | ||
diff --git a/testes/files.lua b/testes/files.lua index 05fae49b..2c802047 100644 --- a/testes/files.lua +++ b/testes/files.lua | |||
@@ -696,6 +696,37 @@ do | |||
696 | end | 696 | end |
697 | 697 | ||
698 | 698 | ||
699 | if T and T.nonblock then | ||
700 | print("testing failed write") | ||
701 | |||
702 | -- unable to write anything to /dev/full | ||
703 | local f = io.open("/dev/full", "w") | ||
704 | assert(f:setvbuf("no")) | ||
705 | local _, _, err, count = f:write("abcd") | ||
706 | assert(err > 0 and count == 0) | ||
707 | assert(f:close()) | ||
708 | |||
709 | -- receiver will read a "few" bytes (enough to empty a large buffer) | ||
710 | local receiver = [[ | ||
711 | lua -e 'assert(io.stdin:setvbuf("no")); assert(#io.read(1e4) == 1e4)' ]] | ||
712 | |||
713 | local f = io.popen(receiver, "w") | ||
714 | assert(f:setvbuf("no")) | ||
715 | T.nonblock(f) | ||
716 | |||
717 | -- able to write a few bytes | ||
718 | assert(f:write(string.rep("a", 1e2))) | ||
719 | |||
720 | -- Unable to write more bytes than the pipe buffer supports. | ||
721 | -- (In Linux, the pipe buffer size is 64K (2^16). Posix requires at | ||
722 | -- least 512 bytes.) | ||
723 | local _, _, err, count = f:write("abcd", string.rep("a", 2^17)) | ||
724 | assert(err > 0 and count >= 512 and count < 2^17) | ||
725 | |||
726 | assert(f:close()) | ||
727 | end | ||
728 | |||
729 | |||
699 | if not _soft then | 730 | if not _soft then |
700 | print("testing large files (> BUFSIZ)") | 731 | print("testing large files (> BUFSIZ)") |
701 | io.output(file) | 732 | io.output(file) |