From ffc20e48de64f73ea57b6b7c121e2b50de30097f Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Thu, 4 Mar 2021 15:15:26 +0100 Subject: Move `std::sys::windows::ext` to `std::os::windows` --- library/std/src/os/mod.rs | 6 +- library/std/src/os/windows/ffi.rs | 134 +++++++ library/std/src/os/windows/fs.rs | 558 +++++++++++++++++++++++++++++ library/std/src/os/windows/io.rs | 234 ++++++++++++ library/std/src/os/windows/mod.rs | 39 ++ library/std/src/os/windows/process.rs | 141 ++++++++ library/std/src/os/windows/raw.rs | 14 + library/std/src/os/windows/thread.rs | 23 ++ library/std/src/sys/mod.rs | 13 +- library/std/src/sys/windows/ext/ffi.rs | 134 ------- library/std/src/sys/windows/ext/fs.rs | 558 ----------------------------- library/std/src/sys/windows/ext/io.rs | 234 ------------ library/std/src/sys/windows/ext/mod.rs | 40 --- library/std/src/sys/windows/ext/process.rs | 141 -------- library/std/src/sys/windows/ext/raw.rs | 14 - library/std/src/sys/windows/ext/thread.rs | 23 -- library/std/src/sys/windows/mod.rs | 1 - 17 files changed, 1148 insertions(+), 1159 deletions(-) create mode 100644 library/std/src/os/windows/ffi.rs create mode 100644 library/std/src/os/windows/fs.rs create mode 100644 library/std/src/os/windows/io.rs create mode 100644 library/std/src/os/windows/mod.rs create mode 100644 library/std/src/os/windows/process.rs create mode 100644 library/std/src/os/windows/raw.rs create mode 100644 library/std/src/os/windows/thread.rs delete mode 100644 library/std/src/sys/windows/ext/ffi.rs delete mode 100644 library/std/src/sys/windows/ext/fs.rs delete mode 100644 library/std/src/sys/windows/ext/io.rs delete mode 100644 library/std/src/sys/windows/ext/mod.rs delete mode 100644 library/std/src/sys/windows/ext/process.rs delete mode 100644 library/std/src/sys/windows/ext/raw.rs delete mode 100644 library/std/src/sys/windows/ext/thread.rs (limited to 'library/std/src') diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index fc684f0912f..85ffe8adb1f 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -23,8 +23,7 @@ cfg_if::cfg_if! { #[stable(feature = "wasi_ext_doc", since = "1.35.0")] pub use crate::sys::wasi_ext as wasi; - #[stable(feature = "rust1", since = "1.0.0")] - pub use crate::sys::windows_ext as windows; + pub mod windows; } else if #[cfg(doc)] { // On certain platforms right now the "main modules" modules that are // documented don't compile (missing things in `libc` which is empty), @@ -94,7 +93,6 @@ cfg_if::cfg_if! { pub mod wasi; #[cfg(windows)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use crate::sys::ext as windows; + pub mod windows; } } diff --git a/library/std/src/os/windows/ffi.rs b/library/std/src/os/windows/ffi.rs new file mode 100644 index 00000000000..c89b9ff1efa --- /dev/null +++ b/library/std/src/os/windows/ffi.rs @@ -0,0 +1,134 @@ +//! Windows-specific extensions to the primitives in the `std::ffi` module. +//! +//! # Overview +//! +//! For historical reasons, the Windows API uses a form of potentially +//! ill-formed UTF-16 encoding for strings. Specifically, the 16-bit +//! code units in Windows strings may contain [isolated surrogate code +//! points which are not paired together][ill-formed-utf-16]. The +//! Unicode standard requires that surrogate code points (those in the +//! range U+D800 to U+DFFF) always be *paired*, because in the UTF-16 +//! encoding a *surrogate code unit pair* is used to encode a single +//! character. For compatibility with code that does not enforce +//! these pairings, Windows does not enforce them, either. +//! +//! While it is not always possible to convert such a string losslessly into +//! a valid UTF-16 string (or even UTF-8), it is often desirable to be +//! able to round-trip such a string from and to Windows APIs +//! losslessly. For example, some Rust code may be "bridging" some +//! Windows APIs together, just passing `WCHAR` strings among those +//! APIs without ever really looking into the strings. +//! +//! If Rust code *does* need to look into those strings, it can +//! convert them to valid UTF-8, possibly lossily, by substituting +//! invalid sequences with [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], as is +//! conventionally done in other Rust APIs that deal with string +//! encodings. +//! +//! # `OsStringExt` and `OsStrExt` +//! +//! [`OsString`] is the Rust wrapper for owned strings in the +//! preferred representation of the operating system. On Windows, +//! this struct gets augmented with an implementation of the +//! [`OsStringExt`] trait, which has a [`OsStringExt::from_wide`] method. This +//! lets you create an [`OsString`] from a `&[u16]` slice; presumably +//! you get such a slice out of a `WCHAR` Windows API. +//! +//! Similarly, [`OsStr`] is the Rust wrapper for borrowed strings from +//! preferred representation of the operating system. On Windows, the +//! [`OsStrExt`] trait provides the [`OsStrExt::encode_wide`] method, which +//! outputs an [`EncodeWide`] iterator. You can [`collect`] this +//! iterator, for example, to obtain a `Vec`; you can later get a +//! pointer to this vector's contents and feed it to Windows APIs. +//! +//! These traits, along with [`OsString`] and [`OsStr`], work in +//! conjunction so that it is possible to **round-trip** strings from +//! Windows and back, with no loss of data, even if the strings are +//! ill-formed UTF-16. +//! +//! [ill-formed-utf-16]: https://simonsapin.github.io/wtf-8/#ill-formed-utf-16 +//! [`collect`]: crate::iter::Iterator::collect +//! [U+FFFD]: crate::char::REPLACEMENT_CHARACTER + +#![stable(feature = "rust1", since = "1.0.0")] + +use crate::ffi::{OsStr, OsString}; +use crate::sealed::Sealed; +use crate::sys::os_str::Buf; +use crate::sys_common::wtf8::Wtf8Buf; +use crate::sys_common::{AsInner, FromInner}; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use crate::sys_common::wtf8::EncodeWide; + +/// Windows-specific extensions to [`OsString`]. +/// +/// This trait is sealed: it cannot be implemented outside the standard library. +/// This is so that future additional methods are not breaking changes. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait OsStringExt: Sealed { + /// Creates an `OsString` from a potentially ill-formed UTF-16 slice of + /// 16-bit code units. + /// + /// This is lossless: calling [`OsStrExt::encode_wide`] on the resulting string + /// will always return the original code units. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::OsString; + /// use std::os::windows::prelude::*; + /// + /// // UTF-16 encoding for "Unicode". + /// let source = [0x0055, 0x006E, 0x0069, 0x0063, 0x006F, 0x0064, 0x0065]; + /// + /// let string = OsString::from_wide(&source[..]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + fn from_wide(wide: &[u16]) -> Self; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl OsStringExt for OsString { + fn from_wide(wide: &[u16]) -> OsString { + FromInner::from_inner(Buf { inner: Wtf8Buf::from_wide(wide) }) + } +} + +/// Windows-specific extensions to [`OsStr`]. +/// +/// This trait is sealed: it cannot be implemented outside the standard library. +/// This is so that future additional methods are not breaking changes. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait OsStrExt: Sealed { + /// Re-encodes an `OsStr` as a wide character sequence, i.e., potentially + /// ill-formed UTF-16. + /// + /// This is lossless: calling [`OsStringExt::from_wide`] and then + /// `encode_wide` on the result will yield the original code units. + /// Note that the encoding does not add a final null terminator. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::OsString; + /// use std::os::windows::prelude::*; + /// + /// // UTF-16 encoding for "Unicode". + /// let source = [0x0055, 0x006E, 0x0069, 0x0063, 0x006F, 0x0064, 0x0065]; + /// + /// let string = OsString::from_wide(&source[..]); + /// + /// let result: Vec = string.encode_wide().collect(); + /// assert_eq!(&source[..], &result[..]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + fn encode_wide(&self) -> EncodeWide<'_>; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl OsStrExt for OsStr { + fn encode_wide(&self) -> EncodeWide<'_> { + self.as_inner().inner.encode_wide() + } +} diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs new file mode 100644 index 00000000000..b20eafb4d53 --- /dev/null +++ b/library/std/src/os/windows/fs.rs @@ -0,0 +1,558 @@ +//! Windows-specific extensions for the primitives in the `std::fs` module. + +#![stable(feature = "rust1", since = "1.0.0")] + +use crate::fs::{self, Metadata, OpenOptions}; +use crate::io; +use crate::path::Path; +use crate::sys; +use crate::sys_common::{AsInner, AsInnerMut}; + +/// Windows-specific extensions to [`fs::File`]. +#[stable(feature = "file_offset", since = "1.15.0")] +pub trait FileExt { + /// Seeks to a given position and reads a number of bytes. + /// + /// Returns the number of bytes read. + /// + /// The offset is relative to the start of the file and thus independent + /// from the current cursor. The current cursor **is** affected by this + /// function, it is set to the end of the read. + /// + /// Reading beyond the end of the file will always return with a length of + /// 0\. + /// + /// Note that similar to `File::read`, it is not an error to return with a + /// short read. When returning from such a short read, the file pointer is + /// still updated. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::fs::File; + /// use std::os::windows::prelude::*; + /// + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// let mut buffer = [0; 10]; + /// + /// // Read 10 bytes, starting 72 bytes from the + /// // start of the file. + /// file.seek_read(&mut buffer[..], 72)?; + /// Ok(()) + /// } + /// ``` + #[stable(feature = "file_offset", since = "1.15.0")] + fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result; + + /// Seeks to a given position and writes a number of bytes. + /// + /// Returns the number of bytes written. + /// + /// The offset is relative to the start of the file and thus independent + /// from the current cursor. The current cursor **is** affected by this + /// function, it is set to the end of the write. + /// + /// When writing beyond the end of the file, the file is appropriately + /// extended and the intermediate bytes are left uninitialized. + /// + /// Note that similar to `File::write`, it is not an error to return a + /// short write. When returning from such a short write, the file pointer + /// is still updated. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs::File; + /// use std::os::windows::prelude::*; + /// + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; + /// + /// // Write a byte string starting 72 bytes from + /// // the start of the file. + /// buffer.seek_write(b"some bytes", 72)?; + /// Ok(()) + /// } + /// ``` + #[stable(feature = "file_offset", since = "1.15.0")] + fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result; +} + +#[stable(feature = "file_offset", since = "1.15.0")] +impl FileExt for fs::File { + fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result { + self.as_inner().read_at(buf, offset) + } + + fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result { + self.as_inner().write_at(buf, offset) + } +} + +/// Windows-specific extensions to [`fs::OpenOptions`]. +#[stable(feature = "open_options_ext", since = "1.10.0")] +pub trait OpenOptionsExt { + /// 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 std::fs::OpenOptions; + /// use std::os::windows::prelude::*; + /// + /// // 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"); + /// ``` + /// + /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea + #[stable(feature = "open_options_ext", since = "1.10.0")] + 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 std::fs::OpenOptions; + /// use std::os::windows::prelude::*; + /// + /// // 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"); + /// ``` + /// + /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea + #[stable(feature = "open_options_ext", since = "1.10.0")] + 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 + /// # #[cfg(for_demonstration_only)] + /// extern crate winapi; + /// # mod winapi { pub const FILE_FLAG_DELETE_ON_CLOSE: u32 = 0x04000000; } + /// + /// use std::fs::OpenOptions; + /// use std::os::windows::prelude::*; + /// + /// let file = OpenOptions::new() + /// .create(true) + /// .write(true) + /// .custom_flags(winapi::FILE_FLAG_DELETE_ON_CLOSE) + /// .open("foo.txt"); + /// ``` + /// + /// [`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 + #[stable(feature = "open_options_ext", since = "1.10.0")] + 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 + /// # #[cfg(for_demonstration_only)] + /// extern crate winapi; + /// # mod winapi { pub const FILE_ATTRIBUTE_HIDDEN: u32 = 2; } + /// + /// use std::fs::OpenOptions; + /// use std::os::windows::prelude::*; + /// + /// let file = OpenOptions::new() + /// .write(true) + /// .create(true) + /// .attributes(winapi::FILE_ATTRIBUTE_HIDDEN) + /// .open("foo.txt"); + /// ``` + /// + /// [`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 + #[stable(feature = "open_options_ext", since = "1.10.0")] + 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 + /// # #[cfg(for_demonstration_only)] + /// extern crate winapi; + /// # mod winapi { pub const SECURITY_IDENTIFICATION: u32 = 0; } + /// use std::fs::OpenOptions; + /// use std::os::windows::prelude::*; + /// + /// let file = OpenOptions::new() + /// .write(true) + /// .create(true) + /// + /// // Sets the flag value to `SecurityIdentification`. + /// .security_qos_flags(winapi::SECURITY_IDENTIFICATION) + /// + /// .open(r"\\.\pipe\MyPipe"); + /// ``` + /// + /// [`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 + #[stable(feature = "open_options_ext", since = "1.10.0")] + fn security_qos_flags(&mut self, flags: u32) -> &mut Self; +} + +#[stable(feature = "open_options_ext", since = "1.10.0")] +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 + } +} + +/// Windows-specific extensions to [`fs::Metadata`]. +/// +/// The data members that this trait exposes correspond to the members +/// of the [`BY_HANDLE_FILE_INFORMATION`] structure. +/// +/// [`BY_HANDLE_FILE_INFORMATION`]: +/// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information +#[stable(feature = "metadata_ext", since = "1.1.0")] +pub trait MetadataExt { + /// Returns the value of the `dwFileAttributes` field of this metadata. + /// + /// This field contains the file system attribute information for a file + /// or directory. For possible values and their descriptions, see + /// [File Attribute Constants] in the Windows Dev Center. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::fs; + /// use std::os::windows::prelude::*; + /// + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let attributes = metadata.file_attributes(); + /// Ok(()) + /// } + /// ``` + /// + /// [File Attribute Constants]: + /// https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn file_attributes(&self) -> u32; + + /// Returns the value of the `ftCreationTime` field of this metadata. + /// + /// The returned 64-bit value is equivalent to a [`FILETIME`] struct, + /// which represents the number of 100-nanosecond intervals since + /// January 1, 1601 (UTC). The struct is automatically + /// converted to a `u64` value, as that is the recommended way + /// to use it. + /// + /// If the underlying filesystem does not support creation time, the + /// returned value is 0. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::fs; + /// use std::os::windows::prelude::*; + /// + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let creation_time = metadata.creation_time(); + /// Ok(()) + /// } + /// ``` + /// + /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn creation_time(&self) -> u64; + + /// Returns the value of the `ftLastAccessTime` field of this metadata. + /// + /// The returned 64-bit value is equivalent to a [`FILETIME`] struct, + /// which represents the number of 100-nanosecond intervals since + /// January 1, 1601 (UTC). The struct is automatically + /// converted to a `u64` value, as that is the recommended way + /// to use it. + /// + /// For a file, the value specifies the last time that a file was read + /// from or written to. For a directory, the value specifies when + /// the directory was created. For both files and directories, the + /// specified date is correct, but the time of day is always set to + /// midnight. + /// + /// If the underlying filesystem does not support last access time, the + /// returned value is 0. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::fs; + /// use std::os::windows::prelude::*; + /// + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let last_access_time = metadata.last_access_time(); + /// Ok(()) + /// } + /// ``` + /// + /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn last_access_time(&self) -> u64; + + /// Returns the value of the `ftLastWriteTime` field of this metadata. + /// + /// The returned 64-bit value is equivalent to a [`FILETIME`] struct, + /// which represents the number of 100-nanosecond intervals since + /// January 1, 1601 (UTC). The struct is automatically + /// converted to a `u64` value, as that is the recommended way + /// to use it. + /// + /// For a file, the value specifies the last time that a file was written + /// to. For a directory, the structure specifies when the directory was + /// created. + /// + /// If the underlying filesystem does not support the last write time, + /// the returned value is 0. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::fs; + /// use std::os::windows::prelude::*; + /// + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let last_write_time = metadata.last_write_time(); + /// Ok(()) + /// } + /// ``` + /// + /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn last_write_time(&self) -> u64; + + /// Returns the value of the `nFileSize{High,Low}` fields of this + /// metadata. + /// + /// The returned value does not have meaning for directories. + /// + /// # Examples + /// + /// ```no_run + /// use std::io; + /// use std::fs; + /// use std::os::windows::prelude::*; + /// + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let file_size = metadata.file_size(); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn file_size(&self) -> u64; + + /// Returns the value of the `dwVolumeSerialNumber` field of this + /// metadata. + /// + /// This will return `None` if the `Metadata` instance was created from a + /// call to `DirEntry::metadata`. If this `Metadata` was created by using + /// `fs::metadata` or `File::metadata`, then this will return `Some`. + #[unstable(feature = "windows_by_handle", issue = "63010")] + fn volume_serial_number(&self) -> Option; + + /// Returns the value of the `nNumberOfLinks` field of this + /// metadata. + /// + /// This will return `None` if the `Metadata` instance was created from a + /// call to `DirEntry::metadata`. If this `Metadata` was created by using + /// `fs::metadata` or `File::metadata`, then this will return `Some`. + #[unstable(feature = "windows_by_handle", issue = "63010")] + fn number_of_links(&self) -> Option; + + /// Returns the value of the `nFileIndex{Low,High}` fields of this + /// metadata. + /// + /// This will return `None` if the `Metadata` instance was created from a + /// call to `DirEntry::metadata`. If this `Metadata` was created by using + /// `fs::metadata` or `File::metadata`, then this will return `Some`. + #[unstable(feature = "windows_by_handle", issue = "63010")] + fn file_index(&self) -> Option; +} + +#[stable(feature = "metadata_ext", since = "1.1.0")] +impl MetadataExt for Metadata { + fn file_attributes(&self) -> u32 { + self.as_inner().attrs() + } + fn creation_time(&self) -> u64 { + self.as_inner().created_u64() + } + fn last_access_time(&self) -> u64 { + self.as_inner().accessed_u64() + } + fn last_write_time(&self) -> u64 { + self.as_inner().modified_u64() + } + fn file_size(&self) -> u64 { + self.as_inner().size() + } + fn volume_serial_number(&self) -> Option { + self.as_inner().volume_serial_number() + } + fn number_of_links(&self) -> Option { + self.as_inner().number_of_links() + } + fn file_index(&self) -> Option { + self.as_inner().file_index() + } +} + +/// Windows-specific extensions to [`fs::FileType`]. +/// +/// On Windows, a symbolic link knows whether it is a file or directory. +#[unstable(feature = "windows_file_type_ext", issue = "none")] +pub trait FileTypeExt { + /// Returns `true` if this file type is a symbolic link that is also a directory. + #[unstable(feature = "windows_file_type_ext", issue = "none")] + fn is_symlink_dir(&self) -> bool; + /// Returns `true` if this file type is a symbolic link that is also a file. + #[unstable(feature = "windows_file_type_ext", issue = "none")] + fn is_symlink_file(&self) -> bool; +} + +#[unstable(feature = "windows_file_type_ext", issue = "none")] +impl FileTypeExt for fs::FileType { + fn is_symlink_dir(&self) -> bool { + self.as_inner().is_symlink_dir() + } + fn is_symlink_file(&self) -> bool { + self.as_inner().is_symlink_file() + } +} + +/// Creates a new file symbolic link on the filesystem. +/// +/// The `link` path will be a file symbolic link pointing to the `original` +/// path. +/// +/// # Examples +/// +/// ```no_run +/// use std::os::windows::fs; +/// +/// fn main() -> std::io::Result<()> { +/// fs::symlink_file("a.txt", "b.txt")?; +/// Ok(()) +/// } +/// ``` +#[stable(feature = "symlink", since = "1.1.0")] +pub fn symlink_file, Q: AsRef>(original: P, link: Q) -> io::Result<()> { + sys::fs::symlink_inner(original.as_ref(), link.as_ref(), false) +} + +/// Creates a new directory symlink on the filesystem. +/// +/// The `link` path will be a directory symbolic link pointing to the `original` +/// path. +/// +/// # Examples +/// +/// ```no_run +/// use std::os::windows::fs; +/// +/// fn main() -> std::io::Result<()> { +/// fs::symlink_dir("a", "b")?; +/// Ok(()) +/// } +/// ``` +#[stable(feature = "symlink", since = "1.1.0")] +pub fn symlink_dir, Q: AsRef>(original: P, link: Q) -> io::Result<()> { + sys::fs::symlink_inner(original.as_ref(), link.as_ref(), true) +} diff --git a/library/std/src/os/windows/io.rs b/library/std/src/os/windows/io.rs new file mode 100644 index 00000000000..31b5d015ed0 --- /dev/null +++ b/library/std/src/os/windows/io.rs @@ -0,0 +1,234 @@ +//! Windows-specific extensions to general I/O primitives. + +#![stable(feature = "rust1", since = "1.0.0")] + +use crate::fs; +use crate::io; +use crate::net; +use crate::os::windows::raw; +use crate::sys; +use crate::sys::c; +use crate::sys_common::{self, AsInner, FromInner, IntoInner}; + +/// Raw HANDLEs. +#[stable(feature = "rust1", since = "1.0.0")] +pub type RawHandle = raw::HANDLE; + +/// Raw SOCKETs. +#[stable(feature = "rust1", since = "1.0.0")] +pub type RawSocket = raw::SOCKET; + +/// Extracts raw handles. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait AsRawHandle { + /// Extracts the raw handle, without taking any ownership. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_raw_handle(&self) -> RawHandle; +} + +/// Construct I/O objects from raw handles. +#[stable(feature = "from_raw_os", since = "1.1.0")] +pub trait FromRawHandle { + /// Constructs a new I/O object from the specified raw handle. + /// + /// This function will **consume ownership** of the handle given, + /// passing responsibility for closing the handle to the returned + /// object. + /// + /// This function is also unsafe as the primitives currently returned + /// have the contract that they are the sole owner of the file + /// descriptor they are wrapping. Usage of this function could + /// accidentally allow violating this contract which can cause memory + /// unsafety in code that relies on it being true. + #[stable(feature = "from_raw_os", since = "1.1.0")] + unsafe fn from_raw_handle(handle: RawHandle) -> Self; +} + +/// A trait to express the ability to consume an object and acquire ownership of +/// its raw `HANDLE`. +#[stable(feature = "into_raw_os", since = "1.4.0")] +pub trait IntoRawHandle { + /// Consumes this object, returning the raw underlying handle. + /// + /// This function **transfers ownership** of the underlying handle to the + /// caller. Callers are then the unique owners of the handle and must close + /// it once it's no longer needed. + #[stable(feature = "into_raw_os", since = "1.4.0")] + fn into_raw_handle(self) -> RawHandle; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRawHandle for fs::File { + #[inline] + fn as_raw_handle(&self) -> RawHandle { + self.as_inner().handle().raw() as RawHandle + } +} + +#[stable(feature = "asraw_stdio", since = "1.21.0")] +impl AsRawHandle for io::Stdin { + fn as_raw_handle(&self) -> RawHandle { + unsafe { c::GetStdHandle(c::STD_INPUT_HANDLE) as RawHandle } + } +} + +#[stable(feature = "asraw_stdio", since = "1.21.0")] +impl AsRawHandle for io::Stdout { + fn as_raw_handle(&self) -> RawHandle { + unsafe { c::GetStdHandle(c::STD_OUTPUT_HANDLE) as RawHandle } + } +} + +#[stable(feature = "asraw_stdio", since = "1.21.0")] +impl AsRawHandle for io::Stderr { + fn as_raw_handle(&self) -> RawHandle { + unsafe { c::GetStdHandle(c::STD_ERROR_HANDLE) as RawHandle } + } +} + +#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] +impl<'a> AsRawHandle for io::StdinLock<'a> { + fn as_raw_handle(&self) -> RawHandle { + unsafe { c::GetStdHandle(c::STD_INPUT_HANDLE) as RawHandle } + } +} + +#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] +impl<'a> AsRawHandle for io::StdoutLock<'a> { + fn as_raw_handle(&self) -> RawHandle { + unsafe { c::GetStdHandle(c::STD_OUTPUT_HANDLE) as RawHandle } + } +} + +#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] +impl<'a> AsRawHandle for io::StderrLock<'a> { + fn as_raw_handle(&self) -> RawHandle { + unsafe { c::GetStdHandle(c::STD_ERROR_HANDLE) as RawHandle } + } +} + +#[stable(feature = "from_raw_os", since = "1.1.0")] +impl FromRawHandle for fs::File { + #[inline] + unsafe fn from_raw_handle(handle: RawHandle) -> fs::File { + let handle = handle as c::HANDLE; + fs::File::from_inner(sys::fs::File::from_inner(handle)) + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawHandle for fs::File { + #[inline] + fn into_raw_handle(self) -> RawHandle { + self.into_inner().into_handle().into_raw() as *mut _ + } +} + +/// Extracts raw sockets. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait AsRawSocket { + /// Extracts the underlying raw socket from this object. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_raw_socket(&self) -> RawSocket; +} + +/// Creates I/O objects from raw sockets. +#[stable(feature = "from_raw_os", since = "1.1.0")] +pub trait FromRawSocket { + /// Creates a new I/O object from the given raw socket. + /// + /// This function will **consume ownership** of the socket provided and + /// it will be closed when the returned object goes out of scope. + /// + /// This function is also unsafe as the primitives currently returned + /// have the contract that they are the sole owner of the file + /// descriptor they are wrapping. Usage of this function could + /// accidentally allow violating this contract which can cause memory + /// unsafety in code that relies on it being true. + #[stable(feature = "from_raw_os", since = "1.1.0")] + unsafe fn from_raw_socket(sock: RawSocket) -> Self; +} + +/// A trait to express the ability to consume an object and acquire ownership of +/// its raw `SOCKET`. +#[stable(feature = "into_raw_os", since = "1.4.0")] +pub trait IntoRawSocket { + /// Consumes this object, returning the raw underlying socket. + /// + /// This function **transfers ownership** of the underlying socket to the + /// caller. Callers are then the unique owners of the socket and must close + /// it once it's no longer needed. + #[stable(feature = "into_raw_os", since = "1.4.0")] + fn into_raw_socket(self) -> RawSocket; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRawSocket for net::TcpStream { + #[inline] + fn as_raw_socket(&self) -> RawSocket { + *self.as_inner().socket().as_inner() + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRawSocket for net::TcpListener { + #[inline] + fn as_raw_socket(&self) -> RawSocket { + *self.as_inner().socket().as_inner() + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRawSocket for net::UdpSocket { + #[inline] + fn as_raw_socket(&self) -> RawSocket { + *self.as_inner().socket().as_inner() + } +} + +#[stable(feature = "from_raw_os", since = "1.1.0")] +impl FromRawSocket for net::TcpStream { + #[inline] + unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpStream { + let sock = sys::net::Socket::from_inner(sock); + net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(sock)) + } +} +#[stable(feature = "from_raw_os", since = "1.1.0")] +impl FromRawSocket for net::TcpListener { + #[inline] + unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpListener { + let sock = sys::net::Socket::from_inner(sock); + net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(sock)) + } +} +#[stable(feature = "from_raw_os", since = "1.1.0")] +impl FromRawSocket for net::UdpSocket { + #[inline] + unsafe fn from_raw_socket(sock: RawSocket) -> net::UdpSocket { + let sock = sys::net::Socket::from_inner(sock); + net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(sock)) + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawSocket for net::TcpStream { + #[inline] + fn into_raw_socket(self) -> RawSocket { + self.into_inner().into_socket().into_inner() + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawSocket for net::TcpListener { + #[inline] + fn into_raw_socket(self) -> RawSocket { + self.into_inner().into_socket().into_inner() + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawSocket for net::UdpSocket { + #[inline] + fn into_raw_socket(self) -> RawSocket { + self.into_inner().into_socket().into_inner() + } +} diff --git a/library/std/src/os/windows/mod.rs b/library/std/src/os/windows/mod.rs new file mode 100644 index 00000000000..52ac508f9f7 --- /dev/null +++ b/library/std/src/os/windows/mod.rs @@ -0,0 +1,39 @@ +//! Platform-specific extensions to `std` for Windows. +//! +//! Provides access to platform-level information for Windows, and exposes +//! Windows-specific idioms that would otherwise be inappropriate as part +//! the core `std` library. These extensions allow developers to use +//! `std` types and idioms with Windows in a way that the normal +//! platform-agnostic idioms would not normally support. + +#![stable(feature = "rust1", since = "1.0.0")] +#![doc(cfg(windows))] + +pub mod ffi; +pub mod fs; +pub mod io; +pub mod process; +pub mod raw; +pub mod thread; + +/// A prelude for conveniently writing platform-specific code. +/// +/// Includes all extension traits, and some important type definitions. +#[stable(feature = "rust1", since = "1.0.0")] +pub mod prelude { + #[doc(no_inline)] + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::ffi::{OsStrExt, OsStringExt}; + #[doc(no_inline)] + #[stable(feature = "file_offset", since = "1.15.0")] + pub use super::fs::FileExt; + #[doc(no_inline)] + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::fs::{MetadataExt, OpenOptionsExt}; + #[doc(no_inline)] + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::io::{AsRawHandle, AsRawSocket, RawHandle, RawSocket}; + #[doc(no_inline)] + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::io::{FromRawHandle, FromRawSocket, IntoRawHandle, IntoRawSocket}; +} diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs new file mode 100644 index 00000000000..67756b15531 --- /dev/null +++ b/library/std/src/os/windows/process.rs @@ -0,0 +1,141 @@ +//! Extensions to `std::process` for Windows. + +#![stable(feature = "process_extensions", since = "1.2.0")] + +use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; +use crate::process; +use crate::sealed::Sealed; +use crate::sys; +use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; + +#[stable(feature = "process_extensions", since = "1.2.0")] +impl FromRawHandle for process::Stdio { + unsafe fn from_raw_handle(handle: RawHandle) -> process::Stdio { + let handle = sys::handle::Handle::new(handle as *mut _); + let io = sys::process::Stdio::Handle(handle); + process::Stdio::from_inner(io) + } +} + +#[stable(feature = "process_extensions", since = "1.2.0")] +impl AsRawHandle for process::Child { + #[inline] + fn as_raw_handle(&self) -> RawHandle { + self.as_inner().handle().raw() as *mut _ + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawHandle for process::Child { + fn into_raw_handle(self) -> RawHandle { + self.into_inner().into_handle().into_raw() as *mut _ + } +} + +#[stable(feature = "process_extensions", since = "1.2.0")] +impl AsRawHandle for process::ChildStdin { + #[inline] + fn as_raw_handle(&self) -> RawHandle { + self.as_inner().handle().raw() as *mut _ + } +} + +#[stable(feature = "process_extensions", since = "1.2.0")] +impl AsRawHandle for process::ChildStdout { + #[inline] + fn as_raw_handle(&self) -> RawHandle { + self.as_inner().handle().raw() as *mut _ + } +} + +#[stable(feature = "process_extensions", since = "1.2.0")] +impl AsRawHandle for process::ChildStderr { + #[inline] + fn as_raw_handle(&self) -> RawHandle { + self.as_inner().handle().raw() as *mut _ + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawHandle for process::ChildStdin { + fn into_raw_handle(self) -> RawHandle { + self.into_inner().into_handle().into_raw() as *mut _ + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawHandle for process::ChildStdout { + fn into_raw_handle(self) -> RawHandle { + self.into_inner().into_handle().into_raw() as *mut _ + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawHandle for process::ChildStderr { + fn into_raw_handle(self) -> RawHandle { + self.into_inner().into_handle().into_raw() as *mut _ + } +} + +/// Windows-specific extensions to [`process::ExitStatus`]. +/// +/// This trait is sealed: it cannot be implemented outside the standard library. +/// This is so that future additional methods are not breaking changes. +#[stable(feature = "exit_status_from", since = "1.12.0")] +pub trait ExitStatusExt: Sealed { + /// Creates a new `ExitStatus` from the raw underlying `u32` return value of + /// a process. + #[stable(feature = "exit_status_from", since = "1.12.0")] + fn from_raw(raw: u32) -> Self; +} + +#[stable(feature = "exit_status_from", since = "1.12.0")] +impl ExitStatusExt for process::ExitStatus { + fn from_raw(raw: u32) -> Self { + process::ExitStatus::from_inner(From::from(raw)) + } +} + +/// Windows-specific extensions to the [`process::Command`] builder. +/// +/// This trait is sealed: it cannot be implemented outside the standard library. +/// This is so that future additional methods are not breaking changes. +#[stable(feature = "windows_process_extensions", since = "1.16.0")] +pub trait CommandExt: Sealed { + /// Sets the [process creation flags][1] to be passed to `CreateProcess`. + /// + /// These will always be ORed with `CREATE_UNICODE_ENVIRONMENT`. + /// + /// [1]: https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags + #[stable(feature = "windows_process_extensions", since = "1.16.0")] + fn creation_flags(&mut self, flags: u32) -> &mut process::Command; + + /// Forces all arguments to be wrapped in quote (`"`) characters. + /// + /// This is useful for passing arguments to [MSYS2/Cygwin][1] based + /// executables: these programs will expand unquoted arguments containing + /// wildcard characters (`?` and `*`) by searching for any file paths + /// matching the wildcard pattern. + /// + /// Adding quotes has no effect when passing arguments to programs + /// that use [msvcrt][2]. This includes programs built with both + /// MinGW and MSVC. + /// + /// [1]: + /// [2]: + #[unstable(feature = "windows_process_extensions_force_quotes", issue = "82227")] + fn force_quotes(&mut self, enabled: bool) -> &mut process::Command; +} + +#[stable(feature = "windows_process_extensions", since = "1.16.0")] +impl CommandExt for process::Command { + fn creation_flags(&mut self, flags: u32) -> &mut process::Command { + self.as_inner_mut().creation_flags(flags); + self + } + + fn force_quotes(&mut self, enabled: bool) -> &mut process::Command { + self.as_inner_mut().force_quotes(enabled); + self + } +} diff --git a/library/std/src/os/windows/raw.rs b/library/std/src/os/windows/raw.rs new file mode 100644 index 00000000000..5014e008eb5 --- /dev/null +++ b/library/std/src/os/windows/raw.rs @@ -0,0 +1,14 @@ +//! Windows-specific primitives. + +#![stable(feature = "raw_ext", since = "1.1.0")] + +use crate::os::raw::c_void; + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type HANDLE = *mut c_void; +#[cfg(target_pointer_width = "32")] +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type SOCKET = u32; +#[cfg(target_pointer_width = "64")] +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type SOCKET = u64; diff --git a/library/std/src/os/windows/thread.rs b/library/std/src/os/windows/thread.rs new file mode 100644 index 00000000000..6bd02054f71 --- /dev/null +++ b/library/std/src/os/windows/thread.rs @@ -0,0 +1,23 @@ +//! Extensions to `std::thread` for Windows. + +#![stable(feature = "thread_extensions", since = "1.9.0")] + +use crate::os::windows::io::{AsRawHandle, IntoRawHandle, RawHandle}; +use crate::sys_common::{AsInner, IntoInner}; +use crate::thread; + +#[stable(feature = "thread_extensions", since = "1.9.0")] +impl AsRawHandle for thread::JoinHandle { + #[inline] + fn as_raw_handle(&self) -> RawHandle { + self.as_inner().handle().raw() as *mut _ + } +} + +#[stable(feature = "thread_extensions", since = "1.9.0")] +impl IntoRawHandle for thread::JoinHandle { + #[inline] + fn into_raw_handle(self) -> RawHandle { + self.into_inner().into_handle().into_raw() as *mut _ + } +} diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 33e68d12b0a..6b38f62dfe5 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -78,23 +78,16 @@ cfg_if::cfg_if! { all(target_vendor = "fortanix", target_env = "sgx") )))] cfg_if::cfg_if! { - if #[cfg(windows)] { - #[allow(missing_docs)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use self::ext as windows_ext; - } else { + if #[cfg(not(windows))] { // On non-Windows platforms (aka linux/osx/etc) pull in a "minimal" // amount of windows goop which ends up compiling #[macro_use] #[path = "windows/compat.rs"] - mod compat; + pub mod compat; #[path = "windows/c.rs"] - mod c; - - #[path = "windows/ext/mod.rs"] - pub mod windows_ext; + pub mod c; } } diff --git a/library/std/src/sys/windows/ext/ffi.rs b/library/std/src/sys/windows/ext/ffi.rs deleted file mode 100644 index c89b9ff1efa..00000000000 --- a/library/std/src/sys/windows/ext/ffi.rs +++ /dev/null @@ -1,134 +0,0 @@ -//! Windows-specific extensions to the primitives in the `std::ffi` module. -//! -//! # Overview -//! -//! For historical reasons, the Windows API uses a form of potentially -//! ill-formed UTF-16 encoding for strings. Specifically, the 16-bit -//! code units in Windows strings may contain [isolated surrogate code -//! points which are not paired together][ill-formed-utf-16]. The -//! Unicode standard requires that surrogate code points (those in the -//! range U+D800 to U+DFFF) always be *paired*, because in the UTF-16 -//! encoding a *surrogate code unit pair* is used to encode a single -//! character. For compatibility with code that does not enforce -//! these pairings, Windows does not enforce them, either. -//! -//! While it is not always possible to convert such a string losslessly into -//! a valid UTF-16 string (or even UTF-8), it is often desirable to be -//! able to round-trip such a string from and to Windows APIs -//! losslessly. For example, some Rust code may be "bridging" some -//! Windows APIs together, just passing `WCHAR` strings among those -//! APIs without ever really looking into the strings. -//! -//! If Rust code *does* need to look into those strings, it can -//! convert them to valid UTF-8, possibly lossily, by substituting -//! invalid sequences with [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], as is -//! conventionally done in other Rust APIs that deal with string -//! encodings. -//! -//! # `OsStringExt` and `OsStrExt` -//! -//! [`OsString`] is the Rust wrapper for owned strings in the -//! preferred representation of the operating system. On Windows, -//! this struct gets augmented with an implementation of the -//! [`OsStringExt`] trait, which has a [`OsStringExt::from_wide`] method. This -//! lets you create an [`OsString`] from a `&[u16]` slice; presumably -//! you get such a slice out of a `WCHAR` Windows API. -//! -//! Similarly, [`OsStr`] is the Rust wrapper for borrowed strings from -//! preferred representation of the operating system. On Windows, the -//! [`OsStrExt`] trait provides the [`OsStrExt::encode_wide`] method, which -//! outputs an [`EncodeWide`] iterator. You can [`collect`] this -//! iterator, for example, to obtain a `Vec`; you can later get a -//! pointer to this vector's contents and feed it to Windows APIs. -//! -//! These traits, along with [`OsString`] and [`OsStr`], work in -//! conjunction so that it is possible to **round-trip** strings from -//! Windows and back, with no loss of data, even if the strings are -//! ill-formed UTF-16. -//! -//! [ill-formed-utf-16]: https://simonsapin.github.io/wtf-8/#ill-formed-utf-16 -//! [`collect`]: crate::iter::Iterator::collect -//! [U+FFFD]: crate::char::REPLACEMENT_CHARACTER - -#![stable(feature = "rust1", since = "1.0.0")] - -use crate::ffi::{OsStr, OsString}; -use crate::sealed::Sealed; -use crate::sys::os_str::Buf; -use crate::sys_common::wtf8::Wtf8Buf; -use crate::sys_common::{AsInner, FromInner}; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use crate::sys_common::wtf8::EncodeWide; - -/// Windows-specific extensions to [`OsString`]. -/// -/// This trait is sealed: it cannot be implemented outside the standard library. -/// This is so that future additional methods are not breaking changes. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait OsStringExt: Sealed { - /// Creates an `OsString` from a potentially ill-formed UTF-16 slice of - /// 16-bit code units. - /// - /// This is lossless: calling [`OsStrExt::encode_wide`] on the resulting string - /// will always return the original code units. - /// - /// # Examples - /// - /// ``` - /// use std::ffi::OsString; - /// use std::os::windows::prelude::*; - /// - /// // UTF-16 encoding for "Unicode". - /// let source = [0x0055, 0x006E, 0x0069, 0x0063, 0x006F, 0x0064, 0x0065]; - /// - /// let string = OsString::from_wide(&source[..]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn from_wide(wide: &[u16]) -> Self; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl OsStringExt for OsString { - fn from_wide(wide: &[u16]) -> OsString { - FromInner::from_inner(Buf { inner: Wtf8Buf::from_wide(wide) }) - } -} - -/// Windows-specific extensions to [`OsStr`]. -/// -/// This trait is sealed: it cannot be implemented outside the standard library. -/// This is so that future additional methods are not breaking changes. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait OsStrExt: Sealed { - /// Re-encodes an `OsStr` as a wide character sequence, i.e., potentially - /// ill-formed UTF-16. - /// - /// This is lossless: calling [`OsStringExt::from_wide`] and then - /// `encode_wide` on the result will yield the original code units. - /// Note that the encoding does not add a final null terminator. - /// - /// # Examples - /// - /// ``` - /// use std::ffi::OsString; - /// use std::os::windows::prelude::*; - /// - /// // UTF-16 encoding for "Unicode". - /// let source = [0x0055, 0x006E, 0x0069, 0x0063, 0x006F, 0x0064, 0x0065]; - /// - /// let string = OsString::from_wide(&source[..]); - /// - /// let result: Vec = string.encode_wide().collect(); - /// assert_eq!(&source[..], &result[..]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn encode_wide(&self) -> EncodeWide<'_>; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl OsStrExt for OsStr { - fn encode_wide(&self) -> EncodeWide<'_> { - self.as_inner().inner.encode_wide() - } -} diff --git a/library/std/src/sys/windows/ext/fs.rs b/library/std/src/sys/windows/ext/fs.rs deleted file mode 100644 index b20eafb4d53..00000000000 --- a/library/std/src/sys/windows/ext/fs.rs +++ /dev/null @@ -1,558 +0,0 @@ -//! Windows-specific extensions for the primitives in the `std::fs` module. - -#![stable(feature = "rust1", since = "1.0.0")] - -use crate::fs::{self, Metadata, OpenOptions}; -use crate::io; -use crate::path::Path; -use crate::sys; -use crate::sys_common::{AsInner, AsInnerMut}; - -/// Windows-specific extensions to [`fs::File`]. -#[stable(feature = "file_offset", since = "1.15.0")] -pub trait FileExt { - /// Seeks to a given position and reads a number of bytes. - /// - /// Returns the number of bytes read. - /// - /// The offset is relative to the start of the file and thus independent - /// from the current cursor. The current cursor **is** affected by this - /// function, it is set to the end of the read. - /// - /// Reading beyond the end of the file will always return with a length of - /// 0\. - /// - /// Note that similar to `File::read`, it is not an error to return with a - /// short read. When returning from such a short read, the file pointer is - /// still updated. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::fs::File; - /// use std::os::windows::prelude::*; - /// - /// fn main() -> io::Result<()> { - /// let mut file = File::open("foo.txt")?; - /// let mut buffer = [0; 10]; - /// - /// // Read 10 bytes, starting 72 bytes from the - /// // start of the file. - /// file.seek_read(&mut buffer[..], 72)?; - /// Ok(()) - /// } - /// ``` - #[stable(feature = "file_offset", since = "1.15.0")] - fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result; - - /// Seeks to a given position and writes a number of bytes. - /// - /// Returns the number of bytes written. - /// - /// The offset is relative to the start of the file and thus independent - /// from the current cursor. The current cursor **is** affected by this - /// function, it is set to the end of the write. - /// - /// When writing beyond the end of the file, the file is appropriately - /// extended and the intermediate bytes are left uninitialized. - /// - /// Note that similar to `File::write`, it is not an error to return a - /// short write. When returning from such a short write, the file pointer - /// is still updated. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs::File; - /// use std::os::windows::prelude::*; - /// - /// fn main() -> std::io::Result<()> { - /// let mut buffer = File::create("foo.txt")?; - /// - /// // Write a byte string starting 72 bytes from - /// // the start of the file. - /// buffer.seek_write(b"some bytes", 72)?; - /// Ok(()) - /// } - /// ``` - #[stable(feature = "file_offset", since = "1.15.0")] - fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result; -} - -#[stable(feature = "file_offset", since = "1.15.0")] -impl FileExt for fs::File { - fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result { - self.as_inner().read_at(buf, offset) - } - - fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result { - self.as_inner().write_at(buf, offset) - } -} - -/// Windows-specific extensions to [`fs::OpenOptions`]. -#[stable(feature = "open_options_ext", since = "1.10.0")] -pub trait OpenOptionsExt { - /// 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 std::fs::OpenOptions; - /// use std::os::windows::prelude::*; - /// - /// // 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"); - /// ``` - /// - /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea - #[stable(feature = "open_options_ext", since = "1.10.0")] - 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 std::fs::OpenOptions; - /// use std::os::windows::prelude::*; - /// - /// // 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"); - /// ``` - /// - /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea - #[stable(feature = "open_options_ext", since = "1.10.0")] - 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 - /// # #[cfg(for_demonstration_only)] - /// extern crate winapi; - /// # mod winapi { pub const FILE_FLAG_DELETE_ON_CLOSE: u32 = 0x04000000; } - /// - /// use std::fs::OpenOptions; - /// use std::os::windows::prelude::*; - /// - /// let file = OpenOptions::new() - /// .create(true) - /// .write(true) - /// .custom_flags(winapi::FILE_FLAG_DELETE_ON_CLOSE) - /// .open("foo.txt"); - /// ``` - /// - /// [`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 - #[stable(feature = "open_options_ext", since = "1.10.0")] - 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 - /// # #[cfg(for_demonstration_only)] - /// extern crate winapi; - /// # mod winapi { pub const FILE_ATTRIBUTE_HIDDEN: u32 = 2; } - /// - /// use std::fs::OpenOptions; - /// use std::os::windows::prelude::*; - /// - /// let file = OpenOptions::new() - /// .write(true) - /// .create(true) - /// .attributes(winapi::FILE_ATTRIBUTE_HIDDEN) - /// .open("foo.txt"); - /// ``` - /// - /// [`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 - #[stable(feature = "open_options_ext", since = "1.10.0")] - 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 - /// # #[cfg(for_demonstration_only)] - /// extern crate winapi; - /// # mod winapi { pub const SECURITY_IDENTIFICATION: u32 = 0; } - /// use std::fs::OpenOptions; - /// use std::os::windows::prelude::*; - /// - /// let file = OpenOptions::new() - /// .write(true) - /// .create(true) - /// - /// // Sets the flag value to `SecurityIdentification`. - /// .security_qos_flags(winapi::SECURITY_IDENTIFICATION) - /// - /// .open(r"\\.\pipe\MyPipe"); - /// ``` - /// - /// [`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 - #[stable(feature = "open_options_ext", since = "1.10.0")] - fn security_qos_flags(&mut self, flags: u32) -> &mut Self; -} - -#[stable(feature = "open_options_ext", since = "1.10.0")] -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 - } -} - -/// Windows-specific extensions to [`fs::Metadata`]. -/// -/// The data members that this trait exposes correspond to the members -/// of the [`BY_HANDLE_FILE_INFORMATION`] structure. -/// -/// [`BY_HANDLE_FILE_INFORMATION`]: -/// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information -#[stable(feature = "metadata_ext", since = "1.1.0")] -pub trait MetadataExt { - /// Returns the value of the `dwFileAttributes` field of this metadata. - /// - /// This field contains the file system attribute information for a file - /// or directory. For possible values and their descriptions, see - /// [File Attribute Constants] in the Windows Dev Center. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::fs; - /// use std::os::windows::prelude::*; - /// - /// fn main() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let attributes = metadata.file_attributes(); - /// Ok(()) - /// } - /// ``` - /// - /// [File Attribute Constants]: - /// https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn file_attributes(&self) -> u32; - - /// Returns the value of the `ftCreationTime` field of this metadata. - /// - /// The returned 64-bit value is equivalent to a [`FILETIME`] struct, - /// which represents the number of 100-nanosecond intervals since - /// January 1, 1601 (UTC). The struct is automatically - /// converted to a `u64` value, as that is the recommended way - /// to use it. - /// - /// If the underlying filesystem does not support creation time, the - /// returned value is 0. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::fs; - /// use std::os::windows::prelude::*; - /// - /// fn main() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let creation_time = metadata.creation_time(); - /// Ok(()) - /// } - /// ``` - /// - /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn creation_time(&self) -> u64; - - /// Returns the value of the `ftLastAccessTime` field of this metadata. - /// - /// The returned 64-bit value is equivalent to a [`FILETIME`] struct, - /// which represents the number of 100-nanosecond intervals since - /// January 1, 1601 (UTC). The struct is automatically - /// converted to a `u64` value, as that is the recommended way - /// to use it. - /// - /// For a file, the value specifies the last time that a file was read - /// from or written to. For a directory, the value specifies when - /// the directory was created. For both files and directories, the - /// specified date is correct, but the time of day is always set to - /// midnight. - /// - /// If the underlying filesystem does not support last access time, the - /// returned value is 0. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::fs; - /// use std::os::windows::prelude::*; - /// - /// fn main() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let last_access_time = metadata.last_access_time(); - /// Ok(()) - /// } - /// ``` - /// - /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn last_access_time(&self) -> u64; - - /// Returns the value of the `ftLastWriteTime` field of this metadata. - /// - /// The returned 64-bit value is equivalent to a [`FILETIME`] struct, - /// which represents the number of 100-nanosecond intervals since - /// January 1, 1601 (UTC). The struct is automatically - /// converted to a `u64` value, as that is the recommended way - /// to use it. - /// - /// For a file, the value specifies the last time that a file was written - /// to. For a directory, the structure specifies when the directory was - /// created. - /// - /// If the underlying filesystem does not support the last write time, - /// the returned value is 0. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::fs; - /// use std::os::windows::prelude::*; - /// - /// fn main() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let last_write_time = metadata.last_write_time(); - /// Ok(()) - /// } - /// ``` - /// - /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn last_write_time(&self) -> u64; - - /// Returns the value of the `nFileSize{High,Low}` fields of this - /// metadata. - /// - /// The returned value does not have meaning for directories. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::fs; - /// use std::os::windows::prelude::*; - /// - /// fn main() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let file_size = metadata.file_size(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn file_size(&self) -> u64; - - /// Returns the value of the `dwVolumeSerialNumber` field of this - /// metadata. - /// - /// This will return `None` if the `Metadata` instance was created from a - /// call to `DirEntry::metadata`. If this `Metadata` was created by using - /// `fs::metadata` or `File::metadata`, then this will return `Some`. - #[unstable(feature = "windows_by_handle", issue = "63010")] - fn volume_serial_number(&self) -> Option; - - /// Returns the value of the `nNumberOfLinks` field of this - /// metadata. - /// - /// This will return `None` if the `Metadata` instance was created from a - /// call to `DirEntry::metadata`. If this `Metadata` was created by using - /// `fs::metadata` or `File::metadata`, then this will return `Some`. - #[unstable(feature = "windows_by_handle", issue = "63010")] - fn number_of_links(&self) -> Option; - - /// Returns the value of the `nFileIndex{Low,High}` fields of this - /// metadata. - /// - /// This will return `None` if the `Metadata` instance was created from a - /// call to `DirEntry::metadata`. If this `Metadata` was created by using - /// `fs::metadata` or `File::metadata`, then this will return `Some`. - #[unstable(feature = "windows_by_handle", issue = "63010")] - fn file_index(&self) -> Option; -} - -#[stable(feature = "metadata_ext", since = "1.1.0")] -impl MetadataExt for Metadata { - fn file_attributes(&self) -> u32 { - self.as_inner().attrs() - } - fn creation_time(&self) -> u64 { - self.as_inner().created_u64() - } - fn last_access_time(&self) -> u64 { - self.as_inner().accessed_u64() - } - fn last_write_time(&self) -> u64 { - self.as_inner().modified_u64() - } - fn file_size(&self) -> u64 { - self.as_inner().size() - } - fn volume_serial_number(&self) -> Option { - self.as_inner().volume_serial_number() - } - fn number_of_links(&self) -> Option { - self.as_inner().number_of_links() - } - fn file_index(&self) -> Option { - self.as_inner().file_index() - } -} - -/// Windows-specific extensions to [`fs::FileType`]. -/// -/// On Windows, a symbolic link knows whether it is a file or directory. -#[unstable(feature = "windows_file_type_ext", issue = "none")] -pub trait FileTypeExt { - /// Returns `true` if this file type is a symbolic link that is also a directory. - #[unstable(feature = "windows_file_type_ext", issue = "none")] - fn is_symlink_dir(&self) -> bool; - /// Returns `true` if this file type is a symbolic link that is also a file. - #[unstable(feature = "windows_file_type_ext", issue = "none")] - fn is_symlink_file(&self) -> bool; -} - -#[unstable(feature = "windows_file_type_ext", issue = "none")] -impl FileTypeExt for fs::FileType { - fn is_symlink_dir(&self) -> bool { - self.as_inner().is_symlink_dir() - } - fn is_symlink_file(&self) -> bool { - self.as_inner().is_symlink_file() - } -} - -/// Creates a new file symbolic link on the filesystem. -/// -/// The `link` path will be a file symbolic link pointing to the `original` -/// path. -/// -/// # Examples -/// -/// ```no_run -/// use std::os::windows::fs; -/// -/// fn main() -> std::io::Result<()> { -/// fs::symlink_file("a.txt", "b.txt")?; -/// Ok(()) -/// } -/// ``` -#[stable(feature = "symlink", since = "1.1.0")] -pub fn symlink_file, Q: AsRef>(original: P, link: Q) -> io::Result<()> { - sys::fs::symlink_inner(original.as_ref(), link.as_ref(), false) -} - -/// Creates a new directory symlink on the filesystem. -/// -/// The `link` path will be a directory symbolic link pointing to the `original` -/// path. -/// -/// # Examples -/// -/// ```no_run -/// use std::os::windows::fs; -/// -/// fn main() -> std::io::Result<()> { -/// fs::symlink_dir("a", "b")?; -/// Ok(()) -/// } -/// ``` -#[stable(feature = "symlink", since = "1.1.0")] -pub fn symlink_dir, Q: AsRef>(original: P, link: Q) -> io::Result<()> { - sys::fs::symlink_inner(original.as_ref(), link.as_ref(), true) -} diff --git a/library/std/src/sys/windows/ext/io.rs b/library/std/src/sys/windows/ext/io.rs deleted file mode 100644 index 31b5d015ed0..00000000000 --- a/library/std/src/sys/windows/ext/io.rs +++ /dev/null @@ -1,234 +0,0 @@ -//! Windows-specific extensions to general I/O primitives. - -#![stable(feature = "rust1", since = "1.0.0")] - -use crate::fs; -use crate::io; -use crate::net; -use crate::os::windows::raw; -use crate::sys; -use crate::sys::c; -use crate::sys_common::{self, AsInner, FromInner, IntoInner}; - -/// Raw HANDLEs. -#[stable(feature = "rust1", since = "1.0.0")] -pub type RawHandle = raw::HANDLE; - -/// Raw SOCKETs. -#[stable(feature = "rust1", since = "1.0.0")] -pub type RawSocket = raw::SOCKET; - -/// Extracts raw handles. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait AsRawHandle { - /// Extracts the raw handle, without taking any ownership. - #[stable(feature = "rust1", since = "1.0.0")] - fn as_raw_handle(&self) -> RawHandle; -} - -/// Construct I/O objects from raw handles. -#[stable(feature = "from_raw_os", since = "1.1.0")] -pub trait FromRawHandle { - /// Constructs a new I/O object from the specified raw handle. - /// - /// This function will **consume ownership** of the handle given, - /// passing responsibility for closing the handle to the returned - /// object. - /// - /// This function is also unsafe as the primitives currently returned - /// have the contract that they are the sole owner of the file - /// descriptor they are wrapping. Usage of this function could - /// accidentally allow violating this contract which can cause memory - /// unsafety in code that relies on it being true. - #[stable(feature = "from_raw_os", since = "1.1.0")] - unsafe fn from_raw_handle(handle: RawHandle) -> Self; -} - -/// A trait to express the ability to consume an object and acquire ownership of -/// its raw `HANDLE`. -#[stable(feature = "into_raw_os", since = "1.4.0")] -pub trait IntoRawHandle { - /// Consumes this object, returning the raw underlying handle. - /// - /// This function **transfers ownership** of the underlying handle to the - /// caller. Callers are then the unique owners of the handle and must close - /// it once it's no longer needed. - #[stable(feature = "into_raw_os", since = "1.4.0")] - fn into_raw_handle(self) -> RawHandle; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRawHandle for fs::File { - #[inline] - fn as_raw_handle(&self) -> RawHandle { - self.as_inner().handle().raw() as RawHandle - } -} - -#[stable(feature = "asraw_stdio", since = "1.21.0")] -impl AsRawHandle for io::Stdin { - fn as_raw_handle(&self) -> RawHandle { - unsafe { c::GetStdHandle(c::STD_INPUT_HANDLE) as RawHandle } - } -} - -#[stable(feature = "asraw_stdio", since = "1.21.0")] -impl AsRawHandle for io::Stdout { - fn as_raw_handle(&self) -> RawHandle { - unsafe { c::GetStdHandle(c::STD_OUTPUT_HANDLE) as RawHandle } - } -} - -#[stable(feature = "asraw_stdio", since = "1.21.0")] -impl AsRawHandle for io::Stderr { - fn as_raw_handle(&self) -> RawHandle { - unsafe { c::GetStdHandle(c::STD_ERROR_HANDLE) as RawHandle } - } -} - -#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] -impl<'a> AsRawHandle for io::StdinLock<'a> { - fn as_raw_handle(&self) -> RawHandle { - unsafe { c::GetStdHandle(c::STD_INPUT_HANDLE) as RawHandle } - } -} - -#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] -impl<'a> AsRawHandle for io::StdoutLock<'a> { - fn as_raw_handle(&self) -> RawHandle { - unsafe { c::GetStdHandle(c::STD_OUTPUT_HANDLE) as RawHandle } - } -} - -#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] -impl<'a> AsRawHandle for io::StderrLock<'a> { - fn as_raw_handle(&self) -> RawHandle { - unsafe { c::GetStdHandle(c::STD_ERROR_HANDLE) as RawHandle } - } -} - -#[stable(feature = "from_raw_os", since = "1.1.0")] -impl FromRawHandle for fs::File { - #[inline] - unsafe fn from_raw_handle(handle: RawHandle) -> fs::File { - let handle = handle as c::HANDLE; - fs::File::from_inner(sys::fs::File::from_inner(handle)) - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawHandle for fs::File { - #[inline] - fn into_raw_handle(self) -> RawHandle { - self.into_inner().into_handle().into_raw() as *mut _ - } -} - -/// Extracts raw sockets. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait AsRawSocket { - /// Extracts the underlying raw socket from this object. - #[stable(feature = "rust1", since = "1.0.0")] - fn as_raw_socket(&self) -> RawSocket; -} - -/// Creates I/O objects from raw sockets. -#[stable(feature = "from_raw_os", since = "1.1.0")] -pub trait FromRawSocket { - /// Creates a new I/O object from the given raw socket. - /// - /// This function will **consume ownership** of the socket provided and - /// it will be closed when the returned object goes out of scope. - /// - /// This function is also unsafe as the primitives currently returned - /// have the contract that they are the sole owner of the file - /// descriptor they are wrapping. Usage of this function could - /// accidentally allow violating this contract which can cause memory - /// unsafety in code that relies on it being true. - #[stable(feature = "from_raw_os", since = "1.1.0")] - unsafe fn from_raw_socket(sock: RawSocket) -> Self; -} - -/// A trait to express the ability to consume an object and acquire ownership of -/// its raw `SOCKET`. -#[stable(feature = "into_raw_os", since = "1.4.0")] -pub trait IntoRawSocket { - /// Consumes this object, returning the raw underlying socket. - /// - /// This function **transfers ownership** of the underlying socket to the - /// caller. Callers are then the unique owners of the socket and must close - /// it once it's no longer needed. - #[stable(feature = "into_raw_os", since = "1.4.0")] - fn into_raw_socket(self) -> RawSocket; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRawSocket for net::TcpStream { - #[inline] - fn as_raw_socket(&self) -> RawSocket { - *self.as_inner().socket().as_inner() - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRawSocket for net::TcpListener { - #[inline] - fn as_raw_socket(&self) -> RawSocket { - *self.as_inner().socket().as_inner() - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRawSocket for net::UdpSocket { - #[inline] - fn as_raw_socket(&self) -> RawSocket { - *self.as_inner().socket().as_inner() - } -} - -#[stable(feature = "from_raw_os", since = "1.1.0")] -impl FromRawSocket for net::TcpStream { - #[inline] - unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpStream { - let sock = sys::net::Socket::from_inner(sock); - net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(sock)) - } -} -#[stable(feature = "from_raw_os", since = "1.1.0")] -impl FromRawSocket for net::TcpListener { - #[inline] - unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpListener { - let sock = sys::net::Socket::from_inner(sock); - net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(sock)) - } -} -#[stable(feature = "from_raw_os", since = "1.1.0")] -impl FromRawSocket for net::UdpSocket { - #[inline] - unsafe fn from_raw_socket(sock: RawSocket) -> net::UdpSocket { - let sock = sys::net::Socket::from_inner(sock); - net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(sock)) - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawSocket for net::TcpStream { - #[inline] - fn into_raw_socket(self) -> RawSocket { - self.into_inner().into_socket().into_inner() - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawSocket for net::TcpListener { - #[inline] - fn into_raw_socket(self) -> RawSocket { - self.into_inner().into_socket().into_inner() - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawSocket for net::UdpSocket { - #[inline] - fn into_raw_socket(self) -> RawSocket { - self.into_inner().into_socket().into_inner() - } -} diff --git a/library/std/src/sys/windows/ext/mod.rs b/library/std/src/sys/windows/ext/mod.rs deleted file mode 100644 index 613d3dc189a..00000000000 --- a/library/std/src/sys/windows/ext/mod.rs +++ /dev/null @@ -1,40 +0,0 @@ -//! Platform-specific extensions to `std` for Windows. -//! -//! Provides access to platform-level information for Windows, and exposes -//! Windows-specific idioms that would otherwise be inappropriate as part -//! the core `std` library. These extensions allow developers to use -//! `std` types and idioms with Windows in a way that the normal -//! platform-agnostic idioms would not normally support. - -#![stable(feature = "rust1", since = "1.0.0")] -#![doc(cfg(windows))] -#![allow(missing_docs)] - -pub mod ffi; -pub mod fs; -pub mod io; -pub mod process; -pub mod raw; -pub mod thread; - -/// A prelude for conveniently writing platform-specific code. -/// -/// Includes all extension traits, and some important type definitions. -#[stable(feature = "rust1", since = "1.0.0")] -pub mod prelude { - #[doc(no_inline)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use super::ffi::{OsStrExt, OsStringExt}; - #[doc(no_inline)] - #[stable(feature = "file_offset", since = "1.15.0")] - pub use super::fs::FileExt; - #[doc(no_inline)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use super::fs::{MetadataExt, OpenOptionsExt}; - #[doc(no_inline)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use super::io::{AsRawHandle, AsRawSocket, RawHandle, RawSocket}; - #[doc(no_inline)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use super::io::{FromRawHandle, FromRawSocket, IntoRawHandle, IntoRawSocket}; -} diff --git a/library/std/src/sys/windows/ext/process.rs b/library/std/src/sys/windows/ext/process.rs deleted file mode 100644 index 67756b15531..00000000000 --- a/library/std/src/sys/windows/ext/process.rs +++ /dev/null @@ -1,141 +0,0 @@ -//! Extensions to `std::process` for Windows. - -#![stable(feature = "process_extensions", since = "1.2.0")] - -use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; -use crate::process; -use crate::sealed::Sealed; -use crate::sys; -use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; - -#[stable(feature = "process_extensions", since = "1.2.0")] -impl FromRawHandle for process::Stdio { - unsafe fn from_raw_handle(handle: RawHandle) -> process::Stdio { - let handle = sys::handle::Handle::new(handle as *mut _); - let io = sys::process::Stdio::Handle(handle); - process::Stdio::from_inner(io) - } -} - -#[stable(feature = "process_extensions", since = "1.2.0")] -impl AsRawHandle for process::Child { - #[inline] - fn as_raw_handle(&self) -> RawHandle { - self.as_inner().handle().raw() as *mut _ - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawHandle for process::Child { - fn into_raw_handle(self) -> RawHandle { - self.into_inner().into_handle().into_raw() as *mut _ - } -} - -#[stable(feature = "process_extensions", since = "1.2.0")] -impl AsRawHandle for process::ChildStdin { - #[inline] - fn as_raw_handle(&self) -> RawHandle { - self.as_inner().handle().raw() as *mut _ - } -} - -#[stable(feature = "process_extensions", since = "1.2.0")] -impl AsRawHandle for process::ChildStdout { - #[inline] - fn as_raw_handle(&self) -> RawHandle { - self.as_inner().handle().raw() as *mut _ - } -} - -#[stable(feature = "process_extensions", since = "1.2.0")] -impl AsRawHandle for process::ChildStderr { - #[inline] - fn as_raw_handle(&self) -> RawHandle { - self.as_inner().handle().raw() as *mut _ - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawHandle for process::ChildStdin { - fn into_raw_handle(self) -> RawHandle { - self.into_inner().into_handle().into_raw() as *mut _ - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawHandle for process::ChildStdout { - fn into_raw_handle(self) -> RawHandle { - self.into_inner().into_handle().into_raw() as *mut _ - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawHandle for process::ChildStderr { - fn into_raw_handle(self) -> RawHandle { - self.into_inner().into_handle().into_raw() as *mut _ - } -} - -/// Windows-specific extensions to [`process::ExitStatus`]. -/// -/// This trait is sealed: it cannot be implemented outside the standard library. -/// This is so that future additional methods are not breaking changes. -#[stable(feature = "exit_status_from", since = "1.12.0")] -pub trait ExitStatusExt: Sealed { - /// Creates a new `ExitStatus` from the raw underlying `u32` return value of - /// a process. - #[stable(feature = "exit_status_from", since = "1.12.0")] - fn from_raw(raw: u32) -> Self; -} - -#[stable(feature = "exit_status_from", since = "1.12.0")] -impl ExitStatusExt for process::ExitStatus { - fn from_raw(raw: u32) -> Self { - process::ExitStatus::from_inner(From::from(raw)) - } -} - -/// Windows-specific extensions to the [`process::Command`] builder. -/// -/// This trait is sealed: it cannot be implemented outside the standard library. -/// This is so that future additional methods are not breaking changes. -#[stable(feature = "windows_process_extensions", since = "1.16.0")] -pub trait CommandExt: Sealed { - /// Sets the [process creation flags][1] to be passed to `CreateProcess`. - /// - /// These will always be ORed with `CREATE_UNICODE_ENVIRONMENT`. - /// - /// [1]: https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags - #[stable(feature = "windows_process_extensions", since = "1.16.0")] - fn creation_flags(&mut self, flags: u32) -> &mut process::Command; - - /// Forces all arguments to be wrapped in quote (`"`) characters. - /// - /// This is useful for passing arguments to [MSYS2/Cygwin][1] based - /// executables: these programs will expand unquoted arguments containing - /// wildcard characters (`?` and `*`) by searching for any file paths - /// matching the wildcard pattern. - /// - /// Adding quotes has no effect when passing arguments to programs - /// that use [msvcrt][2]. This includes programs built with both - /// MinGW and MSVC. - /// - /// [1]: - /// [2]: - #[unstable(feature = "windows_process_extensions_force_quotes", issue = "82227")] - fn force_quotes(&mut self, enabled: bool) -> &mut process::Command; -} - -#[stable(feature = "windows_process_extensions", since = "1.16.0")] -impl CommandExt for process::Command { - fn creation_flags(&mut self, flags: u32) -> &mut process::Command { - self.as_inner_mut().creation_flags(flags); - self - } - - fn force_quotes(&mut self, enabled: bool) -> &mut process::Command { - self.as_inner_mut().force_quotes(enabled); - self - } -} diff --git a/library/std/src/sys/windows/ext/raw.rs b/library/std/src/sys/windows/ext/raw.rs deleted file mode 100644 index 5014e008eb5..00000000000 --- a/library/std/src/sys/windows/ext/raw.rs +++ /dev/null @@ -1,14 +0,0 @@ -//! Windows-specific primitives. - -#![stable(feature = "raw_ext", since = "1.1.0")] - -use crate::os::raw::c_void; - -#[stable(feature = "raw_ext", since = "1.1.0")] -pub type HANDLE = *mut c_void; -#[cfg(target_pointer_width = "32")] -#[stable(feature = "raw_ext", since = "1.1.0")] -pub type SOCKET = u32; -#[cfg(target_pointer_width = "64")] -#[stable(feature = "raw_ext", since = "1.1.0")] -pub type SOCKET = u64; diff --git a/library/std/src/sys/windows/ext/thread.rs b/library/std/src/sys/windows/ext/thread.rs deleted file mode 100644 index 6bd02054f71..00000000000 --- a/library/std/src/sys/windows/ext/thread.rs +++ /dev/null @@ -1,23 +0,0 @@ -//! Extensions to `std::thread` for Windows. - -#![stable(feature = "thread_extensions", since = "1.9.0")] - -use crate::os::windows::io::{AsRawHandle, IntoRawHandle, RawHandle}; -use crate::sys_common::{AsInner, IntoInner}; -use crate::thread; - -#[stable(feature = "thread_extensions", since = "1.9.0")] -impl AsRawHandle for thread::JoinHandle { - #[inline] - fn as_raw_handle(&self) -> RawHandle { - self.as_inner().handle().raw() as *mut _ - } -} - -#[stable(feature = "thread_extensions", since = "1.9.0")] -impl IntoRawHandle for thread::JoinHandle { - #[inline] - fn into_raw_handle(self) -> RawHandle { - self.into_inner().into_handle().into_raw() as *mut _ - } -} diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index 2208ff025c0..cc60ca375ea 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -18,7 +18,6 @@ pub mod c; pub mod cmath; pub mod condvar; pub mod env; -pub mod ext; pub mod fs; pub mod handle; pub mod io; -- cgit 1.4.1-3-g733a5