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#if defined(RESTINIO_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
14
15#include <cstdio>
16
17namespace restinio
18{
19
23using file_descriptor_t = HANDLE;
24using file_offset_t = std::uint64_t;
25using file_size_t = std::uint64_t;
27
36inline file_descriptor_t null_file_descriptor(){ return INVALID_HANDLE_VALUE; }
37
40open_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(
58 RESTINIO_FMT_FORMAT_STRING( "unable to openfile '{}': error({})" ),
59 file_path, GetLastError() )
60 };
61 }
62
63 return file_descriptor;
64}
65
67template < typename META >
68META
70{
71 file_size_t fsize = 0;
72 std::chrono::system_clock::time_point flastmodified;
73
74 if( null_file_descriptor() != fd )
75 {
76 LARGE_INTEGER file_size;
77 // Obtain file size:
78 if( GetFileSizeEx( fd, &file_size ) )
79 {
80 fsize = static_cast< file_size_t >( file_size.QuadPart );
81 }
82 else
83 {
84 throw exception_t{
85 fmt::format(
87 "unable to get file size: error code:{}" ),
88 GetLastError() )
89 };
90 }
91
92 FILETIME ftWrite;
93 if( GetFileTime( fd, NULL, NULL, &ftWrite ) )
94 {
95 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284(v=vs.85).aspx
96
97 // Microseconds between 1601-01-01 00:00:00 UTC and 1970-01-01 00:00:00 UTC
98 constexpr std::uint64_t nanosec100_in_microsec = 10;
99 constexpr std::uint64_t epoch_difference_in_microsec =
100 11644473600ULL * 1000 *1000;
101
102 // First convert 100-ns intervals to microseconds, then adjust for the
103 // epoch difference
104 ULARGE_INTEGER ull;
105 ull.LowPart = ftWrite.dwLowDateTime;
106 ull.HighPart = ftWrite.dwHighDateTime;
107
108 flastmodified =
109 std::chrono::system_clock::time_point{
110 std::chrono::microseconds(
111 ull.QuadPart / nanosec100_in_microsec - epoch_difference_in_microsec ) };
112 }
113 else
114 {
115 throw exception_t{
116 fmt::format(
118 "unable to get file last modification: error code:{}" ),
119 GetLastError() )
120 };
121 }
122 }
123
124 return META{ fsize, flastmodified};
125}
126
128inline void
130{
131 CloseHandle( fd );
132}
134
135} /* namespace restinio */
136
137#else // #if defined(RESTINIO_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
138
140
141#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.
std::uint64_t file_size_t
void close_file(file_descriptor_t fd)
Close file by its descriptor.
std::int64_t file_offset_t
std::FILE * file_descriptor_t
file_descriptor_t open_file(const char *file_path)
Open file.
META get_file_meta(file_descriptor_t fd)
Get file size.