std/os/windows/fs.rs
1//! Windows-specific extensions to primitives in the [`std::fs`] module.
2//!
3//! [`std::fs`]: crate::fs
4
5#![stable(feature = "rust1", since = "1.0.0")]
6
7use crate::fs::{self, Metadata, OpenOptions};
8use crate::path::Path;
9use crate::sealed::Sealed;
10use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
11use crate::time::SystemTime;
12use crate::{io, sys};
13
14/// Windows-specific extensions to [`fs::File`].
15#[stable(feature = "file_offset", since = "1.15.0")]
16pub trait FileExt {
17 /// Seeks to a given position and reads a number of bytes.
18 ///
19 /// Returns the number of bytes read.
20 ///
21 /// The offset is relative to the start of the file and thus independent
22 /// from the current cursor. The current cursor **is** affected by this
23 /// function, it is set to the end of the read.
24 ///
25 /// Reading beyond the end of the file will always return with a length of
26 /// 0\.
27 ///
28 /// Note that similar to `File::read`, it is not an error to return with a
29 /// short read. When returning from such a short read, the file pointer is
30 /// still updated.
31 ///
32 /// # Examples
33 ///
34 /// ```no_run
35 /// use std::io;
36 /// use std::fs::File;
37 /// use std::os::windows::prelude::*;
38 ///
39 /// fn main() -> io::Result<()> {
40 /// let mut file = File::open("foo.txt")?;
41 /// let mut buffer = [0; 10];
42 ///
43 /// // Read 10 bytes, starting 72 bytes from the
44 /// // start of the file.
45 /// file.seek_read(&mut buffer[..], 72)?;
46 /// Ok(())
47 /// }
48 /// ```
49 #[stable(feature = "file_offset", since = "1.15.0")]
50 fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
51
52 /// Seeks to a given position and writes a number of bytes.
53 ///
54 /// Returns the number of bytes written.
55 ///
56 /// The offset is relative to the start of the file and thus independent
57 /// from the current cursor. The current cursor **is** affected by this
58 /// function, it is set to the end of the write.
59 ///
60 /// When writing beyond the end of the file, the file is appropriately
61 /// extended and the intermediate bytes are set to zero.
62 ///
63 /// Note that similar to `File::write`, it is not an error to return a
64 /// short write. When returning from such a short write, the file pointer
65 /// is still updated.
66 ///
67 /// # Examples
68 ///
69 /// ```no_run
70 /// use std::fs::File;
71 /// use std::os::windows::prelude::*;
72 ///
73 /// fn main() -> std::io::Result<()> {
74 /// let mut buffer = File::create("foo.txt")?;
75 ///
76 /// // Write a byte string starting 72 bytes from
77 /// // the start of the file.
78 /// buffer.seek_write(b"some bytes", 72)?;
79 /// Ok(())
80 /// }
81 /// ```
82 #[stable(feature = "file_offset", since = "1.15.0")]
83 fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
84}
85
86#[stable(feature = "file_offset", since = "1.15.0")]
87impl FileExt for fs::File {
88 fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
89 self.as_inner().read_at(buf, offset)
90 }
91
92 fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
93 self.as_inner().write_at(buf, offset)
94 }
95}
96
97/// Windows-specific extensions to [`fs::OpenOptions`].
98#[stable(feature = "open_options_ext", since = "1.10.0")]
99pub trait OpenOptionsExt {
100 /// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`]
101 /// with the specified value.
102 ///
103 /// This will override the `read`, `write`, and `append` flags on the
104 /// `OpenOptions` structure. This method provides fine-grained control over
105 /// the permissions to read, write and append data, attributes (like hidden
106 /// and system), and extended attributes.
107 ///
108 /// # Examples
109 ///
110 /// ```no_run
111 /// use std::fs::OpenOptions;
112 /// use std::os::windows::prelude::*;
113 ///
114 /// // Open without read and write permission, for example if you only need
115 /// // to call `stat` on the file
116 /// let file = OpenOptions::new().access_mode(0).open("foo.txt");
117 /// ```
118 ///
119 /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
120 #[stable(feature = "open_options_ext", since = "1.10.0")]
121 fn access_mode(&mut self, access: u32) -> &mut Self;
122
123 /// Overrides the `dwShareMode` argument to the call to [`CreateFile`] with
124 /// the specified value.
125 ///
126 /// By default `share_mode` is set to
127 /// `FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE`. This allows
128 /// other processes to read, write, and delete/rename the same file
129 /// while it is open. Removing any of the flags will prevent other
130 /// processes from performing the corresponding operation until the file
131 /// handle is closed.
132 ///
133 /// # Examples
134 ///
135 /// ```no_run
136 /// use std::fs::OpenOptions;
137 /// use std::os::windows::prelude::*;
138 ///
139 /// // Do not allow others to read or modify this file while we have it open
140 /// // for writing.
141 /// let file = OpenOptions::new()
142 /// .write(true)
143 /// .share_mode(0)
144 /// .open("foo.txt");
145 /// ```
146 ///
147 /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
148 #[stable(feature = "open_options_ext", since = "1.10.0")]
149 fn share_mode(&mut self, val: u32) -> &mut Self;
150
151 /// Sets extra flags for the `dwFileFlags` argument to the call to
152 /// [`CreateFile2`] to the specified value (or combines it with
153 /// `attributes` and `security_qos_flags` to set the `dwFlagsAndAttributes`
154 /// for [`CreateFile`]).
155 ///
156 /// Custom flags can only set flags, not remove flags set by Rust's options.
157 /// This option overwrites any previously set custom flags.
158 ///
159 /// # Examples
160 ///
161 /// ```no_run
162 /// # #![allow(unexpected_cfgs)]
163 /// # #[cfg(for_demonstration_only)]
164 /// extern crate winapi;
165 /// # mod winapi { pub const FILE_FLAG_DELETE_ON_CLOSE: u32 = 0x04000000; }
166 ///
167 /// use std::fs::OpenOptions;
168 /// use std::os::windows::prelude::*;
169 ///
170 /// let file = OpenOptions::new()
171 /// .create(true)
172 /// .write(true)
173 /// .custom_flags(winapi::FILE_FLAG_DELETE_ON_CLOSE)
174 /// .open("foo.txt");
175 /// ```
176 ///
177 /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
178 /// [`CreateFile2`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2
179 #[stable(feature = "open_options_ext", since = "1.10.0")]
180 fn custom_flags(&mut self, flags: u32) -> &mut Self;
181
182 /// Sets the `dwFileAttributes` argument to the call to [`CreateFile2`] to
183 /// the specified value (or combines it with `custom_flags` and
184 /// `security_qos_flags` to set the `dwFlagsAndAttributes` for
185 /// [`CreateFile`]).
186 ///
187 /// If a _new_ file is created because it does not yet exist and
188 /// `.create(true)` or `.create_new(true)` are specified, the new file is
189 /// given the attributes declared with `.attributes()`.
190 ///
191 /// If an _existing_ file is opened with `.create(true).truncate(true)`, its
192 /// existing attributes are preserved and combined with the ones declared
193 /// with `.attributes()`.
194 ///
195 /// In all other cases the attributes get ignored.
196 ///
197 /// # Examples
198 ///
199 /// ```no_run
200 /// # #![allow(unexpected_cfgs)]
201 /// # #[cfg(for_demonstration_only)]
202 /// extern crate winapi;
203 /// # mod winapi { pub const FILE_ATTRIBUTE_HIDDEN: u32 = 2; }
204 ///
205 /// use std::fs::OpenOptions;
206 /// use std::os::windows::prelude::*;
207 ///
208 /// let file = OpenOptions::new()
209 /// .write(true)
210 /// .create(true)
211 /// .attributes(winapi::FILE_ATTRIBUTE_HIDDEN)
212 /// .open("foo.txt");
213 /// ```
214 ///
215 /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
216 /// [`CreateFile2`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2
217 #[stable(feature = "open_options_ext", since = "1.10.0")]
218 fn attributes(&mut self, val: u32) -> &mut Self;
219
220 /// Sets the `dwSecurityQosFlags` argument to the call to [`CreateFile2`] to
221 /// the specified value (or combines it with `custom_flags` and `attributes`
222 /// to set the `dwFlagsAndAttributes` for [`CreateFile`]).
223 ///
224 /// By default `security_qos_flags` is not set. It should be specified when
225 /// opening a named pipe, to control to which degree a server process can
226 /// act on behalf of a client process (security impersonation level).
227 ///
228 /// When `security_qos_flags` is not set, a malicious program can gain the
229 /// elevated privileges of a privileged Rust process when it allows opening
230 /// user-specified paths, by tricking it into opening a named pipe. So
231 /// arguably `security_qos_flags` should also be set when opening arbitrary
232 /// paths. However the bits can then conflict with other flags, specifically
233 /// `FILE_FLAG_OPEN_NO_RECALL`.
234 ///
235 /// For information about possible values, see [Impersonation Levels] on the
236 /// Windows Dev Center site. The `SECURITY_SQOS_PRESENT` flag is set
237 /// automatically when using this method.
238
239 /// # Examples
240 ///
241 /// ```no_run
242 /// # #![allow(unexpected_cfgs)]
243 /// # #[cfg(for_demonstration_only)]
244 /// extern crate winapi;
245 /// # mod winapi { pub const SECURITY_IDENTIFICATION: u32 = 0; }
246 /// use std::fs::OpenOptions;
247 /// use std::os::windows::prelude::*;
248 ///
249 /// let file = OpenOptions::new()
250 /// .write(true)
251 /// .create(true)
252 ///
253 /// // Sets the flag value to `SecurityIdentification`.
254 /// .security_qos_flags(winapi::SECURITY_IDENTIFICATION)
255 ///
256 /// .open(r"\\.\pipe\MyPipe");
257 /// ```
258 ///
259 /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
260 /// [`CreateFile2`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2
261 /// [Impersonation Levels]:
262 /// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-security_impersonation_level
263 #[stable(feature = "open_options_ext", since = "1.10.0")]
264 fn security_qos_flags(&mut self, flags: u32) -> &mut Self;
265}
266
267#[stable(feature = "open_options_ext", since = "1.10.0")]
268impl OpenOptionsExt for OpenOptions {
269 fn access_mode(&mut self, access: u32) -> &mut OpenOptions {
270 self.as_inner_mut().access_mode(access);
271 self
272 }
273
274 fn share_mode(&mut self, share: u32) -> &mut OpenOptions {
275 self.as_inner_mut().share_mode(share);
276 self
277 }
278
279 fn custom_flags(&mut self, flags: u32) -> &mut OpenOptions {
280 self.as_inner_mut().custom_flags(flags);
281 self
282 }
283
284 fn attributes(&mut self, attributes: u32) -> &mut OpenOptions {
285 self.as_inner_mut().attributes(attributes);
286 self
287 }
288
289 fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions {
290 self.as_inner_mut().security_qos_flags(flags);
291 self
292 }
293}
294
295/// Windows-specific extensions to [`fs::Metadata`].
296///
297/// The data members that this trait exposes correspond to the members
298/// of the [`BY_HANDLE_FILE_INFORMATION`] structure.
299///
300/// [`BY_HANDLE_FILE_INFORMATION`]:
301/// https://docs.microsoft.com/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information
302#[stable(feature = "metadata_ext", since = "1.1.0")]
303pub trait MetadataExt {
304 /// Returns the value of the `dwFileAttributes` field of this metadata.
305 ///
306 /// This field contains the file system attribute information for a file
307 /// or directory. For possible values and their descriptions, see
308 /// [File Attribute Constants] in the Windows Dev Center.
309 ///
310 /// # Examples
311 ///
312 /// ```no_run
313 /// use std::io;
314 /// use std::fs;
315 /// use std::os::windows::prelude::*;
316 ///
317 /// fn main() -> io::Result<()> {
318 /// let metadata = fs::metadata("foo.txt")?;
319 /// let attributes = metadata.file_attributes();
320 /// Ok(())
321 /// }
322 /// ```
323 ///
324 /// [File Attribute Constants]:
325 /// https://docs.microsoft.com/windows/win32/fileio/file-attribute-constants
326 #[stable(feature = "metadata_ext", since = "1.1.0")]
327 fn file_attributes(&self) -> u32;
328
329 /// Returns the value of the `ftCreationTime` field of this metadata.
330 ///
331 /// The returned 64-bit value is equivalent to a [`FILETIME`] struct,
332 /// which represents the number of 100-nanosecond intervals since
333 /// January 1, 1601 (UTC). The struct is automatically
334 /// converted to a `u64` value, as that is the recommended way
335 /// to use it.
336 ///
337 /// If the underlying filesystem does not support creation time, the
338 /// returned value is 0.
339 ///
340 /// # Examples
341 ///
342 /// ```no_run
343 /// use std::io;
344 /// use std::fs;
345 /// use std::os::windows::prelude::*;
346 ///
347 /// fn main() -> io::Result<()> {
348 /// let metadata = fs::metadata("foo.txt")?;
349 /// let creation_time = metadata.creation_time();
350 /// Ok(())
351 /// }
352 /// ```
353 ///
354 /// [`FILETIME`]: https://docs.microsoft.com/windows/win32/api/minwinbase/ns-minwinbase-filetime
355 #[stable(feature = "metadata_ext", since = "1.1.0")]
356 fn creation_time(&self) -> u64;
357
358 /// Returns the value of the `ftLastAccessTime` field of this metadata.
359 ///
360 /// The returned 64-bit value is equivalent to a [`FILETIME`] struct,
361 /// which represents the number of 100-nanosecond intervals since
362 /// January 1, 1601 (UTC). The struct is automatically
363 /// converted to a `u64` value, as that is the recommended way
364 /// to use it.
365 ///
366 /// For a file, the value specifies the last time that a file was read
367 /// from or written to. For a directory, the value specifies when
368 /// the directory was created. For both files and directories, the
369 /// specified date is correct, but the time of day is always set to
370 /// midnight.
371 ///
372 /// If the underlying filesystem does not support last access time, the
373 /// returned value is 0.
374 ///
375 /// # Examples
376 ///
377 /// ```no_run
378 /// use std::io;
379 /// use std::fs;
380 /// use std::os::windows::prelude::*;
381 ///
382 /// fn main() -> io::Result<()> {
383 /// let metadata = fs::metadata("foo.txt")?;
384 /// let last_access_time = metadata.last_access_time();
385 /// Ok(())
386 /// }
387 /// ```
388 ///
389 /// [`FILETIME`]: https://docs.microsoft.com/windows/win32/api/minwinbase/ns-minwinbase-filetime
390 #[stable(feature = "metadata_ext", since = "1.1.0")]
391 fn last_access_time(&self) -> u64;
392
393 /// Returns the value of the `ftLastWriteTime` field of this metadata.
394 ///
395 /// The returned 64-bit value is equivalent to a [`FILETIME`] struct,
396 /// which represents the number of 100-nanosecond intervals since
397 /// January 1, 1601 (UTC). The struct is automatically
398 /// converted to a `u64` value, as that is the recommended way
399 /// to use it.
400 ///
401 /// For a file, the value specifies the last time that a file was written
402 /// to. For a directory, the structure specifies when the directory was
403 /// created.
404 ///
405 /// If the underlying filesystem does not support the last write time,
406 /// the returned value is 0.
407 ///
408 /// # Examples
409 ///
410 /// ```no_run
411 /// use std::io;
412 /// use std::fs;
413 /// use std::os::windows::prelude::*;
414 ///
415 /// fn main() -> io::Result<()> {
416 /// let metadata = fs::metadata("foo.txt")?;
417 /// let last_write_time = metadata.last_write_time();
418 /// Ok(())
419 /// }
420 /// ```
421 ///
422 /// [`FILETIME`]: https://docs.microsoft.com/windows/win32/api/minwinbase/ns-minwinbase-filetime
423 #[stable(feature = "metadata_ext", since = "1.1.0")]
424 fn last_write_time(&self) -> u64;
425
426 /// Returns the value of the `nFileSize` fields of this
427 /// metadata.
428 ///
429 /// The returned value does not have meaning for directories.
430 ///
431 /// # Examples
432 ///
433 /// ```no_run
434 /// use std::io;
435 /// use std::fs;
436 /// use std::os::windows::prelude::*;
437 ///
438 /// fn main() -> io::Result<()> {
439 /// let metadata = fs::metadata("foo.txt")?;
440 /// let file_size = metadata.file_size();
441 /// Ok(())
442 /// }
443 /// ```
444 #[stable(feature = "metadata_ext", since = "1.1.0")]
445 fn file_size(&self) -> u64;
446
447 /// Returns the value of the `dwVolumeSerialNumber` field of this
448 /// metadata.
449 ///
450 /// This will return `None` if the `Metadata` instance was created from a
451 /// call to `DirEntry::metadata`. If this `Metadata` was created by using
452 /// `fs::metadata` or `File::metadata`, then this will return `Some`.
453 #[unstable(feature = "windows_by_handle", issue = "63010")]
454 fn volume_serial_number(&self) -> Option<u32>;
455
456 /// Returns the value of the `nNumberOfLinks` field of this
457 /// metadata.
458 ///
459 /// This will return `None` if the `Metadata` instance was created from a
460 /// call to `DirEntry::metadata`. If this `Metadata` was created by using
461 /// `fs::metadata` or `File::metadata`, then this will return `Some`.
462 #[unstable(feature = "windows_by_handle", issue = "63010")]
463 fn number_of_links(&self) -> Option<u32>;
464
465 /// Returns the value of the `nFileIndex` fields of this
466 /// metadata.
467 ///
468 /// This will return `None` if the `Metadata` instance was created from a
469 /// call to `DirEntry::metadata`. If this `Metadata` was created by using
470 /// `fs::metadata` or `File::metadata`, then this will return `Some`.
471 #[unstable(feature = "windows_by_handle", issue = "63010")]
472 fn file_index(&self) -> Option<u64>;
473
474 /// Returns the value of the `ChangeTime` fields of this metadata.
475 ///
476 /// `ChangeTime` is the last time file metadata was changed, such as
477 /// renames, attributes, etc.
478 ///
479 /// This will return `None` if `Metadata` instance was created from a call to
480 /// `DirEntry::metadata` or if the `target_vendor` is outside the current platform
481 /// support for this api.
482 #[unstable(feature = "windows_change_time", issue = "121478")]
483 fn change_time(&self) -> Option<u64>;
484}
485
486#[stable(feature = "metadata_ext", since = "1.1.0")]
487impl MetadataExt for Metadata {
488 fn file_attributes(&self) -> u32 {
489 self.as_inner().attrs()
490 }
491 fn creation_time(&self) -> u64 {
492 self.as_inner().created_u64()
493 }
494 fn last_access_time(&self) -> u64 {
495 self.as_inner().accessed_u64()
496 }
497 fn last_write_time(&self) -> u64 {
498 self.as_inner().modified_u64()
499 }
500 fn file_size(&self) -> u64 {
501 self.as_inner().size()
502 }
503 fn volume_serial_number(&self) -> Option<u32> {
504 self.as_inner().volume_serial_number()
505 }
506 fn number_of_links(&self) -> Option<u32> {
507 self.as_inner().number_of_links()
508 }
509 fn file_index(&self) -> Option<u64> {
510 self.as_inner().file_index()
511 }
512 fn change_time(&self) -> Option<u64> {
513 self.as_inner().changed_u64()
514 }
515}
516
517/// Windows-specific extensions to [`fs::FileType`].
518///
519/// On Windows, a symbolic link knows whether it is a file or directory.
520#[stable(feature = "windows_file_type_ext", since = "1.64.0")]
521pub trait FileTypeExt: Sealed {
522 /// Returns `true` if this file type is a symbolic link that is also a directory.
523 #[stable(feature = "windows_file_type_ext", since = "1.64.0")]
524 fn is_symlink_dir(&self) -> bool;
525 /// Returns `true` if this file type is a symbolic link that is also a file.
526 #[stable(feature = "windows_file_type_ext", since = "1.64.0")]
527 fn is_symlink_file(&self) -> bool;
528}
529
530#[stable(feature = "windows_file_type_ext", since = "1.64.0")]
531impl Sealed for fs::FileType {}
532
533#[stable(feature = "windows_file_type_ext", since = "1.64.0")]
534impl FileTypeExt for fs::FileType {
535 fn is_symlink_dir(&self) -> bool {
536 self.as_inner().is_symlink_dir()
537 }
538 fn is_symlink_file(&self) -> bool {
539 self.as_inner().is_symlink_file()
540 }
541}
542
543/// Windows-specific extensions to [`fs::FileTimes`].
544#[stable(feature = "file_set_times", since = "1.75.0")]
545pub trait FileTimesExt: Sealed {
546 /// Set the creation time of a file.
547 #[stable(feature = "file_set_times", since = "1.75.0")]
548 fn set_created(self, t: SystemTime) -> Self;
549}
550
551#[stable(feature = "file_set_times", since = "1.75.0")]
552impl FileTimesExt for fs::FileTimes {
553 fn set_created(mut self, t: SystemTime) -> Self {
554 self.as_inner_mut().set_created(t.into_inner());
555 self
556 }
557}
558
559/// Creates a new symlink to a non-directory file on the filesystem.
560///
561/// The `link` path will be a file symbolic link pointing to the `original`
562/// path.
563///
564/// The `original` path should not be a directory or a symlink to a directory,
565/// otherwise the symlink will be broken. Use [`symlink_dir`] for directories.
566///
567/// This function currently corresponds to [`CreateSymbolicLinkW`][CreateSymbolicLinkW].
568/// Note that this [may change in the future][changes].
569///
570/// [CreateSymbolicLinkW]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw
571/// [changes]: io#platform-specific-behavior
572///
573/// # Examples
574///
575/// ```no_run
576/// use std::os::windows::fs;
577///
578/// fn main() -> std::io::Result<()> {
579/// fs::symlink_file("a.txt", "b.txt")?;
580/// Ok(())
581/// }
582/// ```
583///
584/// # Limitations
585///
586/// Windows treats symlink creation as a [privileged action][symlink-security],
587/// therefore this function is likely to fail unless the user makes changes to
588/// their system to permit symlink creation. Users can try enabling Developer
589/// Mode, granting the `SeCreateSymbolicLinkPrivilege` privilege, or running
590/// the process as an administrator.
591///
592/// [symlink-security]: https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links
593#[stable(feature = "symlink", since = "1.1.0")]
594pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
595 sys::fs::symlink_inner(original.as_ref(), link.as_ref(), false)
596}
597
598/// Creates a new symlink to a directory on the filesystem.
599///
600/// The `link` path will be a directory symbolic link pointing to the `original`
601/// path.
602///
603/// The `original` path must be a directory or a symlink to a directory,
604/// otherwise the symlink will be broken. Use [`symlink_file`] for other files.
605///
606/// This function currently corresponds to [`CreateSymbolicLinkW`][CreateSymbolicLinkW].
607/// Note that this [may change in the future][changes].
608///
609/// [CreateSymbolicLinkW]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw
610/// [changes]: io#platform-specific-behavior
611///
612/// # Examples
613///
614/// ```no_run
615/// use std::os::windows::fs;
616///
617/// fn main() -> std::io::Result<()> {
618/// fs::symlink_dir("a", "b")?;
619/// Ok(())
620/// }
621/// ```
622///
623/// # Limitations
624///
625/// Windows treats symlink creation as a [privileged action][symlink-security],
626/// therefore this function is likely to fail unless the user makes changes to
627/// their system to permit symlink creation. Users can try enabling Developer
628/// Mode, granting the `SeCreateSymbolicLinkPrivilege` privilege, or running
629/// the process as an administrator.
630///
631/// [symlink-security]: https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links
632#[stable(feature = "symlink", since = "1.1.0")]
633pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
634 sys::fs::symlink_inner(original.as_ref(), link.as_ref(), true)
635}
636
637/// Creates a junction point.
638///
639/// The `link` path will be a directory junction pointing to the original path.
640/// If `link` is a relative path then it will be made absolute prior to creating the junction point.
641/// The `original` path must be a directory or a link to a directory, otherwise the junction point will be broken.
642///
643/// If either path is not a local file path then this will fail.
644#[unstable(feature = "junction_point", issue = "121709")]
645pub fn junction_point<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
646 sys::fs::junction_point(original.as_ref(), link.as_ref())
647}