diff options
author | tjr <tjr@FreeBSD.org> | 2003-11-12 08:49:12 +0000 |
---|---|---|
committer | tjr <tjr@FreeBSD.org> | 2003-11-12 08:49:12 +0000 |
commit | 7a8b48f087c4a62a12071799a28207667b63a16b (patch) | |
tree | 4f1c64b78bbc04a578ca7c5b40d14387302ad2d5 /lib/libc/stdio/vfwprintf.c | |
parent | aabfe725f2f55fa838b7dab6ab99e790b0f27ef7 (diff) | |
download | FreeBSD-src-7a8b48f087c4a62a12071799a28207667b63a16b.zip FreeBSD-src-7a8b48f087c4a62a12071799a28207667b63a16b.tar.gz |
Use __sfvwrite() instead of __sputc() via __fputwc() to write to fake
string files (__SSTR flag set). This is necessary because __sputc()
does not respect the __SALC flag, and crashes trying to flush the buffer
instead of resizing it.
PR: 59167
Diffstat (limited to 'lib/libc/stdio/vfwprintf.c')
-rw-r--r-- | lib/libc/stdio/vfwprintf.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/lib/libc/stdio/vfwprintf.c b/lib/libc/stdio/vfwprintf.c index 3be9365..a679288 100644 --- a/lib/libc/stdio/vfwprintf.c +++ b/lib/libc/stdio/vfwprintf.c @@ -114,6 +114,7 @@ enum typeid { }; static int __sbprintf(FILE *, const wchar_t *, va_list); +static wint_t __xfputwc(wchar_t, FILE *); static wchar_t *__ujtoa(uintmax_t, wchar_t *, int, int, const wchar_t *, int, char, const char *); static wchar_t *__ultoa(u_long, wchar_t *, int, int, const wchar_t *, int, @@ -156,6 +157,34 @@ __sbprintf(FILE *fp, const wchar_t *fmt, va_list ap) } /* + * Like __fputwc, but handles fake string (__SSTR) files properly. + * File must already be locked. + */ +static wint_t +__xfputwc(wchar_t wc, FILE *fp) +{ + char buf[MB_LEN_MAX]; + struct __suio uio; + struct __siov iov; + size_t i, len; + int ret; + + if ((fp->_flags & __SSTR) == 0) + return (__fputwc(wc, fp)); + + if ((len = wcrtomb(buf, wc, NULL)) == (size_t)-1) { + fp->_flags |= __SERR; + return (WEOF); + } + uio.uio_iov = &iov; + uio.uio_resid = len; + uio.uio_iovcnt = 1; + iov.iov_base = buf; + iov.iov_len = len; + return (__sfvwrite(fp, &uio) != EOF ? (wint_t)wc : WEOF); +} + +/* * Macros for converting digits to letters and vice versa */ #define to_digit(c) ((c) - '0') @@ -529,7 +558,7 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap) */ #define PRINT(ptr, len) do { \ for (n3 = 0; n3 < (len); n3++) \ - __fputwc((ptr)[n3], fp); \ + __xfputwc((ptr)[n3], fp); \ } while (0) #define PAD(howmany, with) do { \ if ((n = (howmany)) > 0) { \ |