aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2022-01-23 06:52:59 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2022-01-25 15:26:05 +0000
commit86a16ada1ea608408cec370171d9f59353e97c77 (patch)
tree0c5efdf3ebd866d7e199e5b7177231c142af3e99
parent59d465e200bb7058dfdb183c061730c10dd5bc03 (diff)
downloadsrc-86a16ada1ea608408cec370171d9f59353e97c77.tar.gz
src-86a16ada1ea608408cec370171d9f59353e97c77.zip
__sflush(): on write error, if nothing was written, reset FILE state back
otherwise the data is just dropped. Check for current position equal to the buffer base at the entry of the function; if not equal, setvbuf() was done from the write method and it is not our business to override the decision. PR: 76398 Reviewed by: markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D34007
-rw-r--r--lib/libc/stdio/fflush.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/lib/libc/stdio/fflush.c b/lib/libc/stdio/fflush.c
index f7d2fbdc28e5..decc974907f4 100644
--- a/lib/libc/stdio/fflush.c
+++ b/lib/libc/stdio/fflush.c
@@ -105,8 +105,8 @@ __weak_reference(__fflush, fflush_unlocked);
int
__sflush(FILE *fp)
{
- unsigned char *p;
- int n, t;
+ unsigned char *p, *old_p;
+ int n, t, old_w;
t = fp->_flags;
if ((t & __SWR) == 0)
@@ -121,7 +121,9 @@ __sflush(FILE *fp)
* Set these immediately to avoid problems with longjmp and to allow
* exchange buffering (via setvbuf) in user write function.
*/
+ old_p = fp->_p;
fp->_p = p;
+ old_w = fp->_w;
fp->_w = t & (__SLBF|__SNBF) ? 0 : fp->_bf._size;
for (; n > 0; n -= t, p += t) {
@@ -134,6 +136,9 @@ __sflush(FILE *fp)
fp->_p += n;
if ((fp->_flags & (__SLBF | __SNBF)) == 0)
fp->_w -= n;
+ } else if (p == fp->_p) { /* cond. to handle setvbuf */
+ fp->_p = old_p;
+ fp->_w = old_w;
}
fp->_flags |= __SERR;
return (EOF);