diff options
| author | Sayan Nandan <17377258+sntdevco@users.noreply.github.com> | 2019-08-09 13:01:05 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-08-09 13:01:05 +0530 |
| commit | fb3a01354ffecc41d7a189e4dd225d706387a522 (patch) | |
| tree | 41492dfe93f1dccba847dadb56ac6aa079edaaa9 /src/libstd/sys_common | |
| parent | 33445aea509cadcd715009c79795d289268daa7c (diff) | |
| parent | 5aa3d9a7b5d3a46a7f158e8881146331a6bc9243 (diff) | |
| download | rust-fb3a01354ffecc41d7a189e4dd225d706387a522.tar.gz rust-fb3a01354ffecc41d7a189e4dd225d706387a522.zip | |
Merge pull request #1 from rust-lang/master
Merge recent changes into master
Diffstat (limited to 'src/libstd/sys_common')
| -rw-r--r-- | src/libstd/sys_common/alloc.rs | 3 | ||||
| -rw-r--r-- | src/libstd/sys_common/at_exit_imp.rs | 5 | ||||
| -rw-r--r-- | src/libstd/sys_common/backtrace.rs | 305 | ||||
| -rw-r--r-- | src/libstd/sys_common/bytestring.rs | 6 | ||||
| -rw-r--r-- | src/libstd/sys_common/fs.rs | 41 | ||||
| -rw-r--r-- | src/libstd/sys_common/gnu/libbacktrace.rs | 175 | ||||
| -rw-r--r-- | src/libstd/sys_common/gnu/mod.rs | 5 | ||||
| -rw-r--r-- | src/libstd/sys_common/io.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys_common/mod.rs | 28 | ||||
| -rw-r--r-- | src/libstd/sys_common/mutex.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys_common/net.rs | 22 | ||||
| -rw-r--r-- | src/libstd/sys_common/os_str_bytes.rs | 247 | ||||
| -rw-r--r-- | src/libstd/sys_common/poison.rs | 8 | ||||
| -rw-r--r-- | src/libstd/sys_common/remutex.rs | 10 | ||||
| -rw-r--r-- | src/libstd/sys_common/thread.rs | 3 | ||||
| -rw-r--r-- | src/libstd/sys_common/util.rs | 4 | ||||
| -rw-r--r-- | src/libstd/sys_common/wtf8.rs | 28 |
17 files changed, 510 insertions, 384 deletions
diff --git a/src/libstd/sys_common/alloc.rs b/src/libstd/sys_common/alloc.rs index 978a70bee09..1cfc7ed17f2 100644 --- a/src/libstd/sys_common/alloc.rs +++ b/src/libstd/sys_common/alloc.rs @@ -12,7 +12,8 @@ use crate::ptr; target_arch = "powerpc", target_arch = "powerpc64", target_arch = "asmjs", - target_arch = "wasm32")))] + target_arch = "wasm32", + target_arch = "hexagon")))] pub const MIN_ALIGN: usize = 8; #[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64", diff --git a/src/libstd/sys_common/at_exit_imp.rs b/src/libstd/sys_common/at_exit_imp.rs index 1181b861611..cdb72ee872e 100644 --- a/src/libstd/sys_common/at_exit_imp.rs +++ b/src/libstd/sys_common/at_exit_imp.rs @@ -2,12 +2,11 @@ //! //! Documentation can be found on the `rt::at_exit` function. -use crate::boxed::FnBox; use crate::ptr; use crate::mem; use crate::sys_common::mutex::Mutex; -type Queue = Vec<Box<dyn FnBox()>>; +type Queue = Vec<Box<dyn FnOnce()>>; // NB these are specifically not types from `std::sync` as they currently rely // on poisoning and this module needs to operate at a lower level than requiring @@ -61,7 +60,7 @@ pub fn cleanup() { } } -pub fn push(f: Box<dyn FnBox()>) -> bool { +pub fn push(f: Box<dyn FnOnce()>) -> bool { unsafe { let _guard = LOCK.lock(); if init() { diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 1a80908779e..bf37ff7ddbd 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -2,40 +2,17 @@ /// supported platforms. use crate::env; -use crate::io::prelude::*; use crate::io; +use crate::io::prelude::*; +use crate::mem; use crate::path::{self, Path}; use crate::ptr; -use crate::str; use crate::sync::atomic::{self, Ordering}; use crate::sys::mutex::Mutex; -use rustc_demangle::demangle; - -pub use crate::sys::backtrace::{ - unwind_backtrace, - resolve_symname, - foreach_symbol_fileline, - BacktraceContext -}; - -#[cfg(target_pointer_width = "64")] -pub const HEX_WIDTH: usize = 18; - -#[cfg(target_pointer_width = "32")] -pub const HEX_WIDTH: usize = 10; - -/// Represents an item in the backtrace list. See `unwind_backtrace` for how -/// it is created. -#[derive(Debug, Copy, Clone)] -pub struct Frame { - /// Exact address of the call that failed. - pub exact_position: *const u8, - /// Address of the enclosing function. - pub symbol_addr: *const u8, - /// Which inlined function is this frame referring to - pub inline_context: u32, -} +use backtrace::{BytesOrWideString, Frame, Symbol}; + +pub const HEX_WIDTH: usize = 2 + 2 * mem::size_of::<usize>(); /// Max number of frames to print. const MAX_NB_FRAMES: usize = 100; @@ -49,7 +26,7 @@ pub fn print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> { // test mode immediately return here to optimize away any references to the // libbacktrace symbols if cfg!(test) { - return Ok(()) + return Ok(()); } // Use a lock to prevent mixed output in multithreading context. @@ -63,75 +40,39 @@ pub fn print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> { } fn _print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> { - let mut frames = [Frame { - exact_position: ptr::null(), - symbol_addr: ptr::null(), - inline_context: 0, - }; MAX_NB_FRAMES]; - let (nb_frames, context) = unwind_backtrace(&mut frames)?; - let (skipped_before, skipped_after) = - filter_frames(&frames[..nb_frames], format, &context); - if skipped_before + skipped_after > 0 { - writeln!(w, "note: Some details are omitted, \ - run with `RUST_BACKTRACE=full` for a verbose backtrace.")?; - } writeln!(w, "stack backtrace:")?; - let filtered_frames = &frames[..nb_frames - skipped_after]; - for (index, frame) in filtered_frames.iter().skip(skipped_before).enumerate() { - resolve_symname(*frame, |symname| { - output(w, index, *frame, symname, format) - }, &context)?; - let has_more_filenames = foreach_symbol_fileline(*frame, |file, line| { - output_fileline(w, file, line, format) - }, &context)?; - if has_more_filenames { - w.write_all(b" <... and possibly more>")?; - } - } - - Ok(()) -} - -/// Returns a number of frames to remove at the beginning and at the end of the -/// backtrace, according to the backtrace format. -fn filter_frames(frames: &[Frame], - format: PrintFormat, - context: &BacktraceContext) -> (usize, usize) -{ - if format == PrintFormat::Full { - return (0, 0); - } - - let skipped_before = 0; - - let skipped_after = frames.len() - frames.iter().position(|frame| { - let mut is_marker = false; - let _ = resolve_symname(*frame, |symname| { - if let Some(mangled_symbol_name) = symname { - // Use grep to find the concerned functions - if mangled_symbol_name.contains("__rust_begin_short_backtrace") { - is_marker = true; - } + let mut printer = Printer::new(format, w); + unsafe { + backtrace::trace_unsynchronized(|frame| { + let mut hit = false; + backtrace::resolve_frame_unsynchronized(frame, |symbol| { + hit = true; + printer.output(frame, Some(symbol)); + }); + if !hit { + printer.output(frame, None); } - Ok(()) - }, context); - is_marker - }).unwrap_or(frames.len()); - - if skipped_before + skipped_after >= frames.len() { - // Avoid showing completely empty backtraces - return (0, 0); + !printer.done + }); } - - (skipped_before, skipped_after) + if printer.skipped { + writeln!( + w, + "note: Some details are omitted, \ + run with `RUST_BACKTRACE=full` for a verbose backtrace." + )?; + } + Ok(()) } - /// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. #[inline(never)] pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T - where F: FnOnce() -> T, F: Send, T: Send +where + F: FnOnce() -> T, + F: Send, + T: Send, { f() } @@ -156,7 +97,7 @@ pub fn log_enabled() -> Option<PrintFormat> { _ => return Some(PrintFormat::Full), } - let val = env::var_os("RUST_BACKTRACE").and_then(|x| + let val = env::var_os("RUST_BACKTRACE").and_then(|x| { if &x == "0" { None } else if &x == "full" { @@ -164,81 +105,141 @@ pub fn log_enabled() -> Option<PrintFormat> { } else { Some(PrintFormat::Short) } + }); + ENABLED.store( + match val { + Some(v) => v as isize, + None => 1, + }, + Ordering::SeqCst, ); - ENABLED.store(match val { - Some(v) => v as isize, - None => 1, - }, Ordering::SeqCst); val } -/// Prints the symbol of the backtrace frame. -/// -/// These output functions should now be used everywhere to ensure consistency. -/// You may want to also use `output_fileline`. -fn output(w: &mut dyn Write, idx: usize, frame: Frame, - s: Option<&str>, format: PrintFormat) -> io::Result<()> { - // Remove the `17: 0x0 - <unknown>` line. - if format == PrintFormat::Short && frame.exact_position == ptr::null() { - return Ok(()); +struct Printer<'a, 'b> { + format: PrintFormat, + done: bool, + skipped: bool, + idx: usize, + out: &'a mut (dyn Write + 'b), +} + +impl<'a, 'b> Printer<'a, 'b> { + fn new(format: PrintFormat, out: &'a mut (dyn Write + 'b)) -> Printer<'a, 'b> { + Printer { format, done: false, skipped: false, idx: 0, out } } - match format { - PrintFormat::Full => write!(w, - " {:2}: {:2$?} - ", - idx, - frame.exact_position, - HEX_WIDTH)?, - PrintFormat::Short => write!(w, " {:2}: ", idx)?, + + /// Prints the symbol of the backtrace frame. + /// + /// These output functions should now be used everywhere to ensure consistency. + /// You may want to also use `output_fileline`. + fn output(&mut self, frame: &Frame, symbol: Option<&Symbol>) { + if self.idx > MAX_NB_FRAMES { + self.done = true; + self.skipped = true; + return; + } + if self._output(frame, symbol).is_err() { + self.done = true; + } + self.idx += 1; } - match s { - Some(string) => { - let symbol = demangle(string); - match format { - PrintFormat::Full => write!(w, "{}", symbol)?, - // strip the trailing hash if short mode - PrintFormat::Short => write!(w, "{:#}", symbol)?, + + fn _output(&mut self, frame: &Frame, symbol: Option<&Symbol>) -> io::Result<()> { + if self.format == PrintFormat::Short { + if let Some(sym) = symbol.and_then(|s| s.name()).and_then(|s| s.as_str()) { + if sym.contains("__rust_begin_short_backtrace") { + self.skipped = true; + self.done = true; + return Ok(()); + } + } + + // Remove the `17: 0x0 - <unknown>` line. + if self.format == PrintFormat::Short && frame.ip() == ptr::null_mut() { + self.skipped = true; + return Ok(()); } } - None => w.write_all(b"<unknown>")?, - } - w.write_all(b"\n") -} -/// Prints the filename and line number of the backtrace frame. -/// -/// See also `output`. -#[allow(dead_code)] -fn output_fileline(w: &mut dyn Write, - file: &[u8], - line: u32, - format: PrintFormat) -> io::Result<()> { - // prior line: " ##: {:2$} - func" - w.write_all(b"")?; - match format { - PrintFormat::Full => write!(w, - " {:1$}", - "", - HEX_WIDTH)?, - PrintFormat::Short => write!(w, " ")?, - } + match self.format { + PrintFormat::Full => { + write!(self.out, " {:2}: {:2$?} - ", self.idx, frame.ip(), HEX_WIDTH)? + } + PrintFormat::Short => write!(self.out, " {:2}: ", self.idx)?, + } - let file = str::from_utf8(file).unwrap_or("<unknown>"); - let file_path = Path::new(file); - let mut already_printed = false; - if format == PrintFormat::Short && file_path.is_absolute() { - if let Ok(cwd) = env::current_dir() { - if let Ok(stripped) = file_path.strip_prefix(&cwd) { - if let Some(s) = stripped.to_str() { - write!(w, " at .{}{}:{}", path::MAIN_SEPARATOR, s, line)?; - already_printed = true; + match symbol.and_then(|s| s.name()) { + Some(symbol) => { + match self.format { + PrintFormat::Full => write!(self.out, "{}", symbol)?, + // Strip the trailing hash if short mode. + PrintFormat::Short => write!(self.out, "{:#}", symbol)?, } } + None => self.out.write_all(b"<unknown>")?, } - } - if !already_printed { - write!(w, " at {}:{}", file, line)?; + self.out.write_all(b"\n")?; + if let Some(sym) = symbol { + self.output_fileline(sym)?; + } + Ok(()) } - w.write_all(b"\n") -} + /// Prints the filename and line number of the backtrace frame. + /// + /// See also `output`. + fn output_fileline(&mut self, symbol: &Symbol) -> io::Result<()> { + #[cfg(windows)] + let path_buf; + let file = match symbol.filename_raw() { + #[cfg(unix)] + Some(BytesOrWideString::Bytes(bytes)) => { + use crate::os::unix::prelude::*; + Path::new(crate::ffi::OsStr::from_bytes(bytes)) + } + #[cfg(not(unix))] + Some(BytesOrWideString::Bytes(bytes)) => { + Path::new(crate::str::from_utf8(bytes).unwrap_or("<unknown>")) + } + #[cfg(windows)] + Some(BytesOrWideString::Wide(wide)) => { + use crate::os::windows::prelude::*; + path_buf = crate::ffi::OsString::from_wide(wide); + Path::new(&path_buf) + } + #[cfg(not(windows))] + Some(BytesOrWideString::Wide(_wide)) => { + Path::new("<unknown>") + } + None => return Ok(()), + }; + let line = match symbol.lineno() { + Some(line) => line, + None => return Ok(()), + }; + // prior line: " ##: {:2$} - func" + self.out.write_all(b"")?; + match self.format { + PrintFormat::Full => write!(self.out, " {:1$}", "", HEX_WIDTH)?, + PrintFormat::Short => write!(self.out, " ")?, + } + let mut already_printed = false; + if self.format == PrintFormat::Short && file.is_absolute() { + if let Ok(cwd) = env::current_dir() { + if let Ok(stripped) = file.strip_prefix(&cwd) { + if let Some(s) = stripped.to_str() { + write!(self.out, " at .{}{}:{}", path::MAIN_SEPARATOR, s, line)?; + already_printed = true; + } + } + } + } + if !already_printed { + write!(self.out, " at {}:{}", file.display(), line)?; + } + + self.out.write_all(b"\n") + } +} diff --git a/src/libstd/sys_common/bytestring.rs b/src/libstd/sys_common/bytestring.rs index 273d586a5a0..429ecf6281b 100644 --- a/src/libstd/sys_common/bytestring.rs +++ b/src/libstd/sys_common/bytestring.rs @@ -3,9 +3,9 @@ use crate::fmt::{Formatter, Result, Write}; use core::str::lossy::{Utf8Lossy, Utf8LossyChunk}; -pub fn debug_fmt_bytestring(slice: &[u8], f: &mut Formatter) -> Result { +pub fn debug_fmt_bytestring(slice: &[u8], f: &mut Formatter<'_>) -> Result { // Writes out a valid unicode string with the correct escape sequences - fn write_str_escaped(f: &mut Formatter, s: &str) -> Result { + fn write_str_escaped(f: &mut Formatter<'_>, s: &str) -> Result { for c in s.chars().flat_map(|c| c.escape_debug()) { f.write_char(c)? } @@ -32,7 +32,7 @@ mod tests { struct Helper<'a>(&'a [u8]); impl Debug for Helper<'_> { - fn fmt(&self, f: &mut Formatter) -> Result { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { debug_fmt_bytestring(self.0, f) } } diff --git a/src/libstd/sys_common/fs.rs b/src/libstd/sys_common/fs.rs new file mode 100644 index 00000000000..7152fcd215c --- /dev/null +++ b/src/libstd/sys_common/fs.rs @@ -0,0 +1,41 @@ +#![allow(dead_code)] // not used on all platforms + +use crate::path::Path; +use crate::fs; +use crate::io::{self, Error, ErrorKind}; + +pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { + if !from.is_file() { + return Err(Error::new(ErrorKind::InvalidInput, + "the source path is not an existing regular file")) + } + + let mut reader = fs::File::open(from)?; + let mut writer = fs::File::create(to)?; + let perm = reader.metadata()?.permissions(); + + let ret = io::copy(&mut reader, &mut writer)?; + fs::set_permissions(to, perm)?; + Ok(ret) +} + +pub fn remove_dir_all(path: &Path) -> io::Result<()> { + let filetype = fs::symlink_metadata(path)?.file_type(); + if filetype.is_symlink() { + fs::remove_file(path) + } else { + remove_dir_all_recursive(path) + } +} + +fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { + for child in fs::read_dir(path)? { + let child = child?; + if child.file_type()?.is_dir() { + remove_dir_all_recursive(&child.path())?; + } else { + fs::remove_file(&child.path())?; + } + } + fs::remove_dir(path) +} diff --git a/src/libstd/sys_common/gnu/libbacktrace.rs b/src/libstd/sys_common/gnu/libbacktrace.rs deleted file mode 100644 index 6cd050242dd..00000000000 --- a/src/libstd/sys_common/gnu/libbacktrace.rs +++ /dev/null @@ -1,175 +0,0 @@ -use backtrace_sys::backtrace_state; - -use crate::ffi::CStr; -use crate::io; -use crate::mem; -use crate::ptr; -use crate::sys::backtrace::BacktraceContext; -use crate::sys_common::backtrace::Frame; - -pub fn foreach_symbol_fileline<F>(frame: Frame, - mut f: F, - _: &BacktraceContext) -> io::Result<bool> -where F: FnMut(&[u8], u32) -> io::Result<()> -{ - // pcinfo may return an arbitrary number of file:line pairs, - // in the order of stack trace (i.e., inlined calls first). - // in order to avoid allocation, we stack-allocate a fixed size of entries. - const FILELINE_SIZE: usize = 32; - let mut fileline_buf = [(ptr::null(), !0); FILELINE_SIZE]; - let ret; - let fileline_count = { - let state = unsafe { init_state() }; - if state.is_null() { - return Err(io::Error::new( - io::ErrorKind::Other, - "failed to allocate libbacktrace state") - ) - } - let mut fileline_win: &mut [FileLine] = &mut fileline_buf; - let fileline_addr = &mut fileline_win as *mut &mut [FileLine]; - ret = unsafe { - backtrace_sys::backtrace_pcinfo( - state, - frame.exact_position as libc::uintptr_t, - pcinfo_cb, - error_cb, - fileline_addr as *mut libc::c_void, - ) - }; - FILELINE_SIZE - fileline_win.len() - }; - if ret == 0 { - for &(file, line) in &fileline_buf[..fileline_count] { - if file.is_null() { continue; } // just to be sure - let file = unsafe { CStr::from_ptr(file).to_bytes() }; - f(file, line)?; - } - Ok(fileline_count == FILELINE_SIZE) - } else { - Ok(false) - } -} - -/// Converts a pointer to symbol to its string value. -pub fn resolve_symname<F>(frame: Frame, - callback: F, - _: &BacktraceContext) -> io::Result<()> - where F: FnOnce(Option<&str>) -> io::Result<()> -{ - let symname = { - let state = unsafe { init_state() }; - if state.is_null() { - return Err(io::Error::new( - io::ErrorKind::Other, - "failed to allocate libbacktrace state") - ) - } - let mut data: *const libc::c_char = ptr::null(); - let data_addr = &mut data as *mut *const libc::c_char; - let ret = unsafe { - backtrace_sys::backtrace_syminfo( - state, - frame.symbol_addr as libc::uintptr_t, - syminfo_cb, - error_cb, - data_addr as *mut libc::c_void, - ) - }; - if ret == 0 || data.is_null() { - None - } else { - unsafe { - CStr::from_ptr(data).to_str().ok() - } - } - }; - callback(symname) -} - -//////////////////////////////////////////////////////////////////////// -// helper callbacks -//////////////////////////////////////////////////////////////////////// - -type FileLine = (*const libc::c_char, u32); - -extern fn error_cb(_data: *mut libc::c_void, _msg: *const libc::c_char, - _errnum: libc::c_int) { - // do nothing for now -} -extern fn syminfo_cb(data: *mut libc::c_void, - _pc: libc::uintptr_t, - symname: *const libc::c_char, - _symval: libc::uintptr_t, - _symsize: libc::uintptr_t) { - let slot = data as *mut *const libc::c_char; - unsafe { *slot = symname; } -} -extern fn pcinfo_cb(data: *mut libc::c_void, - _pc: libc::uintptr_t, - filename: *const libc::c_char, - lineno: libc::c_int, - _function: *const libc::c_char) -> libc::c_int { - if !filename.is_null() { - let slot = data as *mut &mut [FileLine]; - let buffer = unsafe {ptr::read(slot)}; - - // if the buffer is not full, add file:line to the buffer - // and adjust the buffer for next possible calls to pcinfo_cb. - if !buffer.is_empty() { - buffer[0] = (filename, lineno as u32); - unsafe { ptr::write(slot, &mut buffer[1..]); } - } - } - - 0 -} - -// The libbacktrace API supports creating a state, but it does not -// support destroying a state. I personally take this to mean that a -// state is meant to be created and then live forever. -// -// I would love to register an at_exit() handler which cleans up this -// state, but libbacktrace provides no way to do so. -// -// With these constraints, this function has a statically cached state -// that is calculated the first time this is requested. Remember that -// backtracing all happens serially (one global lock). -// -// Things don't work so well on not-Linux since libbacktrace can't track -// down that executable this is. We at one point used env::current_exe but -// it turns out that there are some serious security issues with that -// approach. -// -// Specifically, on certain platforms like BSDs, a malicious actor can cause -// an arbitrary file to be placed at the path returned by current_exe. -// libbacktrace does not behave defensively in the presence of ill-formed -// DWARF information, and has been demonstrated to segfault in at least one -// case. There is no evidence at the moment to suggest that a more carefully -// constructed file can't cause arbitrary code execution. As a result of all -// of this, we don't hint libbacktrace with the path to the current process. -unsafe fn init_state() -> *mut backtrace_state { - static mut STATE: *mut backtrace_state = ptr::null_mut(); - if !STATE.is_null() { return STATE } - - let filename = match crate::sys::backtrace::gnu::get_executable_filename() { - Ok((filename, file)) => { - // filename is purposely leaked here since libbacktrace requires - // it to stay allocated permanently, file is also leaked so that - // the file stays locked - let filename_ptr = filename.as_ptr(); - mem::forget(filename); - mem::forget(file); - filename_ptr - }, - Err(_) => ptr::null(), - }; - - STATE = backtrace_sys::backtrace_create_state( - filename, - 0, - error_cb, - ptr::null_mut(), - ); - STATE -} diff --git a/src/libstd/sys_common/gnu/mod.rs b/src/libstd/sys_common/gnu/mod.rs deleted file mode 100644 index d6959697f2a..00000000000 --- a/src/libstd/sys_common/gnu/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![allow(missing_docs)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] - -pub mod libbacktrace; diff --git a/src/libstd/sys_common/io.rs b/src/libstd/sys_common/io.rs index 44b0963302d..8789abe55c3 100644 --- a/src/libstd/sys_common/io.rs +++ b/src/libstd/sys_common/io.rs @@ -16,7 +16,7 @@ pub mod test { p.join(path) } - pub fn path<'a>(&'a self) -> &'a Path { + pub fn path(&self) -> &Path { let TempDir(ref p) = *self; p } diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index 1fc32365408..9190a3b0d5f 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -28,6 +28,17 @@ macro_rules! rtassert { }) } +#[allow(unused_macros)] // not used on all platforms +macro_rules! rtunwrap { + ($ok:ident, $e:expr) => (match $e { + $ok(v) => v, + ref err => { + let err = err.as_ref().map(|_|()); // map Ok/Some which might not be Debug + rtabort!(concat!("unwrap failed: ", stringify!($e), " = {:?}"), err) + }, + }) +} + pub mod alloc; pub mod at_exit_imp; #[cfg(feature = "backtrace")] @@ -35,6 +46,13 @@ pub mod backtrace; pub mod condvar; pub mod io; pub mod mutex; +#[cfg(any(rustdoc, // see `mod os`, docs are generated for multiple platforms + unix, + target_os = "redox", + target_os = "cloudabi", + target_arch = "wasm32", + all(target_vendor = "fortanix", target_env = "sgx")))] +pub mod os_str_bytes; pub mod poison; pub mod remutex; pub mod rwlock; @@ -45,11 +63,11 @@ pub mod util; pub mod wtf8; pub mod bytestring; pub mod process; +pub mod fs; -cfg_if! { +cfg_if::cfg_if! { if #[cfg(any(target_os = "cloudabi", target_os = "l4re", - target_os = "redox", all(target_arch = "wasm32", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))] { pub use crate::sys::net; @@ -58,12 +76,6 @@ cfg_if! { } } -#[cfg(feature = "backtrace")] -#[cfg(any(all(unix, not(target_os = "emscripten")), - all(windows, target_env = "gnu"), - target_os = "redox"))] -pub mod gnu; - // common error constructors /// A trait for viewing representations from std types diff --git a/src/libstd/sys_common/mutex.rs b/src/libstd/sys_common/mutex.rs index 4b58cac7941..28d85949ffa 100644 --- a/src/libstd/sys_common/mutex.rs +++ b/src/libstd/sys_common/mutex.rs @@ -38,7 +38,7 @@ impl Mutex { /// Calls raw_lock() and then returns an RAII guard to guarantee the mutex /// will be unlocked. #[inline] - pub unsafe fn lock(&self) -> MutexGuard { + pub unsafe fn lock(&self) -> MutexGuard<'_> { self.raw_lock(); MutexGuard(&self.0) } diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs index b9505aaa69b..391f670346f 100644 --- a/src/libstd/sys_common/net.rs +++ b/src/libstd/sys_common/net.rs @@ -1,7 +1,7 @@ use crate::cmp; use crate::ffi::CString; use crate::fmt; -use crate::io::{self, Error, ErrorKind, IoVec, IoVecMut}; +use crate::io::{self, Error, ErrorKind, IoSlice, IoSliceMut}; use crate::mem; use crate::net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr}; use crate::ptr; @@ -37,12 +37,12 @@ use crate::sys::net::netc::IPV6_DROP_MEMBERSHIP; #[cfg(any(target_os = "linux", target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", - target_os = "haiku", target_os = "bitrig"))] + target_os = "haiku"))] use libc::MSG_NOSIGNAL; #[cfg(not(any(target_os = "linux", target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", - target_os = "haiku", target_os = "bitrig")))] + target_os = "haiku")))] const MSG_NOSIGNAL: c_int = 0x0; //////////////////////////////////////////////////////////////////////////////// @@ -256,7 +256,7 @@ impl TcpStream { self.inner.read(buf) } - pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> { + pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { self.inner.read_vectored(bufs) } @@ -271,7 +271,7 @@ impl TcpStream { Ok(ret as usize) } - pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> { + pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { self.inner.write_vectored(bufs) } @@ -328,7 +328,7 @@ impl FromInner<Socket> for TcpStream { } impl fmt::Debug for TcpStream { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut res = f.debug_struct("TcpStream"); if let Ok(addr) = self.socket_addr() { @@ -435,7 +435,7 @@ impl FromInner<Socket> for TcpListener { } impl fmt::Debug for TcpListener { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut res = f.debug_struct("TcpListener"); if let Ok(addr) = self.socket_addr() { @@ -472,6 +472,12 @@ impl UdpSocket { pub fn into_socket(self) -> Socket { self.inner } + pub fn peer_addr(&self) -> io::Result<SocketAddr> { + sockname(|buf, len| unsafe { + c::getpeername(*self.inner.as_inner(), buf, len) + }) + } + pub fn socket_addr(&self) -> io::Result<SocketAddr> { sockname(|buf, len| unsafe { c::getsockname(*self.inner.as_inner(), buf, len) @@ -638,7 +644,7 @@ impl FromInner<Socket> for UdpSocket { } impl fmt::Debug for UdpSocket { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut res = f.debug_struct("UdpSocket"); if let Ok(addr) = self.socket_addr() { diff --git a/src/libstd/sys_common/os_str_bytes.rs b/src/libstd/sys_common/os_str_bytes.rs new file mode 100644 index 00000000000..a4961974d89 --- /dev/null +++ b/src/libstd/sys_common/os_str_bytes.rs @@ -0,0 +1,247 @@ +//! The underlying OsString/OsStr implementation on Unix and many other +//! systems: just a `Vec<u8>`/`[u8]`. + +use crate::borrow::Cow; +use crate::ffi::{OsStr, OsString}; +use crate::fmt; +use crate::str; +use crate::mem; +use crate::rc::Rc; +use crate::sync::Arc; +use crate::sys_common::{FromInner, IntoInner, AsInner}; +use crate::sys_common::bytestring::debug_fmt_bytestring; + +use core::str::lossy::Utf8Lossy; + +#[derive(Clone, Hash)] +pub(crate) struct Buf { + pub inner: Vec<u8> +} + +pub(crate) struct Slice { + pub inner: [u8] +} + +impl fmt::Debug for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + debug_fmt_bytestring(&self.inner, formatter) + } +} + +impl fmt::Display for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter) + } +} + +impl fmt::Debug for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(self.as_slice(), formatter) + } +} + +impl fmt::Display for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self.as_slice(), formatter) + } +} + +impl IntoInner<Vec<u8>> for Buf { + fn into_inner(self) -> Vec<u8> { + self.inner + } +} + +impl AsInner<[u8]> for Buf { + fn as_inner(&self) -> &[u8] { + &self.inner + } +} + + +impl Buf { + pub fn from_string(s: String) -> Buf { + Buf { inner: s.into_bytes() } + } + + #[inline] + pub fn with_capacity(capacity: usize) -> Buf { + Buf { + inner: Vec::with_capacity(capacity) + } + } + + #[inline] + pub fn clear(&mut self) { + self.inner.clear() + } + + #[inline] + pub fn capacity(&self) -> usize { + self.inner.capacity() + } + + #[inline] + pub fn reserve(&mut self, additional: usize) { + self.inner.reserve(additional) + } + + #[inline] + pub fn reserve_exact(&mut self, additional: usize) { + self.inner.reserve_exact(additional) + } + + #[inline] + pub fn shrink_to_fit(&mut self) { + self.inner.shrink_to_fit() + } + + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + + pub fn as_slice(&self) -> &Slice { + unsafe { mem::transmute(&*self.inner) } + } + + pub fn into_string(self) -> Result<String, Buf> { + String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() } ) + } + + pub fn push_slice(&mut self, s: &Slice) { + self.inner.extend_from_slice(&s.inner) + } + + #[inline] + pub fn into_box(self) -> Box<Slice> { + unsafe { mem::transmute(self.inner.into_boxed_slice()) } + } + + #[inline] + pub fn from_box(boxed: Box<Slice>) -> Buf { + let inner: Box<[u8]> = unsafe { mem::transmute(boxed) }; + Buf { inner: inner.into_vec() } + } + + #[inline] + pub fn into_arc(&self) -> Arc<Slice> { + self.as_slice().into_arc() + } + + #[inline] + pub fn into_rc(&self) -> Rc<Slice> { + self.as_slice().into_rc() + } +} + +impl Slice { + fn from_u8_slice(s: &[u8]) -> &Slice { + unsafe { mem::transmute(s) } + } + + pub fn from_str(s: &str) -> &Slice { + Slice::from_u8_slice(s.as_bytes()) + } + + pub fn to_str(&self) -> Option<&str> { + str::from_utf8(&self.inner).ok() + } + + pub fn to_string_lossy(&self) -> Cow<'_, str> { + String::from_utf8_lossy(&self.inner) + } + + pub fn to_owned(&self) -> Buf { + Buf { inner: self.inner.to_vec() } + } + + #[inline] + pub fn into_box(&self) -> Box<Slice> { + let boxed: Box<[u8]> = self.inner.into(); + unsafe { mem::transmute(boxed) } + } + + pub fn empty_box() -> Box<Slice> { + let boxed: Box<[u8]> = Default::default(); + unsafe { mem::transmute(boxed) } + } + + #[inline] + pub fn into_arc(&self) -> Arc<Slice> { + let arc: Arc<[u8]> = Arc::from(&self.inner); + unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) } + } + + #[inline] + pub fn into_rc(&self) -> Rc<Slice> { + let rc: Rc<[u8]> = Rc::from(&self.inner); + unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) } + } +} + +/// Platform-specific extensions to [`OsString`]. +/// +/// [`OsString`]: ../../../../std/ffi/struct.OsString.html +#[stable(feature = "rust1", since = "1.0.0")] +pub trait OsStringExt { + /// Creates an [`OsString`] from a byte vector. + /// + /// See the module docmentation for an example. + /// + /// [`OsString`]: ../../../ffi/struct.OsString.html + #[stable(feature = "rust1", since = "1.0.0")] + fn from_vec(vec: Vec<u8>) -> Self; + + /// Yields the underlying byte vector of this [`OsString`]. + /// + /// See the module docmentation for an example. + /// + /// [`OsString`]: ../../../ffi/struct.OsString.html + #[stable(feature = "rust1", since = "1.0.0")] + fn into_vec(self) -> Vec<u8>; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl OsStringExt for OsString { + fn from_vec(vec: Vec<u8>) -> OsString { + FromInner::from_inner(Buf { inner: vec }) + } + fn into_vec(self) -> Vec<u8> { + self.into_inner().inner + } +} + +/// Platform-specific extensions to [`OsStr`]. +/// +/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html +#[stable(feature = "rust1", since = "1.0.0")] +pub trait OsStrExt { + #[stable(feature = "rust1", since = "1.0.0")] + /// Creates an [`OsStr`] from a byte slice. + /// + /// See the module docmentation for an example. + /// + /// [`OsStr`]: ../../../ffi/struct.OsStr.html + fn from_bytes(slice: &[u8]) -> &Self; + + /// Gets the underlying byte view of the [`OsStr`] slice. + /// + /// See the module docmentation for an example. + /// + /// [`OsStr`]: ../../../ffi/struct.OsStr.html + #[stable(feature = "rust1", since = "1.0.0")] + fn as_bytes(&self) -> &[u8]; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl OsStrExt for OsStr { + #[inline] + fn from_bytes(slice: &[u8]) -> &OsStr { + unsafe { mem::transmute(slice) } + } + #[inline] + fn as_bytes(&self) -> &[u8] { + &self.as_inner().inner + } +} diff --git a/src/libstd/sys_common/poison.rs b/src/libstd/sys_common/poison.rs index d2294235666..adac45f2d59 100644 --- a/src/libstd/sys_common/poison.rs +++ b/src/libstd/sys_common/poison.rs @@ -136,14 +136,14 @@ pub type TryLockResult<Guard> = Result<Guard, TryLockError<Guard>>; #[stable(feature = "rust1", since = "1.0.0")] impl<T> fmt::Debug for PoisonError<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { "PoisonError { inner: .. }".fmt(f) } } #[stable(feature = "rust1", since = "1.0.0")] impl<T> fmt::Display for PoisonError<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { "poisoned lock: another task failed inside".fmt(f) } } @@ -214,7 +214,7 @@ impl<T> From<PoisonError<T>> for TryLockError<T> { #[stable(feature = "rust1", since = "1.0.0")] impl<T> fmt::Debug for TryLockError<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { TryLockError::Poisoned(..) => "Poisoned(..)".fmt(f), TryLockError::WouldBlock => "WouldBlock".fmt(f) @@ -224,7 +224,7 @@ impl<T> fmt::Debug for TryLockError<T> { #[stable(feature = "rust1", since = "1.0.0")] impl<T> fmt::Display for TryLockError<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { TryLockError::Poisoned(..) => "poisoned lock: another task failed inside", TryLockError::WouldBlock => "try_lock failed because the operation would block" diff --git a/src/libstd/sys_common/remutex.rs b/src/libstd/sys_common/remutex.rs index 2aec361d7a4..f08b13c4aa2 100644 --- a/src/libstd/sys_common/remutex.rs +++ b/src/libstd/sys_common/remutex.rs @@ -72,7 +72,7 @@ impl<T> ReentrantMutex<T> { /// If another user of this mutex panicked while holding the mutex, then /// this call will return failure if the mutex would otherwise be /// acquired. - pub fn lock(&self) -> LockResult<ReentrantMutexGuard<T>> { + pub fn lock(&self) -> LockResult<ReentrantMutexGuard<'_, T>> { unsafe { self.inner.lock() } ReentrantMutexGuard::new(&self) } @@ -89,7 +89,7 @@ impl<T> ReentrantMutex<T> { /// If another user of this mutex panicked while holding the mutex, then /// this call will return failure if the mutex would otherwise be /// acquired. - pub fn try_lock(&self) -> TryLockResult<ReentrantMutexGuard<T>> { + pub fn try_lock(&self) -> TryLockResult<ReentrantMutexGuard<'_, T>> { if unsafe { self.inner.try_lock() } { Ok(ReentrantMutexGuard::new(&self)?) } else { @@ -108,7 +108,7 @@ impl<T> Drop for ReentrantMutex<T> { } impl<T: fmt::Debug + 'static> fmt::Debug for ReentrantMutex<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.try_lock() { Ok(guard) => f.debug_struct("ReentrantMutex").field("data", &*guard).finish(), Err(TryLockError::Poisoned(err)) => { @@ -117,7 +117,9 @@ impl<T: fmt::Debug + 'static> fmt::Debug for ReentrantMutex<T> { Err(TryLockError::WouldBlock) => { struct LockedPlaceholder; impl fmt::Debug for LockedPlaceholder { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("<locked>") } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("<locked>") + } } f.debug_struct("ReentrantMutex").field("data", &LockedPlaceholder).finish() diff --git a/src/libstd/sys_common/thread.rs b/src/libstd/sys_common/thread.rs index b2142e75308..6ab0d5cbe9c 100644 --- a/src/libstd/sys_common/thread.rs +++ b/src/libstd/sys_common/thread.rs @@ -1,4 +1,3 @@ -use crate::boxed::FnBox; use crate::env; use crate::sync::atomic::{self, Ordering}; use crate::sys::stack_overflow; @@ -11,7 +10,7 @@ pub unsafe fn start_thread(main: *mut u8) { let _handler = stack_overflow::Handler::new(); // Finally, let's run some code. - Box::from_raw(main as *mut Box<dyn FnBox()>)() + Box::from_raw(main as *mut Box<dyn FnOnce()>)() } pub fn min_stack() -> usize { diff --git a/src/libstd/sys_common/util.rs b/src/libstd/sys_common/util.rs index 206443a6736..7936dd35999 100644 --- a/src/libstd/sys_common/util.rs +++ b/src/libstd/sys_common/util.rs @@ -3,7 +3,7 @@ use crate::io::prelude::*; use crate::sys::stdio::panic_output; use crate::thread; -pub fn dumb_print(args: fmt::Arguments) { +pub fn dumb_print(args: fmt::Arguments<'_>) { if let Some(mut out) = panic_output() { let _ = out.write_fmt(args); } @@ -14,7 +14,7 @@ pub fn dumb_print(args: fmt::Arguments) { // crate::intrinsics::abort() may be used instead. The above implementations cover // all targets currently supported by libstd. -pub fn abort(args: fmt::Arguments) -> ! { +pub fn abort(args: fmt::Arguments<'_>) -> ! { dumb_print(format_args!("fatal runtime error: {}\n", args)); unsafe { crate::sys::abort_internal(); } } diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index b15239e8d87..81e606fc165 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -46,7 +46,7 @@ pub struct CodePoint { /// Example: `U+1F4A9` impl fmt::Debug for CodePoint { #[inline] - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { write!(formatter, "U+{:04X}", self.value) } } @@ -134,7 +134,7 @@ impl ops::DerefMut for Wtf8Buf { /// Example: `"a\u{D800}"` for a string with code points [U+0061, U+D800] impl fmt::Debug for Wtf8Buf { #[inline] - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, formatter) } } @@ -146,10 +146,10 @@ impl Wtf8Buf { Wtf8Buf { bytes: Vec::new() } } - /// Creates a new, empty WTF-8 string with pre-allocated capacity for `n` bytes. + /// Creates a new, empty WTF-8 string with pre-allocated capacity for `capacity` bytes. #[inline] - pub fn with_capacity(n: usize) -> Wtf8Buf { - Wtf8Buf { bytes: Vec::with_capacity(n) } + pub fn with_capacity(capacity: usize) -> Wtf8Buf { + Wtf8Buf { bytes: Vec::with_capacity(capacity) } } /// Creates a WTF-8 string from a UTF-8 `String`. @@ -388,9 +388,7 @@ impl Extend<CodePoint> for Wtf8Buf { let (low, _high) = iterator.size_hint(); // Lower bound of one byte per code point (ASCII only) self.bytes.reserve(low); - for code_point in iterator { - self.push(code_point); - } + iterator.for_each(move |code_point| self.push(code_point)); } } @@ -411,8 +409,8 @@ impl AsInner<[u8]> for Wtf8 { /// and surrogates as `\u` followed by four hexadecimal digits. /// Example: `"a\u{D800}"` for a slice with code points [U+0061, U+D800] impl fmt::Debug for Wtf8 { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - fn write_str_escaped(f: &mut fmt::Formatter, s: &str) -> fmt::Result { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fn write_str_escaped(f: &mut fmt::Formatter<'_>, s: &str) -> fmt::Result { use crate::fmt::Write; for c in s.chars().flat_map(|c| c.escape_debug()) { f.write_char(c)? @@ -441,7 +439,7 @@ impl fmt::Debug for Wtf8 { } impl fmt::Display for Wtf8 { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { let wtf8_bytes = &self.bytes; let mut pos = 0; loop { @@ -522,7 +520,7 @@ impl Wtf8 { /// Returns an iterator for the string’s code points. #[inline] - pub fn code_points(&self) -> Wtf8CodePoints { + pub fn code_points(&self) -> Wtf8CodePoints<'_> { Wtf8CodePoints { bytes: self.bytes.iter() } } @@ -547,7 +545,7 @@ impl Wtf8 { /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”). /// /// This only copies the data if necessary (if it contains any surrogate). - pub fn to_string_lossy(&self) -> Cow<str> { + pub fn to_string_lossy(&self) -> Cow<'_, str> { let surrogate_pos = match self.next_surrogate(0) { None => return Cow::Borrowed(unsafe { str::from_utf8_unchecked(&self.bytes) }), Some((pos, _)) => pos, @@ -579,7 +577,7 @@ impl Wtf8 { /// calling `Wtf8Buf::from_ill_formed_utf16` on the resulting code units /// would always return the original WTF-8 string. #[inline] - pub fn encode_wide(&self) -> EncodeWide { + pub fn encode_wide(&self) -> EncodeWide<'_> { EncodeWide { code_points: self.code_points(), extra: 0 } } @@ -1228,7 +1226,7 @@ mod tests { assert_eq!(Wtf8::from_str("aé 💩").to_string_lossy(), Cow::Borrowed("aé 💩")); let mut string = Wtf8Buf::from_str("aé 💩"); string.push(CodePoint::from_u32(0xD800).unwrap()); - let expected: Cow<str> = Cow::Owned(String::from("aé 💩�")); + let expected: Cow<'_, str> = Cow::Owned(String::from("aé 💩�")); assert_eq!(string.to_string_lossy(), expected); } |
