Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/windirstat/llfio.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'include/llfio/v2.0/fs_handle.hpp')
-rw-r--r--include/llfio/v2.0/fs_handle.hpp100
1 files changed, 97 insertions, 3 deletions
diff --git a/include/llfio/v2.0/fs_handle.hpp b/include/llfio/v2.0/fs_handle.hpp
index 091f2f2e..6b0b9aeb 100644
--- a/include/llfio/v2.0/fs_handle.hpp
+++ b/include/llfio/v2.0/fs_handle.hpp
@@ -39,6 +39,91 @@ Distributed under the Boost Software License, Version 1.0.
LLFIO_V2_NAMESPACE_EXPORT_BEGIN
+class fs_handle;
+
+//! \brief The kinds of win32 path namespace possible.
+enum class win32_path_namespace
+{
+ /*! Map the input path to a valid win32 path as fast as possible for the input.
+ This is currently `guid_volume` followed by `dos`, but may change in the future.
+ */
+ any,
+ /*! Map `\!!\Device\...` form input paths to `\\.\...` for which it is _usually_
+ the case there is a mapping, which results in a valid Win32 path, but which
+ legacy code bases may not accept. This efficiently covers the vast majority of
+ what can be returned by `handle::current_path()` on Windows, but if the input
+ path cannot be mapped, a failure is returned.
+ */
+ device,
+ /*! Map the input path to a DOS drive letter prefix, possibly with `\\?\` prefix
+ to opt out of strict DOS path parsing if the mapped DOS path is incompatible with
+ traditional DOS (e.g. it contains one of the forbidden character sequences such
+ as `CON`, or it exceeds 260 codepoints, and so on). Well written software will
+ correctly handle `\\?\` prefixes, but if the code you are handing the path to is
+ particularly legacy, you ought to ensure that the prefix is not present.
+
+ \warning There is not a one-one mapping between NT kernel paths (which is what
+ LLFIO returns from `handle::current_path()`) and DOS style paths, so what you get
+ may be surprising. It is also possible that there is no mapping at all, in which
+ case a failure is returned.
+ */
+ dos,
+ /*! Map the input path replacing the volume as a GUID, such that say an input path
+ of `C:\foo\bar` might be mapped to `\\?\Volume{9f9bd10e-9003-4da5-b146-70584e30854a}\foo\bar`.
+ This is a valid Win32 path, but legacy code bases may not accept it. This eliminates
+ problems with drive letters vanishing or being ambiguous, and unlike with `dos`,
+ there is a guaranteed one-one mapping between NT kernel paths and `guid_volume` paths.
+ The mapped path is NOT checked for equivalence to the input file.
+ */
+ guid_volume
+#if 0
+ /*! Map the input path replacing the the whole path as a GUID, such that say an input
+ path of `C:\foo\bar` might be mapped to `\\?\Volume{9f9bd10e-9003-4da5-b146-70584e30854a}\{5a13b46c-44b9-40f3-9303-23cf7d918708}`.
+ This is a valid Win32 path, but legacy code bases may not accept it. This eliminates
+ problems with long paths or if the file could be renamed concurrently. Note this may
+ cause the creation of a GUID for the file on some filesystems (NTFS). The mapped path
+ is NOT checked for equivalence to the input file.
+ */
+ guid_all
+
+/*
+- `win32_path_namespace::guid_all` does the same as `guid_volume`, but additionally
+asks Windows for the GUID for the file upon the volume, creating one if one
+doesn't exist if necessary. The path returned consists of two GUIDs, and is a
+perfectly valid Win32 path which most Win32 APIs will accept.
+*/
+#endif
+};
+
+/*! \brief Maps the current path of `h` into a form suitable for Win32 APIs.
+Passes through unmodified on POSIX, so you can use this in portable code.
+\return The mapped current path of `h`, which may have been validated to refer to
+the exact same inode via `.unique_id()` (see below).
+\param h The handle whose `.current_path()` is to be mapped into a form suitable
+for Win32 APIs.
+\param mapping Which Win32 path namespace to map onto.
+
+This implementation may need to validate that the mapping of the current path of `h`
+onto the desired Win32 path namespace does indeed refer to the same file:
+
+- `win32_path_namespace::device` transforms `\!!\Device\...` => `\\.\...` and
+ensures that the mapped file's unique id matches the original, otherwise
+returning failure.
+- `win32_path_namespace::dos` enumerates all the DOS devices on the system and
+what those map onto within the NT kernel namespace. This mapping is for
+obvious reasons quite slow.
+- `win32_path_namespace::guid_volume` simply fetches the GUID of the volume of
+the handle, and constructs a valid Win32 path from that.
+- `win32_path_namespace::any` means attempt `guid_volume` first, and if it fails
+(e.g. your file is on a network share) then it attempts `dos`. This semantic may
+change in the future, however any path emitted will always be a valid Win32 path.
+*/
+#ifdef _WIN32
+LLFIO_HEADERS_ONLY_FUNC_SPEC result<filesystem::path> to_win32_path(const fs_handle &h, win32_path_namespace mapping = win32_path_namespace::any) noexcept;
+#else
+inline result<filesystem::path> to_win32_path(const fs_handle &h, win32_path_namespace mapping = win32_path_namespace::any) noexcept;
+#endif
+
/*! \class fs_handle
\brief A handle to something with a device and inode number.
@@ -46,6 +131,12 @@ LLFIO_V2_NAMESPACE_EXPORT_BEGIN
*/
class LLFIO_DECL fs_handle
{
+#ifdef _WIN32
+ friend LLFIO_HEADERS_ONLY_FUNC_SPEC result<filesystem::path> to_win32_path(const fs_handle &h, win32_path_namespace mapping) noexcept;
+#else
+ friend inline result<filesystem::path> to_win32_path(const fs_handle &h, win32_path_namespace mapping) noexcept { return h._get_handle().current_path(); }
+#endif
+
public:
using dev_t = uint64_t;
using ino_t = uint64_t;
@@ -246,7 +337,8 @@ public:
namespace detail
{
- LLFIO_HEADERS_ONLY_FUNC_SPEC result<path_handle> containing_directory(optional<std::reference_wrapper<filesystem::path>> out_filename, const handle &h, const fs_handle &fsh, deadline d) noexcept;
+ LLFIO_HEADERS_ONLY_FUNC_SPEC result<path_handle> containing_directory(optional<std::reference_wrapper<filesystem::path>> out_filename, const handle &h,
+ const fs_handle &fsh, deadline d) noexcept;
}
// BEGIN make_free_functions.py
@@ -274,9 +366,11 @@ must succeed, else `errc::timed_out` will be returned.
\mallocs Except on platforms with race free syscalls for renaming open handles (Windows), calls
`current_path()` via `parent_path_handle()` and thus is both expensive and calls malloc many times.
*/
-inline result<void> relink(fs_handle &self, const path_handle &base, fs_handle::path_view_type path, bool atomic_replace = true, deadline d = std::chrono::seconds(30)) noexcept
+inline result<void> relink(fs_handle &self, const path_handle &base, fs_handle::path_view_type path, bool atomic_replace = true,
+ deadline d = std::chrono::seconds(30)) noexcept
{
- return self.relink(std::forward<decltype(base)>(base), std::forward<decltype(path)>(path), std::forward<decltype(atomic_replace)>(atomic_replace), std::forward<decltype(d)>(d));
+ return self.relink(std::forward<decltype(base)>(base), std::forward<decltype(path)>(path), std::forward<decltype(atomic_replace)>(atomic_replace),
+ std::forward<decltype(d)>(d));
}
/*! Unlinks the current path of this open handle, causing its entry to immediately disappear from the filing system.
On Windows unless `flag::win_disable_unlink_emulation` is set, this behaviour is