Merge branch 'master' into redox
This commit is contained in:
commit
b3c91dfb6a
268 changed files with 5042 additions and 3096 deletions
|
|
@ -349,12 +349,47 @@ impl File {
|
|||
})
|
||||
}
|
||||
|
||||
/// Changes the permissions on the underlying file.
|
||||
///
|
||||
/// # Platform-specific behavior
|
||||
///
|
||||
/// This function currently corresponds to the `fchmod` function on Unix and
|
||||
/// the `SetFileInformationByHandle` function on Windows. Note that, this
|
||||
/// [may change in the future][changes].
|
||||
///
|
||||
/// [changes]: ../io/index.html#platform-specific-behavior
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return an error if the user lacks permission change
|
||||
/// attributes on the underlying file. It may also return an error in other
|
||||
/// os-specific unspecified cases.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(set_permissions_atomic)]
|
||||
/// # fn foo() -> std::io::Result<()> {
|
||||
/// use std::fs::File;
|
||||
///
|
||||
/// let file = File::open("foo.txt")?;
|
||||
/// let mut perms = file.metadata()?.permissions();
|
||||
/// perms.set_readonly(true);
|
||||
/// file.set_permissions(perms)?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "set_permissions_atomic", issue="37916")]
|
||||
pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> {
|
||||
self.inner.set_permissions(perm.0)
|
||||
}
|
||||
|
||||
/// Get the path that this file points to.
|
||||
///
|
||||
/// This function is only implemented on Redox, but could be
|
||||
/// implemented on other operating systems using readlink
|
||||
#[cfg(target_os = "redox")]
|
||||
#[stable(feature = "rust1", since = "1.14.0")]
|
||||
#[unstable(feature = "file_path", issue="0")]
|
||||
pub fn path(&self) -> io::Result<PathBuf> {
|
||||
self.inner.path()
|
||||
}
|
||||
|
|
@ -2479,6 +2514,24 @@ mod tests {
|
|||
check!(fs::set_permissions(&file, p));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fchmod_works() {
|
||||
let tmpdir = tmpdir();
|
||||
let path = tmpdir.join("in.txt");
|
||||
|
||||
let file = check!(File::create(&path));
|
||||
let attr = check!(fs::metadata(&path));
|
||||
assert!(!attr.permissions().readonly());
|
||||
let mut p = attr.permissions();
|
||||
p.set_readonly(true);
|
||||
check!(file.set_permissions(p.clone()));
|
||||
let attr = check!(fs::metadata(&path));
|
||||
assert!(attr.permissions().readonly());
|
||||
|
||||
p.set_readonly(false);
|
||||
check!(file.set_permissions(p));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sync_doesnt_kill_anything() {
|
||||
let tmpdir = tmpdir();
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ pub enum SocketAddr {
|
|||
/// An IPv4 socket address which is a (ip, port) combination.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4),
|
||||
/// An IPv6 socket address
|
||||
/// An IPv6 socket address.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
V6(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV6),
|
||||
}
|
||||
|
|
@ -48,6 +48,16 @@ pub struct SocketAddrV6 { inner: c::sockaddr_in6 }
|
|||
|
||||
impl SocketAddr {
|
||||
/// Creates a new socket address from the (ip, port) pair.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
///
|
||||
/// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
|
||||
/// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
|
||||
/// assert_eq!(socket.port(), 8080);
|
||||
/// ```
|
||||
#[stable(feature = "ip_addr", since = "1.7.0")]
|
||||
pub fn new(ip: IpAddr, port: u16) -> SocketAddr {
|
||||
match ip {
|
||||
|
|
@ -57,6 +67,15 @@ impl SocketAddr {
|
|||
}
|
||||
|
||||
/// Returns the IP address associated with this socket address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
///
|
||||
/// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
|
||||
/// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
|
||||
/// ```
|
||||
#[stable(feature = "ip_addr", since = "1.7.0")]
|
||||
pub fn ip(&self) -> IpAddr {
|
||||
match *self {
|
||||
|
|
@ -66,6 +85,16 @@ impl SocketAddr {
|
|||
}
|
||||
|
||||
/// Change the IP address associated with this socket address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
///
|
||||
/// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
|
||||
/// socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
|
||||
/// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
|
||||
/// ```
|
||||
#[stable(feature = "sockaddr_setters", since = "1.9.0")]
|
||||
pub fn set_ip(&mut self, new_ip: IpAddr) {
|
||||
// `match (*self, new_ip)` would have us mutate a copy of self only to throw it away.
|
||||
|
|
@ -77,6 +106,15 @@ impl SocketAddr {
|
|||
}
|
||||
|
||||
/// Returns the port number associated with this socket address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
///
|
||||
/// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
|
||||
/// assert_eq!(socket.port(), 8080);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn port(&self) -> u16 {
|
||||
match *self {
|
||||
|
|
@ -86,6 +124,16 @@ impl SocketAddr {
|
|||
}
|
||||
|
||||
/// Change the port number associated with this socket address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
///
|
||||
/// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
|
||||
/// socket.set_port(1025);
|
||||
/// assert_eq!(socket.port(), 1025);
|
||||
/// ```
|
||||
#[stable(feature = "sockaddr_setters", since = "1.9.0")]
|
||||
pub fn set_port(&mut self, new_port: u16) {
|
||||
match *self {
|
||||
|
|
@ -96,6 +144,20 @@ impl SocketAddr {
|
|||
|
||||
/// Returns true if the IP in this `SocketAddr` is a valid IPv4 address,
|
||||
/// false if it's a valid IPv6 address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(sockaddr_checker)]
|
||||
///
|
||||
/// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
///
|
||||
/// fn main() {
|
||||
/// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
|
||||
/// assert_eq!(socket.is_ipv4(), true);
|
||||
/// assert_eq!(socket.is_ipv6(), false);
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "sockaddr_checker", issue = "36949")]
|
||||
pub fn is_ipv4(&self) -> bool {
|
||||
match *self {
|
||||
|
|
@ -106,6 +168,21 @@ impl SocketAddr {
|
|||
|
||||
/// Returns true if the IP in this `SocketAddr` is a valid IPv6 address,
|
||||
/// false if it's a valid IPv4 address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(sockaddr_checker)]
|
||||
///
|
||||
/// use std::net::{IpAddr, Ipv6Addr, SocketAddr};
|
||||
///
|
||||
/// fn main() {
|
||||
/// let socket = SocketAddr::new(
|
||||
/// IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080);
|
||||
/// assert_eq!(socket.is_ipv4(), false);
|
||||
/// assert_eq!(socket.is_ipv6(), true);
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "sockaddr_checker", issue = "36949")]
|
||||
pub fn is_ipv6(&self) -> bool {
|
||||
match *self {
|
||||
|
|
|
|||
|
|
@ -825,6 +825,21 @@ pub fn exit(code: i32) -> ! {
|
|||
::sys::os::exit(code)
|
||||
}
|
||||
|
||||
/// Terminates the process in an abnormal fashion.
|
||||
///
|
||||
/// The function will never return and will immediately terminate the current
|
||||
/// process in a platform specific "abnormal" manner.
|
||||
///
|
||||
/// Note that because this function never returns, and that it terminates the
|
||||
/// process, no destructors on the current stack or any other thread's stack
|
||||
/// will be run. If a clean shutdown is needed it is recommended to only call
|
||||
/// this function at a known point where there are no more destructors left
|
||||
/// to run.
|
||||
#[unstable(feature = "process_abort", issue = "37838")]
|
||||
pub fn abort() -> ! {
|
||||
unsafe { ::sys::abort_internal() };
|
||||
}
|
||||
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
mod tests {
|
||||
use io::prelude::*;
|
||||
|
|
|
|||
|
|
@ -526,6 +526,11 @@ impl File {
|
|||
pub fn fd(&self) -> &FileDesc { &self.0 }
|
||||
|
||||
pub fn into_fd(self) -> FileDesc { self.0 }
|
||||
|
||||
pub fn set_permissions(&self, perm: FilePermissions) -> io::Result<()> {
|
||||
cvt_r(|| unsafe { libc::fchmod(self.0.raw(), perm.mode) })?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl DirBuilder {
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ pub const ERROR_INVALID_HANDLE: DWORD = 6;
|
|||
pub const ERROR_NO_MORE_FILES: DWORD = 18;
|
||||
pub const ERROR_HANDLE_EOF: DWORD = 38;
|
||||
pub const ERROR_FILE_EXISTS: DWORD = 80;
|
||||
pub const ERROR_INVALID_PARAMETER: DWORD = 87;
|
||||
pub const ERROR_BROKEN_PIPE: DWORD = 109;
|
||||
pub const ERROR_CALL_NOT_IMPLEMENTED: DWORD = 120;
|
||||
pub const ERROR_INSUFFICIENT_BUFFER: DWORD = 122;
|
||||
|
|
@ -388,6 +389,15 @@ pub enum FILE_INFO_BY_HANDLE_CLASS {
|
|||
MaximumFileInfoByHandlesClass
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct FILE_BASIC_INFO {
|
||||
pub CreationTime: LARGE_INTEGER,
|
||||
pub LastAccessTime: LARGE_INTEGER,
|
||||
pub LastWriteTime: LARGE_INTEGER,
|
||||
pub ChangeTime: LARGE_INTEGER,
|
||||
pub FileAttributes: DWORD,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct FILE_END_OF_FILE_INFO {
|
||||
pub EndOfFile: LARGE_INTEGER,
|
||||
|
|
|
|||
|
|
@ -417,6 +417,24 @@ impl File {
|
|||
Ok(PathBuf::from(OsString::from_wide(subst)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_permissions(&self, perm: FilePermissions) -> io::Result<()> {
|
||||
let mut info = c::FILE_BASIC_INFO {
|
||||
CreationTime: 0,
|
||||
LastAccessTime: 0,
|
||||
LastWriteTime: 0,
|
||||
ChangeTime: 0,
|
||||
FileAttributes: perm.attrs,
|
||||
};
|
||||
let size = mem::size_of_val(&info);
|
||||
cvt(unsafe {
|
||||
c::SetFileInformationByHandle(self.handle.raw(),
|
||||
c::FileBasicInfo,
|
||||
&mut info as *mut _ as *mut _,
|
||||
size as c::DWORD)
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<c::HANDLE> for File {
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
|||
let reader;
|
||||
let mut name;
|
||||
let mut tries = 0;
|
||||
let mut reject_remote_clients_flag = c::PIPE_REJECT_REMOTE_CLIENTS;
|
||||
loop {
|
||||
tries += 1;
|
||||
let key: u64 = rand::thread_rng().gen();
|
||||
|
|
@ -56,12 +57,12 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
|||
|
||||
let handle = c::CreateNamedPipeW(wide_name.as_ptr(),
|
||||
c::PIPE_ACCESS_INBOUND |
|
||||
c::FILE_FLAG_FIRST_PIPE_INSTANCE |
|
||||
c::FILE_FLAG_OVERLAPPED,
|
||||
c::FILE_FLAG_FIRST_PIPE_INSTANCE |
|
||||
c::FILE_FLAG_OVERLAPPED,
|
||||
c::PIPE_TYPE_BYTE |
|
||||
c::PIPE_READMODE_BYTE |
|
||||
c::PIPE_WAIT |
|
||||
c::PIPE_REJECT_REMOTE_CLIENTS,
|
||||
c::PIPE_READMODE_BYTE |
|
||||
c::PIPE_WAIT |
|
||||
reject_remote_clients_flag,
|
||||
1,
|
||||
4096,
|
||||
4096,
|
||||
|
|
@ -76,11 +77,27 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
|||
//
|
||||
// Don't try again too much though as this could also perhaps be a
|
||||
// legit error.
|
||||
// If ERROR_INVALID_PARAMETER is returned, this probably means we're
|
||||
// running on pre-Vista version where PIPE_REJECT_REMOTE_CLIENTS is
|
||||
// not supported, so we continue retrying without it. This implies
|
||||
// reduced security on Windows versions older than Vista by allowing
|
||||
// connections to this pipe from remote machines.
|
||||
// Proper fix would increase the number of FFI imports and introduce
|
||||
// significant amount of Windows XP specific code with no clean
|
||||
// testing strategy
|
||||
// for more info see https://github.com/rust-lang/rust/pull/37677
|
||||
if handle == c::INVALID_HANDLE_VALUE {
|
||||
let err = io::Error::last_os_error();
|
||||
if tries < 10 &&
|
||||
err.raw_os_error() == Some(c::ERROR_ACCESS_DENIED as i32) {
|
||||
continue
|
||||
let raw_os_err = err.raw_os_error();
|
||||
if tries < 10 {
|
||||
if raw_os_err == Some(c::ERROR_ACCESS_DENIED as i32) {
|
||||
continue
|
||||
} else if reject_remote_clients_flag != 0 &&
|
||||
raw_os_err == Some(c::ERROR_INVALID_PARAMETER as i32) {
|
||||
reject_remote_clients_flag = 0;
|
||||
tries -= 1;
|
||||
continue
|
||||
}
|
||||
}
|
||||
return Err(err)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue