diff --git a/tokio/src/fs/dir_builder.rs b/tokio/src/fs/dir_builder.rs index 8752a3716aa..51207e478bf 100644 --- a/tokio/src/fs/dir_builder.rs +++ b/tokio/src/fs/dir_builder.rs @@ -5,14 +5,10 @@ use std::path::Path; /// A builder for creating directories in various manners. /// -/// Additional Unix-specific options are available via importing the -/// [`DirBuilderExt`] trait. -/// /// This is a specialized version of [`std::fs::DirBuilder`] for usage on /// the Tokio runtime. /// /// [std::fs::DirBuilder]: std::fs::DirBuilder -/// [`DirBuilderExt`]: crate::fs::os::unix::DirBuilderExt #[derive(Debug, Default)] pub struct DirBuilder { /// Indicates whether to create parent directories if they are missing. @@ -115,3 +111,27 @@ impl DirBuilder { asyncify(move || builder.create(path)).await } } + +feature! { + #![unix] + + impl DirBuilder { + /// Sets the mode to create new directories with. + /// + /// This option defaults to 0o777. + /// + /// # Examples + /// + /// + /// ```no_run + /// use tokio::fs::DirBuilder; + /// + /// let mut builder = DirBuilder::new(); + /// builder.mode(0o775); + /// ``` + pub fn mode(&mut self, mode: u32) -> &mut Self { + self.mode = Some(mode); + self + } + } +} diff --git a/tokio/src/fs/mod.rs b/tokio/src/fs/mod.rs index b9b0cd725ce..d4f00749028 100644 --- a/tokio/src/fs/mod.rs +++ b/tokio/src/fs/mod.rs @@ -48,8 +48,6 @@ pub use self::metadata::metadata; mod open_options; pub use self::open_options::OpenOptions; -pub mod os; - mod read; pub use self::read::read; @@ -86,6 +84,23 @@ pub use self::write::write; mod copy; pub use self::copy::copy; +feature! { + #![unix] + + mod symlink; + pub use self::symlink::symlink; +} + +feature! { + #![windows] + + mod symlink_dir; + pub use self::symlink_dir::symlink_dir; + + mod symlink_file; + pub use self::symlink_file::symlink_file; +} + use std::io; pub(crate) async fn asyncify(f: F) -> io::Result diff --git a/tokio/src/fs/open_options.rs b/tokio/src/fs/open_options.rs index acd99a1f9ea..fa37a60dff6 100644 --- a/tokio/src/fs/open_options.rs +++ b/tokio/src/fs/open_options.rs @@ -389,6 +389,262 @@ impl OpenOptions { } } +feature! { + #![unix] + + use std::os::unix::fs::OpenOptionsExt; + + impl OpenOptions { + /// Sets the mode bits that a new file will be created with. + /// + /// If a new file is created as part of an `OpenOptions::open` call then this + /// specified `mode` will be used as the permission bits for the new file. + /// If no `mode` is set, the default of `0o666` will be used. + /// The operating system masks out bits with the system's `umask`, to produce + /// the final permissions. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::fs::OpenOptions; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> io::Result<()> { + /// let mut options = OpenOptions::new(); + /// options.mode(0o644); // Give read/write for owner and read for others. + /// let file = options.open("foo.txt").await?; + /// + /// Ok(()) + /// } + /// ``` + pub fn mode(&mut self, mode: u32) -> &mut OpenOptions { + self.as_inner_mut().mode(mode); + self + } + + /// Pass custom flags to the `flags` argument of `open`. + /// + /// The bits that define the access mode are masked out with `O_ACCMODE`, to + /// ensure they do not interfere with the access mode set by Rusts options. + /// + /// Custom flags can only set flags, not remove flags set by Rusts options. + /// This options overwrites any previously set custom flags. + /// + /// # Examples + /// + /// ```no_run + /// use libc; + /// use tokio::fs::OpenOptions; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> io::Result<()> { + /// let mut options = OpenOptions::new(); + /// options.write(true); + /// if cfg!(unix) { + /// options.custom_flags(libc::O_NOFOLLOW); + /// } + /// let file = options.open("foo.txt").await?; + /// + /// Ok(()) + /// } + /// ``` + pub fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions { + self.as_inner_mut().custom_flags(flags); + self + } + } +} + +feature! { + #![windows] + + use std::os::windows::fs::OpenOptionsExt; + + impl OpenOptions { + /// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`] + /// with the specified value. + /// + /// This will override the `read`, `write`, and `append` flags on the + /// `OpenOptions` structure. This method provides fine-grained control over + /// the permissions to read, write and append data, attributes (like hidden + /// and system), and extended attributes. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::fs::OpenOptions; + /// + /// # #[tokio::main] + /// # async fn main() -> std::io::Result<()> { + /// // Open without read and write permission, for example if you only need + /// // to call `stat` on the file + /// let file = OpenOptions::new().access_mode(0).open("foo.txt").await?; + /// # Ok(()) + /// # } + /// ``` + /// + /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea + pub fn access_mode(&mut self, access: u32) -> &mut OpenOptions { + self.as_inner_mut().access_mode(access); + self + } + + /// Overrides the `dwShareMode` argument to the call to [`CreateFile`] with + /// the specified value. + /// + /// By default `share_mode` is set to + /// `FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE`. This allows + /// other processes to read, write, and delete/rename the same file + /// while it is open. Removing any of the flags will prevent other + /// processes from performing the corresponding operation until the file + /// handle is closed. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::fs::OpenOptions; + /// + /// # #[tokio::main] + /// # async fn main() -> std::io::Result<()> { + /// // Do not allow others to read or modify this file while we have it open + /// // for writing. + /// let file = OpenOptions::new() + /// .write(true) + /// .share_mode(0) + /// .open("foo.txt").await?; + /// # Ok(()) + /// # } + /// ``` + /// + /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea + pub fn share_mode(&mut self, share: u32) -> &mut OpenOptions { + self.as_inner_mut().share_mode(share); + self + } + + /// Sets extra flags for the `dwFileFlags` argument to the call to + /// [`CreateFile2`] to the specified value (or combines it with + /// `attributes` and `security_qos_flags` to set the `dwFlagsAndAttributes` + /// for [`CreateFile`]). + /// + /// Custom flags can only set flags, not remove flags set by Rust's options. + /// This option overwrites any previously set custom flags. + /// + /// # Examples + /// + /// ```no_run + /// use winapi::um::winbase::FILE_FLAG_DELETE_ON_CLOSE; + /// use tokio::fs::OpenOptions; + /// + /// # #[tokio::main] + /// # async fn main() -> std::io::Result<()> { + /// let file = OpenOptions::new() + /// .create(true) + /// .write(true) + /// .custom_flags(FILE_FLAG_DELETE_ON_CLOSE) + /// .open("foo.txt").await?; + /// # Ok(()) + /// # } + /// ``` + /// + /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea + /// [`CreateFile2`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2 + pub fn custom_flags(&mut self, flags: u32) -> &mut OpenOptions { + self.as_inner_mut().custom_flags(flags); + self + } + + /// Sets the `dwFileAttributes` argument to the call to [`CreateFile2`] to + /// the specified value (or combines it with `custom_flags` and + /// `security_qos_flags` to set the `dwFlagsAndAttributes` for + /// [`CreateFile`]). + /// + /// If a _new_ file is created because it does not yet exist and + /// `.create(true)` or `.create_new(true)` are specified, the new file is + /// given the attributes declared with `.attributes()`. + /// + /// If an _existing_ file is opened with `.create(true).truncate(true)`, its + /// existing attributes are preserved and combined with the ones declared + /// with `.attributes()`. + /// + /// In all other cases the attributes get ignored. + /// + /// # Examples + /// + /// ```no_run + /// use winapi::um::winnt::FILE_ATTRIBUTE_HIDDEN; + /// use tokio::fs::OpenOptions; + /// + /// # #[tokio::main] + /// # async fn main() -> std::io::Result<()> { + /// let file = OpenOptions::new() + /// .write(true) + /// .create(true) + /// .attributes(FILE_ATTRIBUTE_HIDDEN) + /// .open("foo.txt").await?; + /// # Ok(()) + /// # } + /// ``` + /// + /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea + /// [`CreateFile2`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2 + pub fn attributes(&mut self, attributes: u32) -> &mut OpenOptions { + self.as_inner_mut().attributes(attributes); + self + } + + /// Sets the `dwSecurityQosFlags` argument to the call to [`CreateFile2`] to + /// the specified value (or combines it with `custom_flags` and `attributes` + /// to set the `dwFlagsAndAttributes` for [`CreateFile`]). + /// + /// By default `security_qos_flags` is not set. It should be specified when + /// opening a named pipe, to control to which degree a server process can + /// act on behalf of a client process (security impersonation level). + /// + /// When `security_qos_flags` is not set, a malicious program can gain the + /// elevated privileges of a privileged Rust process when it allows opening + /// user-specified paths, by tricking it into opening a named pipe. So + /// arguably `security_qos_flags` should also be set when opening arbitrary + /// paths. However the bits can then conflict with other flags, specifically + /// `FILE_FLAG_OPEN_NO_RECALL`. + /// + /// For information about possible values, see [Impersonation Levels] on the + /// Windows Dev Center site. The `SECURITY_SQOS_PRESENT` flag is set + /// automatically when using this method. + /// + /// # Examples + /// + /// ```no_run + /// use winapi::um::winbase::SECURITY_IDENTIFICATION; + /// use tokio::fs::OpenOptions; + /// + /// # #[tokio::main] + /// # async fn main() -> std::io::Result<()> { + /// let file = OpenOptions::new() + /// .write(true) + /// .create(true) + /// + /// // Sets the flag value to `SecurityIdentification`. + /// .security_qos_flags(SECURITY_IDENTIFICATION) + /// + /// .open(r"\\.\pipe\MyPipe").await?; + /// # Ok(()) + /// # } + /// ``` + /// + /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea + /// [`CreateFile2`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2 + /// [Impersonation Levels]: + /// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-security_impersonation_level + pub fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions { + self.as_inner_mut().security_qos_flags(flags); + self + } + } +} + impl From for OpenOptions { fn from(options: std::fs::OpenOptions) -> OpenOptions { OpenOptions(options) diff --git a/tokio/src/fs/os/mod.rs b/tokio/src/fs/os/mod.rs deleted file mode 100644 index f4b8bfb617d..00000000000 --- a/tokio/src/fs/os/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! OS-specific functionality. - -#[cfg(unix)] -pub mod unix; - -#[cfg(windows)] -pub mod windows; diff --git a/tokio/src/fs/os/unix/dir_builder_ext.rs b/tokio/src/fs/os/unix/dir_builder_ext.rs deleted file mode 100644 index ccdc552e6d2..00000000000 --- a/tokio/src/fs/os/unix/dir_builder_ext.rs +++ /dev/null @@ -1,36 +0,0 @@ -use crate::fs::dir_builder::DirBuilder; - -/// Unix-specific extensions to [`DirBuilder`]. -/// -/// [`DirBuilder`]: crate::fs::DirBuilder -pub trait DirBuilderExt: sealed::Sealed { - /// Sets the mode to create new directories with. - /// - /// This option defaults to 0o777. - /// - /// # Examples - /// - /// - /// ```no_run - /// use tokio::fs::DirBuilder; - /// use tokio::fs::os::unix::DirBuilderExt; - /// - /// let mut builder = DirBuilder::new(); - /// builder.mode(0o775); - /// ``` - fn mode(&mut self, mode: u32) -> &mut Self; -} - -impl DirBuilderExt for DirBuilder { - fn mode(&mut self, mode: u32) -> &mut Self { - self.mode = Some(mode); - self - } -} - -impl sealed::Sealed for DirBuilder {} - -pub(crate) mod sealed { - #[doc(hidden)] - pub trait Sealed {} -} diff --git a/tokio/src/fs/os/unix/dir_entry_ext.rs b/tokio/src/fs/os/unix/dir_entry_ext.rs deleted file mode 100644 index 2ac56da2b33..00000000000 --- a/tokio/src/fs/os/unix/dir_entry_ext.rs +++ /dev/null @@ -1,44 +0,0 @@ -use crate::fs::DirEntry; -use std::os::unix::fs::DirEntryExt as _; - -/// Unix-specific extension methods for [`fs::DirEntry`]. -/// -/// This mirrors the definition of [`std::os::unix::fs::DirEntryExt`]. -/// -/// [`fs::DirEntry`]: crate::fs::DirEntry -/// [`std::os::unix::fs::DirEntryExt`]: std::os::unix::fs::DirEntryExt -pub trait DirEntryExt: sealed::Sealed { - /// Returns the underlying `d_ino` field in the contained `dirent` - /// structure. - /// - /// # Examples - /// - /// ``` - /// use tokio::fs; - /// use tokio::fs::os::unix::DirEntryExt; - /// - /// # #[tokio::main] - /// # async fn main() -> std::io::Result<()> { - /// let mut entries = fs::read_dir(".").await?; - /// while let Some(entry) = entries.next_entry().await? { - /// // Here, `entry` is a `DirEntry`. - /// println!("{:?}: {}", entry.file_name(), entry.ino()); - /// } - /// # Ok(()) - /// # } - /// ``` - fn ino(&self) -> u64; -} - -impl DirEntryExt for DirEntry { - fn ino(&self) -> u64 { - self.as_inner().ino() - } -} - -impl sealed::Sealed for DirEntry {} - -pub(crate) mod sealed { - #[doc(hidden)] - pub trait Sealed {} -} diff --git a/tokio/src/fs/os/unix/mod.rs b/tokio/src/fs/os/unix/mod.rs deleted file mode 100644 index a0ae75126df..00000000000 --- a/tokio/src/fs/os/unix/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! Unix-specific extensions to primitives in the `tokio_fs` module. - -mod symlink; -pub use self::symlink::symlink; - -mod open_options_ext; -pub use self::open_options_ext::OpenOptionsExt; - -mod dir_builder_ext; -pub use self::dir_builder_ext::DirBuilderExt; - -mod dir_entry_ext; -pub use self::dir_entry_ext::DirEntryExt; diff --git a/tokio/src/fs/os/unix/open_options_ext.rs b/tokio/src/fs/os/unix/open_options_ext.rs deleted file mode 100644 index 6e0fd2baede..00000000000 --- a/tokio/src/fs/os/unix/open_options_ext.rs +++ /dev/null @@ -1,85 +0,0 @@ -use crate::fs::open_options::OpenOptions; -use std::os::unix::fs::OpenOptionsExt as _; - -/// Unix-specific extensions to [`fs::OpenOptions`]. -/// -/// This mirrors the definition of [`std::os::unix::fs::OpenOptionsExt`]. -/// -/// [`fs::OpenOptions`]: crate::fs::OpenOptions -/// [`std::os::unix::fs::OpenOptionsExt`]: std::os::unix::fs::OpenOptionsExt -pub trait OpenOptionsExt: sealed::Sealed { - /// Sets the mode bits that a new file will be created with. - /// - /// If a new file is created as part of an `OpenOptions::open` call then this - /// specified `mode` will be used as the permission bits for the new file. - /// If no `mode` is set, the default of `0o666` will be used. - /// The operating system masks out bits with the system's `umask`, to produce - /// the final permissions. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::fs::OpenOptions; - /// use tokio::fs::os::unix::OpenOptionsExt; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> io::Result<()> { - /// let mut options = OpenOptions::new(); - /// options.mode(0o644); // Give read/write for owner and read for others. - /// let file = options.open("foo.txt").await?; - /// - /// Ok(()) - /// } - /// ``` - fn mode(&mut self, mode: u32) -> &mut Self; - - /// Pass custom flags to the `flags` argument of `open`. - /// - /// The bits that define the access mode are masked out with `O_ACCMODE`, to - /// ensure they do not interfere with the access mode set by Rusts options. - /// - /// Custom flags can only set flags, not remove flags set by Rusts options. - /// This options overwrites any previously set custom flags. - /// - /// # Examples - /// - /// ```no_run - /// use libc; - /// use tokio::fs::OpenOptions; - /// use tokio::fs::os::unix::OpenOptionsExt; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> io::Result<()> { - /// let mut options = OpenOptions::new(); - /// options.write(true); - /// if cfg!(unix) { - /// options.custom_flags(libc::O_NOFOLLOW); - /// } - /// let file = options.open("foo.txt").await?; - /// - /// Ok(()) - /// } - /// ``` - fn custom_flags(&mut self, flags: i32) -> &mut Self; -} - -impl OpenOptionsExt for OpenOptions { - fn mode(&mut self, mode: u32) -> &mut OpenOptions { - self.as_inner_mut().mode(mode); - self - } - - fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions { - self.as_inner_mut().custom_flags(flags); - self - } -} - -impl sealed::Sealed for OpenOptions {} - -pub(crate) mod sealed { - #[doc(hidden)] - pub trait Sealed {} -} diff --git a/tokio/src/fs/os/windows/mod.rs b/tokio/src/fs/os/windows/mod.rs deleted file mode 100644 index ab98c13cc7d..00000000000 --- a/tokio/src/fs/os/windows/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -//! Windows-specific extensions for the primitives in the `tokio_fs` module. - -mod symlink_dir; -pub use self::symlink_dir::symlink_dir; - -mod symlink_file; -pub use self::symlink_file::symlink_file; - -mod open_options_ext; -pub use self::open_options_ext::OpenOptionsExt; diff --git a/tokio/src/fs/os/windows/open_options_ext.rs b/tokio/src/fs/os/windows/open_options_ext.rs deleted file mode 100644 index ce86fbafbe6..00000000000 --- a/tokio/src/fs/os/windows/open_options_ext.rs +++ /dev/null @@ -1,214 +0,0 @@ -use crate::fs::open_options::OpenOptions; -use std::os::windows::fs::OpenOptionsExt as _; - -/// Unix-specific extensions to [`fs::OpenOptions`]. -/// -/// This mirrors the definition of [`std::os::windows::fs::OpenOptionsExt`]. -/// -/// [`fs::OpenOptions`]: crate::fs::OpenOptions -/// [`std::os::windows::fs::OpenOptionsExt`]: std::os::windows::fs::OpenOptionsExt -pub trait OpenOptionsExt: sealed::Sealed { - /// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`] - /// with the specified value. - /// - /// This will override the `read`, `write`, and `append` flags on the - /// `OpenOptions` structure. This method provides fine-grained control over - /// the permissions to read, write and append data, attributes (like hidden - /// and system), and extended attributes. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::fs::OpenOptions; - /// use tokio::fs::os::windows::OpenOptionsExt; - /// - /// # #[tokio::main] - /// # async fn main() -> std::io::Result<()> { - /// // Open without read and write permission, for example if you only need - /// // to call `stat` on the file - /// let file = OpenOptions::new().access_mode(0).open("foo.txt").await?; - /// # Ok(()) - /// # } - /// ``` - /// - /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea - fn access_mode(&mut self, access: u32) -> &mut Self; - - /// Overrides the `dwShareMode` argument to the call to [`CreateFile`] with - /// the specified value. - /// - /// By default `share_mode` is set to - /// `FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE`. This allows - /// other processes to read, write, and delete/rename the same file - /// while it is open. Removing any of the flags will prevent other - /// processes from performing the corresponding operation until the file - /// handle is closed. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::fs::OpenOptions; - /// use tokio::fs::os::windows::OpenOptionsExt; - /// - /// # #[tokio::main] - /// # async fn main() -> std::io::Result<()> { - /// // Do not allow others to read or modify this file while we have it open - /// // for writing. - /// let file = OpenOptions::new() - /// .write(true) - /// .share_mode(0) - /// .open("foo.txt").await?; - /// # Ok(()) - /// # } - /// ``` - /// - /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea - fn share_mode(&mut self, val: u32) -> &mut Self; - - /// Sets extra flags for the `dwFileFlags` argument to the call to - /// [`CreateFile2`] to the specified value (or combines it with - /// `attributes` and `security_qos_flags` to set the `dwFlagsAndAttributes` - /// for [`CreateFile`]). - /// - /// Custom flags can only set flags, not remove flags set by Rust's options. - /// This option overwrites any previously set custom flags. - /// - /// # Examples - /// - /// ```no_run - /// use winapi::um::winbase::FILE_FLAG_DELETE_ON_CLOSE; - /// use tokio::fs::OpenOptions; - /// use tokio::fs::os::windows::OpenOptionsExt; - /// - /// # #[tokio::main] - /// # async fn main() -> std::io::Result<()> { - /// let file = OpenOptions::new() - /// .create(true) - /// .write(true) - /// .custom_flags(FILE_FLAG_DELETE_ON_CLOSE) - /// .open("foo.txt").await?; - /// # Ok(()) - /// # } - /// ``` - /// - /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea - /// [`CreateFile2`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2 - fn custom_flags(&mut self, flags: u32) -> &mut Self; - - /// Sets the `dwFileAttributes` argument to the call to [`CreateFile2`] to - /// the specified value (or combines it with `custom_flags` and - /// `security_qos_flags` to set the `dwFlagsAndAttributes` for - /// [`CreateFile`]). - /// - /// If a _new_ file is created because it does not yet exist and - /// `.create(true)` or `.create_new(true)` are specified, the new file is - /// given the attributes declared with `.attributes()`. - /// - /// If an _existing_ file is opened with `.create(true).truncate(true)`, its - /// existing attributes are preserved and combined with the ones declared - /// with `.attributes()`. - /// - /// In all other cases the attributes get ignored. - /// - /// # Examples - /// - /// ```no_run - /// use winapi::um::winnt::FILE_ATTRIBUTE_HIDDEN; - /// use tokio::fs::OpenOptions; - /// use tokio::fs::os::windows::OpenOptionsExt; - /// - /// # #[tokio::main] - /// # async fn main() -> std::io::Result<()> { - /// let file = OpenOptions::new() - /// .write(true) - /// .create(true) - /// .attributes(FILE_ATTRIBUTE_HIDDEN) - /// .open("foo.txt").await?; - /// # Ok(()) - /// # } - /// ``` - /// - /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea - /// [`CreateFile2`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2 - fn attributes(&mut self, val: u32) -> &mut Self; - - /// Sets the `dwSecurityQosFlags` argument to the call to [`CreateFile2`] to - /// the specified value (or combines it with `custom_flags` and `attributes` - /// to set the `dwFlagsAndAttributes` for [`CreateFile`]). - /// - /// By default `security_qos_flags` is not set. It should be specified when - /// opening a named pipe, to control to which degree a server process can - /// act on behalf of a client process (security impersonation level). - /// - /// When `security_qos_flags` is not set, a malicious program can gain the - /// elevated privileges of a privileged Rust process when it allows opening - /// user-specified paths, by tricking it into opening a named pipe. So - /// arguably `security_qos_flags` should also be set when opening arbitrary - /// paths. However the bits can then conflict with other flags, specifically - /// `FILE_FLAG_OPEN_NO_RECALL`. - /// - /// For information about possible values, see [Impersonation Levels] on the - /// Windows Dev Center site. The `SECURITY_SQOS_PRESENT` flag is set - /// automatically when using this method. - /// - /// # Examples - /// - /// ```no_run - /// use winapi::um::winbase::SECURITY_IDENTIFICATION; - /// use tokio::fs::OpenOptions; - /// use tokio::fs::os::windows::OpenOptionsExt; - /// - /// # #[tokio::main] - /// # async fn main() -> std::io::Result<()> { - /// let file = OpenOptions::new() - /// .write(true) - /// .create(true) - /// - /// // Sets the flag value to `SecurityIdentification`. - /// .security_qos_flags(SECURITY_IDENTIFICATION) - /// - /// .open(r"\\.\pipe\MyPipe").await?; - /// # Ok(()) - /// # } - /// ``` - /// - /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea - /// [`CreateFile2`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2 - /// [Impersonation Levels]: - /// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-security_impersonation_level - fn security_qos_flags(&mut self, flags: u32) -> &mut Self; -} - -impl OpenOptionsExt for OpenOptions { - fn access_mode(&mut self, access: u32) -> &mut OpenOptions { - self.as_inner_mut().access_mode(access); - self - } - - fn share_mode(&mut self, share: u32) -> &mut OpenOptions { - self.as_inner_mut().share_mode(share); - self - } - - fn custom_flags(&mut self, flags: u32) -> &mut OpenOptions { - self.as_inner_mut().custom_flags(flags); - self - } - - fn attributes(&mut self, attributes: u32) -> &mut OpenOptions { - self.as_inner_mut().attributes(attributes); - self - } - - fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions { - self.as_inner_mut().security_qos_flags(flags); - self - } -} - -impl sealed::Sealed for OpenOptions {} - -pub(crate) mod sealed { - #[doc(hidden)] - pub trait Sealed {} -} diff --git a/tokio/src/fs/read_dir.rs b/tokio/src/fs/read_dir.rs index 8ca583bc2ff..01d1ea8323b 100644 --- a/tokio/src/fs/read_dir.rs +++ b/tokio/src/fs/read_dir.rs @@ -81,6 +81,36 @@ impl ReadDir { } } +feature! { + #![unix] + + use std::os::unix::fs::DirEntryExt; + + impl DirEntry { + /// Returns the underlying `d_ino` field in the contained `dirent` + /// structure. + /// + /// # Examples + /// + /// ``` + /// use tokio::fs; + /// + /// # #[tokio::main] + /// # async fn main() -> std::io::Result<()> { + /// let mut entries = fs::read_dir(".").await?; + /// while let Some(entry) = entries.next_entry().await? { + /// // Here, `entry` is a `DirEntry`. + /// println!("{:?}: {}", entry.file_name(), entry.ino()); + /// } + /// # Ok(()) + /// # } + /// ``` + pub fn ino(&self) -> u64 { + self.as_inner().ino() + } + } +} + #[cfg(feature = "stream")] impl crate::stream::Stream for ReadDir { type Item = io::Result; diff --git a/tokio/src/fs/os/unix/symlink.rs b/tokio/src/fs/symlink.rs similarity index 100% rename from tokio/src/fs/os/unix/symlink.rs rename to tokio/src/fs/symlink.rs diff --git a/tokio/src/fs/os/windows/symlink_dir.rs b/tokio/src/fs/symlink_dir.rs similarity index 100% rename from tokio/src/fs/os/windows/symlink_dir.rs rename to tokio/src/fs/symlink_dir.rs diff --git a/tokio/src/fs/os/windows/symlink_file.rs b/tokio/src/fs/symlink_file.rs similarity index 100% rename from tokio/src/fs/os/windows/symlink_file.rs rename to tokio/src/fs/symlink_file.rs diff --git a/tokio/tests/fs_link.rs b/tokio/tests/fs_link.rs index cbbe27efe42..2ef666fb2f6 100644 --- a/tokio/tests/fs_link.rs +++ b/tokio/tests/fs_link.rs @@ -48,9 +48,7 @@ async fn test_symlink() { let src_2 = src.clone(); let dst_2 = dst.clone(); - assert!(fs::os::unix::symlink(src_2.clone(), dst_2.clone()) - .await - .is_ok()); + assert!(fs::symlink(src_2.clone(), dst_2.clone()).await.is_ok()); let mut content = String::new();