master
hpp 252 lines 7.93 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 filesystem.hpp
8
9 Abstract:
10
11 This file contains file system function declarations.
12
13 --*/
14
15 #pragma once
16
17 #include "wslservice.h"
18
19 #define LXSS_FS_TYPE_DRVFS "drvfs"
20 #define LXSS_FS_TYPE_LXFS "lxfs"
21 #define LXSS_FS_TYPE_SHAREFS "sharefs"
22 #define LXSS_FS_TYPE_TMPFS "tmpfs"
23 #define LXSS_FS_TYPE_WSLFS "wslfs"
24
25 namespace wsl::windows::common::filesystem {
26
27 enum class TempFileFlags
28 {
29 None = 0x0,
30 DeleteOnClose = 0x1,
31 InheritHandle = 0x2
32 };
33
34 DEFINE_ENUM_FLAG_OPERATORS(TempFileFlags);
35
36 // Used only in unit tests.
37 constexpr ULONG c_case_sensitive_folders_only = 0x100;
38
39 // Make sure that the above flag doesn't conflict with create instance flags
40 static_assert((LXSS_CREATE_INSTANCE_FLAGS_ALL & c_case_sensitive_folders_only) == 0);
41
42 struct TempFile
43 {
44 std::filesystem::path Path;
45 wil::unique_hfile Handle;
46 TempFileFlags Flags = TempFileFlags::None;
47
48 TempFile(
49 _In_ DWORD DesiredAccess,
50 _In_ DWORD ShareMode,
51 _In_ DWORD CreationDisposition,
52 _In_ TempFileFlags Flags = TempFileFlags::None,
53 _In_opt_ std::wstring_view Extension = {});
54
55 ~TempFile();
56
57 TempFile(const TempFile&) = delete;
58 TempFile& operator=(const TempFile&) = delete;
59
60 TempFile(TempFile&& other) noexcept
61 {
62 *this = std::move(other);
63 }
64
65 TempFile& operator=(TempFile&& other) noexcept
66 {
67 std::swap(Path, other.Path);
68 std::swap(Handle, other.Handle);
69 std::swap(Flags, other.Flags);
70 return *this;
71 }
72 };
73
74 inline void FreeLXSS_ADDMOUNT(_Inout_opt_ PLX_KMAPPATHS_ADDMOUNT pMount)
75 {
76 if (pMount)
77 {
78 if (pMount->Source)
79 {
80 CoTaskMemFree((LPVOID)pMount->Source);
81 }
82
83 if (pMount->Target)
84 {
85 CoTaskMemFree((LPVOID)pMount->Target);
86 }
87
88 if (pMount->FsType)
89 {
90 CoTaskMemFree((LPVOID)pMount->FsType);
91 }
92
93 if (pMount->WindowsDataRoot && (pMount->WindowsDataRoot != INVALID_HANDLE_VALUE))
94 {
95 CloseHandle(pMount->WindowsDataRoot);
96 }
97 }
98 }
99
100 using unique_lxss_addmount = wil::unique_struct<LX_KMAPPATHS_ADDMOUNT, decltype(&FreeLXSS_ADDMOUNT), FreeLXSS_ADDMOUNT>;
101
102 /// <summary>
103 /// Creates a mount for instance creation.
104 /// </summary>
105 unique_lxss_addmount CreateMount(
106 _In_ PCWSTR NtPath, _In_ PCWSTR Source, _In_opt_ LPCSTR Target, _In_ LPCSTR FsType, _In_ ULONG Mode, _In_ bool forWrite = true);
107
108 /// <summary>
109 /// Creates a directory for the root file system.
110 /// </summary>
111 void CreateRootFs(_In_ PCWSTR Path, _In_ ULONG Version);
112
113 void DeviceIoControl(_In_ HANDLE handle, _In_ ULONG code, _In_ gsl::span<const gsl::byte> input = {});
114
115 NTSTATUS
116 DeviceIoControlNoThrow(_In_ HANDLE handle, _In_ ULONG code, _In_ gsl::span<const gsl::byte> input = {});
117
118 std::pair<ULONG, ULONG> EnumerateFixedDrives(HANDLE Token = nullptr);
119
120 /// <summary>
121 /// Creates a directory with the given path if it does not exist. Throws if creating the directory
122 /// failed.
123 /// </summary>
124 bool EnsureDirectory(_In_ LPCWSTR pPath);
125
126 /// <summary>
127 /// Marks every directory in a tree case-sensitive.
128 /// </summary>
129 void EnsureCaseSensitiveDirectory(_In_ PCWSTR Path, _In_ ULONG Flags);
130
131 /// <summary>
132 /// Creates a directory with the given path if it does not exist, and applies
133 /// the specified attributes if the directory doesn't have any. Throws if
134 /// creating the directory or applying the attributes failed.
135 /// </summary>
136 void EnsureDirectoryWithAttributes(_In_ PCWSTR Path, _In_ ULONG Mode, _In_ ULONG Uid, _In_ ULONG Gid, _In_ ULONG Flags, _In_ ULONG DistroVersion);
137
138 bool FileExists(_In_ LPCWSTR Path);
139
140 /// <summary>
141 /// Resolves Path to an absolute, canonical form. The path is made absolute against the current
142 /// directory first because std::filesystem::weakly_canonical does not reliably resolve a relative
143 /// path on its own. '..' components are collapsed and symlinks are resolved for the portion of the
144 /// path that exists, so a path naming a file that does not exist yet still succeeds.
145 /// Throws on failure.
146 /// </summary>
147 std::filesystem::path GetCanonicalPath(const std::filesystem::path& Path);
148
149 /// <summary>
150 /// Non-throwing overload of GetCanonicalPath. On failure Error is set and an empty path is
151 /// returned; on success Error is cleared.
152 /// </summary>
153 std::filesystem::path GetCanonicalPath(const std::filesystem::path& Path, std::error_code& Error);
154
155 std::filesystem::path GetFullPath(_In_ LPCWSTR Path);
156
157 std::pair<std::string, std::string> GetHostAndDomainNames();
158
159 std::string GetLinuxHostName();
160
161 /// <summary>
162 /// Gets the base path for legacy installs.
163 /// </summary>
164 std::filesystem::path GetLegacyBasePath(_In_ HANDLE UserToken);
165
166 std::filesystem::path GetLocalAppDataPath(_In_ HANDLE userToken);
167
168 std::filesystem::path GetKnownFolderPath(const KNOWNFOLDERID& id, DWORD flags, HANDLE token = nullptr);
169
170 std::filesystem::path GetTempFilename();
171
172 std::filesystem::path GetTempFolderPath(_In_ HANDLE userToken);
173
174 std::string GetWindowsHosts(const std::filesystem::path& Path);
175
176 /// <summary>
177 /// Opens a directory handle with read/execute, optionally also write, & full sharing. The path
178 /// must exist and be a directory. Throws if the directory cannot be opened.
179 /// </summary>
180 wil::unique_hfile OpenDirectoryHandle(_In_ LPCWSTR pPath, _In_ bool forWrite);
181
182 /// <summary>
183 /// Opens a directory handle with read/execute, optionally also write, & full sharing. The path
184 /// must exist and be a directory.
185 /// </summary>
186 wil::unique_hfile OpenDirectoryHandleNoThrow(_In_ LPCWSTR pPath, _In_ bool forWrite);
187
188 /// <summary>
189 /// Opens the null device.
190 /// </summary>
191 wil::unique_hfile OpenNulDevice(_In_ DWORD DesiredAccess);
192
193 wil::unique_hfile OpenRelativeFile(
194 _In_opt_ HANDLE Parent,
195 _In_ PUNICODE_STRING RelativePath,
196 _In_ ACCESS_MASK DesiredAccess,
197 _In_ ULONG Disposition,
198 _In_ ULONG CreateOptions,
199 _In_opt_ PVOID EaBuffer = nullptr,
200 _In_ ULONG EaSize = 0);
201
202 std::pair<NTSTATUS, wil::unique_hfile> OpenRelativeFileNoThrow(
203 _In_opt_ HANDLE Parent,
204 _In_ PUNICODE_STRING RelativePath,
205 _In_ ACCESS_MASK DesiredAccess,
206 _In_ ULONG Disposition,
207 _In_ ULONG CreateOptions,
208 _In_opt_ PVOID EaBuffer = nullptr,
209 _In_ ULONG EaSize = 0);
210
211 wil::unique_hfile ReopenFile(_In_ HANDLE Handle, _In_ ACCESS_MASK DesiredAccess, _In_ ULONG CreateOptions);
212
213 void QueryInformationFile(_In_ HANDLE Handle, _Out_writes_bytes_(Length) PVOID Buffer, _In_ ULONG Length, _In_ FILE_INFORMATION_CLASS FileInformationClass);
214
215 template <typename T>
216 void QueryInformationFile(_In_ HANDLE Handle, _Out_ T& Buffer, _In_ FILE_INFORMATION_CLASS FileInformationClass)
217 {
218 QueryInformationFile(Handle, &Buffer, sizeof(Buffer), FileInformationClass);
219 }
220
221 VOID QuerySingleEaFile(_In_ HANDLE Handle, _Out_ PIO_STATUS_BLOCK IoStatus, _In_ std::string_view EaName, _Out_writes_bytes_(Length) PVOID Buffer, _In_ ULONG Length);
222
223 std::vector<CHAR> QuerySingleEaFile(_In_ HANDLE Handle, _In_ std::string_view EaName);
224
225 NTSTATUS
226 QuerySingleEaFileNoThrow(
227 _In_ HANDLE Handle, _Out_ PIO_STATUS_BLOCK IoStatus, _In_ std::string_view EaName, _Out_writes_bytes_(Length) PVOID Buffer, _In_ ULONG Length);
228
229 void SetInformationFile(_In_ HANDLE Handle, _In_reads_bytes_(Length) PVOID Buffer, _In_ ULONG Length, _In_ FILE_INFORMATION_CLASS FileInformationClass);
230
231 template <typename T>
232 void SetInformationFile(_In_ HANDLE Handle, _In_ T& Buffer, _In_ FILE_INFORMATION_CLASS FileInformationClass)
233 {
234 SetInformationFile(Handle, &Buffer, sizeof(Buffer), FileInformationClass);
235 }
236
237 std::optional<std::filesystem::path> TryGetPathFromFileUrl(const std::wstring& Url);
238
239 std::wstring UnquotePath(_In_ LPCWSTR Path);
240
241 /// <summary>
242 /// Updates the init binary.
243 /// </summary>
244 void UpdateInit(_In_ PCWSTR BasePath, _In_ ULONG DistroVersion);
245
246 /// <summary>
247 /// Wipes out the directory with the given path if it exists, then creates it again and returns
248 /// an open directory handle onto it.
249 /// </summary>
250 wil::unique_hfile WipeAndOpenDirectory(_In_ LPCWSTR pPath);
251
252 } // namespace wsl::windows::common::filesystem