xref: /dflybsd-src/contrib/gcc-4.7/libstdc++-v3/config/io/basic_file_stdio.cc (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino // Wrapper of C-language FILE struct -*- C++ -*-
2*e4b17023SJohn Marino 
3*e4b17023SJohn Marino // Copyright (C) 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2009, 2010
4*e4b17023SJohn Marino // Free Software Foundation, Inc.
5*e4b17023SJohn Marino //
6*e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library.  This library is free
7*e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the
8*e4b17023SJohn Marino // terms of the GNU General Public License as published by the
9*e4b17023SJohn Marino // Free Software Foundation; either version 3, or (at your option)
10*e4b17023SJohn Marino // any later version.
11*e4b17023SJohn Marino 
12*e4b17023SJohn Marino // This library is distributed in the hope that it will be useful,
13*e4b17023SJohn Marino // but WITHOUT ANY WARRANTY; without even the implied warranty of
14*e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*e4b17023SJohn Marino // GNU General Public License for more details.
16*e4b17023SJohn Marino 
17*e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional
18*e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version
19*e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation.
20*e4b17023SJohn Marino 
21*e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and
22*e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program;
23*e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24*e4b17023SJohn Marino // <http://www.gnu.org/licenses/>.
25*e4b17023SJohn Marino 
26*e4b17023SJohn Marino //
27*e4b17023SJohn Marino // ISO C++ 14882: 27.8  File-based streams
28*e4b17023SJohn Marino //
29*e4b17023SJohn Marino 
30*e4b17023SJohn Marino #include <bits/basic_file.h>
31*e4b17023SJohn Marino #include <fcntl.h>
32*e4b17023SJohn Marino #include <errno.h>
33*e4b17023SJohn Marino 
34*e4b17023SJohn Marino #ifdef _GLIBCXX_HAVE_POLL
35*e4b17023SJohn Marino #include <poll.h>
36*e4b17023SJohn Marino #endif
37*e4b17023SJohn Marino 
38*e4b17023SJohn Marino // Pick up ioctl on Solaris 2.8
39*e4b17023SJohn Marino #ifdef _GLIBCXX_HAVE_UNISTD_H
40*e4b17023SJohn Marino #include <unistd.h>
41*e4b17023SJohn Marino #endif
42*e4b17023SJohn Marino 
43*e4b17023SJohn Marino // Pick up FIONREAD on Solaris 2
44*e4b17023SJohn Marino #ifdef _GLIBCXX_HAVE_SYS_IOCTL_H
45*e4b17023SJohn Marino #define BSD_COMP
46*e4b17023SJohn Marino #include <sys/ioctl.h>
47*e4b17023SJohn Marino #endif
48*e4b17023SJohn Marino 
49*e4b17023SJohn Marino // Pick up FIONREAD on Solaris 2.5.
50*e4b17023SJohn Marino #ifdef _GLIBCXX_HAVE_SYS_FILIO_H
51*e4b17023SJohn Marino #include <sys/filio.h>
52*e4b17023SJohn Marino #endif
53*e4b17023SJohn Marino 
54*e4b17023SJohn Marino #ifdef _GLIBCXX_HAVE_SYS_UIO_H
55*e4b17023SJohn Marino #include <sys/uio.h>
56*e4b17023SJohn Marino #endif
57*e4b17023SJohn Marino 
58*e4b17023SJohn Marino #if defined(_GLIBCXX_HAVE_S_ISREG) || defined(_GLIBCXX_HAVE_S_IFREG)
59*e4b17023SJohn Marino # include <sys/stat.h>
60*e4b17023SJohn Marino # ifdef _GLIBCXX_HAVE_S_ISREG
61*e4b17023SJohn Marino #  define _GLIBCXX_ISREG(x) S_ISREG(x)
62*e4b17023SJohn Marino # else
63*e4b17023SJohn Marino #  define _GLIBCXX_ISREG(x) (((x) & S_IFMT) == S_IFREG)
64*e4b17023SJohn Marino # endif
65*e4b17023SJohn Marino #endif
66*e4b17023SJohn Marino 
67*e4b17023SJohn Marino #include <limits> // For <off_t>::max() and min() and <streamsize>::max()
68*e4b17023SJohn Marino 
69*e4b17023SJohn Marino namespace
70*e4b17023SJohn Marino {
71*e4b17023SJohn Marino   // Map ios_base::openmode flags to a string for use in fopen().
72*e4b17023SJohn Marino   // Table of valid combinations as given in [lib.filebuf.members]/2.
73*e4b17023SJohn Marino   static const char*
fopen_mode(std::ios_base::openmode mode)74*e4b17023SJohn Marino   fopen_mode(std::ios_base::openmode mode)
75*e4b17023SJohn Marino   {
76*e4b17023SJohn Marino     enum
77*e4b17023SJohn Marino       {
78*e4b17023SJohn Marino 	in     = std::ios_base::in,
79*e4b17023SJohn Marino 	out    = std::ios_base::out,
80*e4b17023SJohn Marino 	trunc  = std::ios_base::trunc,
81*e4b17023SJohn Marino 	app    = std::ios_base::app,
82*e4b17023SJohn Marino 	binary = std::ios_base::binary
83*e4b17023SJohn Marino       };
84*e4b17023SJohn Marino 
85*e4b17023SJohn Marino     // _GLIBCXX_RESOLVE_LIB_DEFECTS
86*e4b17023SJohn Marino     // 596. 27.8.1.3 Table 112 omits "a+" and "a+b" modes.
87*e4b17023SJohn Marino     switch (mode & (in|out|trunc|app|binary))
88*e4b17023SJohn Marino       {
89*e4b17023SJohn Marino       case (   out                 ): return "w";
90*e4b17023SJohn Marino       case (   out      |app       ): return "a";
91*e4b17023SJohn Marino       case (             app       ): return "a";
92*e4b17023SJohn Marino       case (   out|trunc           ): return "w";
93*e4b17023SJohn Marino       case (in                     ): return "r";
94*e4b17023SJohn Marino       case (in|out                 ): return "r+";
95*e4b17023SJohn Marino       case (in|out|trunc           ): return "w+";
96*e4b17023SJohn Marino       case (in|out      |app       ): return "a+";
97*e4b17023SJohn Marino       case (in          |app       ): return "a+";
98*e4b17023SJohn Marino 
99*e4b17023SJohn Marino       case (   out          |binary): return "wb";
100*e4b17023SJohn Marino       case (   out      |app|binary): return "ab";
101*e4b17023SJohn Marino       case (             app|binary): return "ab";
102*e4b17023SJohn Marino       case (   out|trunc    |binary): return "wb";
103*e4b17023SJohn Marino       case (in              |binary): return "rb";
104*e4b17023SJohn Marino       case (in|out          |binary): return "r+b";
105*e4b17023SJohn Marino       case (in|out|trunc    |binary): return "w+b";
106*e4b17023SJohn Marino       case (in|out      |app|binary): return "a+b";
107*e4b17023SJohn Marino       case (in          |app|binary): return "a+b";
108*e4b17023SJohn Marino 
109*e4b17023SJohn Marino       default: return 0; // invalid
110*e4b17023SJohn Marino       }
111*e4b17023SJohn Marino   }
112*e4b17023SJohn Marino 
113*e4b17023SJohn Marino   // Wrapper handling partial write.
114*e4b17023SJohn Marino   static std::streamsize
xwrite(int __fd,const char * __s,std::streamsize __n)115*e4b17023SJohn Marino   xwrite(int __fd, const char* __s, std::streamsize __n)
116*e4b17023SJohn Marino   {
117*e4b17023SJohn Marino     std::streamsize __nleft = __n;
118*e4b17023SJohn Marino 
119*e4b17023SJohn Marino     for (;;)
120*e4b17023SJohn Marino       {
121*e4b17023SJohn Marino 	const std::streamsize __ret = write(__fd, __s, __nleft);
122*e4b17023SJohn Marino 	if (__ret == -1L && errno == EINTR)
123*e4b17023SJohn Marino 	  continue;
124*e4b17023SJohn Marino 	if (__ret == -1L)
125*e4b17023SJohn Marino 	  break;
126*e4b17023SJohn Marino 
127*e4b17023SJohn Marino 	__nleft -= __ret;
128*e4b17023SJohn Marino 	if (__nleft == 0)
129*e4b17023SJohn Marino 	  break;
130*e4b17023SJohn Marino 
131*e4b17023SJohn Marino 	__s += __ret;
132*e4b17023SJohn Marino       }
133*e4b17023SJohn Marino 
134*e4b17023SJohn Marino     return __n - __nleft;
135*e4b17023SJohn Marino   }
136*e4b17023SJohn Marino 
137*e4b17023SJohn Marino #ifdef _GLIBCXX_HAVE_WRITEV
138*e4b17023SJohn Marino   // Wrapper handling partial writev.
139*e4b17023SJohn Marino   static std::streamsize
xwritev(int __fd,const char * __s1,std::streamsize __n1,const char * __s2,std::streamsize __n2)140*e4b17023SJohn Marino   xwritev(int __fd, const char* __s1, std::streamsize __n1,
141*e4b17023SJohn Marino 	  const char* __s2, std::streamsize __n2)
142*e4b17023SJohn Marino   {
143*e4b17023SJohn Marino     std::streamsize __nleft = __n1 + __n2;
144*e4b17023SJohn Marino     std::streamsize __n1_left = __n1;
145*e4b17023SJohn Marino 
146*e4b17023SJohn Marino     struct iovec __iov[2];
147*e4b17023SJohn Marino     __iov[1].iov_base = const_cast<char*>(__s2);
148*e4b17023SJohn Marino     __iov[1].iov_len = __n2;
149*e4b17023SJohn Marino 
150*e4b17023SJohn Marino     for (;;)
151*e4b17023SJohn Marino       {
152*e4b17023SJohn Marino 	__iov[0].iov_base = const_cast<char*>(__s1);
153*e4b17023SJohn Marino 	__iov[0].iov_len = __n1_left;
154*e4b17023SJohn Marino 
155*e4b17023SJohn Marino 	const std::streamsize __ret = writev(__fd, __iov, 2);
156*e4b17023SJohn Marino 	if (__ret == -1L && errno == EINTR)
157*e4b17023SJohn Marino 	  continue;
158*e4b17023SJohn Marino 	if (__ret == -1L)
159*e4b17023SJohn Marino 	  break;
160*e4b17023SJohn Marino 
161*e4b17023SJohn Marino 	__nleft -= __ret;
162*e4b17023SJohn Marino 	if (__nleft == 0)
163*e4b17023SJohn Marino 	  break;
164*e4b17023SJohn Marino 
165*e4b17023SJohn Marino 	const std::streamsize __off = __ret - __n1_left;
166*e4b17023SJohn Marino 	if (__off >= 0)
167*e4b17023SJohn Marino 	  {
168*e4b17023SJohn Marino 	    __nleft -= xwrite(__fd, __s2 + __off, __n2 - __off);
169*e4b17023SJohn Marino 	    break;
170*e4b17023SJohn Marino 	  }
171*e4b17023SJohn Marino 
172*e4b17023SJohn Marino 	__s1 += __ret;
173*e4b17023SJohn Marino 	__n1_left -= __ret;
174*e4b17023SJohn Marino       }
175*e4b17023SJohn Marino 
176*e4b17023SJohn Marino     return __n1 + __n2 - __nleft;
177*e4b17023SJohn Marino   }
178*e4b17023SJohn Marino #endif
179*e4b17023SJohn Marino } // anonymous namespace
180*e4b17023SJohn Marino 
181*e4b17023SJohn Marino 
182*e4b17023SJohn Marino namespace std _GLIBCXX_VISIBILITY(default)
183*e4b17023SJohn Marino {
184*e4b17023SJohn Marino _GLIBCXX_BEGIN_NAMESPACE_VERSION
185*e4b17023SJohn Marino 
186*e4b17023SJohn Marino   // Definitions for __basic_file<char>.
__basic_file(__c_lock *)187*e4b17023SJohn Marino   __basic_file<char>::__basic_file(__c_lock* /*__lock*/) throw()
188*e4b17023SJohn Marino   : _M_cfile(NULL), _M_cfile_created(false) { }
189*e4b17023SJohn Marino 
~__basic_file()190*e4b17023SJohn Marino   __basic_file<char>::~__basic_file()
191*e4b17023SJohn Marino   { this->close(); }
192*e4b17023SJohn Marino 
193*e4b17023SJohn Marino   __basic_file<char>*
sys_open(__c_file * __file,ios_base::openmode)194*e4b17023SJohn Marino   __basic_file<char>::sys_open(__c_file* __file, ios_base::openmode)
195*e4b17023SJohn Marino   {
196*e4b17023SJohn Marino     __basic_file* __ret = NULL;
197*e4b17023SJohn Marino     if (!this->is_open() && __file)
198*e4b17023SJohn Marino       {
199*e4b17023SJohn Marino 	int __err;
200*e4b17023SJohn Marino 	errno = 0;
201*e4b17023SJohn Marino 	do
202*e4b17023SJohn Marino 	  __err = this->sync();
203*e4b17023SJohn Marino 	while (__err && errno == EINTR);
204*e4b17023SJohn Marino 	if (!__err)
205*e4b17023SJohn Marino 	  {
206*e4b17023SJohn Marino 	    _M_cfile = __file;
207*e4b17023SJohn Marino 	    _M_cfile_created = false;
208*e4b17023SJohn Marino 	    __ret = this;
209*e4b17023SJohn Marino 	  }
210*e4b17023SJohn Marino       }
211*e4b17023SJohn Marino     return __ret;
212*e4b17023SJohn Marino   }
213*e4b17023SJohn Marino 
214*e4b17023SJohn Marino   __basic_file<char>*
sys_open(int __fd,ios_base::openmode __mode)215*e4b17023SJohn Marino   __basic_file<char>::sys_open(int __fd, ios_base::openmode __mode) throw ()
216*e4b17023SJohn Marino   {
217*e4b17023SJohn Marino     __basic_file* __ret = NULL;
218*e4b17023SJohn Marino     const char* __c_mode = fopen_mode(__mode);
219*e4b17023SJohn Marino     if (__c_mode && !this->is_open() && (_M_cfile = fdopen(__fd, __c_mode)))
220*e4b17023SJohn Marino       {
221*e4b17023SJohn Marino 	char* __buf = NULL;
222*e4b17023SJohn Marino 	_M_cfile_created = true;
223*e4b17023SJohn Marino 	if (__fd == 0)
224*e4b17023SJohn Marino 	  setvbuf(_M_cfile, __buf, _IONBF, 0);
225*e4b17023SJohn Marino 	__ret = this;
226*e4b17023SJohn Marino       }
227*e4b17023SJohn Marino     return __ret;
228*e4b17023SJohn Marino   }
229*e4b17023SJohn Marino 
230*e4b17023SJohn Marino   __basic_file<char>*
open(const char * __name,ios_base::openmode __mode,int)231*e4b17023SJohn Marino   __basic_file<char>::open(const char* __name, ios_base::openmode __mode,
232*e4b17023SJohn Marino 			   int /*__prot*/)
233*e4b17023SJohn Marino   {
234*e4b17023SJohn Marino     __basic_file* __ret = NULL;
235*e4b17023SJohn Marino     const char* __c_mode = fopen_mode(__mode);
236*e4b17023SJohn Marino     if (__c_mode && !this->is_open())
237*e4b17023SJohn Marino       {
238*e4b17023SJohn Marino #ifdef _GLIBCXX_USE_LFS
239*e4b17023SJohn Marino 	if ((_M_cfile = fopen64(__name, __c_mode)))
240*e4b17023SJohn Marino #else
241*e4b17023SJohn Marino 	if ((_M_cfile = fopen(__name, __c_mode)))
242*e4b17023SJohn Marino #endif
243*e4b17023SJohn Marino 	  {
244*e4b17023SJohn Marino 	    _M_cfile_created = true;
245*e4b17023SJohn Marino 	    __ret = this;
246*e4b17023SJohn Marino 	  }
247*e4b17023SJohn Marino       }
248*e4b17023SJohn Marino     return __ret;
249*e4b17023SJohn Marino   }
250*e4b17023SJohn Marino 
251*e4b17023SJohn Marino   bool
is_open() const252*e4b17023SJohn Marino   __basic_file<char>::is_open() const throw ()
253*e4b17023SJohn Marino   { return _M_cfile != 0; }
254*e4b17023SJohn Marino 
255*e4b17023SJohn Marino   int
fd()256*e4b17023SJohn Marino   __basic_file<char>::fd() throw ()
257*e4b17023SJohn Marino   { return fileno(_M_cfile); }
258*e4b17023SJohn Marino 
259*e4b17023SJohn Marino   __c_file*
file()260*e4b17023SJohn Marino   __basic_file<char>::file() throw ()
261*e4b17023SJohn Marino   { return _M_cfile; }
262*e4b17023SJohn Marino 
263*e4b17023SJohn Marino   __basic_file<char>*
close()264*e4b17023SJohn Marino   __basic_file<char>::close()
265*e4b17023SJohn Marino   {
266*e4b17023SJohn Marino     __basic_file* __ret = static_cast<__basic_file*>(NULL);
267*e4b17023SJohn Marino     if (this->is_open())
268*e4b17023SJohn Marino       {
269*e4b17023SJohn Marino 	int __err = 0;
270*e4b17023SJohn Marino 	if (_M_cfile_created)
271*e4b17023SJohn Marino 	  {
272*e4b17023SJohn Marino 	    // In general, no need to zero errno in advance if checking
273*e4b17023SJohn Marino 	    // for error first. However, C89/C99 (at variance with IEEE
274*e4b17023SJohn Marino 	    // 1003.1, f.i.) do not mandate that fclose must set errno
275*e4b17023SJohn Marino 	    // upon error.
276*e4b17023SJohn Marino 	    errno = 0;
277*e4b17023SJohn Marino 	    do
278*e4b17023SJohn Marino 	      __err = fclose(_M_cfile);
279*e4b17023SJohn Marino 	    while (__err && errno == EINTR);
280*e4b17023SJohn Marino 	  }
281*e4b17023SJohn Marino 	_M_cfile = 0;
282*e4b17023SJohn Marino 	if (!__err)
283*e4b17023SJohn Marino 	  __ret = this;
284*e4b17023SJohn Marino       }
285*e4b17023SJohn Marino     return __ret;
286*e4b17023SJohn Marino   }
287*e4b17023SJohn Marino 
288*e4b17023SJohn Marino   streamsize
xsgetn(char * __s,streamsize __n)289*e4b17023SJohn Marino   __basic_file<char>::xsgetn(char* __s, streamsize __n)
290*e4b17023SJohn Marino   {
291*e4b17023SJohn Marino     streamsize __ret;
292*e4b17023SJohn Marino     do
293*e4b17023SJohn Marino       __ret = read(this->fd(), __s, __n);
294*e4b17023SJohn Marino     while (__ret == -1L && errno == EINTR);
295*e4b17023SJohn Marino     return __ret;
296*e4b17023SJohn Marino   }
297*e4b17023SJohn Marino 
298*e4b17023SJohn Marino   streamsize
xsputn(const char * __s,streamsize __n)299*e4b17023SJohn Marino   __basic_file<char>::xsputn(const char* __s, streamsize __n)
300*e4b17023SJohn Marino   { return xwrite(this->fd(), __s, __n); }
301*e4b17023SJohn Marino 
302*e4b17023SJohn Marino   streamsize
xsputn_2(const char * __s1,streamsize __n1,const char * __s2,streamsize __n2)303*e4b17023SJohn Marino   __basic_file<char>::xsputn_2(const char* __s1, streamsize __n1,
304*e4b17023SJohn Marino 			       const char* __s2, streamsize __n2)
305*e4b17023SJohn Marino   {
306*e4b17023SJohn Marino     streamsize __ret = 0;
307*e4b17023SJohn Marino #ifdef _GLIBCXX_HAVE_WRITEV
308*e4b17023SJohn Marino     __ret = xwritev(this->fd(), __s1, __n1, __s2, __n2);
309*e4b17023SJohn Marino #else
310*e4b17023SJohn Marino     if (__n1)
311*e4b17023SJohn Marino       __ret = xwrite(this->fd(), __s1, __n1);
312*e4b17023SJohn Marino 
313*e4b17023SJohn Marino     if (__ret == __n1)
314*e4b17023SJohn Marino       __ret += xwrite(this->fd(), __s2, __n2);
315*e4b17023SJohn Marino #endif
316*e4b17023SJohn Marino     return __ret;
317*e4b17023SJohn Marino   }
318*e4b17023SJohn Marino 
319*e4b17023SJohn Marino   streamoff
seekoff(streamoff __off,ios_base::seekdir __way)320*e4b17023SJohn Marino   __basic_file<char>::seekoff(streamoff __off, ios_base::seekdir __way) throw ()
321*e4b17023SJohn Marino   {
322*e4b17023SJohn Marino #ifdef _GLIBCXX_USE_LFS
323*e4b17023SJohn Marino     return lseek64(this->fd(), __off, __way);
324*e4b17023SJohn Marino #else
325*e4b17023SJohn Marino     if (__off > numeric_limits<off_t>::max()
326*e4b17023SJohn Marino 	|| __off < numeric_limits<off_t>::min())
327*e4b17023SJohn Marino       return -1L;
328*e4b17023SJohn Marino     return lseek(this->fd(), __off, __way);
329*e4b17023SJohn Marino #endif
330*e4b17023SJohn Marino   }
331*e4b17023SJohn Marino 
332*e4b17023SJohn Marino   int
sync()333*e4b17023SJohn Marino   __basic_file<char>::sync()
334*e4b17023SJohn Marino   { return fflush(_M_cfile); }
335*e4b17023SJohn Marino 
336*e4b17023SJohn Marino   streamsize
showmanyc()337*e4b17023SJohn Marino   __basic_file<char>::showmanyc()
338*e4b17023SJohn Marino   {
339*e4b17023SJohn Marino #ifndef _GLIBCXX_NO_IOCTL
340*e4b17023SJohn Marino #ifdef FIONREAD
341*e4b17023SJohn Marino     // Pipes and sockets.
342*e4b17023SJohn Marino #ifdef _GLIBCXX_FIONREAD_TAKES_OFF_T
343*e4b17023SJohn Marino     off_t __num = 0;
344*e4b17023SJohn Marino #else
345*e4b17023SJohn Marino     int __num = 0;
346*e4b17023SJohn Marino #endif
347*e4b17023SJohn Marino     int __r = ioctl(this->fd(), FIONREAD, &__num);
348*e4b17023SJohn Marino     if (!__r && __num >= 0)
349*e4b17023SJohn Marino       return __num;
350*e4b17023SJohn Marino #endif
351*e4b17023SJohn Marino #endif
352*e4b17023SJohn Marino 
353*e4b17023SJohn Marino #ifdef _GLIBCXX_HAVE_POLL
354*e4b17023SJohn Marino     // Cheap test.
355*e4b17023SJohn Marino     struct pollfd __pfd[1];
356*e4b17023SJohn Marino     __pfd[0].fd = this->fd();
357*e4b17023SJohn Marino     __pfd[0].events = POLLIN;
358*e4b17023SJohn Marino     if (poll(__pfd, 1, 0) <= 0)
359*e4b17023SJohn Marino       return 0;
360*e4b17023SJohn Marino #endif
361*e4b17023SJohn Marino 
362*e4b17023SJohn Marino #if defined(_GLIBCXX_HAVE_S_ISREG) || defined(_GLIBCXX_HAVE_S_IFREG)
363*e4b17023SJohn Marino     // Regular files.
364*e4b17023SJohn Marino #ifdef _GLIBCXX_USE_LFS
365*e4b17023SJohn Marino     struct stat64 __buffer;
366*e4b17023SJohn Marino     const int __err = fstat64(this->fd(), &__buffer);
367*e4b17023SJohn Marino     if (!__err && _GLIBCXX_ISREG(__buffer.st_mode))
368*e4b17023SJohn Marino       {
369*e4b17023SJohn Marino 	const streamoff __off = __buffer.st_size - lseek64(this->fd(), 0,
370*e4b17023SJohn Marino 							   ios_base::cur);
371*e4b17023SJohn Marino 	return std::min(__off, streamoff(numeric_limits<streamsize>::max()));
372*e4b17023SJohn Marino       }
373*e4b17023SJohn Marino #else
374*e4b17023SJohn Marino     struct stat __buffer;
375*e4b17023SJohn Marino     const int __err = fstat(this->fd(), &__buffer);
376*e4b17023SJohn Marino     if (!__err && _GLIBCXX_ISREG(__buffer.st_mode))
377*e4b17023SJohn Marino       return __buffer.st_size - lseek(this->fd(), 0, ios_base::cur);
378*e4b17023SJohn Marino #endif
379*e4b17023SJohn Marino #endif
380*e4b17023SJohn Marino     return 0;
381*e4b17023SJohn Marino   }
382*e4b17023SJohn Marino 
383*e4b17023SJohn Marino _GLIBCXX_END_NAMESPACE_VERSION
384*e4b17023SJohn Marino } // namespace
385*e4b17023SJohn Marino 
386