Skip to content

Commit 938b845

Browse files
committed
Add example of openat() on Windows for WG21 paper.
1 parent dfe95ff commit 938b845

File tree

9 files changed

+155
-10
lines changed

9 files changed

+155
-10
lines changed

cmake/tests.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ set(llfio_COMPILE_TESTS
4949
"example/malloc2.cpp"
5050
"example/map_file.cpp"
5151
"example/mapped_file.cpp"
52+
"example/path_view_openat.cpp"
5253
"example/read_directory.cpp"
5354
"example/read_entire_file1.cpp"
5455
"example/read_stats.cpp"

doc/html

Submodule html updated 231 files

example/path_view_openat.cpp

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/* Examples of LLFIO use
2+
(C) 2024 Niall Douglas <http://www.nedproductions.biz/> (2 commits)
3+
File Created: Aug 2024
4+
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License in the accompanying file
9+
Licence.txt or at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
19+
20+
Distributed under the Boost Software License, Version 1.0.
21+
(See accompanying file Licence.txt or copy at
22+
http://www.boost.org/LICENSE_1_0.txt)
23+
*/
24+
25+
#include "../include/llfio.hpp"
26+
27+
#if defined(_WIN32) && _HAS_CXX20
28+
#include "../include/llfio/v2.0/detail/impl/windows/import.hpp"
29+
30+
#include <variant>
31+
32+
using namespace LLFIO_V2_NAMESPACE;
33+
using namespace LLFIO_V2_NAMESPACE::windows_nt_kernel;
34+
using namespace std;
35+
36+
HANDLE openat(HANDLE base, path_view path)
37+
{
38+
static constexpr DWORD access = GENERIC_READ;
39+
static constexpr DWORD share =
40+
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
41+
static constexpr DWORD creation = OPEN_EXISTING;
42+
static constexpr DWORD flags = FILE_ATTRIBUTE_NORMAL;
43+
return visit(
44+
[&](auto sv) -> HANDLE
45+
{
46+
using type = typename decltype(sv)::value_type;
47+
if constexpr(is_same_v<type, byte>)
48+
{
49+
if(sv.size() == 16)
50+
{
51+
FILE_ID_DESCRIPTOR fid{};
52+
fid.dwSize = sizeof(fid);
53+
fid.Type = 1;
54+
memcpy(&fid.ObjectId, sv.data(), 16);
55+
return OpenFileById(base, &fid, access, share, nullptr, flags);
56+
}
57+
throw std::runtime_error("binary key must be exactly 16 bytes long");
58+
}
59+
// A "\!!\" or "\??\" prefix enables direct use of the NT kernel API
60+
// or setting base, as the Win32 doesn't support paths relative to a base
61+
const bool is_ntpath =
62+
sv.size() >= 4 && sv[0] == '\\' && sv[3] == '\\' &&
63+
((sv[1] == '!' && sv[2] == '!') || (sv[1] == '?' && sv[2] == '?'));
64+
if(base != nullptr || is_ntpath)
65+
{
66+
// The NT kernel always takes the system wide encoding
67+
auto zpath = path.render_unterminated<wchar_t>(path);
68+
UNICODE_STRING _path{};
69+
_path.Buffer = const_cast<wchar_t *>(zpath.data());
70+
_path.MaximumLength =
71+
(_path.Length = static_cast<USHORT>(zpath.size() * sizeof(wchar_t))) +
72+
sizeof(wchar_t);
73+
// The "\!!\" prefix is library local and the NT kernel doesn't
74+
// understand it, so strip it off
75+
if(zpath.size() >= 4 && _path.Buffer[0] == '\\' &&
76+
_path.Buffer[1] == '!' && _path.Buffer[2] == '!' &&
77+
_path.Buffer[3] == '\\')
78+
{
79+
_path.Buffer += 3;
80+
_path.Length -= 3 * sizeof(wchar_t);
81+
_path.MaximumLength -= 3 * sizeof(wchar_t);
82+
}
83+
84+
OBJECT_ATTRIBUTES oa{};
85+
oa.Length = sizeof(OBJECT_ATTRIBUTES);
86+
oa.ObjectName = &_path;
87+
oa.RootDirectory = base;
88+
oa.Attributes = 0;
89+
90+
IO_STATUS_BLOCK isb{};
91+
LARGE_INTEGER AllocationSize{};
92+
HANDLE ret = INVALID_HANDLE_VALUE;
93+
NTSTATUS ntstat =
94+
NtCreateFile(&ret, access, &oa, &isb, &AllocationSize, 0, share,
95+
FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, nullptr, 0);
96+
if(ntstat < 0)
97+
{
98+
// Might want to call RtlNtStatusToDosError(ntstat)?
99+
}
100+
return ret;
101+
}
102+
else
103+
{
104+
if constexpr(is_same_v<type, char>)
105+
{
106+
// Render to the system narrow encoding null terminated
107+
auto zpath = path.render_null_terminated<char>(path);
108+
return CreateFileA(zpath.c_str(), access, share, nullptr, creation,
109+
flags, nullptr);
110+
}
111+
// Render to the system wide encoding null terminated
112+
auto zpath = path.render_null_terminated<wchar_t>(path);
113+
return CreateFileW(zpath.c_str(), access, share, nullptr, creation,
114+
flags, nullptr);
115+
}
116+
// Should never reach here
117+
std::terminate();
118+
},
119+
path);
120+
}
121+
#endif
122+
123+
// clang-format off
124+
125+
int main()
126+
{
127+
return 0;
128+
}

include/llfio/revision.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
2-
#define LLFIO_PREVIOUS_COMMIT_REF c0326169a2f9577d617f38dd039df21f7492a548
3-
#define LLFIO_PREVIOUS_COMMIT_DATE "2024-08-18 12:32:44 +00:00"
4-
#define LLFIO_PREVIOUS_COMMIT_UNIQUE c0326169
2+
#define LLFIO_PREVIOUS_COMMIT_REF dfe95ff5e36c495df11f9a4420ddeb866be4d658
3+
#define LLFIO_PREVIOUS_COMMIT_DATE "2024-08-20 07:56:43 +00:00"
4+
#define LLFIO_PREVIOUS_COMMIT_UNIQUE dfe95ff5

include/llfio/v2.0/byte_socket_handle.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ namespace ip
8585
/*! \class address
8686
\brief A version independent IP address.
8787
88+
\warning This is deprecated and scheduled for removal in 2025.
89+
8890
This is inspired by `asio::ip::address`, but it also adds `port()` from `asio::ip::endpoint`
8991
and a few other observer member functions i.e. it fuses ASIO's many types into one.
9092
@@ -238,6 +240,8 @@ namespace ip
238240
/*! \brief Retrieve a list of potential `address` for a given name and service e.g.
239241
"www.google.com" and "https" optionally within a bounded deadline.
240242
243+
\warning This is deprecated and scheduled for removal in 2025.
244+
241245
The object returned by this function can take many seconds to become ready as multiple network requests may
242246
need to be made. The deadline can be used to bound execution times -- like in a few
243247
other places in LLFIO, this deadline does not cause timed out errors, rather it aborts
@@ -354,6 +358,8 @@ namespace ip
354358
/*! \class byte_socket_handle
355359
\brief A handle to a byte-orientated socket-like entity.
356360
361+
\warning This is deprecated and scheduled for removal in 2025.
362+
357363
This handle, or subclasses thereof, may refer to:
358364
359365
- a BSD socket in the kernel configured for TCP.

include/llfio/v2.0/dynamic_thread_pool_group.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ namespace detail
5656
/*! \class dynamic_thread_pool_group
5757
\brief Work group within the global dynamic thread pool.
5858
59+
\warning This is deprecated and scheduled for removal in 2025.
60+
5961
Some operating systems provide a per-process global kernel thread pool capable of
6062
dynamically adjusting its kernel thread count to how many of the threads in
6163
the pool are currently blocked. The platform will choose the exact strategy used,

include/llfio/v2.0/path_view.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,7 +1568,7 @@ class LLFIO_DECL path_view_component
15681568
LLFIO_TREQUIRES(LLFIO_TPRED(is_source_acceptable<T>),
15691569
LLFIO_TEXPR(std::is_constructible<rendered_path<zero_termination::zero_terminated, T, AllocatorOrDeleter, _internal_buffer_size>,
15701570
path_view_component, Args...>::value))
1571-
rendered_path<zero_termination::zero_terminated, T, AllocatorOrDeleter, _internal_buffer_size> render_zero_terminated(path_view_component view,
1571+
rendered_path<zero_termination::zero_terminated, T, AllocatorOrDeleter, _internal_buffer_size> render_null_terminated(path_view_component view,
15721572
Args &&...args) const
15731573
{
15741574
return rendered_path<zero_termination::zero_terminated, T, AllocatorOrDeleter, _internal_buffer_size>(view, std::forward<Args>(args)...);
@@ -1579,8 +1579,8 @@ class LLFIO_DECL path_view_component
15791579
LLFIO_TREQUIRES(LLFIO_TPRED(is_source_acceptable<T>),
15801580
LLFIO_TEXPR(std::is_constructible<rendered_path<zero_termination::zero_terminated, T, AllocatorOrDeleter, _internal_buffer_size>,
15811581
path_view_component, Args...>::value))
1582-
rendered_path<zero_termination::not_zero_terminated, T, AllocatorOrDeleter, _internal_buffer_size> render_not_zero_terminated(path_view_component view,
1583-
Args &&...args) const
1582+
rendered_path<zero_termination::not_zero_terminated, T, AllocatorOrDeleter, _internal_buffer_size> render_unterminated(path_view_component view,
1583+
Args &&...args) const
15841584
{
15851585
return rendered_path<zero_termination::not_zero_terminated, T, AllocatorOrDeleter, _internal_buffer_size>(view, std::forward<Args>(args)...);
15861586
}

include/llfio/v2.0/tls_socket_handle.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ QUICKCPPLIB_BITFIELD_BEGIN(tls_algorithm) //
6565
/*! \class tls_socket_handle
6666
\brief A handle to a TLS secure socket-like entity.
6767
68+
\warning This is deprecated and scheduled for removal in 2025.
69+
6870
As you cannot create one of these on your own, one generally acquires one of these
6971
from a `tls_socket_source`.
7072
*/
@@ -328,6 +330,8 @@ struct tls_socket_source_implementation_information;
328330
\brief A source of `tls_socket_handle` and `listening_tls_socket_handle` and possibly a `byte_io_multiplexer`
329331
to multiplex i/o on multiple socket instances at the same time.
330332
333+
\warning This is deprecated and scheduled for removal in 2025.
334+
331335
The socket handles returned by this source may be _very_ different implementations
332336
to the kernel socket handles returned by `byte_socket_handle::byte_socket()` -- they
333337
may have all virtual functions overridden AND a custom i/o multiplexer set, plus RTTI
@@ -470,6 +474,8 @@ inline std::ostream &operator<<(std::ostream &s, const tls_socket_source_impleme
470474
/*! \class tls_socket_source_registry
471475
\brief A process-wide registry of `tls_socket_source`.
472476
477+
\warning This is deprecated and scheduled for removal in 2025.
478+
473479
Probably the most common use case for this will be fetching the default source of TLS
474480
secured sockets, so here is some example boilerplate:
475481

test/tests/path_view.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* Integration test kernel for whether path views work
2-
(C) 2017-2020 Niall Douglas <http://www.nedproductions.biz/> (2 commits)
2+
(C) 2017-2024 Niall Douglas <http://www.nedproductions.biz/> (2 commits)
33
File Created: Aug 2017
44
55
@@ -227,14 +227,16 @@ static inline void TestPathView()
227227
CheckPathIteration("boostish/testdir/");
228228
CheckPathIteration("/a/c");
229229
CheckPathIteration("/a/c/");
230+
#ifdef _WIN32
230231
CheckPathIteration("//a/c");
231232
CheckPathIteration("//a");
232233
CheckPathIteration("//a/");
233234
// CheckPathIteration("///a/c"); // FIXME: fails, /// not ///a should be iterated
234235
// CheckPathIteration("////a/c"); // FIXME: fails, //// not ////a should be iterated
235236
CheckPathIteration("//a/c//");
236-
// CheckPathIteration("///a/c//"); // FIXME: fails, /// not ///a should be iterated
237-
// CheckPathIteration("////a/c////"); // FIXME: fails, //// not ////a should be iterated
237+
// CheckPathIteration("///a/c//"); // FIXME: fails, /// not ///a should be iterated
238+
// CheckPathIteration("////a/c////"); // FIXME: fails, //// not ////a should be iterated
239+
#endif
238240
CheckPathIteration("/a/c//");
239241
CheckPathIteration("/a/c////");
240242
CheckPathIteration("a/c");

0 commit comments

Comments
 (0)