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}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy