Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2016-03-13 01:37:01 +0300
committerCorinna Vinschen <corinna@vinschen.de>2016-03-13 01:37:01 +0300
commit99d0e2341d3ff37b98eff9163b195b715ff8bddf (patch)
tree1f07ba8d032a413f253d0efd199c0ce7f8925be8 /newlib/libc
parent6b97fabf1ba0c13921549ec4a89b6953da881078 (diff)
Add __swhatbuf function from OpenBSD
To fix a long-standing setvbuf bug, import __swhatbuf function from OpenBSD and only slightly rearrange for newlib. * libc/stdio/local.h (__swhatbuf_r): Declare. * libc/stdio/makebuf (__smakebuf_r): New function. (__smakebuf_r): Drop file handling code and call __smakebuf_r. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diffstat (limited to 'newlib/libc')
-rw-r--r--newlib/libc/stdio/local.h1
-rw-r--r--newlib/libc/stdio/makebuf.c108
2 files changed, 60 insertions, 49 deletions
diff --git a/newlib/libc/stdio/local.h b/newlib/libc/stdio/local.h
index cf8e6a921..471442e26 100644
--- a/newlib/libc/stdio/local.h
+++ b/newlib/libc/stdio/local.h
@@ -182,6 +182,7 @@ extern int _EXFUN(__stextmode,(int));
extern _VOID _EXFUN(__sinit,(struct _reent *));
extern _VOID _EXFUN(_cleanup_r,(struct _reent *));
extern _VOID _EXFUN(__smakebuf_r,(struct _reent *, FILE *));
+extern int _EXFUN(__swhatbuf_r,(struct _reent *, FILE *, size_t *, int *));
extern int _EXFUN(_fwalk,(struct _reent *, int (*)(FILE *)));
extern int _EXFUN(_fwalk_reent,(struct _reent *, int (*)(struct _reent *, FILE *)));
struct _glue * _EXFUN(__sfmoreglue,(struct _reent *,int n));
diff --git a/newlib/libc/stdio/makebuf.c b/newlib/libc/stdio/makebuf.c
index 349783ded..c592578b8 100644
--- a/newlib/libc/stdio/makebuf.c
+++ b/newlib/libc/stdio/makebuf.c
@@ -39,13 +39,10 @@ _DEFUN(__smakebuf_r, (ptr, fp),
struct _reent *ptr _AND
register FILE *fp)
{
- register size_t size, couldbetty;
register _PTR p;
-#ifdef __USE_INTERNAL_STAT64
- struct stat64 st;
-#else
- struct stat st;
-#endif
+ int flags;
+ size_t size;
+ int couldbetty;
if (fp->_flags & __SNBF)
{
@@ -53,49 +50,7 @@ _DEFUN(__smakebuf_r, (ptr, fp),
fp->_bf._size = 1;
return;
}
-#ifdef __USE_INTERNAL_STAT64
- if (fp->_file < 0 || _fstat64_r (ptr, fp->_file, &st) < 0)
-#else
- if (fp->_file < 0 || _fstat_r (ptr, fp->_file, &st) < 0)
-#endif
- {
- couldbetty = 0;
- /* Check if we are be called by asprintf family for initial buffer. */
- if (fp->_flags & __SMBF)
- size = _DEFAULT_ASPRINTF_BUFSIZE;
- else
- size = BUFSIZ;
-#ifdef _FSEEK_OPTIMIZATION
- /* do not try to optimise fseek() */
- fp->_flags |= __SNPT;
-#endif
- }
- else
- {
- couldbetty = (st.st_mode & S_IFMT) == S_IFCHR;
-#ifdef HAVE_BLKSIZE
- size = st.st_blksize <= 0 ? BUFSIZ : st.st_blksize;
-#else
- size = BUFSIZ;
-#endif
-#ifdef _FSEEK_OPTIMIZATION
- /*
- * Optimize fseek() only if it is a regular file.
- * (The test for __sseek is mainly paranoia.)
- */
- if ((st.st_mode & S_IFMT) == S_IFREG && fp->_seek == __sseek)
- {
- fp->_flags |= __SOPT;
-#ifdef HAVE_BLKSIZE
- fp->_blksize = st.st_blksize;
-#else
- fp->_blksize = 1024;
-#endif
- }
- else
- fp->_flags |= __SNPT;
-#endif
- }
+ flags = __swhatbuf_r (ptr, fp, &size, &couldbetty);
if ((p = _malloc_r (ptr, size)) == NULL)
{
if (!(fp->_flags & __SSTR))
@@ -113,5 +68,60 @@ _DEFUN(__smakebuf_r, (ptr, fp),
fp->_bf._size = size;
if (couldbetty && _isatty_r (ptr, fp->_file))
fp->_flags |= __SLBF;
+ fp->_flags |= flags;
}
}
+
+/*
+ * Internal routine to determine `proper' buffering for a file.
+ */
+int
+_DEFUN(__swhatbuf_r, (ptr, fp, bufsize, couldbetty),
+ struct _reent *ptr _AND
+ FILE *fp _AND
+ size_t *bufsize _AND
+ int *couldbetty)
+{
+#ifdef _FSEEK_OPTIMIZATION
+ const int snpt = __SNPT;
+#else
+ const int snpt = 0;
+#endif
+
+#ifdef __USE_INTERNAL_STAT64
+ struct stat64 st;
+
+ if (fp->_file < 0 || _fstat64_r (ptr, fp->_file, &st) < 0)
+#else
+ struct stat st;
+
+ if (fp->_file < 0 || _fstat_r (ptr, fp->_file, &st) < 0)
+#endif
+ {
+ *couldbetty = 0;
+ /* Check if we are be called by asprintf family for initial buffer. */
+ if (fp->_flags & __SMBF)
+ *bufsize = _DEFAULT_ASPRINTF_BUFSIZE;
+ else
+ *bufsize = BUFSIZ;
+ return (0);
+ }
+
+ /* could be a tty iff it is a character device */
+ *couldbetty = S_ISCHR(st.st_mode);
+#ifdef HAVE_BLKSIZE
+ if (st.st_blksize > 0)
+ {
+ /*
+ * Optimise fseek() only if it is a regular file. (The test for
+ * __sseek is mainly paranoia.) It is safe to set _blksize
+ * unconditionally; it will only be used if __SOPT is also set.
+ */
+ *bufsize = st.st_blksize;
+ fp->_blksize = st.st_blksize;
+ return ((st.st_mode & S_IFMT) == S_IFREG ? __SOPT : snpt);
+ }
+#endif
+ *bufsize = BUFSIZ;
+ return (snpt);
+}