about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorMichał Krasnoborski <mkrdln@gmail.com>2017-02-03 17:48:07 +0100
committerMichał Krasnoborski <mkrdln@gmail.com>2017-02-03 17:48:07 +0100
commit0267529681e2fac6ef4560afe7d8d439d04e6303 (patch)
tree00bac1c7b714a59f1e4f230a64cb5427de2b62eb /src/libstd/sys
parentecda7f314fa79bbfbf2125c99fd66288ca83c875 (diff)
parentaed6410a7b0f15dc68536e0735787436526ba395 (diff)
downloadrust-0267529681e2fac6ef4560afe7d8d439d04e6303.tar.gz
rust-0267529681e2fac6ef4560afe7d8d439d04e6303.zip
Merge remote-tracking branch 'upstream/master' into format-with-capacity
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/redox/ext/fs.rs10
-rw-r--r--src/libstd/sys/unix/backtrace/mod.rs11
-rw-r--r--src/libstd/sys/unix/pipe.rs39
-rw-r--r--src/libstd/sys/windows/backtrace.rs4
-rw-r--r--src/libstd/sys/windows/backtrace_gnu.rs62
-rw-r--r--src/libstd/sys/windows/c.rs40
-rw-r--r--src/libstd/sys/windows/ext/process.rs6
-rw-r--r--src/libstd/sys/windows/mod.rs47
8 files changed, 194 insertions, 25 deletions
diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs
index 7ad8d27b483..fc81cc737d9 100644
--- a/src/libstd/sys/redox/ext/fs.rs
+++ b/src/libstd/sys/redox/ext/fs.rs
@@ -161,6 +161,10 @@ impl OpenOptionsExt for OpenOptions {
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn dev(&self) -> u64;
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn ino(&self) -> u64;
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn mode(&self) -> u32;
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn uid(&self) -> u32;
@@ -184,6 +188,12 @@ pub trait MetadataExt {
 
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 impl MetadataExt for fs::Metadata {
+    fn dev(&self) -> u64 {
+        self.as_inner().as_inner().st_dev as u64
+    }
+    fn ino(&self) -> u64 {
+        self.as_inner().as_inner().st_ino as u64
+    }
     fn mode(&self) -> u32 {
         self.as_inner().as_inner().st_mode as u32
     }
diff --git a/src/libstd/sys/unix/backtrace/mod.rs b/src/libstd/sys/unix/backtrace/mod.rs
index d7c05e513f6..1eef89bf66f 100644
--- a/src/libstd/sys/unix/backtrace/mod.rs
+++ b/src/libstd/sys/unix/backtrace/mod.rs
@@ -89,3 +89,14 @@ pub use self::tracing::write;
 mod tracing;
 // symbol resolvers:
 mod printing;
+
+#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "emscripten")))]
+pub mod gnu {
+    use io;
+    use fs;
+    use libc::c_char;
+
+    pub fn get_executable_filename() -> io::Result<(Vec<c_char>, fs::File)> {
+        Err(io::Error::new(io::ErrorKind::Other, "Not implemented"))
+    }
+}
diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs
index a8ed415b7f4..51e00fc1ab9 100644
--- a/src/libstd/sys/unix/pipe.rs
+++ b/src/libstd/sys/unix/pipe.rs
@@ -13,7 +13,7 @@ use io;
 use libc::{self, c_int};
 use mem;
 use ptr;
-use sys::cvt_r;
+use sys::{cvt, cvt_r};
 use sys::fd::FileDesc;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -29,34 +29,29 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
     // CLOEXEC flag is to use the `pipe2` syscall on Linux. This was added in
     // 2.6.27, however, and because we support 2.6.18 we must detect this
     // support dynamically.
-    if cfg!(target_os = "linux") {
+    if cfg!(any(target_os = "dragonfly",
+                target_os = "freebsd",
+                target_os = "linux",
+                target_os = "netbsd",
+                target_os = "openbsd"))
+    {
         weak! { fn pipe2(*mut c_int, c_int) -> c_int }
         if let Some(pipe) = pipe2.get() {
-            match cvt_r(|| unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) {
-                Ok(_) => {
-                    return Ok((AnonPipe(FileDesc::new(fds[0])),
-                               AnonPipe(FileDesc::new(fds[1]))))
-                }
-                Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {}
-                Err(e) => return Err(e),
-            }
+            cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) })?;
+            return Ok((AnonPipe(FileDesc::new(fds[0])),
+                       AnonPipe(FileDesc::new(fds[1]))));
         }
     }
-    if unsafe { libc::pipe(fds.as_mut_ptr()) == 0 } {
-        let fd0 = FileDesc::new(fds[0]);
-        let fd1 = FileDesc::new(fds[1]);
-        Ok((AnonPipe::from_fd(fd0)?, AnonPipe::from_fd(fd1)?))
-    } else {
-        Err(io::Error::last_os_error())
-    }
+    cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;
+
+    let fd0 = FileDesc::new(fds[0]);
+    let fd1 = FileDesc::new(fds[1]);
+    fd0.set_cloexec()?;
+    fd1.set_cloexec()?;
+    Ok((AnonPipe(fd0), AnonPipe(fd1)))
 }
 
 impl AnonPipe {
-    pub fn from_fd(fd: FileDesc) -> io::Result<AnonPipe> {
-        fd.set_cloexec()?;
-        Ok(AnonPipe(fd))
-    }
-
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         self.0.read(buf)
     }
diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs
index 82a44c1c110..94aaf439f3d 100644
--- a/src/libstd/sys/windows/backtrace.rs
+++ b/src/libstd/sys/windows/backtrace.rs
@@ -51,6 +51,10 @@ mod printing;
 #[path = "printing/gnu.rs"]
 mod printing;
 
+#[cfg(target_env = "gnu")]
+#[path = "backtrace_gnu.rs"]
+pub mod gnu;
+
 type SymInitializeFn =
     unsafe extern "system" fn(c::HANDLE, *mut c_void,
                               c::BOOL) -> c::BOOL;
diff --git a/src/libstd/sys/windows/backtrace_gnu.rs b/src/libstd/sys/windows/backtrace_gnu.rs
new file mode 100644
index 00000000000..f0d29dd4178
--- /dev/null
+++ b/src/libstd/sys/windows/backtrace_gnu.rs
@@ -0,0 +1,62 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use io;
+use sys::c;
+use libc::c_char;
+use path::PathBuf;
+use fs::{OpenOptions, File};
+use sys::ext::fs::OpenOptionsExt;
+use sys::handle::Handle;
+use super::super::{fill_utf16_buf, os2path, to_u16s, wide_char_to_multi_byte};
+
+fn query_full_process_image_name() -> io::Result<PathBuf> {
+    unsafe {
+        let process_handle = Handle::new(c::OpenProcess(c::PROCESS_QUERY_INFORMATION,
+                                                        c::FALSE,
+                                                        c::GetCurrentProcessId()));
+        fill_utf16_buf(|buf, mut sz| {
+            if c::QueryFullProcessImageNameW(process_handle.raw(), 0, buf, &mut sz) == 0 {
+                0
+            } else {
+                sz
+            }
+        }, os2path)
+    }
+}
+
+fn lock_and_get_executable_filename() -> io::Result<(PathBuf, File)> {
+    // We query the current image name, open the file without FILE_SHARE_DELETE so it
+    // can't be moved and then get the current image name again. If the names are the
+    // same than we have successfully locked the file
+    let image_name1 = query_full_process_image_name()?;
+    let file = OpenOptions::new()
+                .read(true)
+                .share_mode(c::FILE_SHARE_READ | c::FILE_SHARE_WRITE)
+                .open(&image_name1)?;
+    let image_name2 = query_full_process_image_name()?;
+
+    if image_name1 != image_name2 {
+        return Err(io::Error::new(io::ErrorKind::Other,
+                                  "executable moved while trying to lock it"));
+    }
+
+    Ok((image_name1, file))
+}
+
+// Get the executable filename for libbacktrace
+// This returns the path in the ANSI code page and a File which should remain open
+// for as long as the path should remain valid
+pub fn get_executable_filename() -> io::Result<(Vec<c_char>, File)> {
+    let (executable, file) = lock_and_get_executable_filename()?;
+    let u16_executable = to_u16s(executable.into_os_string())?;
+    Ok((wide_char_to_multi_byte(c::CP_ACP, c::WC_NO_BEST_FIT_CHARS,
+                                &u16_executable, true)?, file))
+}
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index dc7b2fc9a6b..1b29bf73c7a 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -69,6 +69,7 @@ pub type LPWCH = *mut WCHAR;
 pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW;
 pub type LPWSADATA = *mut WSADATA;
 pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;
+pub type LPSTR = *mut CHAR;
 pub type LPWSTR = *mut WCHAR;
 pub type LPFILETIME = *mut FILETIME;
 
