1 // Wrapper of C-language FILE struct -*- C++ -*- 2 3 // Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 2, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // You should have received a copy of the GNU General Public License along 17 // with this library; see the file COPYING. If not, write to the Free 18 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 19 // USA. 20 21 // As a special exception, you may use this file as part of a free software 22 // library without restriction. Specifically, if other files instantiate 23 // templates or use macros or inline functions from this file, or you compile 24 // this file and link it with other files to produce an executable, this 25 // file does not by itself cause the resulting executable to be covered by 26 // the GNU General Public License. This exception does not however 27 // invalidate any other reasons why the executable file might be covered by 28 // the GNU General Public License. 29 30 // 31 // ISO C++ 14882: 27.8 File-based streams 32 // 33 34 #include <bits/basic_file.h> 35 #include <fcntl.h> 36 #include <unistd.h> 37 38 #ifdef _GLIBCPP_HAVE_SYS_IOCTL_H 39 #define BSD_COMP /* Get FIONREAD on Solaris2. */ 40 #include <sys/ioctl.h> 41 #endif 42 43 // Pick up FIONREAD on Solaris 2.5. 44 #ifdef _GLIBCPP_HAVE_SYS_FILIO_H 45 #include <sys/filio.h> 46 #endif 47 48 #ifdef _GLIBCPP_HAVE_POLL 49 #include <poll.h> 50 #endif 51 52 #if defined(_GLIBCPP_HAVE_S_ISREG) || defined(_GLIBCPP_HAVE_S_IFREG) 53 # include <sys/stat.h> 54 # ifdef _GLIBCPP_HAVE_S_ISREG 55 # define _GLIBCPP_ISREG(x) S_ISREG(x) 56 # else 57 # define _GLIBCPP_ISREG(x) (((x) & S_IFMT) == S_IFREG) 58 # endif 59 #endif 60 61 namespace __gnu_internal 62 { 63 // Map ios_base::openmode flags to a string for use in fopen(). 64 // Table of valid combinations as given in [lib.filebuf.members]/2. 65 static const char* fopen_mode(std::ios_base::openmode mode)66 fopen_mode(std::ios_base::openmode mode) 67 { 68 enum 69 { 70 in = std::ios_base::in, 71 out = std::ios_base::out, 72 trunc = std::ios_base::trunc, 73 app = std::ios_base::app, 74 binary = std::ios_base::binary 75 }; 76 77 switch (mode & (in|out|trunc|app|binary)) 78 { 79 case ( out ): return "w"; 80 case ( out |app ): return "a"; 81 case ( out|trunc ): return "w"; 82 case (in ): return "r"; 83 case (in|out ): return "r+"; 84 case (in|out|trunc ): return "w+"; 85 86 case ( out |binary): return "wb"; 87 case ( out |app|binary): return "ab"; 88 case ( out|trunc |binary): return "wb"; 89 case (in |binary): return "rb"; 90 case (in|out |binary): return "r+b"; 91 case (in|out|trunc |binary): return "w+b"; 92 93 default: return 0; // invalid 94 } 95 } 96 } // namespace __gnu_internal 97 98 namespace std 99 { 100 // Definitions for __basic_file<char>. __basic_file(__c_lock *)101 __basic_file<char>::__basic_file(__c_lock* /*__lock*/) 102 : _M_cfile(NULL), _M_cfile_created(false) { } 103 ~__basic_file()104 __basic_file<char>::~__basic_file() 105 { this->close(); } 106 107 __basic_file<char>* sys_open(__c_file * __file,ios_base::openmode)108 __basic_file<char>::sys_open(__c_file* __file, ios_base::openmode) 109 { 110 __basic_file* __ret = NULL; 111 if (!this->is_open() && __file) 112 { 113 _M_cfile = __file; 114 _M_cfile_created = false; 115 __ret = this; 116 } 117 return __ret; 118 } 119 120 __basic_file<char>* sys_open(int __fd,ios_base::openmode __mode,bool __del)121 __basic_file<char>::sys_open(int __fd, ios_base::openmode __mode, 122 bool __del) 123 { 124 __basic_file* __ret = NULL; 125 const char* __c_mode = __gnu_internal::fopen_mode(__mode); 126 if (__c_mode && !this->is_open() 127 && (_M_cfile = fdopen(__fd, __c_mode))) 128 { 129 // Iff __del is true, then close will fclose the fd. 130 _M_cfile_created = __del; 131 132 if (__fd == 0) 133 setvbuf(_M_cfile, reinterpret_cast<char*>(NULL), _IONBF, 0); 134 135 __ret = this; 136 } 137 return __ret; 138 } 139 140 int sys_getc()141 __basic_file<char>::sys_getc() 142 { return getc(_M_cfile); } 143 144 int sys_ungetc(int __c)145 __basic_file<char>::sys_ungetc(int __c) 146 { return ungetc(__c, _M_cfile); } 147 148 __basic_file<char>* open(const char * __name,ios_base::openmode __mode,int)149 __basic_file<char>::open(const char* __name, ios_base::openmode __mode, 150 int /*__prot*/) 151 { 152 __basic_file* __ret = NULL; 153 const char* __c_mode = __gnu_internal::fopen_mode(__mode); 154 if (__c_mode && !this->is_open()) 155 { 156 if ((_M_cfile = fopen(__name, __c_mode))) 157 { 158 _M_cfile_created = true; 159 __ret = this; 160 } 161 } 162 return __ret; 163 } 164 165 bool is_open() const166 __basic_file<char>::is_open() const 167 { return _M_cfile != 0; } 168 169 int fd()170 __basic_file<char>::fd() 171 { return fileno(_M_cfile) ; } 172 173 __basic_file<char>* close()174 __basic_file<char>::close() 175 { 176 __basic_file* __retval = static_cast<__basic_file*>(NULL); 177 if (this->is_open()) 178 { 179 if (_M_cfile_created) 180 fclose(_M_cfile); 181 else 182 fflush(_M_cfile); 183 _M_cfile = 0; 184 __retval = this; 185 } 186 return __retval; 187 } 188 189 streamsize xsgetn(char * __s,streamsize __n)190 __basic_file<char>::xsgetn(char* __s, streamsize __n) 191 { return fread(__s, 1, __n, _M_cfile); } 192 193 streamsize xsputn(const char * __s,streamsize __n)194 __basic_file<char>::xsputn(const char* __s, streamsize __n) 195 { return fwrite(__s, 1, __n, _M_cfile); } 196 197 streamoff seekoff(streamoff __off,ios_base::seekdir __way,ios_base::openmode)198 __basic_file<char>::seekoff(streamoff __off, ios_base::seekdir __way, 199 ios_base::openmode /*__mode*/) 200 { 201 if (!fseek(_M_cfile, __off, __way)) 202 return ftell(_M_cfile); 203 else 204 // Fseek failed. 205 return -1L; 206 } 207 208 streamoff seekpos(streamoff __pos,ios_base::openmode)209 __basic_file<char>::seekpos(streamoff __pos, ios_base::openmode /*__mode*/) 210 { 211 if (!fseek(_M_cfile, __pos, ios_base::beg)) 212 return ftell(_M_cfile); 213 else 214 // Fseek failed. 215 return -1L; 216 } 217 218 int sync()219 __basic_file<char>::sync() 220 { return fflush(_M_cfile); } 221 222 streamsize showmanyc_helper()223 __basic_file<char>::showmanyc_helper() 224 { 225 #ifdef FIONREAD 226 // Pipes and sockets. 227 int __num = 0; 228 int __r = ioctl(this->fd(), FIONREAD, &__num); 229 if (!__r && __num >= 0) 230 return __num; 231 #endif 232 233 #ifdef _GLIBCPP_HAVE_POLL 234 // Cheap test. 235 struct pollfd __pfd[1]; 236 __pfd[0].fd = this->fd(); 237 __pfd[0].events = POLLIN; 238 if (poll(__pfd, 1, 0) <= 0) 239 return 0; 240 #endif 241 242 #if defined(_GLIBCPP_HAVE_S_ISREG) || defined(_GLIBCPP_HAVE_S_IFREG) 243 // Regular files. 244 struct stat __buffer; 245 int __ret = fstat(this->fd(), &__buffer); 246 if (!__ret && _GLIBCPP_ISREG(__buffer.st_mode)) 247 return __buffer.st_size - ftell(_M_cfile); 248 #endif 249 return 0; 250 } 251 } // namespace std 252