+ // Map ios_base::openmode flags to a string for use in fopen().
+ // Table of valid combinations as given in [lib.filebuf.members]/2.
+ static const char*
+ fopen_mode(std::ios_base::openmode mode)
+ {
+ enum
+ {
+ in = std::ios_base::in,
+ out = std::ios_base::out,
+ trunc = std::ios_base::trunc,
+ app = std::ios_base::app,
+ binary = std::ios_base::binary
+ };
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 596. 27.8.1.3 Table 112 omits "a+" and "a+b" modes.
+ switch (mode & (in|out|trunc|app|binary))
+ {
+ case ( out ): return "w";
+ case ( out |app ): return "a";
+ case ( app ): return "a";
+ case ( out|trunc ): return "w";
+ case (in ): return "r";
+ case (in|out ): return "r+";
+ case (in|out|trunc ): return "w+";
+ case (in|out |app ): return "a+";
+ case (in |app ): return "a+";
+
+ case ( out |binary): return "wb";
+ case ( out |app|binary): return "ab";
+ case ( app|binary): return "ab";
+ case ( out|trunc |binary): return "wb";
+ case (in |binary): return "rb";
+ case (in|out |binary): return "r+b";
+ case (in|out|trunc |binary): return "w+b";
+ case (in|out |app|binary): return "a+b";
+ case (in |app|binary): return "a+b";
+
+ default: return 0; // invalid
+ }
+ }
+
+ // Wrapper handling partial write.
+ static std::streamsize
+ xwrite(int __fd, const char* __s, std::streamsize __n)
+ {
+ std::streamsize __nleft = __n;
+
+ for (;;)
+ {
+ const std::streamsize __ret = write(__fd, __s, __nleft);
+ if (__ret == -1L && errno == EINTR)
+ continue;
+ if (__ret == -1L)
+ break;
+
+ __nleft -= __ret;
+ if (__nleft == 0)
+ break;
+
+ __s += __ret;
+ }
+
+ return __n - __nleft;
+ }
+
+#ifdef _GLIBCXX_HAVE_WRITEV
+ // Wrapper handling partial writev.
+ static std::streamsize
+ xwritev(int __fd, const char* __s1, std::streamsize __n1,
+ const char* __s2, std::streamsize __n2)
+ {
+ std::streamsize __nleft = __n1 + __n2;
+ std::streamsize __n1_left = __n1;
+
+ struct iovec __iov[2];
+ __iov[1].iov_base = const_cast<char*>(__s2);
+ __iov[1].iov_len = __n2;
+
+ for (;;)
+ {
+ __iov[0].iov_base = const_cast<char*>(__s1);
+ __iov[0].iov_len = __n1_left;
+
+ const std::streamsize __ret = writev(__fd, __iov, 2);
+ if (__ret == -1L && errno == EINTR)
+ continue;
+ if (__ret == -1L)
+ break;
+
+ __nleft -= __ret;
+ if (__nleft == 0)
+ break;
+
+ const std::streamsize __off = __ret - __n1_left;
+ if (__off >= 0)
+ {
+ __nleft -= xwrite(__fd, __s2 + __off, __n2 - __off);
+ break;
+ }
+
+ __s1 += __ret;
+ __n1_left -= __ret;
+ }
+
+ return __n1 + __n2 - __nleft;
+ }
+#endif
+} // anonymous namespace
+
+
+_GLIBCXX_BEGIN_NAMESPACE(std)
+