@@ -973,6 +974,14 @@ extern "system" {
     pub fn DeleteFileW(lpPathName: LPCWSTR) -> BOOL;
     pub fn GetCurrentDirectoryW(nBufferLength: DWORD, lpBuffer: LPWSTR) -> DWORD;
     pub fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL;
+    pub fn WideCharToMultiByte(CodePage: UINT,
+                               dwFlags: DWORD,
+                               lpWideCharStr: LPCWSTR,
+                               cchWideChar: c_int,
+                               lpMultiByteStr: LPSTR,
+                               cbMultiByte: c_int,
+                               lpDefaultChar: LPCSTR,
+                               lpUsedDefaultChar: LPBOOL) -> c_int;
 
     pub fn closesocket(socket: SOCKET) -> c_int;
     pub fn recv(socket: SOCKET, buf: *mut c_void, len: c_int,
@@ -1178,3 +1187,34 @@ compat_fn! {
         panic!("rwlocks not available")
     }
 }
+
+#[cfg(target_env = "gnu")]
+mod gnu {
+    use super::*;
+
+    pub const PROCESS_QUERY_INFORMATION: DWORD = 0x0400;
+
+    pub const CP_ACP: UINT = 0;
+
+    pub const WC_NO_BEST_FIT_CHARS: DWORD = 0x00000400;
+
+    extern "system" {
+        pub fn OpenProcess(dwDesiredAccess: DWORD,
+                           bInheritHandle: BOOL,
+                           dwProcessId: DWORD) -> HANDLE;
+    }
+
+    compat_fn! {
+        kernel32:
+
+        pub fn QueryFullProcessImageNameW(_hProcess: HANDLE,
+                                          _dwFlags: DWORD,
+                                          _lpExeName: LPWSTR,
+                                          _lpdwSize: LPDWORD) -> BOOL {
+            SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
+        }
+    }
+}
+
+#[cfg(target_env = "gnu")]
+pub use self::gnu::*;
diff --git a/src/libstd/sys/windows/ext/process.rs b/src/libstd/sys/windows/ext/process.rs
index 0a3221aeae6..1419a4af427 100644
--- a/src/libstd/sys/windows/ext/process.rs
+++ b/src/libstd/sys/windows/ext/process.rs
@@ -99,17 +99,17 @@ impl ExitStatusExt for process::ExitStatus {
 }
 
 /// Windows-specific extensions to the `std::process::Command` builder
-#[unstable(feature = "windows_process_extensions", issue = "37827")]
+#[stable(feature = "windows_process_extensions", since = "1.16.0")]
 pub trait CommandExt {
     /// Sets the [process creation flags][1] to be passed to `CreateProcess`.
     ///
     /// These will always be ORed with `CREATE_UNICODE_ENVIRONMENT`.
     /// [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx
-    #[unstable(feature = "windows_process_extensions", issue = "37827")]
+    #[stable(feature = "windows_process_extensions", since = "1.16.0")]
     fn creation_flags(&mut self, flags: u32) -> &mut process::Command;
 }
 
-#[unstable(feature = "windows_process_extensions", issue = "37827")]
+#[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);
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index defc41c5f46..4424c6c6136 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -10,6 +10,7 @@
 
 #![allow(missing_docs, bad_style)]
 
+use ptr;
 use ffi::{OsStr, OsString};
 use io::{self, ErrorKind};
 use os::windows::ffi::{OsStrExt, OsStringExt};
@@ -171,6 +172,52 @@ fn os2path(s: &[u16]) -> PathBuf {
     PathBuf::from(OsString::from_wide(s))
 }
 
+#[allow(dead_code)] // Only used in backtrace::gnu::get_executable_filename()
+fn wide_char_to_multi_byte(code_page: u32,
+                           flags: u32,
+                           s: &[u16],
+                           no_default_char: bool)
+                           -> io::Result<Vec<i8>> {
+    unsafe {
+        let mut size = c::WideCharToMultiByte(code_page,
+                                              flags,
+                                              s.as_ptr(),
+                                              s.len() as i32,
+                                              ptr::null_mut(),
+                                              0,
+                                              ptr::null(),
+                                              ptr::null_mut());
+        if size == 0 {
+            return Err(io::Error::last_os_error());
+        }
+
+        let mut buf = Vec::with_capacity(size as usize);
+        buf.set_len(size as usize);
+
+        let mut used_default_char = c::FALSE;
+        size = c::WideCharToMultiByte(code_page,
+                                      flags,
+                                      s.as_ptr(),
+                                      s.len() as i32,
+                                      buf.as_mut_ptr(),
+                                      buf.len() as i32,
+                                      ptr::null(),
+                                      if no_default_char { &mut used_default_char }
+                                      else { ptr::null_mut() });
+        if size == 0 {
+            return Err(io::Error::last_os_error());
+        }
+        if no_default_char && used_default_char == c::TRUE {
+            return Err(io::Error::new(io::ErrorKind::InvalidData,
+                                      "string cannot be converted to requested code page"));
+        }
+
+        buf.set_len(size as usize);
+
+        Ok(buf)
+    }
+}
+
 pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] {
     match v.iter().position(|c| *c == 0) {
         // don't include the 0