RESTinio
sendfile_defs_win.hpp
Go to the documentation of this file.
1 /*
2  restinio
3 */
4 
11 #pragma once
12 
13 #if defined(RESTINIO_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
14 
15 #include <cstdio>
16 
17 namespace restinio
18 {
19 
22 using file_descriptor_t = HANDLE;
24 using file_offset_t = std::uint64_t;
25 using file_size_t = std::uint64_t;
27 
34 inline file_descriptor_t null_file_descriptor(){ return INVALID_HANDLE_VALUE; }
37 
39 inline file_descriptor_t
40 open_file( const char * file_path )
41 {
42  file_descriptor_t file_descriptor =
43  // We don't support Unicode on Windows, so call Ansi-version of
44  // CreateFile directly.
45  ::CreateFileA(
46  file_path,
47  GENERIC_READ,
48  FILE_SHARE_READ,
49  0,
50  OPEN_EXISTING,
51  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
52  0 );
53 
54  if( null_file_descriptor() == file_descriptor )
55  {
56  throw exception_t{
57  fmt::format( "unable to openfile '{}': error({})", file_path, GetLastError() ) };
58  }
59 
60  return file_descriptor;
61 }
62 
64 template < typename META >
65 META
67 {
68  file_size_t fsize = 0;
69  std::chrono::system_clock::time_point flastmodified;
70 
71  if( null_file_descriptor() != fd )
72  {
73  LARGE_INTEGER file_size;
74  // Obtain file size:
75  if( GetFileSizeEx( fd, &file_size ) )
76  {
77  fsize = static_cast< file_size_t >( file_size.QuadPart );
78  }
79  else
80  {
81  throw exception_t{
82  fmt::format( "unable to get file size: error code:{}", GetLastError() ) };
83  }
84 
85  FILETIME ftWrite;
86  if( GetFileTime( fd, NULL, NULL, &ftWrite ) )
87  {
88  // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284(v=vs.85).aspx
89 
90  // Microseconds between 1601-01-01 00:00:00 UTC and 1970-01-01 00:00:00 UTC
91  constexpr std::uint64_t nanosec100_in_microsec = 10;
92  constexpr std::uint64_t epoch_difference_in_microsec =
93  11644473600ULL * 1000 *1000;
94 
95  // First convert 100-ns intervals to microseconds, then adjust for the
96  // epoch difference
97  ULARGE_INTEGER ull;
98  ull.LowPart = ftWrite.dwLowDateTime;
99  ull.HighPart = ftWrite.dwHighDateTime;
100 
101  flastmodified =
102  std::chrono::system_clock::time_point{
103  std::chrono::microseconds(
104  ull.QuadPart / nanosec100_in_microsec - epoch_difference_in_microsec ) };
105  }
106  else
107  {
108  throw exception_t{
109  fmt::format(
110  "unable to get file last modification: error code:{}",
111  GetLastError() ) };
112  }
113  }
114 
115  return META{ fsize, flastmodified};
116 }
117 
119 inline void
121 {
122  CloseHandle( fd );
123 }
125 
126 } /* namespace restinio */
127 
128 #else // #if defined(RESTINIO_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
129 
131 
132 #endif // #if defined(RESTINIO_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
restinio::file_size_t
std::uint64_t file_size_t
Definition: sendfile_defs_default.hpp:23
sendfile_defs_default.hpp
restinio::file_descriptor_t
std::FILE * file_descriptor_t
Definition: sendfile_defs_default.hpp:21
restinio::file_offset_t
std::int64_t file_offset_t
Definition: sendfile_defs_default.hpp:22
restinio::close_file
void close_file(file_descriptor_t fd)
Close file by its descriptor.
Definition: sendfile_defs_default.hpp:89
restinio::open_file
file_descriptor_t open_file(const char *file_path)
Open file.
Definition: sendfile_defs_default.hpp:40
restinio::get_file_meta
META get_file_meta(file_descriptor_t fd)
Get file size.
Definition: sendfile_defs_default.hpp:55
restinio::null_file_descriptor
constexpr file_descriptor_t null_file_descriptor()
Get file descriptor which stands for null.
Definition: sendfile_defs_default.hpp:36
restinio
Definition: asio_include.hpp:21