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_STDIO_IPP
0011 #define BOOST_BEAST_CORE_IMPL_FILE_STDIO_IPP
0012
0013 #include <boost/beast/core/file_stdio.hpp>
0014 #include <boost/beast/core/detail/win32_unicode_path.hpp>
0015 #include <boost/config/workaround.hpp>
0016 #include <boost/core/exchange.hpp>
0017 #include <limits>
0018
0019 namespace boost {
0020 namespace beast {
0021
0022 file_stdio::
0023 ~file_stdio()
0024 {
0025 if(f_)
0026 fclose(f_);
0027 }
0028
0029 file_stdio::
0030 file_stdio(file_stdio&& other)
0031 : f_(boost::exchange(other.f_, nullptr))
0032 {
0033 }
0034
0035 file_stdio&
0036 file_stdio::
0037 operator=(file_stdio&& other)
0038 {
0039 if(&other == this)
0040 return *this;
0041 if(f_)
0042 fclose(f_);
0043 f_ = other.f_;
0044 other.f_ = nullptr;
0045 return *this;
0046 }
0047
0048 void
0049 file_stdio::
0050 native_handle(std::FILE* f)
0051 {
0052 if(f_)
0053 fclose(f_);
0054 f_ = f;
0055 }
0056
0057 void
0058 file_stdio::
0059 close(error_code& ec)
0060 {
0061 if(f_)
0062 {
0063 int failed = fclose(f_);
0064 f_ = nullptr;
0065 if(failed)
0066 {
0067 ec.assign(errno, generic_category());
0068 return;
0069 }
0070 }
0071 ec = {};
0072 }
0073
0074 void
0075 file_stdio::
0076 open(char const* path, file_mode mode, error_code& ec)
0077 {
0078 if(f_)
0079 {
0080 fclose(f_);
0081 f_ = nullptr;
0082 }
0083 ec = {};
0084 #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0085 boost::winapi::WCHAR_ const* s;
0086 detail::win32_unicode_path unicode_path(path, ec);
0087 if (ec)
0088 return;
0089 #else
0090 char const* s;
0091 #endif
0092 switch(mode)
0093 {
0094 default:
0095 case file_mode::read:
0096 #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0097 s = L"rb";
0098 #else
0099 s = "rb";
0100 #endif
0101 break;
0102
0103 case file_mode::scan:
0104 #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0105 s = L"rbS";
0106 #else
0107 s = "rb";
0108 #endif
0109 break;
0110
0111 case file_mode::write:
0112 #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0113 s = L"wb+";
0114 #else
0115 s = "wb+";
0116 #endif
0117 break;
0118
0119 case file_mode::write_new:
0120 {
0121 #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0122 # if (defined(BOOST_MSVC) && BOOST_MSVC >= 1910) || (defined(_MSVC_STL_VERSION) && _MSVC_STL_VERSION >= 141)
0123 s = L"wbx";
0124 # else
0125 std::FILE* f0;
0126 auto const ev = ::_wfopen_s(&f0, unicode_path.c_str(), L"rb");
0127 if(! ev)
0128 {
0129 std::fclose(f0);
0130 ec = make_error_code(errc::file_exists);
0131 return;
0132 }
0133 else if(ev !=
0134 errc::no_such_file_or_directory)
0135 {
0136 ec.assign(ev, generic_category());
0137 return;
0138 }
0139 s = L"wb";
0140 # endif
0141 #else
0142 s = "wbx";
0143 #endif
0144 break;
0145 }
0146
0147 case file_mode::write_existing:
0148 #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0149 s = L"rb+";
0150 #else
0151 s = "rb+";
0152 #endif
0153 break;
0154
0155 case file_mode::append:
0156 #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0157 s = L"ab";
0158 #else
0159 s = "ab";
0160 #endif
0161 break;
0162
0163 case file_mode::append_existing:
0164 {
0165 #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0166 std::FILE* f0;
0167 auto const ev =
0168 ::_wfopen_s(&f0, unicode_path.c_str(), L"rb+");
0169 if(ev)
0170 {
0171 ec.assign(ev, generic_category());
0172 return;
0173 }
0174 #else
0175 auto const f0 =
0176 std::fopen(path, "rb+");
0177 if(! f0)
0178 {
0179 ec.assign(errno, generic_category());
0180 return;
0181 }
0182 #endif
0183 std::fclose(f0);
0184 #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0185 s = L"ab";
0186 #else
0187 s = "ab";
0188 #endif
0189 break;
0190 }
0191 }
0192
0193 #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0194 auto const ev = ::_wfopen_s(&f_, unicode_path.c_str(), s);
0195 if(ev)
0196 {
0197 f_ = nullptr;
0198 ec.assign(ev, generic_category());
0199 return;
0200 }
0201 #else
0202 f_ = std::fopen(path, s);
0203 if(! f_)
0204 {
0205 ec.assign(errno, generic_category());
0206 return;
0207 }
0208 #endif
0209 }
0210
0211 std::uint64_t
0212 file_stdio::
0213 size(error_code& ec) const
0214 {
0215 if(! f_)
0216 {
0217 ec = make_error_code(errc::bad_file_descriptor);
0218 return 0;
0219 }
0220 long pos = std::ftell(f_);
0221 if(pos == -1L)
0222 {
0223 ec.assign(errno, generic_category());
0224 return 0;
0225 }
0226 int result = std::fseek(f_, 0, SEEK_END);
0227 if(result != 0)
0228 {
0229 ec.assign(errno, generic_category());
0230 return 0;
0231 }
0232 long size = std::ftell(f_);
0233 if(size == -1L)
0234 {
0235 ec.assign(errno, generic_category());
0236 std::fseek(f_, pos, SEEK_SET);
0237 return 0;
0238 }
0239 result = std::fseek(f_, pos, SEEK_SET);
0240 if(result != 0)
0241 ec.assign(errno, generic_category());
0242 else
0243 ec = {};
0244 return size;
0245 }
0246
0247 std::uint64_t
0248 file_stdio::
0249 pos(error_code& ec) const
0250 {
0251 if(! f_)
0252 {
0253 ec = make_error_code(errc::bad_file_descriptor);
0254 return 0;
0255 }
0256 long pos = std::ftell(f_);
0257 if(pos == -1L)
0258 {
0259 ec.assign(errno, generic_category());
0260 return 0;
0261 }
0262 ec = {};
0263 return pos;
0264 }
0265
0266 void
0267 file_stdio::
0268 seek(std::uint64_t offset, error_code& ec)
0269 {
0270 if(! f_)
0271 {
0272 ec = make_error_code(errc::bad_file_descriptor);
0273 return;
0274 }
0275 if(offset > static_cast<std::uint64_t>((std::numeric_limits<long>::max)()))
0276 {
0277 ec = make_error_code(errc::invalid_seek);
0278 return;
0279 }
0280 int result = std::fseek(f_,
0281 static_cast<long>(offset), SEEK_SET);
0282 if(result != 0)
0283 ec.assign(errno, generic_category());
0284 else
0285 ec = {};
0286 }
0287
0288 std::size_t
0289 file_stdio::
0290 read(void* buffer, std::size_t n, error_code& ec) const
0291 {
0292 if(! f_)
0293 {
0294 ec = make_error_code(errc::bad_file_descriptor);
0295 return 0;
0296 }
0297 auto nread = std::fread(buffer, 1, n, f_);
0298 if(std::ferror(f_))
0299 {
0300 ec.assign(errno, generic_category());
0301 return 0;
0302 }
0303 return nread;
0304 }
0305
0306 std::size_t
0307 file_stdio::
0308 write(void const* buffer, std::size_t n, error_code& ec)
0309 {
0310 if(! f_)
0311 {
0312 ec = make_error_code(errc::bad_file_descriptor);
0313 return 0;
0314 }
0315 auto nwritten = std::fwrite(buffer, 1, n, f_);
0316 if(std::ferror(f_))
0317 {
0318 ec.assign(errno, generic_category());
0319 return 0;
0320 }
0321 return nwritten;
0322 }
0323
0324 }
0325 }
0326
0327 #endif