RESTinio
Loading...
Searching...
No Matches
sendfile_defs_win.hpp
Go to the documentation of this file.
1/*
2 restinio
3*/
4
11#pragma once
12
13//eao197: this code has to be uncommented to check the default
14//implementation of sendfile operation.
15//#if defined(RESTINIO_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
16//#undef RESTINIO_ASIO_HAS_WINDOWS_OVERLAPPED_PTR
17//#endif
18
19#if defined(RESTINIO_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
20
21#include <cstdio>
22
23namespace restinio
24{
25
30using file_offset_t = std::uint64_t;
31using file_size_t = std::uint64_t;
33
42[[nodiscard]]
44
46[[nodiscard]]
48open_file( const char * file_path )
49{
50 file_descriptor_t file_descriptor =
51 // We don't support Unicode on Windows, so call Ansi-version of
52 // CreateFile directly.
57 0,
60 0 );
61
62 if( null_file_descriptor() == file_descriptor )
63 {
64 throw exception_t{
65 fmt::format(
66 RESTINIO_FMT_FORMAT_STRING( "unable to openfile '{}': error({})" ),
68 };
69 }
70
71 return file_descriptor;
72}
73
87[[nodiscard]]
89open_file( const std::filesystem::path & file_path )
90{
91 const auto wide_file_path = file_path.wstring();
92 file_descriptor_t file_descriptor =
93 // Use wide-char version of CreateFile.
95 wide_file_path.c_str(),
98 0,
101 0 );
102
103 if( null_file_descriptor() == file_descriptor )
104 {
105 //NOTE(eao197): I don't know a simple way to add `file_path` value into
106 //error message (with respect to the fact that file_path can contain name
107 //in Unicode, in UCS-2, but not in UTF-8).
108 //Because of that the current version doesn't include file name in the
109 //error description.
110 throw exception_t{
111 fmt::format(
113 "open_file(std::filesystem::path) "
114 "unable to openfile: error({})" ),
115 GetLastError() )
116 };
117 }
118
119 return file_descriptor;
120}
121
122
124template < typename META >
125[[nodiscard]]
126META
128{
129 file_size_t fsize = 0;
130 std::chrono::system_clock::time_point flastmodified;
131
132 if( null_file_descriptor() != fd )
133 {
135 // Obtain file size:
136 if( GetFileSizeEx( fd, &file_size ) )
137 {
138 fsize = static_cast< file_size_t >( file_size.QuadPart );
139 }
140 else
141 {
142 throw exception_t{
143 fmt::format(
145 "unable to get file size: error code:{}" ),
146 GetLastError() )
147 };
148 }
149
151 if( GetFileTime( fd, NULL, NULL, &ftWrite ) )
152 {
153 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284(v=vs.85).aspx
154
155 // Microseconds between 1601-01-01 00:00:00 UTC and 1970-01-01 00:00:00 UTC
156 constexpr std::uint64_t nanosec100_in_microsec = 10;
157 constexpr std::uint64_t epoch_difference_in_microsec =
158 11644473600ULL * 1000 *1000;
159
160 // First convert 100-ns intervals to microseconds, then adjust for the
161 // epoch difference
163 ull.LowPart = ftWrite.dwLowDateTime;
164 ull.HighPart = ftWrite.dwHighDateTime;
165
167 std::chrono::system_clock::time_point{
168 std::chrono::microseconds(
170 }
171 else
172 {
173 throw exception_t{
174 fmt::format(
176 "unable to get file last modification: error code:{}" ),
177 GetLastError() )
178 };
179 }
180 }
181
182 return META{ fsize, flastmodified};
183}
184
186inline void
188{
189 CloseHandle( fd );
190}
192
193} /* namespace restinio */
194
195#else // #if defined(RESTINIO_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
196
198
199#endif // #if defined(RESTINIO_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
#define RESTINIO_FMT_FORMAT_STRING(s)
constexpr file_descriptor_t null_file_descriptor()
Get file descriptor which stands for null.
run_on_this_thread_settings_t< Traits > on_this_thread()
A special marker for the case when http_server must be run on the context of the current thread.
void close_file(file_descriptor_t fd)
Close file by its descriptor.
file_descriptor_t open_file(const char *file_path)
Open file.
std::FILE * file_descriptor_t
std::int64_t file_offset_t
META get_file_meta(file_descriptor_t fd)
Get file size.
std::uint64_t file_size_t