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