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