File indexing completed on 2025-01-18 09:29:26
0001
0002
0003
0004
0005
0006
0007
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
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
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
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
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
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 }
0335 }
0336
0337 #endif
0338
0339 #endif