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