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