// // Copyright (c) 2015-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // #ifndef BOOST_BEAST_CORE_IMPL_FILE_STDIO_IPP #define BOOST_BEAST_CORE_IMPL_FILE_STDIO_IPP #include #include #include #include #include namespace boost { namespace beast { file_stdio:: ~file_stdio() { if(f_) fclose(f_); } file_stdio:: file_stdio(file_stdio&& other) : f_(boost::exchange(other.f_, nullptr)) { } file_stdio& file_stdio:: operator=(file_stdio&& other) { if(&other == this) return *this; if(f_) fclose(f_); f_ = other.f_; other.f_ = nullptr; return *this; } void file_stdio:: native_handle(std::FILE* f) { if(f_) fclose(f_); f_ = f; } void file_stdio:: close(error_code& ec) { if(f_) { int failed = fclose(f_); f_ = nullptr; if(failed) { ec.assign(errno, generic_category()); return; } } ec = {}; } void file_stdio:: open(char const* path, file_mode mode, error_code& ec) { if(f_) { fclose(f_); f_ = nullptr; } ec = {}; #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) boost::winapi::WCHAR_ const* s; detail::win32_unicode_path unicode_path(path, ec); if (ec) return; #else char const* s; #endif switch(mode) { default: case file_mode::read: #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) s = L"rb"; #else s = "rb"; #endif break; case file_mode::scan: #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) s = L"rbS"; #else s = "rb"; #endif break; case file_mode::write: #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) s = L"wb+"; #else s = "wb+"; #endif break; case file_mode::write_new: { #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) # if (defined(BOOST_MSVC) && BOOST_MSVC >= 1910) || (defined(_MSVC_STL_VERSION) && _MSVC_STL_VERSION >= 141) s = L"wbx"; # else std::FILE* f0; auto const ev = ::_wfopen_s(&f0, unicode_path.c_str(), L"rb"); if(! ev) { std::fclose(f0); ec = make_error_code(errc::file_exists); return; } else if(ev != errc::no_such_file_or_directory) { ec.assign(ev, generic_category()); return; } s = L"wb"; # endif #else s = "wbx"; #endif break; } case file_mode::write_existing: #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) s = L"rb+"; #else s = "rb+"; #endif break; case file_mode::append: #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) s = L"ab"; #else s = "ab"; #endif break; case file_mode::append_existing: { #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) std::FILE* f0; auto const ev = ::_wfopen_s(&f0, unicode_path.c_str(), L"rb+"); if(ev) { ec.assign(ev, generic_category()); return; } #else auto const f0 = std::fopen(path, "rb+"); if(! f0) { ec.assign(errno, generic_category()); return; } #endif std::fclose(f0); #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) s = L"ab"; #else s = "ab"; #endif break; } } #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) auto const ev = ::_wfopen_s(&f_, unicode_path.c_str(), s); if(ev) { f_ = nullptr; ec.assign(ev, generic_category()); return; } #else f_ = std::fopen(path, s); if(! f_) { ec.assign(errno, generic_category()); return; } #endif } std::uint64_t file_stdio:: size(error_code& ec) const { if(! f_) { ec = make_error_code(errc::bad_file_descriptor); return 0; } long pos = std::ftell(f_); if(pos == -1L) { ec.assign(errno, generic_category()); return 0; } int result = std::fseek(f_, 0, SEEK_END); if(result != 0) { ec.assign(errno, generic_category()); return 0; } long size = std::ftell(f_); if(size == -1L) { ec.assign(errno, generic_category()); std::fseek(f_, pos, SEEK_SET); return 0; } result = std::fseek(f_, pos, SEEK_SET); if(result != 0) ec.assign(errno, generic_category()); else ec = {}; return size; } std::uint64_t file_stdio:: pos(error_code& ec) const { if(! f_) { ec = make_error_code(errc::bad_file_descriptor); return 0; } long pos = std::ftell(f_); if(pos == -1L) { ec.assign(errno, generic_category()); return 0; } ec = {}; return pos; } void file_stdio:: seek(std::uint64_t offset, error_code& ec) { if(! f_) { ec = make_error_code(errc::bad_file_descriptor); return; } if(offset > static_cast((std::numeric_limits::max)())) { ec = make_error_code(errc::invalid_seek); return; } int result = std::fseek(f_, static_cast(offset), SEEK_SET); if(result != 0) ec.assign(errno, generic_category()); else ec = {}; } std::size_t file_stdio:: read(void* buffer, std::size_t n, error_code& ec) const { if(! f_) { ec = make_error_code(errc::bad_file_descriptor); return 0; } auto nread = std::fread(buffer, 1, n, f_); if(std::ferror(f_)) { ec.assign(errno, generic_category()); return 0; } return nread; } std::size_t file_stdio:: write(void const* buffer, std::size_t n, error_code& ec) { if(! f_) { ec = make_error_code(errc::bad_file_descriptor); return 0; } auto nwritten = std::fwrite(buffer, 1, n, f_); if(std::ferror(f_)) { ec.assign(errno, generic_category()); return 0; } return nwritten; } } // beast } // boost #endif