file_descriptor.cpp
来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 287 行
CPP
287 行
// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)// (C) Copyright 2003-2007 Jonathan Turkanis// Distributed under the Boost Software License, Version 1.0. (See accompanying// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)// See http://www.boost.org/libs/iostreams for documentation.// Inspired by fdstream.hpp, (C) Copyright Nicolai M. Josuttis 2001,// available at http://www.josuttis.com/cppcode/fdstream.html.// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>// knows that we are building the library (possibly exporting code), rather// than using it (possibly importing code).#define BOOST_IOSTREAMS_SOURCE#include <cassert>#include <cerrno>#include <cstdio> // SEEK_SET, etc.#include <boost/config.hpp> // BOOST_JOIN#include <boost/iostreams/detail/error.hpp>#include <boost/iostreams/detail/config/dyn_link.hpp>#include <boost/iostreams/detail/config/rtl.hpp> // BOOST_IOSTREAMS_FD_XXX#include <boost/iostreams/detail/config/windows_posix.hpp>#include <boost/iostreams/detail/ios.hpp> // openmodes, failure.#include <boost/iostreams/device/file_descriptor.hpp>#include <boost/integer_traits.hpp> // OS-specific headers for low-level i/o.#include <fcntl.h> // file opening flags.#include <sys/stat.h> // file access permissions.#ifdef BOOST_IOSTREAMS_WINDOWS# include <io.h> // low-level file i/o.# define WINDOWS_LEAN_AND_MEAN# include <windows.h># ifndef INVALID_SET_FILE_POINTER# define INVALID_SET_FILE_POINTER ((DWORD)-1)# endif#else# include <sys/types.h> // mode_t.# include <unistd.h> // low-level file i/o.#endifnamespace boost { namespace iostreams {//------------------Implementation of file_descriptor-------------------------//file_descriptor::file_descriptor() : pimpl_(new impl) { }file_descriptor::file_descriptor(handle_type fd, bool close_on_exit) : pimpl_(new impl(fd, close_on_exit)) { }#ifdef BOOST_IOSTREAMS_WINDOWS file_descriptor::file_descriptor(int fd, bool close_on_exit) : pimpl_(new impl(int_to_handle(fd), close_on_exit)) { }#endiffile_descriptor::file_descriptor( const char* path, BOOST_IOS::openmode mode, BOOST_IOS::openmode base_mode ) : pimpl_(new impl){ open(std::string(path), mode, base_mode); }file_descriptor::file_descriptor( const std::string& path, BOOST_IOS::openmode mode, BOOST_IOS::openmode base_mode ) : pimpl_(new impl){ open(path, mode, base_mode); }void file_descriptor::open ( const std::string& path, BOOST_IOS::openmode m, BOOST_IOS::openmode base ){ using namespace std; m |= base;#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------// DWORD dwDesiredAccess; DWORD dwCreationDisposition; if ( (m & (BOOST_IOS::in | BOOST_IOS::out)) == (BOOST_IOS::in | BOOST_IOS::out) ) { if (m & BOOST_IOS::app) throw BOOST_IOSTREAMS_FAILURE("bad open mode"); dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; dwCreationDisposition = (m & BOOST_IOS::trunc) ? OPEN_ALWAYS : OPEN_EXISTING; } else if (m & BOOST_IOS::in) { if (m & (BOOST_IOS::app |BOOST_IOS::trunc)) throw BOOST_IOSTREAMS_FAILURE("bad open mode"); dwDesiredAccess = GENERIC_READ; dwCreationDisposition = OPEN_EXISTING; } else if (m & BOOST_IOS::out) { dwDesiredAccess = GENERIC_WRITE; dwCreationDisposition = OPEN_ALWAYS; if (m & BOOST_IOS::app) pimpl_->flags_ |= impl::append; } else { throw BOOST_IOSTREAMS_FAILURE("bad open mode"); } HANDLE handle = ::CreateFileA( path.c_str(), dwDesiredAccess, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, // lpSecurityAttributes dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL ); // hTemplateFile if (handle != INVALID_HANDLE_VALUE) { pimpl_->handle_ = handle; pimpl_->flags_ |= impl::close_on_exit; } else { pimpl_->flags_ = 0; throw BOOST_IOSTREAMS_FAILURE("bad open"); }#else // #ifdef BOOST_IOSTREAMS_WINDOWS //------------------------------------// // Calculate oflag argument to open. int oflag = 0; if ( (m & (BOOST_IOS::in | BOOST_IOS::out)) == (BOOST_IOS::in | BOOST_IOS::out) ) { assert(!(m & BOOST_IOS::app)); oflag |= O_RDWR; } else if (m & BOOST_IOS::in) { assert(!(m & (BOOST_IOS::app |BOOST_IOS::trunc))); oflag |= O_RDONLY; } else if (m & BOOST_IOS::out) { oflag |= O_WRONLY; m |= BOOST_IOS::trunc; if (m & BOOST_IOS::app) oflag |= O_APPEND; } if (m & BOOST_IOS::trunc) oflag |= O_CREAT; #ifdef _LARGEFILE64_SOURCE oflag |= O_LARGEFILE; #endif // Calculate pmode argument to open. mode_t pmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; // Open file. int fd = BOOST_IOSTREAMS_FD_OPEN(path.c_str(), oflag, pmode); if (fd == -1) { throw BOOST_IOSTREAMS_FAILURE("bad open"); } else { pimpl_->handle_ = fd; pimpl_->flags_ = impl::close_on_exit; }#endif // #ifndef BOOST_IOSTREAMS_WINDOWS //----------------------------------//}void file_descriptor::open ( const char* path, BOOST_IOS::openmode m, BOOST_IOS::openmode base ){ open(std::string(path), m, base); }std::streamsize file_descriptor::read(char_type* s, std::streamsize n){#ifdef BOOST_IOSTREAMS_WINDOWS DWORD result; if (!::ReadFile(pimpl_->handle_, s, n, &result, NULL)) throw detail::bad_read(); return result == 0 ? -1 : static_cast<std::streamsize>(result);#else // #ifdef BOOST_IOSTREAMS_WINDOWS errno = 0; std::streamsize result = BOOST_IOSTREAMS_FD_READ(pimpl_->handle_, s, n); if (errno != 0) throw detail::bad_read(); return result == 0 ? -1 : result;#endif // #ifdef BOOST_IOSTREAMS_WINDOWS}std::streamsize file_descriptor::write(const char_type* s, std::streamsize n){#ifdef BOOST_IOSTREAMS_WINDOWS if (pimpl_->flags_ & impl::append) { DWORD const dwResult = ::SetFilePointer(pimpl_->handle_, 0, NULL, FILE_END); if ( dwResult == INVALID_SET_FILE_POINTER && ::GetLastError() != NO_ERROR ) { throw detail::bad_seek(); } } DWORD ignore; if (!::WriteFile(pimpl_->handle_, s, n, &ignore, NULL)) throw detail::bad_write(); return n;#else // #ifdef BOOST_IOSTREAMS_WINDOWS int amt = BOOST_IOSTREAMS_FD_WRITE(pimpl_->handle_, s, n); if (amt < n) throw detail::bad_write(); // Handles blocking fd's only. return n;#endif // #ifdef BOOST_IOSTREAMS_WINDOWS}std::streampos file_descriptor::seek (stream_offset off, BOOST_IOS::seekdir way){ using namespace std;#ifdef BOOST_IOSTREAMS_WINDOWS LONG lDistanceToMove = static_cast<LONG>(off & 0xffffffff); LONG lDistanceToMoveHigh = static_cast<LONG>(off >> 32); DWORD dwResultLow = ::SetFilePointer( pimpl_->handle_, lDistanceToMove, &lDistanceToMoveHigh, way == BOOST_IOS::beg ? FILE_BEGIN : way == BOOST_IOS::cur ? FILE_CURRENT : FILE_END ); if ( dwResultLow == INVALID_SET_FILE_POINTER && ::GetLastError() != NO_ERROR ) { throw detail::bad_seek(); } else { return offset_to_position( (stream_offset(lDistanceToMoveHigh) << 32) + dwResultLow ); }#else // #ifdef BOOST_IOSTREAMS_WINDOWS if ( off > integer_traits<BOOST_IOSTREAMS_FD_OFFSET>::const_max || off < integer_traits<BOOST_IOSTREAMS_FD_OFFSET>::const_min ) { throw BOOST_IOSTREAMS_FAILURE("bad offset"); } stream_offset result = BOOST_IOSTREAMS_FD_SEEK( pimpl_->handle_, static_cast<BOOST_IOSTREAMS_FD_OFFSET>(off), ( way == BOOST_IOS::beg ? SEEK_SET : way == BOOST_IOS::cur ? SEEK_CUR : SEEK_END ) ); if (result == -1) throw detail::bad_seek(); return offset_to_position(result);#endif // #ifdef BOOST_IOSTREAMS_WINDOWS}void file_descriptor::close() { close_impl(*pimpl_); }void file_descriptor::close_impl(impl& i){#ifdef BOOST_IOSTREAMS_WINDOWS if (i.handle_ != reinterpret_cast<handle_type>(-1)) { if (!::CloseHandle(i.handle_)) throw BOOST_IOSTREAMS_FAILURE("bad close"); i.handle_ = reinterpret_cast<handle_type>(-1); i.flags_ = 0; return; }#else // #ifdef BOOST_IOSTREAMS_WINDOWS if (i.handle_ != -1) { if (BOOST_IOSTREAMS_FD_CLOSE(i.handle_) == -1) throw BOOST_IOSTREAMS_FAILURE("bad close"); i.handle_ = -1; i.flags_ = 0; }#endif // #ifdef BOOST_IOSTREAMS_WINDOWS}#ifdef BOOST_IOSTREAMS_WINDOWSfile_descriptor::handle_type file_descriptor::int_to_handle(int fd){ return reinterpret_cast<handle_type>(_get_osfhandle(fd));}#endif} } // End namespaces iostreams, boost.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?