197403Sobrien// Wrapper of C-language FILE struct -*- C++ -*- 297403Sobrien 3169691Skan// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2006 4169691Skan// Free Software Foundation, Inc. 597403Sobrien// 697403Sobrien// This file is part of the GNU ISO C++ Library. This library is free 797403Sobrien// software; you can redistribute it and/or modify it under the 897403Sobrien// terms of the GNU General Public License as published by the 997403Sobrien// Free Software Foundation; either version 2, or (at your option) 1097403Sobrien// any later version. 1197403Sobrien 1297403Sobrien// This library is distributed in the hope that it will be useful, 1397403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of 1497403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1597403Sobrien// GNU General Public License for more details. 1697403Sobrien 1797403Sobrien// You should have received a copy of the GNU General Public License along 1897403Sobrien// with this library; see the file COPYING. If not, write to the Free 19169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 2097403Sobrien// USA. 2197403Sobrien 2297403Sobrien// As a special exception, you may use this file as part of a free software 2397403Sobrien// library without restriction. Specifically, if other files instantiate 2497403Sobrien// templates or use macros or inline functions from this file, or you compile 2597403Sobrien// this file and link it with other files to produce an executable, this 2697403Sobrien// file does not by itself cause the resulting executable to be covered by 2797403Sobrien// the GNU General Public License. This exception does not however 2897403Sobrien// invalidate any other reasons why the executable file might be covered by 2997403Sobrien// the GNU General Public License. 3097403Sobrien 3197403Sobrien// 3297403Sobrien// ISO C++ 14882: 27.8 File-based streams 3397403Sobrien// 3497403Sobrien 3597403Sobrien#include <bits/basic_file.h> 36117397Skan#include <fcntl.h> 37132720Skan#include <errno.h> 38132720Skan 39132720Skan#ifdef _GLIBCXX_HAVE_POLL 40132720Skan#include <poll.h> 41132720Skan#endif 42132720Skan 43132720Skan// Pick up ioctl on Solaris 2.8 44132720Skan#ifdef _GLIBCXX_HAVE_UNISTD_H 45117397Skan#include <unistd.h> 46132720Skan#endif 4797403Sobrien 48132720Skan// Pick up FIONREAD on Solaris 2 49132720Skan#ifdef _GLIBCXX_HAVE_SYS_IOCTL_H 50132720Skan#define BSD_COMP 51117397Skan#include <sys/ioctl.h> 52117397Skan#endif 53117397Skan 54117397Skan// Pick up FIONREAD on Solaris 2.5. 55132720Skan#ifdef _GLIBCXX_HAVE_SYS_FILIO_H 56117397Skan#include <sys/filio.h> 57117397Skan#endif 58117397Skan 59132720Skan#ifdef _GLIBCXX_HAVE_SYS_UIO_H 60132720Skan#include <sys/uio.h> 61117397Skan#endif 62117397Skan 63132720Skan#if defined(_GLIBCXX_HAVE_S_ISREG) || defined(_GLIBCXX_HAVE_S_IFREG) 64117397Skan# include <sys/stat.h> 65132720Skan# ifdef _GLIBCXX_HAVE_S_ISREG 66132720Skan# define _GLIBCXX_ISREG(x) S_ISREG(x) 67117397Skan# else 68132720Skan# define _GLIBCXX_ISREG(x) (((x) & S_IFMT) == S_IFREG) 69117397Skan# endif 70117397Skan#endif 71117397Skan 72169691Skan#include <limits> // For <off_t>::max() and min() and <streamsize>::max() 73132720Skan 74169691Skannamespace 7597403Sobrien{ 76132720Skan // Map ios_base::openmode flags to a string for use in fopen(). 77132720Skan // Table of valid combinations as given in [lib.filebuf.members]/2. 78132720Skan static const char* 79132720Skan fopen_mode(std::ios_base::openmode mode) 80132720Skan { 81132720Skan enum 82117397Skan { 83132720Skan in = std::ios_base::in, 84132720Skan out = std::ios_base::out, 85132720Skan trunc = std::ios_base::trunc, 86132720Skan app = std::ios_base::app, 87132720Skan binary = std::ios_base::binary 88132720Skan }; 89132720Skan 90132720Skan switch (mode & (in|out|trunc|app|binary)) 91117397Skan { 92132720Skan case ( out ): return "w"; 93132720Skan case ( out |app ): return "a"; 94132720Skan case ( out|trunc ): return "w"; 95132720Skan case (in ): return "r"; 96132720Skan case (in|out ): return "r+"; 97132720Skan case (in|out|trunc ): return "w+"; 98169691Skan // Extension to Table 92. 99169691Skan case (in|out |app ): return "a+"; 100132720Skan 101132720Skan case ( out |binary): return "wb"; 102132720Skan case ( out |app|binary): return "ab"; 103132720Skan case ( out|trunc |binary): return "wb"; 104132720Skan case (in |binary): return "rb"; 105132720Skan case (in|out |binary): return "r+b"; 106132720Skan case (in|out|trunc |binary): return "w+b"; 107169691Skan // Extension to Table 92. 108169691Skan case (in|out |app|binary): return "a+b"; 109132720Skan 110132720Skan default: return 0; // invalid 111117397Skan } 112132720Skan } 113132720Skan 114132720Skan // Wrapper handling partial write. 115132720Skan static std::streamsize 116132720Skan xwrite(int __fd, const char* __s, std::streamsize __n) 117132720Skan { 118132720Skan std::streamsize __nleft = __n; 119132720Skan 120132720Skan for (;;) 121117397Skan { 122132720Skan const std::streamsize __ret = write(__fd, __s, __nleft); 123132720Skan if (__ret == -1L && errno == EINTR) 124132720Skan continue; 125132720Skan if (__ret == -1L) 126132720Skan break; 127132720Skan 128132720Skan __nleft -= __ret; 129132720Skan if (__nleft == 0) 130132720Skan break; 131132720Skan 132132720Skan __s += __ret; 133117397Skan } 134117397Skan 135132720Skan return __n - __nleft; 136132720Skan } 137132720Skan 138132720Skan#ifdef _GLIBCXX_HAVE_WRITEV 139132720Skan // Wrapper handling partial writev. 140132720Skan static std::streamsize 141132720Skan xwritev(int __fd, const char* __s1, std::streamsize __n1, 142132720Skan const char* __s2, std::streamsize __n2) 143132720Skan { 144132720Skan std::streamsize __nleft = __n1 + __n2; 145132720Skan std::streamsize __n1_left = __n1; 146132720Skan 147132720Skan struct iovec __iov[2]; 148132720Skan __iov[1].iov_base = const_cast<char*>(__s2); 149132720Skan __iov[1].iov_len = __n2; 150132720Skan 151132720Skan for (;;) 152117397Skan { 153132720Skan __iov[0].iov_base = const_cast<char*>(__s1); 154132720Skan __iov[0].iov_len = __n1_left; 155132720Skan 156132720Skan const std::streamsize __ret = writev(__fd, __iov, 2); 157132720Skan if (__ret == -1L && errno == EINTR) 158132720Skan continue; 159132720Skan if (__ret == -1L) 160132720Skan break; 161132720Skan 162132720Skan __nleft -= __ret; 163132720Skan if (__nleft == 0) 164132720Skan break; 165132720Skan 166132720Skan const std::streamsize __off = __ret - __n1_left; 167132720Skan if (__off >= 0) 168132720Skan { 169132720Skan __nleft -= xwrite(__fd, __s2 + __off, __n2 - __off); 170132720Skan break; 171132720Skan } 172132720Skan 173132720Skan __s1 += __ret; 174132720Skan __n1_left -= __ret; 175117397Skan } 176132720Skan 177132720Skan return __n1 + __n2 - __nleft; 17897403Sobrien } 179132720Skan#endif 180169691Skan} // anonymous namespace 181132720Skan 182169691Skan 183169691Skan_GLIBCXX_BEGIN_NAMESPACE(std) 184169691Skan 185132720Skan // Definitions for __basic_file<char>. 186132720Skan __basic_file<char>::__basic_file(__c_lock* /*__lock*/) 187132720Skan : _M_cfile(NULL), _M_cfile_created(false) { } 188132720Skan 189132720Skan __basic_file<char>::~__basic_file() 190132720Skan { this->close(); } 191132720Skan 19297403Sobrien __basic_file<char>* 19397403Sobrien __basic_file<char>::sys_open(__c_file* __file, ios_base::openmode) 19497403Sobrien { 19597403Sobrien __basic_file* __ret = NULL; 19697403Sobrien if (!this->is_open() && __file) 19797403Sobrien { 198146897Skan int __err; 199146897Skan errno = 0; 200146897Skan do 201146897Skan __err = this->sync(); 202146897Skan while (__err && errno == EINTR); 203146897Skan if (!__err) 204146897Skan { 205146897Skan _M_cfile = __file; 206146897Skan _M_cfile_created = false; 207146897Skan __ret = this; 208146897Skan } 20997403Sobrien } 21097403Sobrien return __ret; 21197403Sobrien } 21297403Sobrien 21397403Sobrien __basic_file<char>* 214132720Skan __basic_file<char>::sys_open(int __fd, ios_base::openmode __mode) 21597403Sobrien { 21697403Sobrien __basic_file* __ret = NULL; 217169691Skan const char* __c_mode = fopen_mode(__mode); 218132720Skan if (__c_mode && !this->is_open() && (_M_cfile = fdopen(__fd, __c_mode))) 21997403Sobrien { 220132720Skan char* __buf = NULL; 221132720Skan _M_cfile_created = true; 22297403Sobrien if (__fd == 0) 223132720Skan setvbuf(_M_cfile, __buf, _IONBF, 0); 22497403Sobrien __ret = this; 22597403Sobrien } 22697403Sobrien return __ret; 22797403Sobrien } 22897403Sobrien 22997403Sobrien __basic_file<char>* 23097403Sobrien __basic_file<char>::open(const char* __name, ios_base::openmode __mode, 23197403Sobrien int /*__prot*/) 23297403Sobrien { 23397403Sobrien __basic_file* __ret = NULL; 234169691Skan const char* __c_mode = fopen_mode(__mode); 235132720Skan if (__c_mode && !this->is_open()) 23697403Sobrien { 237132720Skan#ifdef _GLIBCXX_USE_LFS 238132720Skan if ((_M_cfile = fopen64(__name, __c_mode))) 239132720Skan#else 24097403Sobrien if ((_M_cfile = fopen(__name, __c_mode))) 241132720Skan#endif 24297403Sobrien { 24397403Sobrien _M_cfile_created = true; 24497403Sobrien __ret = this; 24597403Sobrien } 24697403Sobrien } 24797403Sobrien return __ret; 24897403Sobrien } 24997403Sobrien 25097403Sobrien bool 25197403Sobrien __basic_file<char>::is_open() const 25297403Sobrien { return _M_cfile != 0; } 25397403Sobrien 25497403Sobrien int 25597403Sobrien __basic_file<char>::fd() 256132720Skan { return fileno(_M_cfile); } 25797403Sobrien 258132720Skan __c_file* 259132720Skan __basic_file<char>::file() 260132720Skan { return _M_cfile; } 261132720Skan 26297403Sobrien __basic_file<char>* 26397403Sobrien __basic_file<char>::close() 26497403Sobrien { 265132720Skan __basic_file* __ret = static_cast<__basic_file*>(NULL); 26697403Sobrien if (this->is_open()) 26797403Sobrien { 268146897Skan int __err = 0; 269117397Skan if (_M_cfile_created) 270146897Skan { 271146897Skan // In general, no need to zero errno in advance if checking 272146897Skan // for error first. However, C89/C99 (at variance with IEEE 273146897Skan // 1003.1, f.i.) do not mandate that fclose must set errno 274146897Skan // upon error. 275146897Skan errno = 0; 276146897Skan do 277146897Skan __err = fclose(_M_cfile); 278146897Skan while (__err && errno == EINTR); 279146897Skan } 280117397Skan _M_cfile = 0; 281146897Skan if (!__err) 282146897Skan __ret = this; 28397403Sobrien } 284132720Skan return __ret; 28597403Sobrien } 28697403Sobrien 28797403Sobrien streamsize 28897403Sobrien __basic_file<char>::xsgetn(char* __s, streamsize __n) 289132720Skan { 290132720Skan streamsize __ret; 291132720Skan do 292132720Skan __ret = read(this->fd(), __s, __n); 293132720Skan while (__ret == -1L && errno == EINTR); 294132720Skan return __ret; 295132720Skan } 296132720Skan 29797403Sobrien streamsize 29897403Sobrien __basic_file<char>::xsputn(const char* __s, streamsize __n) 299169691Skan { return xwrite(this->fd(), __s, __n); } 300132720Skan 301132720Skan streamsize 302132720Skan __basic_file<char>::xsputn_2(const char* __s1, streamsize __n1, 303132720Skan const char* __s2, streamsize __n2) 304132720Skan { 305132720Skan streamsize __ret = 0; 306132720Skan#ifdef _GLIBCXX_HAVE_WRITEV 307169691Skan __ret = xwritev(this->fd(), __s1, __n1, __s2, __n2); 308132720Skan#else 309132720Skan if (__n1) 310169691Skan __ret = xwrite(this->fd(), __s1, __n1); 311132720Skan 312132720Skan if (__ret == __n1) 313169691Skan __ret += xwrite(this->fd(), __s2, __n2); 314132720Skan#endif 315132720Skan return __ret; 31697403Sobrien } 31797403Sobrien 31897403Sobrien streamoff 319132720Skan __basic_file<char>::seekoff(streamoff __off, ios_base::seekdir __way) 320132720Skan { 321132720Skan#ifdef _GLIBCXX_USE_LFS 322132720Skan return lseek64(this->fd(), __off, __way); 323132720Skan#else 324169691Skan if (__off > numeric_limits<off_t>::max() 325169691Skan || __off < numeric_limits<off_t>::min()) 326117397Skan return -1L; 327132720Skan return lseek(this->fd(), __off, __way); 328132720Skan#endif 32997403Sobrien } 330132720Skan 33197403Sobrien int 33297403Sobrien __basic_file<char>::sync() 33397403Sobrien { return fflush(_M_cfile); } 334117397Skan 335117397Skan streamsize 336132720Skan __basic_file<char>::showmanyc() 337117397Skan { 338117397Skan#ifdef FIONREAD 339117397Skan // Pipes and sockets. 340132720Skan#ifdef _GLIBCXX_FIONREAD_TAKES_OFF_T 341132720Skan off_t __num = 0; 342132720Skan#else 343117397Skan int __num = 0; 344132720Skan#endif 345117397Skan int __r = ioctl(this->fd(), FIONREAD, &__num); 346117397Skan if (!__r && __num >= 0) 347117397Skan return __num; 348117397Skan#endif 349117397Skan 350132720Skan#ifdef _GLIBCXX_HAVE_POLL 351117397Skan // Cheap test. 352117397Skan struct pollfd __pfd[1]; 353117397Skan __pfd[0].fd = this->fd(); 354117397Skan __pfd[0].events = POLLIN; 355117397Skan if (poll(__pfd, 1, 0) <= 0) 356117397Skan return 0; 357117397Skan#endif 358117397Skan 359132720Skan#if defined(_GLIBCXX_HAVE_S_ISREG) || defined(_GLIBCXX_HAVE_S_IFREG) 360117397Skan // Regular files. 361169691Skan#ifdef _GLIBCXX_USE_LFS 362169691Skan struct stat64 __buffer; 363169691Skan const int __err = fstat64(this->fd(), &__buffer); 364169691Skan if (!__err && _GLIBCXX_ISREG(__buffer.st_mode)) 365169691Skan { 366169691Skan const streamoff __off = __buffer.st_size - lseek64(this->fd(), 0, 367169691Skan ios_base::cur); 368169691Skan return std::min(__off, streamoff(numeric_limits<streamsize>::max())); 369169691Skan } 370169691Skan#else 371117397Skan struct stat __buffer; 372169691Skan const int __err = fstat(this->fd(), &__buffer); 373169691Skan if (!__err && _GLIBCXX_ISREG(__buffer.st_mode)) 374169691Skan return __buffer.st_size - lseek(this->fd(), 0, ios_base::cur); 375117397Skan#endif 376169691Skan#endif 377117397Skan return 0; 378117397Skan } 379169691Skan 380169691Skan_GLIBCXX_END_NAMESPACE 381169691Skan 382