Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:26

0001 //
0002 // Copyright (c) 2015-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/beast
0008 //
0009 
0010 #ifndef BOOST_BEAST_CORE_IMPL_FILE_POSIX_IPP
0011 #define BOOST_BEAST_CORE_IMPL_FILE_POSIX_IPP
0012 
0013 #include <boost/beast/core/file_posix.hpp>
0014 
0015 #if BOOST_BEAST_USE_POSIX_FILE
0016 
0017 #include <boost/core/exchange.hpp>
0018 #include <limits>
0019 #include <fcntl.h>
0020 #include <sys/types.h>
0021 #include <sys/uio.h>
0022 #include <sys/stat.h>
0023 #include <unistd.h>
0024 #include <limits.h>
0025 
0026 #if ! defined(BOOST_BEAST_NO_POSIX_FADVISE)
0027 # if defined(__APPLE__) || (defined(__ANDROID__) && (__ANDROID_API__ < 21))
0028 #  define BOOST_BEAST_NO_POSIX_FADVISE
0029 # endif
0030 #endif
0031 
0032 #if ! defined(BOOST_BEAST_USE_POSIX_FADVISE)
0033 # if ! defined(BOOST_BEAST_NO_POSIX_FADVISE)
0034 #  define BOOST_BEAST_USE_POSIX_FADVISE 1
0035 # else
0036 #  define BOOST_BEAST_USE_POSIX_FADVISE 0
0037 # endif
0038 #endif
0039 
0040 namespace boost {
0041 namespace beast {
0042 
0043 int
0044 file_posix::
0045 native_close(native_handle_type& fd)
0046 {
0047 /*  https://github.com/boostorg/beast/issues/1445
0048 
0049     This function is tuned for Linux / Mac OS:
0050     
0051     * only calls close() once
0052     * returns the error directly to the caller
0053     * does not loop on EINTR
0054 
0055     If this is incorrect for the platform, then the
0056     caller will need to implement their own type
0057     meeting the File requirements and use the correct
0058     behavior.
0059 
0060     See:
0061         http://man7.org/linux/man-pages/man2/close.2.html
0062 */
0063     int ev = 0;
0064     if(fd != -1)
0065     {
0066         if(::close(fd) != 0)
0067             ev = errno;
0068         fd = -1;
0069     }
0070     return ev;
0071 }
0072 
0073 file_posix::
0074 ~file_posix()
0075 {
0076     native_close(fd_);
0077 }
0078 
0079 file_posix::
0080 file_posix(file_posix&& other)
0081     : fd_(boost::exchange(other.fd_, -1))
0082 {
0083 }
0084 
0085 file_posix&
0086 file_posix::
0087 operator=(file_posix&& other)
0088 {
0089     if(&other == this)
0090         return *this;
0091     native_close(fd_);
0092     fd_ = other.fd_;
0093     other.fd_ = -1;
0094     return *this;
0095 }
0096 
0097 void
0098 file_posix::
0099 native_handle(native_handle_type fd)
0100 {
0101     native_close(fd_);
0102     fd_ = fd;
0103 }
0104 
0105 void
0106 file_posix::
0107 close(error_code& ec)
0108 {
0109     auto const ev = native_close(fd_);
0110     if(ev)
0111         ec.assign(ev, system_category());
0112     else
0113         ec = {};
0114 }
0115 
0116 void
0117 file_posix::
0118 open(char const* path, file_mode mode, error_code& ec)
0119 {
0120     auto const ev = native_close(fd_);
0121     if(ev)
0122         ec.assign(ev, system_category());
0123     else
0124         ec = {};
0125 
0126     int f = 0;
0127 #if BOOST_BEAST_USE_POSIX_FADVISE
0128     int advise = 0;
0129 #endif
0130     switch(mode)
0131     {
0132     default:
0133     case file_mode::read:
0134         f = O_RDONLY;
0135     #if BOOST_BEAST_USE_POSIX_FADVISE
0136         advise = POSIX_FADV_RANDOM;
0137     #endif
0138         break;
0139     case file_mode::scan:
0140         f = O_RDONLY;
0141     #if BOOST_BEAST_USE_POSIX_FADVISE
0142         advise = POSIX_FADV_SEQUENTIAL;
0143     #endif
0144         break;
0145 
0146     case file_mode::write:
0147         f = O_RDWR | O_CREAT | O_TRUNC;
0148     #if BOOST_BEAST_USE_POSIX_FADVISE
0149         advise = POSIX_FADV_RANDOM;
0150     #endif
0151         break;
0152 
0153     case file_mode::write_new:      
0154         f = O_RDWR | O_CREAT | O_EXCL;
0155     #if BOOST_BEAST_USE_POSIX_FADVISE
0156         advise = POSIX_FADV_RANDOM;
0157     #endif
0158         break;
0159 
0160     case file_mode::write_existing: 
0161         f = O_RDWR | O_EXCL;
0162     #if BOOST_BEAST_USE_POSIX_FADVISE
0163         advise = POSIX_FADV_RANDOM;
0164     #endif
0165         break;
0166 
0167     case file_mode::append:         
0168         f = O_WRONLY | O_CREAT | O_APPEND;
0169     #if BOOST_BEAST_USE_POSIX_FADVISE
0170         advise = POSIX_FADV_SEQUENTIAL;
0171     #endif
0172         break;
0173 
0174     case file_mode::append_existing:
0175         f = O_WRONLY | O_APPEND;
0176     #if BOOST_BEAST_USE_POSIX_FADVISE
0177         advise = POSIX_FADV_SEQUENTIAL;
0178     #endif
0179         break;
0180     }
0181     for(;;)
0182     {
0183         fd_ = ::open(path, f, 0644);
0184         if(fd_ != -1)
0185             break;
0186         auto const ev = errno;
0187         if(ev != EINTR)
0188         {
0189             ec.assign(ev, system_category());
0190             return;
0191         }
0192     }
0193 #if BOOST_BEAST_USE_POSIX_FADVISE
0194     if(::posix_fadvise(fd_, 0, 0, advise))
0195     {
0196         auto const ev = errno;
0197         native_close(fd_);
0198         ec.assign(ev, system_category());
0199         return;
0200     }
0201 #endif
0202     ec = {};
0203 }
0204 
0205 std::uint64_t
0206 file_posix::
0207 size(error_code& ec) const
0208 {
0209     if(fd_ == -1)
0210     {
0211         ec = make_error_code(errc::bad_file_descriptor);
0212         return 0;
0213     }
0214     struct stat st;
0215     if(::fstat(fd_, &st) != 0)
0216     {
0217         ec.assign(errno, system_category());
0218         return 0;
0219     }
0220     ec = {};
0221     return st.st_size;
0222 }
0223 
0224 std::uint64_t
0225 file_posix::
0226 pos(error_code& ec) const
0227 {
0228     if(fd_ == -1)
0229     {
0230         ec = make_error_code(errc::bad_file_descriptor);
0231         return 0;
0232     }
0233     auto const result = ::lseek(fd_, 0, SEEK_CUR);
0234     if(result == (off_t)-1)
0235     {
0236         ec.assign(errno, system_category());
0237         return 0;
0238     }
0239     ec = {};
0240     return result;
0241 }
0242 
0243 void
0244 file_posix::
0245 seek(std::uint64_t offset, error_code& ec)
0246 {
0247     if(fd_ == -1)
0248     {
0249         ec = make_error_code(errc::bad_file_descriptor);
0250         return;
0251     }
0252     auto const result = ::lseek(fd_, offset, SEEK_SET);
0253     if(result == static_cast<off_t>(-1))
0254     {
0255         ec.assign(errno, system_category());
0256         return;
0257     }
0258     ec = {};
0259 }
0260 
0261 std::size_t
0262 file_posix::
0263 read(void* buffer, std::size_t n, error_code& ec) const
0264 {
0265     if(fd_ == -1)
0266     {
0267         ec = make_error_code(errc::bad_file_descriptor);
0268         return 0;
0269     }
0270     std::size_t nread = 0;
0271     while(n > 0)
0272     {
0273         // <limits> not required to define SSIZE_MAX so we avoid it
0274         constexpr auto ssmax =
0275             static_cast<std::size_t>((std::numeric_limits<
0276                 decltype(::read(fd_, buffer, n))>::max)());
0277         auto const amount = (std::min)(
0278             n, ssmax);
0279         auto const result = ::read(fd_, buffer, amount);
0280         if(result == -1)
0281         {
0282             auto const ev = errno;
0283             if(ev == EINTR)
0284                 continue;
0285             ec.assign(ev, system_category());
0286             return nread;
0287         }
0288         if(result == 0)
0289         {
0290             // short read
0291             return nread;
0292         }
0293         n -= result;
0294         nread += result;
0295         buffer = static_cast<char*>(buffer) + result;
0296     }
0297     return nread;
0298 }
0299 
0300 std::size_t
0301 file_posix::
0302 write(void const* buffer, std::size_t n, error_code& ec)
0303 {
0304     if(fd_ == -1)
0305     {
0306         ec = make_error_code(errc::bad_file_descriptor);
0307         return 0;
0308     }
0309     std::size_t nwritten = 0;
0310     while(n > 0)
0311     {
0312         // <limits> not required to define SSIZE_MAX so we avoid it
0313         constexpr auto ssmax =
0314             static_cast<std::size_t>((std::numeric_limits<
0315                 decltype(::write(fd_, buffer, n))>::max)());
0316         auto const amount = (std::min)(
0317             n, ssmax);
0318         auto const result = ::write(fd_, buffer, amount);
0319         if(result == -1)
0320         {
0321             auto const ev = errno;
0322             if(ev == EINTR)
0323                 continue;
0324             ec.assign(ev, system_category());
0325             return nwritten;
0326         }
0327         n -= result;
0328         nwritten += result;
0329         buffer = static_cast<char const*>(buffer) + result;
0330     }
0331     return nwritten;
0332 }
0333 
0334 } // beast
0335 } // boost
0336 
0337 #endif
0338 
0339 #endif