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