1 // (C) Copyright 2010 Daniel James
2 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
3 // (C) Copyright 2003-2007 Jonathan Turkanis
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
6 
7 // A few methods for getting and manipulating file handles.
8 
9 #ifndef BOOST_IOSTREAMS_FILE_HANDLE_HPP_INCLUDED
10 #define BOOST_IOSTREAMS_FILE_HANDLE_HPP_INCLUDED
11 
12 #include <boost/iostreams/detail/file_handle.hpp>
13 #include <boost/iostreams/detail/config/rtl.hpp>
14 #include <boost/test/test_tools.hpp>
15 #include <string>
16 
17 #ifdef BOOST_IOSTREAMS_WINDOWS
18 # include <io.h>         // low-level file i/o.
19 # define WINDOWS_LEAN_AND_MEAN
20 # include <windows.h>
21 #else
22 # include <sys/stat.h>
23 # include <fcntl.h>
24 #endif
25 
26 namespace boost { namespace iostreams { namespace test {
27 
28 #ifdef BOOST_IOSTREAMS_WINDOWS
29 
30 // Windows implementation
31 
open_file_handle(std::string const & name)32 boost::iostreams::detail::file_handle open_file_handle(std::string const& name)
33 {
34     HANDLE handle =
35         ::CreateFileA( name.c_str(),
36                        GENERIC_READ | GENERIC_WRITE,
37                        FILE_SHARE_READ | FILE_SHARE_WRITE,
38                        NULL,                   // lpSecurityAttributes
39                        OPEN_EXISTING,
40                        FILE_ATTRIBUTE_NORMAL,
41                        NULL );                 // hTemplateFile
42 
43     BOOST_REQUIRE (handle != INVALID_HANDLE_VALUE);
44     return handle;
45 }
46 
close_file_handle(boost::iostreams::detail::file_handle handle)47 void close_file_handle(boost::iostreams::detail::file_handle handle)
48 {
49     BOOST_REQUIRE(::CloseHandle(handle) == 1);
50 }
51 
52 #define BOOST_CHECK_HANDLE_CLOSED(handle)
53 #define BOOST_CHECK_HANDLE_OPEN(handle)
54 
55 #else // BOOST_IOSTREAMS_WINDOWS
56 
57 // Non-windows implementation
58 
59 boost::iostreams::detail::file_handle open_file_handle(std::string const& name)
60 {
61     int oflag = O_RDWR;
62 
63     #ifdef _LARGEFILE64_SOURCE
64         oflag |= O_LARGEFILE;
65     #endif
66 
67     // Calculate pmode argument to open.
68 
69     mode_t pmode = S_IRUSR | S_IWUSR |
70                    S_IRGRP | S_IWGRP |
71                    S_IROTH | S_IWOTH;
72 
73         // Open file.
74 
75     int fd = BOOST_IOSTREAMS_FD_OPEN(name.c_str(), oflag, pmode);
76     BOOST_REQUIRE (fd != -1);
77 
78     return fd;
79 }
80 
81 void close_file_handle(boost::iostreams::detail::file_handle handle)
82 {
83     BOOST_REQUIRE(BOOST_IOSTREAMS_FD_CLOSE(handle) != -1);
84 }
85 
86 // This is pretty dubious. First you must make sure that no other
87 // operations that could open a descriptor are called before this
88 // check, otherwise it's quite likely that a closed descriptor
89 // could be used. Secondly, I'm not sure if it's guaranteed that
90 // fcntl will know that the descriptor is closed but this seems
91 // to work okay, and I can't see any other convenient way to check
92 // that a descripter has been closed.
93 bool is_handle_open(boost::iostreams::detail::file_handle handle)
94 {
95     return ::fcntl(handle, F_GETFD) != -1;
96 }
97 
98 #define BOOST_CHECK_HANDLE_CLOSED(handle) \
99     BOOST_CHECK(!::boost::iostreams::test::is_handle_open(handle))
100 #define BOOST_CHECK_HANDLE_OPEN(handle) \
101     BOOST_CHECK(::boost::iostreams::test::is_handle_open(handle))
102 
103 
104 #endif // BOOST_IOSTREAMS_WINDOWS
105 
106 }}}
107 
108 #endif // BOOST_IOSTREAMS_FILE_HANDLE_HPP_INCLUDED
109