aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/config/io/basic_file_stdio.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/config/io/basic_file_stdio.cc')
-rw-r--r--libstdc++-v3/config/io/basic_file_stdio.cc86
1 files changed, 70 insertions, 16 deletions
diff --git a/libstdc++-v3/config/io/basic_file_stdio.cc b/libstdc++-v3/config/io/basic_file_stdio.cc
index ff23d983ae8..a0947bf3dd5 100644
--- a/libstdc++-v3/config/io/basic_file_stdio.cc
+++ b/libstdc++-v3/config/io/basic_file_stdio.cc
@@ -34,6 +34,29 @@
#include <bits/basic_file.h>
#include <fcntl.h>
+#ifdef _GLIBCPP_HAVE_SYS_IOCTL_H
+#define BSD_COMP /* Get FIONREAD on Solaris2. */
+#include <sys/ioctl.h>
+#endif
+
+// Pick up FIONREAD on Solaris 2.5.
+#ifdef _GLIBCPP_HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+
+#ifdef _GLIBCPP_HAVE_POLL
+#include <poll.h>
+#endif
+
+#if defined(_GLIBCPP_HAVE_S_ISREG) || defined(_GLIBCPP_HAVE_S_IFREG)
+# include <sys/stat.h>
+# ifdef _GLIBCPP_HAVE_S_ISREG
+# define _GLIBCPP_ISREG(x) S_ISREG(x)
+# else
+# define _GLIBCPP_ISREG(x) (((x) & S_IFMT) == S_IFREG)
+# endif
+#endif
+
namespace std
{
// Definitions for __basic_file<char>.
@@ -74,7 +97,7 @@ namespace std
if (__testi && !__testo && !__testt && !__testa)
{
strcpy(__c_mode, "r");
- __p_mode |= O_RDONLY | O_NONBLOCK;
+ __p_mode |= O_RDONLY;
}
if (__testi && __testo && !__testt && !__testa)
{
@@ -150,11 +173,6 @@ namespace std
if ((_M_cfile = fopen(__name, __c_mode)))
{
_M_cfile_created = true;
-
- // Set input to nonblocking for fifos.
- if (__mode & ios_base::in)
- fcntl(this->fd(), F_SETFL, O_NONBLOCK);
-
__ret = this;
}
}
@@ -175,12 +193,12 @@ namespace std
__basic_file* __retval = static_cast<__basic_file*>(NULL);
if (this->is_open())
{
- fflush(_M_cfile);
- if ((_M_cfile_created && fclose(_M_cfile) == 0) || !_M_cfile_created)
- {
- _M_cfile = 0;
- __retval = this;
- }
+ if (_M_cfile_created)
+ fclose(_M_cfile);
+ else
+ fflush(_M_cfile);
+ _M_cfile = 0;
+ __retval = this;
}
return __retval;
}
@@ -197,18 +215,54 @@ namespace std
__basic_file<char>::seekoff(streamoff __off, ios_base::seekdir __way,
ios_base::openmode /*__mode*/)
{
- fseek(_M_cfile, __off, __way);
- return ftell(_M_cfile);
+ if (!fseek(_M_cfile, __off, __way))
+ return ftell(_M_cfile);
+ else
+ // Fseek failed.
+ return -1L;
}
streamoff
__basic_file<char>::seekpos(streamoff __pos, ios_base::openmode /*__mode*/)
{
- fseek(_M_cfile, __pos, ios_base::beg);
- return ftell(_M_cfile);
+ if (!fseek(_M_cfile, __pos, ios_base::beg))
+ return ftell(_M_cfile);
+ else
+ // Fseek failed.
+ return -1L;
}
int
__basic_file<char>::sync()
{ return fflush(_M_cfile); }
+
+ streamsize
+ __basic_file<char>::showmanyc_helper()
+ {
+#ifdef FIONREAD
+ // Pipes and sockets.
+ int __num = 0;
+ int __r = ioctl(this->fd(), FIONREAD, &__num);
+ if (!__r && __num >= 0)
+ return __num;
+#endif
+
+#ifdef _GLIBCPP_HAVE_POLL
+ // Cheap test.
+ struct pollfd __pfd[1];
+ __pfd[0].fd = this->fd();
+ __pfd[0].events = POLLIN;
+ if (poll(__pfd, 1, 0) <= 0)
+ return 0;
+#endif
+
+#if defined(_GLIBCPP_HAVE_S_ISREG) || defined(_GLIBCPP_HAVE_S_IFREG)
+ // Regular files.
+ struct stat __buffer;
+ int __ret = fstat(this->fd(), &__buffer);
+ if (!__ret && _GLIBCPP_ISREG(__buffer.st_mode))
+ return __buffer.st_size - ftell(_M_cfile);
+#endif
+ return 0;
+ }
} // namespace std