1 // Wrapper of C-language FILE struct -*- C++ -*- 2 3 // Copyright (C) 2000, 2001, 2002 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 std 62 { 63 // Definitions for __basic_file<char>. 64 __basic_file<char>::__basic_file(__c_lock* /*__lock*/) 65 : _M_cfile(NULL), _M_cfile_created(false) { } 66 67 __basic_file<char>::~__basic_file() 68 { this->close(); } 69 70 void 71 __basic_file<char>::_M_open_mode(ios_base::openmode __mode, int& __p_mode, 72 int&, char* __c_mode) 73 { 74 bool __testb = __mode & ios_base::binary; 75 bool __testi = __mode & ios_base::in; 76 bool __testo = __mode & ios_base::out; 77 bool __testt = __mode & ios_base::trunc; 78 bool __testa = __mode & ios_base::app; 79 80 // Set __c_mode for use in fopen. 81 // Set __p_mode for use in open. 82 if (!__testi && __testo && !__testt && !__testa) 83 { 84 strcpy(__c_mode, "w"); 85 __p_mode = (O_WRONLY | O_CREAT); 86 } 87 if (!__testi && __testo && !__testt && __testa) 88 { 89 strcpy(__c_mode, "a"); 90 __p_mode |= O_WRONLY | O_CREAT | O_APPEND; 91 } 92 if (!__testi && __testo && __testt && !__testa) 93 { 94 strcpy(__c_mode, "w"); 95 __p_mode |= O_WRONLY | O_CREAT | O_TRUNC; 96 } 97 98 if (__testi && !__testo && !__testt && !__testa) 99 { 100 strcpy(__c_mode, "r"); 101 __p_mode |= O_RDONLY; 102 } 103 if (__testi && __testo && !__testt && !__testa) 104 { 105 strcpy(__c_mode, "r+"); 106 __p_mode |= O_RDWR | O_CREAT; 107 } 108 if (__testi && __testo && __testt && !__testa) 109 { 110 strcpy(__c_mode, "w+"); 111 __p_mode |= O_RDWR | O_CREAT | O_TRUNC; 112 } 113 if (__testb) 114 strcat(__c_mode, "b"); 115 } 116 117 __basic_file<char>* 118 __basic_file<char>::sys_open(__c_file* __file, ios_base::openmode) 119 { 120 __basic_file* __ret = NULL; 121 if (!this->is_open() && __file) 122 { 123 _M_cfile = __file; 124 _M_cfile_created = false; 125 __ret = this; 126 } 127 return __ret; 128 } 129 130 __basic_file<char>* 131 __basic_file<char>::sys_open(int __fd, ios_base::openmode __mode, 132 bool __del) 133 { 134 __basic_file* __ret = NULL; 135 int __p_mode = 0; 136 int __rw_mode = 0; 137 char __c_mode[4]; 138 139 _M_open_mode(__mode, __p_mode, __rw_mode, __c_mode); 140 if (!this->is_open() && (_M_cfile = fdopen(__fd, __c_mode))) 141 { 142 // Iff __del is true, then close will fclose the fd. 143 _M_cfile_created = __del; 144 145 if (__fd == 0) 146 setvbuf(_M_cfile, reinterpret_cast<char*>(NULL), _IONBF, 0); 147 148 __ret = this; 149 } 150 return __ret; 151 } 152 153 int 154 __basic_file<char>::sys_getc() 155 { return getc(_M_cfile); } 156 157 int 158 __basic_file<char>::sys_ungetc(int __c) 159 { return ungetc(__c, _M_cfile); } 160 161 __basic_file<char>* 162 __basic_file<char>::open(const char* __name, ios_base::openmode __mode, 163 int /*__prot*/) 164 { 165 __basic_file* __ret = NULL; 166 int __p_mode = 0; 167 int __rw_mode = 0; 168 char __c_mode[4]; 169 170 _M_open_mode(__mode, __p_mode, __rw_mode, __c_mode); 171 172 if (!this->is_open()) 173 { 174 if ((_M_cfile = fopen(__name, __c_mode))) 175 { 176 _M_cfile_created = true; 177 __ret = this; 178 } 179 } 180 return __ret; 181 } 182 183 bool 184 __basic_file<char>::is_open() const 185 { return _M_cfile != 0; } 186 187 int 188 __basic_file<char>::fd() 189 { return fileno(_M_cfile) ; } 190 191 __basic_file<char>* 192 __basic_file<char>::close() 193 { 194 __basic_file* __retval = static_cast<__basic_file*>(NULL); 195 if (this->is_open()) 196 { 197 if (_M_cfile_created) 198 fclose(_M_cfile); 199 else 200 fflush(_M_cfile); 201 _M_cfile = 0; 202 __retval = this; 203 } 204 return __retval; 205 } 206 207 streamsize 208 __basic_file<char>::xsgetn(char* __s, streamsize __n) 209 { return fread(__s, 1, __n, _M_cfile); } 210 211 streamsize 212 __basic_file<char>::xsputn(const char* __s, streamsize __n) 213 { return fwrite(__s, 1, __n, _M_cfile); } 214 215 streamoff 216 __basic_file<char>::seekoff(streamoff __off, ios_base::seekdir __way, 217 ios_base::openmode /*__mode*/) 218 { 219 if (!fseek(_M_cfile, __off, __way)) 220 return ftell(_M_cfile); 221 else 222 // Fseek failed. 223 return -1L; 224 } 225 226 streamoff 227 __basic_file<char>::seekpos(streamoff __pos, ios_base::openmode /*__mode*/) 228 { 229 if (!fseek(_M_cfile, __pos, ios_base::beg)) 230 return ftell(_M_cfile); 231 else 232 // Fseek failed. 233 return -1L; 234 } 235 236 int 237 __basic_file<char>::sync() 238 { return fflush(_M_cfile); } 239 240 streamsize 241 __basic_file<char>::showmanyc_helper() 242 { 243 #ifdef FIONREAD 244 // Pipes and sockets. 245 int __num = 0; 246 int __r = ioctl(this->fd(), FIONREAD, &__num); 247 if (!__r && __num >= 0) 248 return __num; 249 #endif 250 251 #ifdef _GLIBCPP_HAVE_POLL 252 // Cheap test. 253 struct pollfd __pfd[1]; 254 __pfd[0].fd = this->fd(); 255 __pfd[0].events = POLLIN; 256 if (poll(__pfd, 1, 0) <= 0) 257 return 0; 258 #endif 259 260 #if defined(_GLIBCPP_HAVE_S_ISREG) || defined(_GLIBCPP_HAVE_S_IFREG) 261 // Regular files. 262 struct stat __buffer; 263 int __ret = fstat(this->fd(), &__buffer); 264 if (!__ret && _GLIBCPP_ISREG(__buffer.st_mode)) 265 return __buffer.st_size - ftell(_M_cfile); 266 #endif 267 return 0; 268 } 269 } // namespace std 270