git: 86a16ada1ea6 - main - __sflush(): on write error, if nothing was written, reset FILE state back

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Tue, 25 Jan 2022 15:26:10 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=86a16ada1ea608408cec370171d9f59353e97c77

commit 86a16ada1ea608408cec370171d9f59353e97c77
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2022-01-23 06:52:59 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2022-01-25 15:26:05 +0000

    __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
---
 lib/libc/stdio/fflush.c | 9 +++++++--
 1 file 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);