Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/iostreams/src/file_descriptor.cpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 8.0 KB
Line 
1// (C) Copyright Jonathan Turkanis 2003.
2// Distributed under the Boost Software License, Version 1.0. (See accompanying
3// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
4
5// See http://www.boost.org/libs/iostreams for documentation.
6
7// Inspired by fdstream.hpp, (C) Copyright Nicolai M. Josuttis 2001,
8// available at http://www.josuttis.com/cppcode/fdstream.html.
9
10// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>
11// knows that we are building the library (possibly exporting code), rather
12// than using it (possibly importing code).
13#define BOOST_IOSTREAMS_SOURCE
14
15#include <boost/config.hpp> // BOOST_JOIN
16#include <boost/iostreams/detail/error.hpp>
17#include <boost/iostreams/detail/config/dyn_link.hpp>
18#include <boost/iostreams/detail/config/windows_posix.hpp>
19#include <boost/iostreams/detail/ios.hpp>  // openmodes, failure.
20#include <boost/iostreams/device/file_descriptor.hpp>
21#include <boost/integer_traits.hpp>
22
23    // OS-specific headers for low-level i/o.
24
25#include <cassert>
26#include <cstdio>        // SEEK_SET, etc.
27#include <errno.h>
28#include <fcntl.h>       // file opening flags.
29#include <sys/stat.h>    // file access permissions.
30#ifdef BOOST_IOSTREAMS_WINDOWS
31# include <io.h>         // low-level file i/o.
32# define WINDOWS_LEAN_AND_MEAN
33# include <windows.h>
34#else
35# include <sys/types.h>  // mode_t.
36# include <unistd.h>     // low-level file i/o.
37#endif
38
39// Names of runtime library routines vary.
40#if defined(__BORLANDC__)
41# define BOOST_RTL(x) BOOST_JOIN(_rtl_, x)
42#else
43# if defined(BOOST_IOSTREAMS_WINDOWS) && !defined(__CYGWIN__)
44#  define BOOST_RTL(x) BOOST_JOIN(_, x)
45# else
46#  define BOOST_RTL(x) ::x
47# endif
48#endif
49
50namespace boost { namespace iostreams {
51
52//------------------Implementation of file_descriptor-------------------------//
53
54void file_descriptor::open
55    ( const std::string& path, BOOST_IOS::openmode m,
56      BOOST_IOS::openmode base )
57{
58    using namespace std;
59    m |= base;
60#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
61    DWORD dwDesiredAccess;
62    DWORD dwCreationDisposition;
63    if ( (m & (BOOST_IOS::in | BOOST_IOS::out))
64             ==
65         (BOOST_IOS::in | BOOST_IOS::out) )
66    {
67        assert(!(m & BOOST_IOS::app));
68        dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
69        dwCreationDisposition =
70            (m & BOOST_IOS::trunc) ?
71                OPEN_ALWAYS :
72                OPEN_EXISTING;
73    } else if (m & BOOST_IOS::in) {
74        assert(!(m & (BOOST_IOS::app |BOOST_IOS::trunc)));
75        dwDesiredAccess = GENERIC_READ;
76        dwCreationDisposition = OPEN_EXISTING;
77    } else if (m & BOOST_IOS::out) {
78        dwDesiredAccess = GENERIC_WRITE;
79        dwCreationDisposition = OPEN_ALWAYS;
80        if (m & BOOST_IOS::app)
81            pimpl_->flags_ |= impl::append;
82    }
83
84    HANDLE handle =
85        ::CreateFileA( path.c_str(),
86                       dwDesiredAccess,
87                       0,                      // dwShareMode
88                       NULL,                   // lpSecurityAttributes
89                       dwCreationDisposition,
90                       FILE_ATTRIBUTE_NORMAL,
91                       NULL );                 // hTemplateFile
92    if (handle != INVALID_HANDLE_VALUE) {
93        pimpl_->handle_ = handle;
94        pimpl_->flags_ |= impl::close_on_exit | impl::has_handle;
95    } else {
96        pimpl_->flags_ = 0;
97        throw BOOST_IOSTREAMS_FAILURE("bad open");
98    }
99#else // #ifdef BOOST_IOSTREAMS_WINDOWS //------------------------------------//
100
101        // Calculate oflag argument to open.
102
103    int oflag = 0;
104    if ( (m & (BOOST_IOS::in | BOOST_IOS::out))
105             ==
106         (BOOST_IOS::in | BOOST_IOS::out) )
107    {
108        assert(!(m & BOOST_IOS::app));
109        oflag |= O_RDWR;
110    } else if (m & BOOST_IOS::in) {
111        assert(!(m & (BOOST_IOS::app |BOOST_IOS::trunc)));
112        oflag |= O_RDONLY;
113    } else if (m & BOOST_IOS::out) {
114        oflag |= O_WRONLY;
115        m |= BOOST_IOS::trunc;
116        if (m & BOOST_IOS::app)
117            oflag |= O_APPEND;
118    }
119    if (m & BOOST_IOS::trunc)
120        oflag |= O_CREAT;
121
122        // Calculate pmode argument to open.
123
124    mode_t pmode = S_IRUSR | S_IWUSR |
125                   S_IRGRP | S_IWGRP |
126                   S_IROTH | S_IWOTH;
127
128        // Open file.
129
130    int fd = BOOST_RTL(open)(path.c_str(), oflag, pmode);
131    if (fd == -1) {
132        throw BOOST_IOSTREAMS_FAILURE("bad open");
133    } else {
134        pimpl_->fd_ = fd;
135        pimpl_->flags_ = impl::close_on_exit;
136    }
137#endif // #ifndef BOOST_IOSTREAMS_WINDOWS //----------------------------------//
138}
139
140std::streamsize file_descriptor::read(char_type* s, std::streamsize n)
141{
142#ifdef BOOST_IOSTREAMS_WINDOWS
143    if (pimpl_->flags_ & impl::has_handle) {
144        DWORD result;
145        if (!::ReadFile(pimpl_->handle_, s, n, &result, NULL))
146            throw detail::bad_read();
147        return static_cast<std::streamsize>(result);
148    }
149#endif
150    errno = 0;
151    std::streamsize result = BOOST_RTL(read)(pimpl_->fd_, s, n);
152    if (errno != 0)
153        throw detail::bad_read();
154    return result == 0 ? -1 : result;
155}
156
157std::streamsize file_descriptor::write(const char_type* s, std::streamsize n)
158{
159#ifdef BOOST_IOSTREAMS_WINDOWS
160    if (pimpl_->flags_ & impl::has_handle) {
161        if (pimpl_->flags_ & impl::append) {
162            ::SetFilePointer(pimpl_->handle_, 0, NULL, FILE_END);
163            if (::GetLastError() != NO_ERROR)
164                throw detail::bad_seek();
165        }
166        DWORD ignore;
167        if (!::WriteFile(pimpl_->handle_, s, n, &ignore, NULL))
168            throw detail::bad_write();
169        return n;
170    }
171#endif
172    int amt = BOOST_RTL(write)(pimpl_->fd_, s, n);
173    if (amt < n)
174        throw detail::bad_write(); // Handles blocking fd's only.
175    return n;
176}
177
178std::streampos file_descriptor::seek
179    (stream_offset off, BOOST_IOS::seekdir way)
180{
181    using namespace std;
182#ifdef BOOST_IOSTREAMS_WINDOWS
183    if (pimpl_->flags_ & impl::has_handle) {
184        LONG lDistanceToMove = static_cast<LONG>(off & 0xffffffff);
185        LONG lDistanceToMoveHigh = static_cast<LONG>(off >> 32);
186        DWORD dwResultLow =
187            ::SetFilePointer( pimpl_->handle_,
188                              lDistanceToMove,
189                              &lDistanceToMoveHigh,
190                              way == BOOST_IOS::beg ?
191                                  FILE_BEGIN :
192                                  way == BOOST_IOS::cur ?
193                                    FILE_CURRENT :
194                                    FILE_END );
195        if (::GetLastError() != NO_ERROR) {
196            throw detail::bad_seek();
197        } else {
198           return offset_to_position((lDistanceToMoveHigh << 32) + dwResultLow);
199        }
200    }
201#endif // #ifdef BOOST_IOSTREAMS_WINDOWS
202
203#ifndef BOOST_IOSTREAMS_HAS_LSEEK64
204    if ( off > integer_traits<long>::const_max ||
205         off < integer_traits<long>::const_min )
206    {
207        throw BOOST_IOSTREAMS_FAILURE("bad offset");
208    }
209#endif
210
211    stream_offset result =
212        #ifdef BOOST_IOSTREAMS_HAS_LSEEK64
213            lseek64
214        #else
215            lseek
216        #endif
217            ( pimpl_->fd_,
218              #ifdef BOOST_IOSTREAMS_HAS_LSEEK64
219                  off,
220              #else
221                  static_cast<long>(off),
222              #endif
223              way == BOOST_IOS::beg ?
224                  SEEK_SET :
225                      way == BOOST_IOS::cur ?
226                          SEEK_CUR :
227                          SEEK_END );
228    if (result == -1)
229        throw detail::bad_seek();
230    return offset_to_position(result);
231}
232
233void file_descriptor::close() { close_impl(*pimpl_); }
234
235void file_descriptor::close_impl(impl& i)
236{
237#ifdef BOOST_IOSTREAMS_WINDOWS
238    if (i.flags_ & impl::has_handle) {
239        if (!::CloseHandle(i.handle_))
240            throw BOOST_IOSTREAMS_FAILURE("bad close");
241        i.fd_ = -1;
242        i.flags_ = 0;
243        return;
244    }
245#endif
246    if (i.fd_ != -1) {
247        if (BOOST_RTL(close)(i.fd_) == -1)
248            throw BOOST_IOSTREAMS_FAILURE("bad close");
249        i.fd_ = -1;
250        i.flags_ = 0;
251    }
252}
253
254} } // End namespaces iostreams, boost.
Note: See TracBrowser for help on using the repository browser.