Skip to main content

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, Permissions};
8use crate::io::BorrowedCursor;
9use crate::path::Path;
10use crate::sealed::Sealed;
11use crate::sys::{AsInner, AsInnerMut, FromInner, 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::Permissions`]. This extension trait
372/// provides extra utilities to shows what Windows file attributes are enabled
373/// in [`Permissions`] and to manually set file attributes on [`Permissions`].
374///
375/// See Microsoft's [`File Attribute Constants`] page to know what file
376/// attribute metadata are defined and stored on Windows files.
377///
378/// [`Permissions`]: fs::Permissions
379/// [`File Attribute Constants`]:
380///     https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants
381///
382/// # Example
383///
384/// ```no_run
385/// #![feature(windows_permissions_ext)]
386/// use std::fs::Permissions;
387/// use std::os::windows::fs::PermissionsExt;
388///
389/// const FILE_ATTRIBUTE_SYSTEM: u32 = 0x4;
390/// const FILE_ATTRIBUTE_ARCHIVE: u32 = 0x20;
391/// let my_file_attr = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE;
392/// let mut permissions = Permissions::from_file_attributes(my_file_attr);
393/// assert_eq!(permissions.file_attributes(), my_file_attr);
394///
395/// const FILE_ATTRIBUTE_HIDDEN: u32 = 0x2;
396/// let new_file_attr = permissions.file_attributes() | FILE_ATTRIBUTE_HIDDEN;
397/// permissions.set_file_attributes(new_file_attr);
398/// assert_eq!(permissions.file_attributes(), new_file_attr);
399/// ```
400#[unstable(feature = "windows_permissions_ext", issue = "152956")]
401pub trait PermissionsExt: Sealed {
402    /// Returns the file attribute bits.
403    #[unstable(feature = "windows_permissions_ext", issue = "152956")]
404    fn file_attributes(&self) -> u32;
405
406    /// Sets the file attribute bits.
407    #[unstable(feature = "windows_permissions_ext", issue = "152956")]
408    fn set_file_attributes(&mut self, mask: u32);
409
410    /// Creates a new instance from the given file attribute bits.
411    #[unstable(feature = "windows_permissions_ext", issue = "152956")]
412    fn from_file_attributes(mask: u32) -> Self;
413}
414
415#[unstable(feature = "windows_permissions_ext", issue = "152956")]
416impl Sealed for fs::Permissions {}
417
418#[unstable(feature = "windows_permissions_ext", issue = "152956")]
419impl PermissionsExt for fs::Permissions {
420    fn file_attributes(&self) -> u32 {
421        self.as_inner().file_attributes()
422    }
423
424    fn set_file_attributes(&mut self, mask: u32) {
425        *self = Permissions::from_inner(FromInner::from_inner(mask));
426    }
427
428    fn from_file_attributes(mask: u32) -> Self {
429        Permissions::from_inner(FromInner::from_inner(mask))
430    }
431}
432
433/// Windows-specific extensions to [`fs::Metadata`].
434///
435/// The data members that this trait exposes correspond to the members
436/// of the [`BY_HANDLE_FILE_INFORMATION`] structure.
437///
438/// [`BY_HANDLE_FILE_INFORMATION`]:
439///     https://docs.microsoft.com/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information
440#[stable(feature = "metadata_ext", since = "1.1.0")]
441pub trait MetadataExt {
442    /// Returns the value of the `dwFileAttributes` field of this metadata.
443    ///
444    /// This field contains the file system attribute information for a file
445    /// or directory. For possible values and their descriptions, see
446    /// [File Attribute Constants] in the Windows Dev Center.
447    ///
448    /// # Examples
449    ///
450    /// ```no_run
451    /// use std::io;
452    /// use std::fs;
453    /// use std::os::windows::prelude::*;
454    ///
455    /// fn main() -> io::Result<()> {
456    ///     let metadata = fs::metadata("foo.txt")?;
457    ///     let attributes = metadata.file_attributes();
458    ///     Ok(())
459    /// }
460    /// ```
461    ///
462    /// [File Attribute Constants]:
463    ///     https://docs.microsoft.com/windows/win32/fileio/file-attribute-constants
464    #[stable(feature = "metadata_ext", since = "1.1.0")]
465    fn file_attributes(&self) -> u32;
466
467    /// Returns the value of the `ftCreationTime` field of this metadata.
468    ///
469    /// The returned 64-bit value is equivalent to a [`FILETIME`] struct,
470    /// which represents the number of 100-nanosecond intervals since
471    /// January 1, 1601 (UTC). The struct is automatically
472    /// converted to a `u64` value, as that is the recommended way
473    /// to use it.
474    ///
475    /// If the underlying filesystem does not support creation time, the
476    /// returned value is 0.
477    ///
478    /// # Examples
479    ///
480    /// ```no_run
481    /// use std::io;
482    /// use std::fs;
483    /// use std::os::windows::prelude::*;
484    ///
485    /// fn main() -> io::Result<()> {
486    ///     let metadata = fs::metadata("foo.txt")?;
487    ///     let creation_time = metadata.creation_time();
488    ///     Ok(())
489    /// }
490    /// ```
491    ///
492    /// [`FILETIME`]: https://docs.microsoft.com/windows/win32/api/minwinbase/ns-minwinbase-filetime
493    #[stable(feature = "metadata_ext", since = "1.1.0")]
494    fn creation_time(&self) -> u64;
495
496    /// Returns the value of the `ftLastAccessTime` field of this metadata.
497    ///
498    /// The returned 64-bit value is equivalent to a [`FILETIME`] struct,
499    /// which represents the number of 100-nanosecond intervals since
500    /// January 1, 1601 (UTC). The struct is automatically
501    /// converted to a `u64` value, as that is the recommended way
502    /// to use it.
503    ///
504    /// For a file, the value specifies the last time that a file was read
505    /// from or written to. For a directory, the value specifies when
506    /// the directory was created. For both files and directories, the
507    /// specified date is correct, but the time of day is always set to
508    /// midnight.
509    ///
510    /// If the underlying filesystem does not support last access time, the
511    /// returned value is 0.
512    ///
513    /// # Examples
514    ///
515    /// ```no_run
516    /// use std::io;
517    /// use std::fs;
518    /// use std::os::windows::prelude::*;
519    ///
520    /// fn main() -> io::Result<()> {
521    ///     let metadata = fs::metadata("foo.txt")?;
522    ///     let last_access_time = metadata.last_access_time();
523    ///     Ok(())
524    /// }
525    /// ```
526    ///
527    /// [`FILETIME`]: https://docs.microsoft.com/windows/win32/api/minwinbase/ns-minwinbase-filetime
528    #[stable(feature = "metadata_ext", since = "1.1.0")]
529    fn last_access_time(&self) -> u64;
530
531    /// Returns the value of the `ftLastWriteTime` field of this metadata.
532    ///
533    /// The returned 64-bit value is equivalent to a [`FILETIME`] struct,
534    /// which represents the number of 100-nanosecond intervals since
535    /// January 1, 1601 (UTC). The struct is automatically
536    /// converted to a `u64` value, as that is the recommended way
537    /// to use it.
538    ///
539    /// For a file, the value specifies the last time that a file was written
540    /// to. For a directory, the structure specifies when the directory was
541    /// created.
542    ///
543    /// If the underlying filesystem does not support the last write time,
544    /// the returned value is 0.
545    ///
546    /// # Examples
547    ///
548    /// ```no_run
549    /// use std::io;
550    /// use std::fs;
551    /// use std::os::windows::prelude::*;
552    ///
553    /// fn main() -> io::Result<()> {
554    ///     let metadata = fs::metadata("foo.txt")?;
555    ///     let last_write_time = metadata.last_write_time();
556    ///     Ok(())
557    /// }
558    /// ```
559    ///
560    /// [`FILETIME`]: https://docs.microsoft.com/windows/win32/api/minwinbase/ns-minwinbase-filetime
561    #[stable(feature = "metadata_ext", since = "1.1.0")]
562    fn last_write_time(&self) -> u64;
563
564    /// Returns the value of the `nFileSize` fields of this
565    /// metadata.
566    ///
567    /// The returned value does not have meaning for directories.
568    ///
569    /// # Examples
570    ///
571    /// ```no_run
572    /// use std::io;
573    /// use std::fs;
574    /// use std::os::windows::prelude::*;
575    ///
576    /// fn main() -> io::Result<()> {
577    ///     let metadata = fs::metadata("foo.txt")?;
578    ///     let file_size = metadata.file_size();
579    ///     Ok(())
580    /// }
581    /// ```
582    #[stable(feature = "metadata_ext", since = "1.1.0")]
583    fn file_size(&self) -> u64;
584
585    /// Returns the value of the `dwVolumeSerialNumber` field of this
586    /// metadata.
587    ///
588    /// This will return `None` if the `Metadata` instance was created from a
589    /// call to `DirEntry::metadata`. If this `Metadata` was created by using
590    /// `fs::metadata` or `File::metadata`, then this will return `Some`.
591    #[unstable(feature = "windows_by_handle", issue = "63010")]
592    fn volume_serial_number(&self) -> Option<u32>;
593
594    /// Returns the value of the `nNumberOfLinks` field of this
595    /// metadata.
596    ///
597    /// This will return `None` if the `Metadata` instance was created from a
598    /// call to `DirEntry::metadata`. If this `Metadata` was created by using
599    /// `fs::metadata` or `File::metadata`, then this will return `Some`.
600    #[unstable(feature = "windows_by_handle", issue = "63010")]
601    fn number_of_links(&self) -> Option<u32>;
602
603    /// Returns the value of the `nFileIndex` fields of this
604    /// metadata.
605    ///
606    /// This will return `None` if the `Metadata` instance was created from a
607    /// call to `DirEntry::metadata`. If this `Metadata` was created by using
608    /// `fs::metadata` or `File::metadata`, then this will return `Some`.
609    #[unstable(feature = "windows_by_handle", issue = "63010")]
610    fn file_index(&self) -> Option<u64>;
611
612    /// Returns the value of the `ChangeTime` fields of this metadata.
613    ///
614    /// `ChangeTime` is the last time file metadata was changed, such as
615    /// renames, attributes, etc.
616    ///
617    /// This will return `None` if `Metadata` instance was created from a call to
618    /// `DirEntry::metadata` or if the `target_vendor` is outside the current platform
619    /// support for this api.
620    #[unstable(feature = "windows_change_time", issue = "121478")]
621    fn change_time(&self) -> Option<u64>;
622}
623
624#[stable(feature = "metadata_ext", since = "1.1.0")]
625impl MetadataExt for Metadata {
626    fn file_attributes(&self) -> u32 {
627        self.as_inner().attrs()
628    }
629    fn creation_time(&self) -> u64 {
630        self.as_inner().created_u64()
631    }
632    fn last_access_time(&self) -> u64 {
633        self.as_inner().accessed_u64()
634    }
635    fn last_write_time(&self) -> u64 {
636        self.as_inner().modified_u64()
637    }
638    fn file_size(&self) -> u64 {
639        self.as_inner().size()
640    }
641    fn volume_serial_number(&self) -> Option<u32> {
642        self.as_inner().volume_serial_number()
643    }
644    fn number_of_links(&self) -> Option<u32> {
645        self.as_inner().number_of_links()
646    }
647    fn file_index(&self) -> Option<u64> {
648        self.as_inner().file_index()
649    }
650    fn change_time(&self) -> Option<u64> {
651        self.as_inner().changed_u64()
652    }
653}
654
655/// Windows-specific extensions to [`fs::FileType`].
656///
657/// On Windows, a symbolic link knows whether it is a file or directory.
658#[stable(feature = "windows_file_type_ext", since = "1.64.0")]
659pub trait FileTypeExt: Sealed {
660    /// Returns `true` if this file type is a symbolic link that is also a directory.
661    #[stable(feature = "windows_file_type_ext", since = "1.64.0")]
662    fn is_symlink_dir(&self) -> bool;
663    /// Returns `true` if this file type is a symbolic link that is also a file.
664    #[stable(feature = "windows_file_type_ext", since = "1.64.0")]
665    fn is_symlink_file(&self) -> bool;
666}
667
668#[stable(feature = "windows_file_type_ext", since = "1.64.0")]
669impl Sealed for fs::FileType {}
670
671#[stable(feature = "windows_file_type_ext", since = "1.64.0")]
672impl FileTypeExt for fs::FileType {
673    fn is_symlink_dir(&self) -> bool {
674        self.as_inner().is_symlink_dir()
675    }
676    fn is_symlink_file(&self) -> bool {
677        self.as_inner().is_symlink_file()
678    }
679}
680
681/// Windows-specific extensions to [`fs::FileTimes`].
682#[stable(feature = "file_set_times", since = "1.75.0")]
683pub trait FileTimesExt: Sealed {
684    /// Set the creation time of a file.
685    #[stable(feature = "file_set_times", since = "1.75.0")]
686    fn set_created(self, t: SystemTime) -> Self;
687}
688
689#[stable(feature = "file_set_times", since = "1.75.0")]
690impl FileTimesExt for fs::FileTimes {
691    fn set_created(mut self, t: SystemTime) -> Self {
692        self.as_inner_mut().set_created(t.into_inner());
693        self
694    }
695}
696
697/// Creates a new symlink to a non-directory file on the filesystem.
698///
699/// The `link` path will be a file symbolic link pointing to the `original`
700/// path.
701///
702/// The `original` path should not be a directory or a symlink to a directory,
703/// otherwise the symlink will be broken. Use [`symlink_dir`] for directories.
704///
705/// This function currently corresponds to [`CreateSymbolicLinkW`][CreateSymbolicLinkW].
706/// Note that this [may change in the future][changes].
707///
708/// [CreateSymbolicLinkW]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw
709/// [changes]: io#platform-specific-behavior
710///
711/// # Examples
712///
713/// ```no_run
714/// use std::os::windows::fs;
715///
716/// fn main() -> std::io::Result<()> {
717///     fs::symlink_file("a.txt", "b.txt")?;
718///     Ok(())
719/// }
720/// ```
721///
722/// # Limitations
723///
724/// Windows treats symlink creation as a [privileged action][symlink-security],
725/// therefore this function is likely to fail unless the user makes changes to
726/// their system to permit symlink creation. Users can try enabling Developer
727/// Mode, granting the `SeCreateSymbolicLinkPrivilege` privilege, or running
728/// the process as an administrator.
729///
730/// [symlink-security]: https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links
731#[stable(feature = "symlink", since = "1.1.0")]
732pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
733    sys::fs::symlink_inner(original.as_ref(), link.as_ref(), false)
734}
735
736/// Creates a new symlink to a directory on the filesystem.
737///
738/// The `link` path will be a directory symbolic link pointing to the `original`
739/// path.
740///
741/// The `original` path must be a directory or a symlink to a directory,
742/// otherwise the symlink will be broken. Use [`symlink_file`] for other files.
743///
744/// This function currently corresponds to [`CreateSymbolicLinkW`][CreateSymbolicLinkW].
745/// Note that this [may change in the future][changes].
746///
747/// [CreateSymbolicLinkW]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw
748/// [changes]: io#platform-specific-behavior
749///
750/// # Examples
751///
752/// ```no_run
753/// use std::os::windows::fs;
754///
755/// fn main() -> std::io::Result<()> {
756///     fs::symlink_dir("a", "b")?;
757///     Ok(())
758/// }
759/// ```
760///
761/// # Limitations
762///
763/// Windows treats symlink creation as a [privileged action][symlink-security],
764/// therefore this function is likely to fail unless the user makes changes to
765/// their system to permit symlink creation. Users can try enabling Developer
766/// Mode, granting the `SeCreateSymbolicLinkPrivilege` privilege, or running
767/// the process as an administrator.
768///
769/// [symlink-security]: https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links
770#[stable(feature = "symlink", since = "1.1.0")]
771pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
772    sys::fs::symlink_inner(original.as_ref(), link.as_ref(), true)
773}
774
775/// Creates a junction point.
776///
777/// The `link` path will be a directory junction pointing to the original path.
778/// If `link` is a relative path then it will be made absolute prior to creating the junction point.
779/// The `original` path must be a directory or a link to a directory, otherwise the junction point will be broken.
780///
781/// If either path is not a local file path then this will fail.
782#[unstable(feature = "junction_point", issue = "121709")]
783pub fn junction_point<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
784    sys::fs::junction_point(original.as_ref(), link.as_ref())
785}