__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
This commit is contained in:
Konstantin Belousov 2022-01-23 08:52:59 +02:00
parent 59d465e200
commit 86a16ada1e

View File

@ -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);