LCOV - code coverage report
Current view: top level - src/detail - file_stdio.cpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 84.9 % 126 107 19
Test Date: 2026-06-13 19:44:58 Functions: 100.0 % 11 11

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
       3                 : //
       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)
       6                 : //
       7                 : // Official repository: https://github.com/cppalliance/http
       8                 : //
       9                 : 
      10                 : #include "src/detail/win32_unicode_path.hpp"
      11                 : #include <boost/http/detail/file_stdio.hpp>
      12                 : #include <boost/http/error.hpp>
      13                 : #include <boost/system/errc.hpp>
      14                 : #include <boost/config/workaround.hpp>
      15                 : #include <boost/core/exchange.hpp>
      16                 : #include <limits>
      17                 : 
      18                 : namespace boost {
      19                 : namespace http {
      20                 : namespace detail {
      21                 : 
      22 HIT          23 : file_stdio::
      23                 : ~file_stdio()
      24                 : {
      25              23 :     if(f_)
      26              11 :         fclose(f_);
      27              23 : }
      28                 : 
      29               1 : file_stdio::
      30                 : file_stdio(
      31               1 :     file_stdio&& other) noexcept
      32               1 :     : f_(boost::exchange(other.f_, nullptr))
      33                 : {
      34               1 : }
      35                 : 
      36                 : file_stdio&
      37               3 : file_stdio::
      38                 : operator=(
      39                 :     file_stdio&& other) noexcept
      40                 : {
      41               3 :     if(&other == this)
      42               1 :         return *this;
      43               2 :     if(f_)
      44               1 :         fclose(f_);
      45               2 :     f_ = other.f_;
      46               2 :     other.f_ = nullptr;
      47               2 :     return *this;
      48                 : }
      49                 : 
      50                 : void
      51               1 : file_stdio::
      52                 : native_handle(std::FILE* f)
      53                 : {
      54               1 :     if(f_)
      55               1 :         fclose(f_);
      56               1 :     f_ = f;
      57               1 : }
      58                 : 
      59                 : void
      60               4 : file_stdio::
      61                 : close(
      62                 :     system::error_code& ec)
      63                 : {
      64               4 :     if(f_)
      65                 :     {
      66               4 :         int failed = fclose(f_);
      67               4 :         f_ = nullptr;
      68               4 :         if(failed)
      69                 :         {
      70 MIS           0 :             ec.assign(errno,
      71                 :                 system::generic_category());
      72               0 :             return;
      73                 :         }
      74                 :     }
      75 HIT           4 :     ec = {};
      76                 : }
      77                 : 
      78                 : void
      79              21 : file_stdio::
      80                 : open(char const* path, file_mode mode,
      81                 :     system::error_code& ec)
      82                 : {
      83              21 :     if(f_)
      84                 :     {
      85               1 :         fclose(f_);
      86               1 :         f_ = nullptr;
      87                 :     }
      88              21 :     ec = {};
      89                 : #ifdef _WIN32
      90                 :     boost::winapi::WCHAR_ const* s;
      91                 :     detail::win32_unicode_path unicode_path(path, ec);
      92                 :     if (ec)
      93                 :         return;
      94                 : #else
      95                 :     char const* s;
      96                 : #endif
      97              21 :     switch(mode)
      98                 :     {
      99               2 :     default:
     100                 :     case file_mode::read:
     101                 :     #ifdef _WIN32
     102                 :         s = L"rb";
     103                 :     #else
     104               2 :         s = "rb";
     105                 :     #endif
     106               2 :         break;
     107                 : 
     108               1 :     case file_mode::scan:
     109                 :     #ifdef _WIN32
     110                 :         s = L"rbS";
     111                 :     #else
     112               1 :         s = "rb";
     113                 :     #endif
     114               1 :         break;
     115                 : 
     116              10 :     case file_mode::write:
     117                 :     #ifdef _WIN32
     118                 :         s = L"wb+";
     119                 :     #else
     120              10 :         s = "wb+";
     121                 :     #endif
     122              10 :         break;
     123                 : 
     124               2 :     case file_mode::write_new:
     125                 :     {
     126                 : #ifdef _WIN32
     127                 : # if (defined(BOOST_MSVC) && BOOST_MSVC >= 1910) || (defined(_MSVC_STL_VERSION) && _MSVC_STL_VERSION >= 141)
     128                 :         s = L"wbx";
     129                 : # else
     130                 :         std::FILE* f0;
     131                 :         auto const ev = ::_wfopen_s(&f0, unicode_path.c_str(), L"rb");
     132                 :         if(! ev)
     133                 :         {
     134                 :             std::fclose(f0);
     135                 :             ec = make_error_code(
     136                 :                 system::errc::file_exists);
     137                 :             return;
     138                 :         }
     139                 :         else if(ev !=
     140                 :             system::errc::no_such_file_or_directory)
     141                 :         {
     142                 :             ec.assign(ev,
     143                 :                 system::generic_category());
     144                 :             return;
     145                 :         }
     146                 :         s = L"wb";
     147                 : # endif
     148                 : #else
     149               2 :         s = "wbx";
     150                 : #endif
     151               2 :         break;
     152                 :     }
     153                 : 
     154               2 :     case file_mode::write_existing:
     155                 :     #ifdef _WIN32
     156                 :         s = L"rb+";
     157                 :     #else
     158               2 :         s = "rb+";
     159                 :     #endif
     160               2 :         break;
     161                 : 
     162               2 :     case file_mode::append:
     163                 :     #ifdef _WIN32
     164                 :         s = L"ab";
     165                 :     #else
     166               2 :         s = "ab";
     167                 :     #endif
     168               2 :         break;
     169                 : 
     170               2 :     case file_mode::append_existing:
     171                 :     {
     172                 : #ifdef _WIN32
     173                 :         std::FILE* f0;
     174                 :         auto const ev =
     175                 :             ::_wfopen_s(&f0, unicode_path.c_str(), L"rb+");
     176                 :         if(ev)
     177                 :         {
     178                 :             ec.assign(ev,
     179                 :                 system::generic_category());
     180                 :             return;
     181                 :         }
     182                 : #else
     183                 :         auto const f0 =
     184               2 :             std::fopen(path, "rb+");
     185               2 :         if(! f0)
     186                 :         {
     187               1 :             ec.assign(errno,
     188                 :                 system::generic_category());
     189               1 :             return;
     190                 :         }
     191                 : #endif
     192               1 :         std::fclose(f0);
     193                 :     #ifdef _WIN32
     194                 :         s = L"ab";
     195                 :     #else
     196               1 :         s = "ab";
     197                 :     #endif
     198               1 :         break;
     199                 :     }
     200                 :     }
     201                 : 
     202                 : #ifdef _WIN32
     203                 :     auto const ev = ::_wfopen_s(
     204                 :         &f_, unicode_path.c_str(), s);
     205                 :     if(ev)
     206                 :     {
     207                 :         f_ = nullptr;
     208                 :         ec.assign(ev,
     209                 :             system::generic_category());
     210                 :         return;
     211                 :     }
     212                 : #else
     213              20 :     f_ = std::fopen(path, s);
     214              20 :     if(! f_)
     215                 :     {
     216               2 :         ec.assign(errno,
     217                 :             system::generic_category());
     218               2 :         return;
     219                 :     }
     220                 : #endif
     221                 : }
     222                 : 
     223                 : std::uint64_t
     224               2 : file_stdio::
     225                 : size(
     226                 :     system::error_code& ec) const
     227                 : {
     228               2 :     if(! f_)
     229                 :     {
     230               1 :         ec = make_error_code(
     231                 :             system::errc::bad_file_descriptor);
     232               1 :         return 0;
     233                 :     }
     234               1 :     long pos = std::ftell(f_);
     235               1 :     if(pos == -1L)
     236                 :     {
     237 MIS           0 :         ec.assign(errno,
     238                 :             system::generic_category());
     239               0 :         return 0;
     240                 :     }
     241 HIT           1 :     int result = std::fseek(f_, 0, SEEK_END);
     242               1 :     if(result != 0)
     243                 :     {
     244 MIS           0 :         ec.assign(errno,
     245                 :             system::generic_category());
     246               0 :         return 0;
     247                 :     }
     248 HIT           1 :     long size = std::ftell(f_);
     249               1 :     if(size == -1L)
     250                 :     {
     251 MIS           0 :         ec.assign(errno,
     252                 :             system::generic_category());
     253               0 :         std::fseek(f_, pos, SEEK_SET);
     254               0 :         return 0;
     255                 :     }
     256 HIT           1 :     result = std::fseek(f_, pos, SEEK_SET);
     257               1 :     if(result != 0)
     258 MIS           0 :         ec.assign(errno,
     259                 :             system::generic_category());
     260                 :     else
     261 HIT           1 :         ec = {};
     262               1 :     return size;
     263                 : }
     264                 : 
     265                 : std::uint64_t
     266               3 : file_stdio::
     267                 : pos(
     268                 :     system::error_code& ec) const
     269                 : {
     270               3 :     if(! f_)
     271                 :     {
     272               1 :         ec = make_error_code(
     273                 :             system::errc::bad_file_descriptor);
     274               1 :         return 0;
     275                 :     }
     276               2 :     long pos = std::ftell(f_);
     277               2 :     if(pos == -1L)
     278                 :     {
     279 MIS           0 :         ec.assign(errno,
     280                 :             system::generic_category());
     281               0 :         return 0;
     282                 :     }
     283 HIT           2 :     ec = {};
     284               2 :     return pos;
     285                 : }
     286                 : 
     287                 : void
     288               2 : file_stdio::
     289                 : seek(std::uint64_t offset,
     290                 :     system::error_code& ec)
     291                 : {
     292               2 :     if(! f_)
     293                 :     {
     294               1 :         ec = make_error_code(
     295                 :             system::errc::bad_file_descriptor);
     296               1 :         return;
     297                 :     }
     298               1 :     if(offset > static_cast<std::uint64_t>((std::numeric_limits<long>::max)()))
     299                 :     {
     300 MIS           0 :         ec = make_error_code(
     301                 :             system::errc::invalid_seek);
     302               0 :         return;
     303                 :     }
     304 HIT           1 :     int result = std::fseek(f_,
     305                 :         static_cast<long>(offset), SEEK_SET);
     306               1 :     if(result != 0)
     307 MIS           0 :         ec.assign(errno,
     308                 :             system::generic_category());
     309                 :     else
     310 HIT           1 :         ec = {};
     311                 : }
     312                 : 
     313                 : std::size_t
     314               3 : file_stdio::
     315                 : read(void* buffer, std::size_t n,
     316                 :     system::error_code& ec)
     317                 : {
     318               3 :     if(! f_)
     319                 :     {
     320               1 :         ec = make_error_code(
     321                 :             system::errc::bad_file_descriptor);
     322               1 :         return 0;
     323                 :     }
     324               2 :     auto nread = std::fread(buffer, 1, n, f_);
     325               2 :     if(std::ferror(f_))
     326                 :     {
     327 MIS           0 :         ec.assign(errno,
     328                 :             system::generic_category());
     329               0 :         return 0;
     330                 :     }
     331 HIT           2 :     return nread;
     332                 : }
     333                 : 
     334                 : std::size_t
     335               5 : file_stdio::
     336                 : write(void const* buffer, std::size_t n,
     337                 :     system::error_code& ec)
     338                 : {
     339               5 :     if(! f_)
     340                 :     {
     341               1 :         ec = make_error_code(
     342                 :             system::errc::bad_file_descriptor);
     343               1 :         return 0;
     344                 :     }
     345               4 :     auto nwritten = std::fwrite(buffer, 1, n, f_);
     346               4 :     if(std::ferror(f_))
     347                 :     {
     348 MIS           0 :         ec.assign(errno,
     349                 :             system::generic_category());
     350               0 :         return 0;
     351                 :     }
     352 HIT           4 :     return nwritten;
     353                 : }
     354                 : 
     355                 : } // detail
     356                 : } // http
     357                 : } // boost
        

Generated by: LCOV version 2.3