2 // Copyright (c) 2015-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
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)
7 // Official repository: https://github.com/boostorg/beast
10 #ifndef BOOST_BEAST_CORE_IMPL_FILE_POSIX_IPP
11 #define BOOST_BEAST_CORE_IMPL_FILE_POSIX_IPP
13 #include <boost/beast/core/file_posix.hpp>
15 #if BOOST_BEAST_USE_POSIX_FILE
17 #include <boost/core/exchange.hpp>
20 #include <sys/types.h>
26 #if ! defined(BOOST_BEAST_NO_POSIX_FADVISE)
27 # if defined(__APPLE__) || (defined(__ANDROID__) && (__ANDROID_API__ < 21))
28 # define BOOST_BEAST_NO_POSIX_FADVISE
32 #if ! defined(BOOST_BEAST_USE_POSIX_FADVISE)
33 # if ! defined(BOOST_BEAST_NO_POSIX_FADVISE)
34 # define BOOST_BEAST_USE_POSIX_FADVISE 1
36 # define BOOST_BEAST_USE_POSIX_FADVISE 0
45 native_close(native_handle_type& fd)
47 /* https://github.com/boostorg/beast/issues/1445
49 This function is tuned for Linux / Mac OS:
51 * only calls close() once
52 * returns the error directly to the caller
53 * does not loop on EINTR
55 If this is incorrect for the platform, then the
56 caller will need to implement their own type
57 meeting the File requirements and use the correct
61 http://man7.org/linux/man-pages/man2/close.2.html
80 file_posix(file_posix&& other)
81 : fd_(boost::exchange(other.fd_, -1))
87 operator=(file_posix&& other)
99 native_handle(native_handle_type fd)
107 close(error_code& ec)
109 auto const ev = native_close(fd_);
111 ec.assign(ev, system_category());
118 open(char const* path, file_mode mode, error_code& ec)
120 auto const ev = native_close(fd_);
122 ec.assign(ev, system_category());
127 #if BOOST_BEAST_USE_POSIX_FADVISE
133 case file_mode::read:
135 #if BOOST_BEAST_USE_POSIX_FADVISE
136 advise = POSIX_FADV_RANDOM;
139 case file_mode::scan:
141 #if BOOST_BEAST_USE_POSIX_FADVISE
142 advise = POSIX_FADV_SEQUENTIAL;
146 case file_mode::write:
147 f = O_RDWR | O_CREAT | O_TRUNC;
148 #if BOOST_BEAST_USE_POSIX_FADVISE
149 advise = POSIX_FADV_RANDOM;
153 case file_mode::write_new:
154 f = O_RDWR | O_CREAT | O_EXCL;
155 #if BOOST_BEAST_USE_POSIX_FADVISE
156 advise = POSIX_FADV_RANDOM;
160 case file_mode::write_existing:
162 #if BOOST_BEAST_USE_POSIX_FADVISE
163 advise = POSIX_FADV_RANDOM;
167 case file_mode::append:
168 f = O_WRONLY | O_CREAT | O_APPEND;
169 #if BOOST_BEAST_USE_POSIX_FADVISE
170 advise = POSIX_FADV_SEQUENTIAL;
174 case file_mode::append_existing:
175 f = O_WRONLY | O_APPEND;
176 #if BOOST_BEAST_USE_POSIX_FADVISE
177 advise = POSIX_FADV_SEQUENTIAL;
183 fd_ = ::open(path, f, 0644);
186 auto const ev = errno;
189 ec.assign(ev, system_category());
193 #if BOOST_BEAST_USE_POSIX_FADVISE
194 if(::posix_fadvise(fd_, 0, 0, advise))
196 auto const ev = errno;
198 ec.assign(ev, system_category());
207 size(error_code& ec) const
211 ec = make_error_code(errc::bad_file_descriptor);
215 if(::fstat(fd_, &st) != 0)
217 ec.assign(errno, system_category());
226 pos(error_code& ec) const
230 ec = make_error_code(errc::bad_file_descriptor);
233 auto const result = ::lseek(fd_, 0, SEEK_CUR);
234 if(result == (off_t)-1)
236 ec.assign(errno, system_category());
245 seek(std::uint64_t offset, error_code& ec)
249 ec = make_error_code(errc::bad_file_descriptor);
252 auto const result = ::lseek(fd_, offset, SEEK_SET);
253 if(result == static_cast<off_t>(-1))
255 ec.assign(errno, system_category());
263 read(void* buffer, std::size_t n, error_code& ec) const
267 ec = make_error_code(errc::bad_file_descriptor);
270 std::size_t nread = 0;
273 // <limits> not required to define SSIZE_MAX so we avoid it
274 constexpr auto ssmax =
275 static_cast<std::size_t>((std::numeric_limits<
276 decltype(::read(fd_, buffer, n))>::max)());
277 auto const amount = (std::min)(
279 auto const result = ::read(fd_, buffer, amount);
282 auto const ev = errno;
285 ec.assign(ev, system_category());
295 buffer = static_cast<char*>(buffer) + result;
302 write(void const* buffer, std::size_t n, error_code& ec)
306 ec = make_error_code(errc::bad_file_descriptor);
309 std::size_t nwritten = 0;
312 // <limits> not required to define SSIZE_MAX so we avoid it
313 constexpr auto ssmax =
314 static_cast<std::size_t>((std::numeric_limits<
315 decltype(::write(fd_, buffer, n))>::max)());
316 auto const amount = (std::min)(
318 auto const result = ::write(fd_, buffer, amount);
321 auto const ev = errno;
324 ec.assign(ev, system_category());
329 buffer = static_cast<char const*>(buffer) + result;