From 090a968fe7680cce0d3aa8fde25a5dc48948e43e Mon Sep 17 00:00:00 2001 From: Ryan Cumming Date: Wed, 10 Jan 2018 20:13:03 +1100 Subject: Only link res_init() on GNU/*nix To workaround a bug in glibc <= 2.26 lookup_host() calls res_init() based on the glibc version detected at runtime. While this avoids calling res_init() on platforms where it's not required we will still end up linking against the symbol. This causes an issue on macOS where res_init() is implemented in a separate library (libresolv.9.dylib) from the main libc. While this is harmless for standalone programs it becomes a problem if Rust code is statically linked against another program. If the linked program doesn't already specify -lresolv it will cause the link to fail. This is captured in issue #46797 Fix this by hooking in to the glibc workaround in `cvt_gai` and only activating it for the "gnu" environment on Unix This should include all glibc platforms while excluding musl, windows-gnu, macOS, FreeBSD, etc. This has the side benefit of removing the #[cfg] in sys_common; only unix.rs has code related to the workaround now. --- src/libstd/sys/unix/l4re.rs | 4 ---- src/libstd/sys/unix/net.rs | 20 +++++++++++++------- 2 files changed, 13 insertions(+), 11 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/l4re.rs b/src/libstd/sys/unix/l4re.rs index c3e8d0b7d95..21218489679 100644 --- a/src/libstd/sys/unix/l4re.rs +++ b/src/libstd/sys/unix/l4re.rs @@ -437,9 +437,5 @@ pub mod net { pub fn lookup_host(_: &str) -> io::Result { unimpl!(); } - - pub fn res_init_if_glibc_before_2_26() -> io::Result<()> { - unimpl!(); - } } diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index e775f857f2b..3f65975e608 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -51,6 +51,10 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { if err == 0 { return Ok(()) } + + // We may need to trigger a glibc workaround. See on_resolver_failure() for details. + on_resolver_failure(); + if err == EAI_SYSTEM { return Err(io::Error::last_os_error()) } @@ -377,21 +381,22 @@ impl IntoInner for Socket { // res_init unconditionally, we call it only when we detect we're linking // against glibc version < 2.26. (That is, when we both know its needed and // believe it's thread-safe). -pub fn res_init_if_glibc_before_2_26() -> io::Result<()> { +#[cfg(target_env = "gnu")] +fn on_resolver_failure() { // If the version fails to parse, we treat it the same as "not glibc". if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) { if let Some(version) = parse_glibc_version(version_str) { if version < (2, 26) { - let ret = unsafe { libc::res_init() }; - if ret != 0 { - return Err(io::Error::last_os_error()); - } + unsafe { libc::res_init() }; } } } - Ok(()) } +#[cfg(not(target_env = "gnu"))] +fn on_resolver_failure() {} + +#[cfg(target_env = "gnu")] fn glibc_version_cstr() -> Option<&'static CStr> { weak! { fn gnu_get_libc_version() -> *const libc::c_char @@ -405,6 +410,7 @@ fn glibc_version_cstr() -> Option<&'static CStr> { // Returns Some((major, minor)) if the string is a valid "x.y" version, // ignoring any extra dot-separated parts. Otherwise return None. +#[cfg(target_env = "gnu")] fn parse_glibc_version(version: &str) -> Option<(usize, usize)> { let mut parsed_ints = version.split(".").map(str::parse::).fuse(); match (parsed_ints.next(), parsed_ints.next()) { @@ -413,7 +419,7 @@ fn parse_glibc_version(version: &str) -> Option<(usize, usize)> { } } -#[cfg(test)] +#[cfg(all(test, taget_env = "gnu"))] mod test { use super::*; -- cgit 1.4.1-3-g733a5 From 14982db2d68268458a3de03e395b2e9afe518b50 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sat, 23 Dec 2017 19:28:33 -0800 Subject: in which the unused-parens lint comes to cover function and method args Resolves #46137. --- src/liballoc/vec_deque.rs | 2 +- src/librustc_apfloat/ieee.rs | 2 +- src/librustc_lint/unused.rs | 12 ++++++++++++ src/librustc_mir/dataflow/impls/borrows.rs | 2 +- src/librustc_resolve/lib.rs | 2 +- src/libstd/sys/unix/thread.rs | 4 ++-- src/test/compile-fail/lint-unnecessary-parens.rs | 12 +++++++----- 7 files changed, 25 insertions(+), 11 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs index f56aa23a4eb..1f6c6660d9b 100644 --- a/src/liballoc/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -2480,7 +2480,7 @@ impl From> for Vec { if other.is_contiguous() { ptr::copy(buf.offset(tail as isize), buf, len); } else { - if (tail - head) >= cmp::min((cap - tail), head) { + if (tail - head) >= cmp::min(cap - tail, head) { // There is enough free space in the centre for the shortest block so we can // do this in at most three copy moves. if (cap - tail) > head { diff --git a/src/librustc_apfloat/ieee.rs b/src/librustc_apfloat/ieee.rs index 3e76b60b84a..7abd02b6656 100644 --- a/src/librustc_apfloat/ieee.rs +++ b/src/librustc_apfloat/ieee.rs @@ -1434,7 +1434,7 @@ impl Float for IeeeFloat { let max_change = S::MAX_EXP as i32 - (S::MIN_EXP as i32 - sig_bits) + 1; // Clamp to one past the range ends to let normalize handle overflow. - let exp_change = cmp::min(cmp::max(exp as i32, (-max_change - 1)), max_change); + let exp_change = cmp::min(cmp::max(exp as i32, -max_change - 1), max_change); self.exp = self.exp.saturating_add(exp_change as ExpInt); self = self.normalize(round, Loss::ExactlyZero).value; if self.is_nan() { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 4e066ecf999..ef6475f9ee4 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -302,6 +302,18 @@ impl EarlyLintPass for UnusedParens { Assign(_, ref value) => (value, "assigned value", false), AssignOp(.., ref value) => (value, "assigned value", false), InPlace(_, ref value) => (value, "emplacement value", false), + Call(_, ref args) => { + for arg in args { + self.check_unused_parens_core(cx, arg, "function argument", false) + } + return; + }, + MethodCall(_, ref args) => { + for arg in &args[1..] { // first "argument" is self (which sometimes needs parens) + self.check_unused_parens_core(cx, arg, "method argument", false) + } + return; + } _ => return, }; self.check_unused_parens_core(cx, &value, msg, struct_lit_needs_parens); diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index f76aea19677..f543a33b130 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -131,7 +131,7 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> { } impl ReserveOrActivateIndex { - fn reserved(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new((i.index() * 2)) } + fn reserved(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new(i.index() * 2) } fn active(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new((i.index() * 2) + 1) } pub(crate) fn is_reservation(self) -> bool { self.index() % 2 == 0 } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 5b9b3767cb6..231a32c4382 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -963,7 +963,7 @@ impl<'a> ModuleData<'a> { unresolved_invocations: RefCell::new(FxHashSet()), no_implicit_prelude: false, glob_importers: RefCell::new(Vec::new()), - globs: RefCell::new((Vec::new())), + globs: RefCell::new(Vec::new()), traits: RefCell::new(None), populated: Cell::new(normal_ancestor_id.is_local()), span, diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index cb249af4254..525882c1e1e 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -311,8 +311,8 @@ pub mod guard { #[cfg(target_os = "macos")] pub unsafe fn current() -> Option { - Some((libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize - - libc::pthread_get_stacksize_np(libc::pthread_self()))) + Some(libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize - + libc::pthread_get_stacksize_np(libc::pthread_self())) } #[cfg(any(target_os = "openbsd", target_os = "bitrig"))] diff --git a/src/test/compile-fail/lint-unnecessary-parens.rs b/src/test/compile-fail/lint-unnecessary-parens.rs index b5eac73a55d..7cd0a6bbf0f 100644 --- a/src/test/compile-fail/lint-unnecessary-parens.rs +++ b/src/test/compile-fail/lint-unnecessary-parens.rs @@ -13,19 +13,19 @@ #[derive(Eq, PartialEq)] struct X { y: bool } impl X { - fn foo(&self) -> bool { self.y } + fn foo(&self, conjunct: bool) -> bool { self.y && conjunct } } fn foo() -> isize { return (1); //~ ERROR unnecessary parentheses around `return` value } -fn bar() -> X { - return (X { y: true }); //~ ERROR unnecessary parentheses around `return` value +fn bar(y: bool) -> X { + return (X { y }); //~ ERROR unnecessary parentheses around `return` value } fn main() { foo(); - bar(); + bar((true)); //~ ERROR unnecessary parentheses around function argument if (true) {} //~ ERROR unnecessary parentheses around `if` condition while (true) {} //~ ERROR unnecessary parentheses around `while` condition @@ -40,13 +40,15 @@ fn main() { if (X { y: true } == v) {} if (X { y: false }.y) {} - while (X { y: false }.foo()) {} + while (X { y: false }.foo(true)) {} while (true | X { y: false }.y) {} match (X { y: false }) { _ => {} } + X { y: false }.foo((true)); //~ ERROR unnecessary parentheses around method argument + let mut _a = (0); //~ ERROR unnecessary parentheses around assigned value _a = (0); //~ ERROR unnecessary parentheses around assigned value _a += (1); //~ ERROR unnecessary parentheses around assigned value -- cgit 1.4.1-3-g733a5 From 831ff775703eb5126f741fc3be1cf829ec060011 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Thu, 25 Jan 2018 15:08:48 -0800 Subject: implement Send for process::Command on unix closes https://github.com/rust-lang/rust/issues/47751 --- src/libstd/sys/unix/process/process_common.rs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index c53bcdbf8e3..b09fc36dee0 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -87,6 +87,11 @@ pub enum Stdio { Fd(FileDesc), } +// Command is not Send by default due to the Command.argv field containing a raw pointers. However +// it is safe to implement Send, because anyway, these pointers point to memory owned by the +// Command.args field. +unsafe impl Send for Command {} + impl Command { pub fn new(program: &OsStr) -> Command { let mut saw_nul = false; -- cgit 1.4.1-3-g733a5 From 634f8cc06a88eb978c5e52390014740c4bab1e33 Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Wed, 15 Nov 2017 18:01:09 +0100 Subject: Print inlined functions on Windows --- src/libstd/sys/cloudabi/backtrace.rs | 1 + src/libstd/sys/redox/backtrace/tracing.rs | 1 + .../sys/unix/backtrace/tracing/backtrace_fn.rs | 1 + src/libstd/sys/unix/backtrace/tracing/gcc_s.rs | 1 + src/libstd/sys/windows/backtrace/mod.rs | 31 ++++++------- src/libstd/sys/windows/backtrace/printing/msvc.rs | 54 ++++++++++++++-------- src/libstd/sys/windows/c.rs | 4 +- src/libstd/sys_common/backtrace.rs | 3 ++ src/test/run-pass/backtrace-debuginfo-aux.rs | 4 +- src/test/run-pass/backtrace-debuginfo.rs | 12 +---- 10 files changed, 62 insertions(+), 50 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/cloudabi/backtrace.rs b/src/libstd/sys/cloudabi/backtrace.rs index 33d93179237..1b970187558 100644 --- a/src/libstd/sys/cloudabi/backtrace.rs +++ b/src/libstd/sys/cloudabi/backtrace.rs @@ -77,6 +77,7 @@ extern "C" fn trace_fn( cx.frames[cx.idx] = Frame { symbol_addr: symaddr as *mut u8, exact_position: ip as *mut u8, + inline_context: 0, }; cx.idx += 1; } diff --git a/src/libstd/sys/redox/backtrace/tracing.rs b/src/libstd/sys/redox/backtrace/tracing.rs index 0a174b3c3f5..bb70ca36037 100644 --- a/src/libstd/sys/redox/backtrace/tracing.rs +++ b/src/libstd/sys/redox/backtrace/tracing.rs @@ -98,6 +98,7 @@ extern fn trace_fn(ctx: *mut uw::_Unwind_Context, cx.frames[cx.idx] = Frame { symbol_addr: symaddr as *mut u8, exact_position: ip as *mut u8, + inline_context: 0, }; cx.idx += 1; } diff --git a/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs b/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs index 400d39cd4bd..6293eeb4ed6 100644 --- a/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs +++ b/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs @@ -38,6 +38,7 @@ pub fn unwind_backtrace(frames: &mut [Frame]) *to = Frame { exact_position: *from as *mut u8, symbol_addr: *from as *mut u8, + inline_context: 0, }; } Ok((nb_frames as usize, BacktraceContext)) diff --git a/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs b/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs index 000c08d2e0d..1b92fc0e6ad 100644 --- a/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs +++ b/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs @@ -98,6 +98,7 @@ extern fn trace_fn(ctx: *mut uw::_Unwind_Context, cx.frames[cx.idx] = Frame { symbol_addr: symaddr as *mut u8, exact_position: ip as *mut u8, + inline_context: 0, }; cx.idx += 1; } diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs index 176891fff23..82498ad4d58 100644 --- a/src/libstd/sys/windows/backtrace/mod.rs +++ b/src/libstd/sys/windows/backtrace/mod.rs @@ -56,14 +56,15 @@ pub fn unwind_backtrace(frames: &mut [Frame]) // Fetch the symbols necessary from dbghelp.dll let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn)?; let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn)?; - let StackWalk64 = sym!(dbghelp, "StackWalk64", StackWalk64Fn)?; + let StackWalkEx = sym!(dbghelp, "StackWalkEx", StackWalkExFn)?; // Allocate necessary structures for doing the stack walk let process = unsafe { c::GetCurrentProcess() }; let thread = unsafe { c::GetCurrentThread() }; let mut context: c::CONTEXT = unsafe { mem::zeroed() }; unsafe { c::RtlCaptureContext(&mut context) }; - let mut frame: c::STACKFRAME64 = unsafe { mem::zeroed() }; + let mut frame: c::STACKFRAME_EX = unsafe { mem::zeroed() }; + frame.StackFrameSize = mem::size_of_val(&frame) as c::DWORD; let image = init_frame(&mut frame, &context); let backtrace_context = BacktraceContext { @@ -79,24 +80,22 @@ pub fn unwind_backtrace(frames: &mut [Frame]) } // And now that we're done with all the setup, do the stack walking! - // Start from -1 to avoid printing this stack frame, which will - // always be exactly the same. let mut i = 0; unsafe { while i < frames.len() && - StackWalk64(image, process, thread, &mut frame, &mut context, + StackWalkEx(image, process, thread, &mut frame, &mut context, ptr::null_mut(), ptr::null_mut(), ptr::null_mut(), - ptr::null_mut()) == c::TRUE + ptr::null_mut(), + 0) == c::TRUE { - let addr = frame.AddrPC.Offset; - if addr == frame.AddrReturn.Offset || addr == 0 || - frame.AddrReturn.Offset == 0 { break } + let addr = (frame.AddrPC.Offset - 1) as *const u8; frames[i] = Frame { - symbol_addr: (addr - 1) as *const u8, - exact_position: (addr - 1) as *const u8, + symbol_addr: addr, + exact_position: addr, + inline_context: frame.InlineFrameContext, }; i += 1; } @@ -111,14 +110,14 @@ type SymInitializeFn = type SymCleanupFn = unsafe extern "system" fn(c::HANDLE) -> c::BOOL; -type StackWalk64Fn = +type StackWalkExFn = unsafe extern "system" fn(c::DWORD, c::HANDLE, c::HANDLE, - *mut c::STACKFRAME64, *mut c::CONTEXT, + *mut c::STACKFRAME_EX, *mut c::CONTEXT, *mut c_void, *mut c_void, - *mut c_void, *mut c_void) -> c::BOOL; + *mut c_void, *mut c_void, c::DWORD) -> c::BOOL; #[cfg(target_arch = "x86")] -fn init_frame(frame: &mut c::STACKFRAME64, +fn init_frame(frame: &mut c::STACKFRAME_EX, ctx: &c::CONTEXT) -> c::DWORD { frame.AddrPC.Offset = ctx.Eip as u64; frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat; @@ -130,7 +129,7 @@ fn init_frame(frame: &mut c::STACKFRAME64, } #[cfg(target_arch = "x86_64")] -fn init_frame(frame: &mut c::STACKFRAME64, +fn init_frame(frame: &mut c::STACKFRAME_EX, ctx: &c::CONTEXT) -> c::DWORD { frame.AddrPC.Offset = ctx.Rip as u64; frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat; diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs index 5a49b77af8e..967df1c8a2d 100644 --- a/src/libstd/sys/windows/backtrace/printing/msvc.rs +++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs @@ -16,12 +16,12 @@ use sys::c; use sys::backtrace::BacktraceContext; use sys_common::backtrace::Frame; -type SymFromAddrFn = - unsafe extern "system" fn(c::HANDLE, u64, *mut u64, - *mut c::SYMBOL_INFO) -> c::BOOL; -type SymGetLineFromAddr64Fn = - unsafe extern "system" fn(c::HANDLE, u64, *mut u32, - *mut c::IMAGEHLP_LINE64) -> c::BOOL; +type SymFromInlineContextFn = + unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, + *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL; +type SymGetLineFromInlineContextFn = + unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, + u64, *mut c::DWORD, *mut c::IMAGEHLP_LINE64) -> c::BOOL; /// Converts a pointer to symbol to its string value. pub fn resolve_symname(frame: Frame, @@ -29,7 +29,9 @@ pub fn resolve_symname(frame: Frame, context: &BacktraceContext) -> io::Result<()> where F: FnOnce(Option<&str>) -> io::Result<()> { - let SymFromAddr = sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn)?; + let SymFromInlineContext = sym!(&context.dbghelp, + "SymFromInlineContext", + SymFromInlineContextFn)?; unsafe { let mut info: c::SYMBOL_INFO = mem::zeroed(); @@ -40,12 +42,22 @@ pub fn resolve_symname(frame: Frame, info.SizeOfStruct = 88; let mut displacement = 0u64; - let ret = SymFromAddr(context.handle, - frame.symbol_addr as u64, - &mut displacement, - &mut info); - - let symname = if ret == c::TRUE { + let ret = SymFromInlineContext(context.handle, + frame.symbol_addr as u64, + frame.inline_context, + &mut displacement, + &mut info); + let valid_range = if ret == c::TRUE && + frame.symbol_addr as usize >= info.Address as usize { + if info.Size != 0 { + (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize + } else { + true + } + } else { + false + }; + let symname = if valid_range { let ptr = info.Name.as_ptr() as *const c_char; CStr::from_ptr(ptr).to_str().ok() } else { @@ -61,19 +73,21 @@ pub fn foreach_symbol_fileline(frame: Frame, -> io::Result where F: FnMut(&[u8], u32) -> io::Result<()> { - let SymGetLineFromAddr64 = sym!(&context.dbghelp, - "SymGetLineFromAddr64", - SymGetLineFromAddr64Fn)?; + let SymGetLineFromInlineContext = sym!(&context.dbghelp, + "SymGetLineFromInlineContext", + SymGetLineFromInlineContextFn)?; unsafe { let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); line.SizeOfStruct = ::mem::size_of::() as u32; let mut displacement = 0u32; - let ret = SymGetLineFromAddr64(context.handle, - frame.exact_position as u64, - &mut displacement, - &mut line); + let ret = SymGetLineFromInlineContext(context.handle, + frame.exact_position as u64, + frame.inline_context, + 0, + &mut displacement, + &mut line); if ret == c::TRUE { let name = CStr::from_ptr(line.Filename).to_bytes(); f(name, line.LineNumber as u32)?; diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 66b44f1402f..6d929f21365 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -619,7 +619,7 @@ pub struct ADDRESS64 { #[repr(C)] #[cfg(feature = "backtrace")] -pub struct STACKFRAME64 { +pub struct STACKFRAME_EX { pub AddrPC: ADDRESS64, pub AddrReturn: ADDRESS64, pub AddrFrame: ADDRESS64, @@ -631,6 +631,8 @@ pub struct STACKFRAME64 { pub Virtual: BOOL, pub Reserved: [u64; 3], pub KdHelp: KDHELP64, + pub StackFrameSize: DWORD, + pub InlineFrameContext: DWORD, } #[repr(C)] diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 36cbce2df75..a364a0392b3 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -41,6 +41,8 @@ pub struct Frame { 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, } /// Max number of frames to print. @@ -64,6 +66,7 @@ fn _print(w: &mut 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) = diff --git a/src/test/run-pass/backtrace-debuginfo-aux.rs b/src/test/run-pass/backtrace-debuginfo-aux.rs index 1236acf3511..cb7ef7e3006 100644 --- a/src/test/run-pass/backtrace-debuginfo-aux.rs +++ b/src/test/run-pass/backtrace-debuginfo-aux.rs @@ -15,9 +15,7 @@ pub fn callback(f: F) where F: FnOnce((&'static str, u32)) { f((file!(), line!())) } -// LLVM does not yet output the required debug info to support showing inlined -// function calls in backtraces when targeting MSVC, so disable inlining in -// this case. +// We emit the wrong location for the caller here when inlined on MSVC #[cfg_attr(not(target_env = "msvc"), inline(always))] #[cfg_attr(target_env = "msvc", inline(never))] pub fn callback_inlined(f: F) where F: FnOnce((&'static str, u32)) { diff --git a/src/test/run-pass/backtrace-debuginfo.rs b/src/test/run-pass/backtrace-debuginfo.rs index 2f1c5c0574a..e8b5f3490e5 100644 --- a/src/test/run-pass/backtrace-debuginfo.rs +++ b/src/test/run-pass/backtrace-debuginfo.rs @@ -62,10 +62,7 @@ type Pos = (&'static str, u32); // this goes to stdout and each line has to be occurred // in the following backtrace to stderr with a correct order. fn dump_filelines(filelines: &[Pos]) { - // Skip top frame for MSVC, because it sees the macro rather than - // the containing function. - let skip = if cfg!(target_env = "msvc") {1} else {0}; - for &(file, line) in filelines.iter().rev().skip(skip) { + for &(file, line) in filelines.iter().rev() { // extract a basename let basename = file.split(&['/', '\\'][..]).last().unwrap(); println!("{}:{}", basename, line); @@ -84,9 +81,7 @@ fn inner(counter: &mut i32, main_pos: Pos, outer_pos: Pos) { }); } -// LLVM does not yet output the required debug info to support showing inlined -// function calls in backtraces when targeting MSVC, so disable inlining in -// this case. +// We emit the wrong location for the caller here when inlined on MSVC #[cfg_attr(not(target_env = "msvc"), inline(always))] #[cfg_attr(target_env = "msvc", inline(never))] fn inner_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos) { @@ -137,9 +132,6 @@ fn run_test(me: &str) { use std::str; use std::process::Command; - let mut template = Command::new(me); - template.env("RUST_BACKTRACE", "full"); - let mut i = 0; loop { let out = Command::new(me) -- cgit 1.4.1-3-g733a5 From 9e6ed17c4f5befef64fa9e8a1d2b2f155c345cac Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Fri, 26 Jan 2018 07:22:43 -0800 Subject: make Command.argv Send on unix platforms Implementing Send for a specific field rather than the whole struct is safer: if a field is changed/modified and becomes non-Send, we can catch it. --- src/libstd/sys/unix/process/process_common.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index b09fc36dee0..7e057401fab 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -45,7 +45,7 @@ pub struct Command { // other keys. program: CString, args: Vec, - argv: Vec<*const c_char>, + argv: Argv, env: CommandEnv, cwd: Option, @@ -58,6 +58,12 @@ pub struct Command { stderr: Option, } +// Create a new type for argv, so that we can make it `Send` +struct Argv(Vec<*const c_char>); + +// It is safe to make Argv Send, because it contains pointers to memory owned by `Command.args` +unsafe impl Send for Argv {} + // passed back to std::process with the pipes connected to the child, if any // were requested pub struct StdioPipes { @@ -87,17 +93,12 @@ pub enum Stdio { Fd(FileDesc), } -// Command is not Send by default due to the Command.argv field containing a raw pointers. However -// it is safe to implement Send, because anyway, these pointers point to memory owned by the -// Command.args field. -unsafe impl Send for Command {} - impl Command { pub fn new(program: &OsStr) -> Command { let mut saw_nul = false; let program = os2c(program, &mut saw_nul); Command { - argv: vec![program.as_ptr(), ptr::null()], + argv: Argv(vec![program.as_ptr(), ptr::null()]), program, args: Vec::new(), env: Default::default(), @@ -116,8 +117,8 @@ impl Command { // Overwrite the trailing NULL pointer in `argv` and then add a new null // pointer. let arg = os2c(arg, &mut self.saw_nul); - self.argv[self.args.len() + 1] = arg.as_ptr(); - self.argv.push(ptr::null()); + self.argv.0[self.args.len() + 1] = arg.as_ptr(); + self.argv.0.push(ptr::null()); // Also make sure we keep track of the owned value to schedule a // destructor for this memory. @@ -138,7 +139,7 @@ impl Command { self.saw_nul } pub fn get_argv(&self) -> &Vec<*const c_char> { - &self.argv + &self.argv.0 } #[allow(dead_code)] -- cgit 1.4.1-3-g733a5 From 36695a37c52a0e6cc582247a506ab0b3c764b48f Mon Sep 17 00:00:00 2001 From: Diggory Blake Date: Sun, 31 Dec 2017 16:40:34 +0000 Subject: Implement extensible syscall interface for wasm --- src/etc/wasm32-shim.js | 149 ++++++++++++++----------- src/librustc_trans/back/write.rs | 6 +- src/libstd/Cargo.toml | 1 + src/libstd/sys/wasm/args.rs | 38 +------ src/libstd/sys/wasm/mod.rs | 233 +++++++++++++++++++++++++++++++++++++-- src/libstd/sys/wasm/os.rs | 38 ++----- src/libstd/sys/wasm/stdio.rs | 35 ++---- src/libstd/sys/wasm/time.rs | 44 ++++---- 8 files changed, 346 insertions(+), 198 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/etc/wasm32-shim.js b/src/etc/wasm32-shim.js index d55083e0f8e..69647f37eec 100644 --- a/src/etc/wasm32-shim.js +++ b/src/etc/wasm32-shim.js @@ -28,14 +28,76 @@ let m = new WebAssembly.Module(buffer); let memory = null; +function viewstruct(data, fields) { + return new Uint32Array(memory.buffer).subarray(data/4, data/4 + fields); +} + function copystr(a, b) { - if (memory === null) { - return null - } - let view = new Uint8Array(memory.buffer).slice(a, a + b); + let view = new Uint8Array(memory.buffer).subarray(a, a + b); return String.fromCharCode.apply(null, view); } +function syscall_write([fd, ptr, len]) { + let s = copystr(ptr, len); + switch (fd) { + case 1: process.stdout.write(s); break; + case 2: process.stderr.write(s); break; + } +} + +function syscall_exit([code]) { + process.exit(code); +} + +function syscall_args(params) { + let [ptr, len] = params; + + // Calculate total required buffer size + let totalLen = -1; + for (let i = 2; i < process.argv.length; ++i) { + totalLen += Buffer.byteLength(process.argv[i]) + 1; + } + if (totalLen < 0) { totalLen = 0; } + params[2] = totalLen; + + // If buffer is large enough, copy data + if (len >= totalLen) { + let view = new Uint8Array(memory.buffer); + for (let i = 2; i < process.argv.length; ++i) { + let value = process.argv[i]; + Buffer.from(value).copy(view, ptr); + ptr += Buffer.byteLength(process.argv[i]) + 1; + } + } +} + +function syscall_getenv(params) { + let [keyPtr, keyLen, valuePtr, valueLen] = params; + + let key = copystr(keyPtr, keyLen); + let value = process.env[key]; + + if (value == null) { + params[4] = 0xFFFFFFFF; + } else { + let view = new Uint8Array(memory.buffer); + let totalLen = Buffer.byteLength(value); + params[4] = totalLen; + if (valueLen >= totalLen) { + Buffer.from(value).copy(view, valuePtr); + } + } +} + +function syscall_time(params) { + let t = Date.now(); + let secs = Math.floor(t / 1000); + let millis = t % 1000; + params[1] = Math.floor(secs / 0x100000000); + params[2] = secs % 0x100000000; + params[3] = Math.floor(millis * 1000000); +} + let imports = {}; imports.env = { // These are generated by LLVM itself for various intrinsic calls. Hopefully @@ -48,68 +110,25 @@ imports.env = { log10: Math.log10, log10f: Math.log10, - // These are called in src/libstd/sys/wasm/stdio.rs and are used when - // debugging is enabled. - rust_wasm_write_stdout: function(a, b) { - let s = copystr(a, b); - if (s !== null) { - process.stdout.write(s); - } - }, - rust_wasm_write_stderr: function(a, b) { - let s = copystr(a, b); - if (s !== null) { - process.stderr.write(s); - } - }, - - // These are called in src/libstd/sys/wasm/args.rs and are used when - // debugging is enabled. - rust_wasm_args_count: function() { - if (memory === null) - return 0; - return process.argv.length - 2; - }, - rust_wasm_args_arg_size: function(i) { - return Buffer.byteLength(process.argv[i + 2]); - }, - rust_wasm_args_arg_fill: function(idx, ptr) { - let arg = process.argv[idx + 2]; - let view = new Uint8Array(memory.buffer); - Buffer.from(arg).copy(view, ptr); - }, - - // These are called in src/libstd/sys/wasm/os.rs and are used when - // debugging is enabled. - rust_wasm_getenv_len: function(a, b) { - let key = copystr(a, b); - if (key === null) { - return -1; + rust_wasm_syscall: function(index, data) { + switch (index) { + case 1: syscall_write(viewstruct(data, 3)); return true; + case 2: syscall_exit(viewstruct(data, 1)); return true; + case 3: syscall_args(viewstruct(data, 3)); return true; + case 4: syscall_getenv(viewstruct(data, 5)); return true; + case 6: syscall_time(viewstruct(data, 4)); return true; + default: + console.log("Unsupported syscall: " + index); + return false; } - if (!(key in process.env)) { - return -1; - } - return Buffer.byteLength(process.env[key]); - }, - rust_wasm_getenv_data: function(a, b, ptr) { - let key = copystr(a, b); - let value = process.env[key]; - let view = new Uint8Array(memory.buffer); - Buffer.from(value).copy(view, ptr); - }, -}; - -let module_imports = WebAssembly.Module.imports(m); - -for (var i = 0; i < module_imports.length; i++) { - let imp = module_imports[i]; - if (imp.module != 'env') { - continue } - if (imp.name == 'memory' && imp.kind == 'memory') { - memory = new WebAssembly.Memory({initial: 20}); - imports.env.memory = memory; - } -} +}; let instance = new WebAssembly.Instance(m, imports); +memory = instance.exports.memory; +try { + instance.exports.main(); +} catch (e) { + console.error(e); + process.exit(101); +} diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 8afa63a5e97..206c73b0174 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -824,9 +824,7 @@ fn binaryen_assemble(cgcx: &CodegenContext, if cgcx.debuginfo != config::NoDebugInfo { options.debuginfo(true); } - if cgcx.crate_types.contains(&config::CrateTypeExecutable) { - options.start("main"); - } + options.stack(1024 * 1024); options.import_memory(cgcx.wasm_import_memory); let assembled = input.and_then(|input| { @@ -1452,7 +1450,7 @@ fn start_executing_work(tcx: TyCtxt, target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(), binaryen_linker: tcx.sess.linker_flavor() == LinkerFlavor::Binaryen, debuginfo: tcx.sess.opts.debuginfo, - wasm_import_memory: wasm_import_memory, + wasm_import_memory, assembler_cmd, }; diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 3430ecabcbe..c1fe4a89d6a 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -48,3 +48,4 @@ jemalloc = ["alloc_jemalloc"] force_alloc_system = [] panic-unwind = ["panic_unwind"] profiler = ["profiler_builtins"] +wasm_syscall = [] diff --git a/src/libstd/sys/wasm/args.rs b/src/libstd/sys/wasm/args.rs index d2a4a7b19d5..b3c6b671e80 100644 --- a/src/libstd/sys/wasm/args.rs +++ b/src/libstd/sys/wasm/args.rs @@ -10,8 +10,8 @@ use ffi::OsString; use marker::PhantomData; -use mem; use vec; +use sys::ArgsSysCall; pub unsafe fn init(_argc: isize, _argv: *const *const u8) { // On wasm these should always be null, so there's nothing for us to do here @@ -21,38 +21,10 @@ pub unsafe fn cleanup() { } pub fn args() -> Args { - // When the runtime debugging is enabled we'll link to some extra runtime - // functions to actually implement this. These are for now just implemented - // in a node.js script but they're off by default as they're sort of weird - // in a web-wasm world. - if !super::DEBUG { - return Args { - iter: Vec::new().into_iter(), - _dont_send_or_sync_me: PhantomData, - } - } - - // You'll find the definitions of these in `src/etc/wasm32-shim.js`. These - // are just meant for debugging and should not be relied on. - extern { - fn rust_wasm_args_count() -> usize; - fn rust_wasm_args_arg_size(a: usize) -> usize; - fn rust_wasm_args_arg_fill(a: usize, ptr: *mut u8); - } - - unsafe { - let cnt = rust_wasm_args_count(); - let mut v = Vec::with_capacity(cnt); - for i in 0..cnt { - let n = rust_wasm_args_arg_size(i); - let mut data = vec![0; n]; - rust_wasm_args_arg_fill(i, data.as_mut_ptr()); - v.push(mem::transmute::, OsString>(data)); - } - Args { - iter: v.into_iter(), - _dont_send_or_sync_me: PhantomData, - } + let v = ArgsSysCall::perform(); + Args { + iter: v.into_iter(), + _dont_send_or_sync_me: PhantomData, } } diff --git a/src/libstd/sys/wasm/mod.rs b/src/libstd/sys/wasm/mod.rs index ba3d6a2813a..c02e5e809c8 100644 --- a/src/libstd/sys/wasm/mod.rs +++ b/src/libstd/sys/wasm/mod.rs @@ -26,17 +26,11 @@ use io; use os::raw::c_char; - -// Right now the wasm backend doesn't even have the ability to print to the -// console by default. Wasm can't import anything from JS! (you have to -// explicitly provide it). -// -// Sometimes that's a real bummer, though, so this flag can be set to `true` to -// enable calling various shims defined in `src/etc/wasm32-shim.js` which should -// help receive debug output and see what's going on. In general this flag -// currently controls "will we call out to our own defined shims in node.js", -// and this flag should always be `false` for release builds. -const DEBUG: bool = false; +use ptr; +use sys::os_str::Buf; +use sys_common::{AsInner, FromInner}; +use ffi::{OsString, OsStr}; +use time::Duration; pub mod args; #[cfg(feature = "backtrace")] @@ -92,7 +86,7 @@ pub unsafe fn strlen(mut s: *const c_char) -> usize { } pub unsafe fn abort_internal() -> ! { - ::intrinsics::abort(); + ExitSysCall::perform(1) } // We don't have randomness yet, but I totally used a random number generator to @@ -103,3 +97,218 @@ pub unsafe fn abort_internal() -> ! { pub fn hashmap_random_keys() -> (u64, u64) { (1, 2) } + +// Implement a minimal set of system calls to enable basic IO +pub enum SysCallIndex { + Read = 0, + Write = 1, + Exit = 2, + Args = 3, + GetEnv = 4, + SetEnv = 5, + Time = 6, +} + +#[repr(C)] +pub struct ReadSysCall { + fd: usize, + ptr: *mut u8, + len: usize, + result: usize, +} + +impl ReadSysCall { + pub fn perform(fd: usize, buffer: &mut [u8]) -> usize { + let mut call_record = ReadSysCall { + fd, + len: buffer.len(), + ptr: buffer.as_mut_ptr(), + result: 0 + }; + if unsafe { syscall(SysCallIndex::Read, &mut call_record) } { + call_record.result + } else { + 0 + } + } +} + +#[repr(C)] +pub struct WriteSysCall { + fd: usize, + ptr: *const u8, + len: usize, +} + +impl WriteSysCall { + pub fn perform(fd: usize, buffer: &[u8]) { + let mut call_record = WriteSysCall { + fd, + len: buffer.len(), + ptr: buffer.as_ptr() + }; + unsafe { syscall(SysCallIndex::Write, &mut call_record); } + } +} + +#[repr(C)] +pub struct ExitSysCall { + code: usize, +} + +impl ExitSysCall { + pub fn perform(code: usize) -> ! { + let mut call_record = ExitSysCall { + code + }; + unsafe { + syscall(SysCallIndex::Exit, &mut call_record); + ::intrinsics::abort(); + } + } +} + +fn receive_buffer Result>(estimate: usize, mut f: F) + -> Result, E> +{ + let mut buffer = vec![0; estimate]; + loop { + let result = f(&mut buffer)?; + if result <= buffer.len() { + buffer.truncate(result); + break; + } + buffer.resize(result, 0); + } + Ok(buffer) +} + +#[repr(C)] +pub struct ArgsSysCall { + ptr: *mut u8, + len: usize, + result: usize +} + +impl ArgsSysCall { + pub fn perform() -> Vec { + receive_buffer(1024, |buffer| -> Result { + let mut call_record = ArgsSysCall { + len: buffer.len(), + ptr: buffer.as_mut_ptr(), + result: 0 + }; + if unsafe { syscall(SysCallIndex::Args, &mut call_record) } { + Ok(call_record.result) + } else { + Ok(0) + } + }) + .unwrap() + .split(|b| *b == 0) + .map(|s| FromInner::from_inner(Buf { inner: s.to_owned() })) + .collect() + } +} + +#[repr(C)] +pub struct GetEnvSysCall { + key_ptr: *const u8, + key_len: usize, + value_ptr: *mut u8, + value_len: usize, + result: usize +} + +impl GetEnvSysCall { + pub fn perform(key: &OsStr) -> Option { + let key_buf = &AsInner::as_inner(key).inner; + receive_buffer(64, |buffer| { + let mut call_record = GetEnvSysCall { + key_len: key_buf.len(), + key_ptr: key_buf.as_ptr(), + value_len: buffer.len(), + value_ptr: buffer.as_mut_ptr(), + result: !0usize + }; + if unsafe { syscall(SysCallIndex::GetEnv, &mut call_record) } { + if call_record.result == !0usize { + Err(()) + } else { + Ok(call_record.result) + } + } else { + Err(()) + } + }).ok().map(|s| { + FromInner::from_inner(Buf { inner: s }) + }) + } +} + +#[repr(C)] +pub struct SetEnvSysCall { + key_ptr: *const u8, + key_len: usize, + value_ptr: *const u8, + value_len: usize +} + +impl SetEnvSysCall { + pub fn perform(key: &OsStr, value: Option<&OsStr>) { + let key_buf = &AsInner::as_inner(key).inner; + let value_buf = value.map(|v| &AsInner::as_inner(v).inner); + let mut call_record = SetEnvSysCall { + key_len: key_buf.len(), + key_ptr: key_buf.as_ptr(), + value_len: value_buf.map(|v| v.len()).unwrap_or(!0usize), + value_ptr: value_buf.map(|v| v.as_ptr()).unwrap_or(ptr::null()) + }; + unsafe { syscall(SysCallIndex::SetEnv, &mut call_record); } + } +} + +pub enum TimeClock { + Monotonic = 0, + System = 1, +} + +#[repr(C)] +pub struct TimeSysCall { + clock: usize, + secs_hi: usize, + secs_lo: usize, + nanos: usize +} + +impl TimeSysCall { + pub fn perform(clock: TimeClock) -> Duration { + let mut call_record = TimeSysCall { + clock: clock as usize, + secs_hi: 0, + secs_lo: 0, + nanos: 0 + }; + if unsafe { syscall(SysCallIndex::Time, &mut call_record) } { + Duration::new( + ((call_record.secs_hi as u64) << 32) | (call_record.secs_lo as u64), + call_record.nanos as u32 + ) + } else { + panic!("Time system call is not implemented by WebAssembly host"); + } + } +} + +unsafe fn syscall(index: SysCallIndex, data: &mut T) -> bool { + #[cfg(feature = "wasm_syscall")] + extern { + #[no_mangle] + fn rust_wasm_syscall(index: usize, data: *mut Void) -> usize; + } + + #[cfg(not(feature = "wasm_syscall"))] + unsafe fn rust_wasm_syscall(_index: usize, _data: *mut Void) -> usize { 0 } + + rust_wasm_syscall(index as usize, data as *mut T as *mut Void) != 0 +} diff --git a/src/libstd/sys/wasm/os.rs b/src/libstd/sys/wasm/os.rs index c98030f7ebf..23ca1754719 100644 --- a/src/libstd/sys/wasm/os.rs +++ b/src/libstd/sys/wasm/os.rs @@ -8,16 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::intrinsics; - use error::Error as StdError; use ffi::{OsString, OsStr}; use fmt; use io; -use mem; use path::{self, PathBuf}; use str; -use sys::{unsupported, Void}; +use sys::{unsupported, Void, ExitSysCall, GetEnvSysCall, SetEnvSysCall}; pub fn errno() -> i32 { 0 @@ -87,36 +84,15 @@ pub fn env() -> Env { } pub fn getenv(k: &OsStr) -> io::Result> { - // If we're debugging the runtime then we actually probe node.js to ask for - // the value of environment variables to help provide inputs to programs. - // The `extern` shims here are defined in `src/etc/wasm32-shim.js` and are - // intended for debugging only, you should not rely on them. - if !super::DEBUG { - return Ok(None) - } - - extern { - fn rust_wasm_getenv_len(k: *const u8, kl: usize) -> isize; - fn rust_wasm_getenv_data(k: *const u8, kl: usize, v: *mut u8); - } - unsafe { - let k: &[u8] = mem::transmute(k); - let n = rust_wasm_getenv_len(k.as_ptr(), k.len()); - if n == -1 { - return Ok(None) - } - let mut data = vec![0; n as usize]; - rust_wasm_getenv_data(k.as_ptr(), k.len(), data.as_mut_ptr()); - Ok(Some(mem::transmute(data))) - } + Ok(GetEnvSysCall::perform(k)) } -pub fn setenv(_k: &OsStr, _v: &OsStr) -> io::Result<()> { - unsupported() +pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + Ok(SetEnvSysCall::perform(k, Some(v))) } -pub fn unsetenv(_n: &OsStr) -> io::Result<()> { - unsupported() +pub fn unsetenv(k: &OsStr) -> io::Result<()> { + Ok(SetEnvSysCall::perform(k, None)) } pub fn temp_dir() -> PathBuf { @@ -128,7 +104,7 @@ pub fn home_dir() -> Option { } pub fn exit(_code: i32) -> ! { - unsafe { intrinsics::abort() } + ExitSysCall::perform(_code as isize as usize) } pub fn getpid() -> u32 { diff --git a/src/libstd/sys/wasm/stdio.rs b/src/libstd/sys/wasm/stdio.rs index 0f75f240251..beb19c0ed2c 100644 --- a/src/libstd/sys/wasm/stdio.rs +++ b/src/libstd/sys/wasm/stdio.rs @@ -9,19 +9,19 @@ // except according to those terms. use io; -use sys::{Void, unsupported}; +use sys::{ReadSysCall, WriteSysCall}; -pub struct Stdin(Void); +pub struct Stdin; pub struct Stdout; pub struct Stderr; impl Stdin { pub fn new() -> io::Result { - unsupported() + Ok(Stdin) } - pub fn read(&self, _data: &mut [u8]) -> io::Result { - match self.0 {} + pub fn read(&self, data: &mut [u8]) -> io::Result { + Ok(ReadSysCall::perform(0, data)) } } @@ -31,19 +31,7 @@ impl Stdout { } pub fn write(&self, data: &[u8]) -> io::Result { - // If runtime debugging is enabled at compile time we'll invoke some - // runtime functions that are defined in our src/etc/wasm32-shim.js - // debugging script. Note that this ffi function call is intended - // *purely* for debugging only and should not be relied upon. - if !super::DEBUG { - return unsupported() - } - extern { - fn rust_wasm_write_stdout(data: *const u8, len: usize); - } - unsafe { - rust_wasm_write_stdout(data.as_ptr(), data.len()) - } + WriteSysCall::perform(1, data); Ok(data.len()) } @@ -58,16 +46,7 @@ impl Stderr { } pub fn write(&self, data: &[u8]) -> io::Result { - // See comments in stdout for what's going on here. - if !super::DEBUG { - return unsupported() - } - extern { - fn rust_wasm_write_stderr(data: *const u8, len: usize); - } - unsafe { - rust_wasm_write_stderr(data.as_ptr(), data.len()) - } + WriteSysCall::perform(2, data); Ok(data.len()) } diff --git a/src/libstd/sys/wasm/time.rs b/src/libstd/sys/wasm/time.rs index c269def98f6..e52435e6339 100644 --- a/src/libstd/sys/wasm/time.rs +++ b/src/libstd/sys/wasm/time.rs @@ -8,56 +8,50 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use fmt; use time::Duration; +use sys::{TimeSysCall, TimeClock}; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] -pub struct Instant; +pub struct Instant(Duration); -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct SystemTime; +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct SystemTime(Duration); -pub const UNIX_EPOCH: SystemTime = SystemTime; +pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); impl Instant { pub fn now() -> Instant { - panic!("not supported on web assembly"); + Instant(TimeSysCall::perform(TimeClock::Monotonic)) } - pub fn sub_instant(&self, _other: &Instant) -> Duration { - panic!("can't sub yet"); + pub fn sub_instant(&self, other: &Instant) -> Duration { + self.0 - other.0 } - pub fn add_duration(&self, _other: &Duration) -> Instant { - panic!("can't add yet"); + pub fn add_duration(&self, other: &Duration) -> Instant { + Instant(self.0 + *other) } - pub fn sub_duration(&self, _other: &Duration) -> Instant { - panic!("can't sub yet"); + pub fn sub_duration(&self, other: &Duration) -> Instant { + Instant(self.0 - *other) } } impl SystemTime { pub fn now() -> SystemTime { - panic!("not supported on web assembly"); + SystemTime(TimeSysCall::perform(TimeClock::System)) } - pub fn sub_time(&self, _other: &SystemTime) + pub fn sub_time(&self, other: &SystemTime) -> Result { - panic!() - } - - pub fn add_duration(&self, _other: &Duration) -> SystemTime { - panic!() + self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) } - pub fn sub_duration(&self, _other: &Duration) -> SystemTime { - panic!() + pub fn add_duration(&self, other: &Duration) -> SystemTime { + SystemTime(self.0 + *other) } -} -impl fmt::Debug for SystemTime { - fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { - panic!() + pub fn sub_duration(&self, other: &Duration) -> SystemTime { + SystemTime(self.0 - *other) } } -- cgit 1.4.1-3-g733a5 From 55b54a999bcdb0b1c1f42b6e1ae670beb0717086 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 31 Jan 2018 11:41:29 -0800 Subject: Use a range to identify SIGSEGV in stack guards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, the `guard::init()` and `guard::current()` functions were returning a `usize` address representing the top of the stack guard, respectively for the main thread and for spawned threads. The `SIGSEGV` handler on `unix` targets checked if a fault was within one page below that address, if so reporting it as a stack overflow. Now `unix` targets report a `Range` representing the guard memory, so it can cover arbitrary guard sizes. Non-`unix` targets which always return `None` for guards now do so with `Option`, so they don't pay any overhead. For `linux-gnu` in particular, the previous guard upper-bound was `stackaddr + guardsize`, as the protected memory was *inside* the stack. This was a glibc bug, and starting from 2.27 they are moving the guard *past* the end of the stack. However, there's no simple way for us to know where the guard page actually lies, so now we declare it as the whole range of `stackaddr ± guardsize`, and any fault therein will be called a stack overflow. This fixes #47863. --- src/libstd/sys/cloudabi/thread.rs | 5 +- src/libstd/sys/redox/thread.rs | 5 +- src/libstd/sys/unix/stack_overflow.rs | 9 +-- src/libstd/sys/unix/thread.rs | 115 +++++++++++++++++++++------------- src/libstd/sys/wasm/thread.rs | 5 +- src/libstd/sys/windows/thread.rs | 5 +- src/libstd/sys_common/thread_info.rs | 9 +-- 7 files changed, 89 insertions(+), 64 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs index c980ae75261..78a3b82546e 100644 --- a/src/libstd/sys/cloudabi/thread.rs +++ b/src/libstd/sys/cloudabi/thread.rs @@ -111,10 +111,11 @@ impl Drop for Thread { #[cfg_attr(test, allow(dead_code))] pub mod guard { - pub unsafe fn current() -> Option { + pub type Guard = !; + pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { + pub unsafe fn init() -> Option { None } } diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs index c4aad8d86f8..c4719a94c7e 100644 --- a/src/libstd/sys/redox/thread.rs +++ b/src/libstd/sys/redox/thread.rs @@ -88,6 +88,7 @@ impl Thread { } pub mod guard { - pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { None } + pub type Guard = !; + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } } diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index 51adbc24ae0..40453f9b8a1 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -57,9 +57,6 @@ mod imp { use sys_common::thread_info; - // This is initialized in init() and only read from after - static mut PAGE_SIZE: usize = 0; - #[cfg(any(target_os = "linux", target_os = "android"))] unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize { #[repr(C)] @@ -102,12 +99,12 @@ mod imp { _data: *mut libc::c_void) { use sys_common::util::report_overflow; - let guard = thread_info::stack_guard().unwrap_or(0); + let guard = thread_info::stack_guard().unwrap_or(0..0); let addr = siginfo_si_addr(info); // If the faulting address is within the guard page, then we print a // message saying so and abort. - if guard != 0 && guard - PAGE_SIZE <= addr && addr < guard { + if guard.start <= addr && addr < guard.end { report_overflow(); rtabort!("stack overflow"); } else { @@ -123,8 +120,6 @@ mod imp { static mut MAIN_ALTSTACK: *mut libc::c_void = ptr::null_mut(); pub unsafe fn init() { - PAGE_SIZE = ::sys::os::page_size(); - let mut action: sigaction = mem::zeroed(); action.sa_flags = SA_SIGINFO | SA_ONSTACK; action.sa_sigaction = signal_handler as sighandler_t; diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 525882c1e1e..72cdb9440b8 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -205,8 +205,10 @@ impl Drop for Thread { not(target_os = "solaris")))] #[cfg_attr(test, allow(dead_code))] pub mod guard { - pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { None } + use ops::Range; + pub type Guard = Range; + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } } @@ -222,14 +224,43 @@ pub mod guard { use libc; use libc::mmap; use libc::{PROT_NONE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED}; + use ops::Range; use sys::os; - #[cfg(any(target_os = "macos", - target_os = "bitrig", - target_os = "openbsd", - target_os = "solaris"))] + // This is initialized in init() and only read from after + static mut PAGE_SIZE: usize = 0; + + pub type Guard = Range; + + #[cfg(target_os = "solaris")] + unsafe fn get_stack_start() -> Option<*mut libc::c_void> { + let mut current_stack: libc::stack_t = ::mem::zeroed(); + assert_eq!(libc::stack_getbounds(&mut current_stack), 0); + Some(current_stack.ss_sp) + } + + #[cfg(target_os = "macos")] unsafe fn get_stack_start() -> Option<*mut libc::c_void> { - current().map(|s| s as *mut libc::c_void) + let stackaddr = libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize - + libc::pthread_get_stacksize_np(libc::pthread_self()); + Some(stackaddr as *mut libc::c_void) + } + + #[cfg(any(target_os = "openbsd", target_os = "bitrig"))] + unsafe fn get_stack_start() -> Option<*mut libc::c_void> { + let mut current_stack: libc::stack_t = ::mem::zeroed(); + assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(), + &mut current_stack), 0); + + let extra = if cfg!(target_os = "bitrig") {3} else {1} * PAGE_SIZE; + let stackaddr = if libc::pthread_main_np() == 1 { + // main thread + current_stack.ss_sp as usize - current_stack.ss_size + extra + } else { + // new thread + current_stack.ss_sp as usize - current_stack.ss_size + }; + Some(stackaddr as *mut libc::c_void) } #[cfg(any(target_os = "android", target_os = "freebsd", @@ -253,8 +284,9 @@ pub mod guard { ret } - pub unsafe fn init() -> Option { - let psize = os::page_size(); + pub unsafe fn init() -> Option { + PAGE_SIZE = os::page_size(); + let mut stackaddr = get_stack_start()?; // Ensure stackaddr is page aligned! A parent process might @@ -263,9 +295,9 @@ pub mod guard { // stackaddr < stackaddr + stacksize, so if stackaddr is not // page-aligned, calculate the fix such that stackaddr < // new_page_aligned_stackaddr < stackaddr + stacksize - let remainder = (stackaddr as usize) % psize; + let remainder = (stackaddr as usize) % PAGE_SIZE; if remainder != 0 { - stackaddr = ((stackaddr as usize) + psize - remainder) + stackaddr = ((stackaddr as usize) + PAGE_SIZE - remainder) as *mut libc::c_void; } @@ -280,60 +312,42 @@ pub mod guard { // Instead, we'll just note where we expect rlimit to start // faulting, so our handler can report "stack overflow", and // trust that the kernel's own stack guard will work. - Some(stackaddr as usize) + let stackaddr = stackaddr as usize; + Some(stackaddr - PAGE_SIZE..stackaddr) } else { // Reallocate the last page of the stack. // This ensures SIGBUS will be raised on // stack overflow. - let result = mmap(stackaddr, psize, PROT_NONE, + let result = mmap(stackaddr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); if result != stackaddr || result == MAP_FAILED { panic!("failed to allocate a guard page"); } + let guardaddr = stackaddr as usize; let offset = if cfg!(target_os = "freebsd") { 2 } else { 1 }; - Some(stackaddr as usize + offset * psize) + Some(guardaddr..guardaddr + offset * PAGE_SIZE) } } - #[cfg(target_os = "solaris")] - pub unsafe fn current() -> Option { - let mut current_stack: libc::stack_t = ::mem::zeroed(); - assert_eq!(libc::stack_getbounds(&mut current_stack), 0); - Some(current_stack.ss_sp as usize) - } - - #[cfg(target_os = "macos")] - pub unsafe fn current() -> Option { - Some(libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize - - libc::pthread_get_stacksize_np(libc::pthread_self())) - } - - #[cfg(any(target_os = "openbsd", target_os = "bitrig"))] - pub unsafe fn current() -> Option { - let mut current_stack: libc::stack_t = ::mem::zeroed(); - assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(), - &mut current_stack), 0); - - let extra = if cfg!(target_os = "bitrig") {3} else {1} * os::page_size(); - Some(if libc::pthread_main_np() == 1 { - // main thread - current_stack.ss_sp as usize - current_stack.ss_size + extra - } else { - // new thread - current_stack.ss_sp as usize - current_stack.ss_size - }) + #[cfg(any(target_os = "macos", + target_os = "bitrig", + target_os = "openbsd", + target_os = "solaris"))] + pub unsafe fn current() -> Option { + let stackaddr = get_stack_start()? as usize; + Some(stackaddr - PAGE_SIZE..stackaddr) } #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux", target_os = "netbsd", target_os = "l4re"))] - pub unsafe fn current() -> Option { + pub unsafe fn current() -> Option { let mut ret = None; let mut attr: libc::pthread_attr_t = ::mem::zeroed(); assert_eq!(libc::pthread_attr_init(&mut attr), 0); @@ -352,12 +366,23 @@ pub mod guard { assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0); + let stackaddr = stackaddr as usize; ret = if cfg!(target_os = "freebsd") { - Some(stackaddr as usize - guardsize) + // FIXME does freebsd really fault *below* the guard addr? + let guardaddr = stackaddr - guardsize; + Some(guardaddr - PAGE_SIZE..guardaddr) } else if cfg!(target_os = "netbsd") { - Some(stackaddr as usize) + Some(stackaddr - guardsize..stackaddr) + } else if cfg!(all(target_os = "linux", target_env = "gnu")) { + // glibc used to include the guard area within the stack, as noted in the BUGS + // section of `man pthread_attr_getguardsize`. This has been corrected starting + // with glibc 2.27, and in some distro backports, so the guard is now placed at the + // end (below) the stack. There's no easy way for us to know which we have at + // runtime, so we'll just match any fault in the range right above or below the + // stack base to call that fault a stack overflow. + Some(stackaddr - guardsize..stackaddr + guardsize) } else { - Some(stackaddr as usize + guardsize) + Some(stackaddr..stackaddr + guardsize) }; } assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs index 13980e0cc19..6a066509b49 100644 --- a/src/libstd/sys/wasm/thread.rs +++ b/src/libstd/sys/wasm/thread.rs @@ -43,6 +43,7 @@ impl Thread { } pub mod guard { - pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { None } + pub type Guard = !; + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } } diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 74786d09285..43abfbb1f64 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -93,6 +93,7 @@ impl Thread { #[cfg_attr(test, allow(dead_code))] pub mod guard { - pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { None } + pub type Guard = !; + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } } diff --git a/src/libstd/sys_common/thread_info.rs b/src/libstd/sys_common/thread_info.rs index 7970042b1d6..6a2b6742367 100644 --- a/src/libstd/sys_common/thread_info.rs +++ b/src/libstd/sys_common/thread_info.rs @@ -11,10 +11,11 @@ #![allow(dead_code)] // stack_guard isn't used right now on all platforms use cell::RefCell; +use sys::thread::guard::Guard; use thread::Thread; struct ThreadInfo { - stack_guard: Option, + stack_guard: Option, thread: Thread, } @@ -38,11 +39,11 @@ pub fn current_thread() -> Option { ThreadInfo::with(|info| info.thread.clone()) } -pub fn stack_guard() -> Option { - ThreadInfo::with(|info| info.stack_guard).and_then(|o| o) +pub fn stack_guard() -> Option { + ThreadInfo::with(|info| info.stack_guard.clone()).and_then(|o| o) } -pub fn set(stack_guard: Option, thread: Thread) { +pub fn set(stack_guard: Option, thread: Thread) { THREAD_INFO.with(|c| assert!(c.borrow().is_none())); THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{ stack_guard, -- cgit 1.4.1-3-g733a5 From b1b9edf5ae3c6a8a862e480174f9fefafeba7143 Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Thu, 1 Feb 2018 20:18:33 -0500 Subject: This is what FileType on Windows should ideally be. --- src/libstd/sys/windows/fs.rs | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 165e1b0609b..001e7ceeb71 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -38,8 +38,9 @@ pub struct FileAttr { } #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -pub enum FileType { - Dir, File, SymlinkFile, SymlinkDir, ReparsePoint, MountPoint, +pub struct FileType { + attributes: c::DWORD, + reparse_tag: c::DWORD, } pub struct ReadDir { @@ -516,30 +517,28 @@ impl FilePermissions { impl FileType { fn new(attrs: c::DWORD, reparse_tag: c::DWORD) -> FileType { - match (attrs & c::FILE_ATTRIBUTE_DIRECTORY != 0, - attrs & c::FILE_ATTRIBUTE_REPARSE_POINT != 0, - reparse_tag) { - (false, false, _) => FileType::File, - (true, false, _) => FileType::Dir, - (false, true, c::IO_REPARSE_TAG_SYMLINK) => FileType::SymlinkFile, - (true, true, c::IO_REPARSE_TAG_SYMLINK) => FileType::SymlinkDir, - (true, true, c::IO_REPARSE_TAG_MOUNT_POINT) => FileType::MountPoint, - (_, true, _) => FileType::ReparsePoint, - // Note: if a _file_ has a reparse tag of the type IO_REPARSE_TAG_MOUNT_POINT it is - // invalid, as junctions always have to be dirs. We set the filetype to ReparsePoint - // to indicate it is something symlink-like, but not something you can follow. + FileType { + attributes: attrs, + reparse_tag: reparse_tag, } } - pub fn is_dir(&self) -> bool { *self == FileType::Dir } - pub fn is_file(&self) -> bool { *self == FileType::File } + pub fn is_dir(&self) -> bool { + self.attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0 + } + pub fn is_file(&self) -> bool { + self.attributes & c::FILE_ATTRIBUTE_DIRECTORY == 0 + } pub fn is_symlink(&self) -> bool { - *self == FileType::SymlinkFile || - *self == FileType::SymlinkDir || - *self == FileType::MountPoint + self.is_reparse_point() && ( + self.reparse_tag == c::IO_REPARSE_TAG_SYMLINK || + self.reparse_tag == c::IO_REPARSE_TAG_MOUNT_POINT) } pub fn is_symlink_dir(&self) -> bool { - *self == FileType::SymlinkDir || *self == FileType::MountPoint + self.is_symlink() && self.is_dir() + } + pub fn is_reparse_point(&self) -> bool { + self.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 } } -- cgit 1.4.1-3-g733a5 From dcf53c1590b741a16e92c7e5a306e923827ae301 Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Thu, 1 Feb 2018 20:35:50 -0500 Subject: Rewrite remove_dir_all to be correct The fact that this had to be rewritten does not bode well --- src/libstd/sys/windows/fs.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 001e7ceeb71..87a09925313 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -611,9 +611,11 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { let child = child?; let child_type = child.file_type()?; if child_type.is_dir() { - remove_dir_all_recursive(&child.path())?; - } else if child_type.is_symlink_dir() { - rmdir(&child.path())?; + if child_type.is_reparse_point() { + rmdir(&child.path())?; + } else { + remove_dir_all_recursive(&child.path())?; + } } else { unlink(&child.path())?; } -- cgit 1.4.1-3-g733a5 From 259b0329d42ea9ce971c0c8c9ff72f8496a73b9e Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Thu, 1 Feb 2018 20:42:31 -0500 Subject: This internal only method is no longer needed. --- src/libstd/sys/windows/fs.rs | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 87a09925313..a49c3569b02 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -534,9 +534,6 @@ impl FileType { self.reparse_tag == c::IO_REPARSE_TAG_SYMLINK || self.reparse_tag == c::IO_REPARSE_TAG_MOUNT_POINT) } - pub fn is_symlink_dir(&self) -> bool { - self.is_symlink() && self.is_dir() - } pub fn is_reparse_point(&self) -> bool { self.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 } -- cgit 1.4.1-3-g733a5 From f4c83693f9e2445b441dfcf43838697d25d1a11f Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Sat, 3 Feb 2018 01:45:58 -0500 Subject: Go back to files directories and symlinks being mutually exclusive Be smarter about what a symlink is however --- src/libstd/sys/windows/fs.rs | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index a49c3569b02..512c9cb838c 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -522,21 +522,27 @@ impl FileType { reparse_tag: reparse_tag, } } - pub fn is_dir(&self) -> bool { - self.attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0 + !self.is_symlink() && self.is_directory() } pub fn is_file(&self) -> bool { - self.attributes & c::FILE_ATTRIBUTE_DIRECTORY == 0 + !self.is_symlink() && !self.is_directory() } pub fn is_symlink(&self) -> bool { - self.is_reparse_point() && ( - self.reparse_tag == c::IO_REPARSE_TAG_SYMLINK || - self.reparse_tag == c::IO_REPARSE_TAG_MOUNT_POINT) + self.is_reparse_point() && self.is_reparse_tag_name_surrogate() + } + pub fn is_symlink_dir(&self) -> bool { + self.is_symlink() && self.is_directory() + } + fn is_directory(&self) -> bool { + self.attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0 } - pub fn is_reparse_point(&self) -> bool { + fn is_reparse_point(&self) -> bool { self.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 } + fn is_reparse_tag_name_surrogate(&self) -> bool { + self.reparse_tag & 0x20000000 != 0 + } } impl DirBuilder { @@ -607,12 +613,10 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { for child in readdir(path)? { let child = child?; let child_type = child.file_type()?; - if child_type.is_dir() { - if child_type.is_reparse_point() { - rmdir(&child.path())?; - } else { - remove_dir_all_recursive(&child.path())?; - } + if child_type.is_symlink_dir() { + rmdir(&child.path())?; + } else if child_type.is_dir() { + remove_dir_all_recursive(&child.path())?; } else { unlink(&child.path())?; } -- cgit 1.4.1-3-g733a5 From c42d76d3c80b4938e26e628706363b677fde6ca1 Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Sat, 3 Feb 2018 01:52:04 -0500 Subject: Somehow this function got flipped around Unflip it --- src/libstd/sys/windows/fs.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 512c9cb838c..7e3b16558d4 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -613,10 +613,10 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { for child in readdir(path)? { let child = child?; let child_type = child.file_type()?; - if child_type.is_symlink_dir() { - rmdir(&child.path())?; - } else if child_type.is_dir() { + if child_type.is_dir() { remove_dir_all_recursive(&child.path())?; + } else if child_type.is_symlink_dir() { + rmdir(&child.path())?; } else { unlink(&child.path())?; } -- cgit 1.4.1-3-g733a5 From 9269e83b37e8e5fd9cef12255fafbc6db6220035 Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Sun, 11 Feb 2018 13:40:46 -0500 Subject: Add an unstable FileTypeExt extension trait for Windows --- src/libstd/sys/windows/ext/fs.rs | 18 ++++++++++++++++++ src/libstd/sys/windows/fs.rs | 3 +++ 2 files changed, 21 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index 24c41046f26..38bf4cca851 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -445,6 +445,24 @@ impl MetadataExt for Metadata { fn file_size(&self) -> u64 { self.as_inner().size() } } +/// Add support for the Windows specific fact that a symbolic link knows whether it is a file +/// or directory. +#[unstable(feature = "windows_file_type_ext", issue = "0")] +pub trait FileTypeExt { + /// Returns whether this file type is a symbolic link that is also a directory. + #[unstable(feature = "windows_file_type_ext", issue = "0")] + fn is_symlink_dir(&self) -> bool; + /// Returns whether this file type is a symbolic link that is also a file. + #[unstable(feature = "windows_file_type_ext", issue = "0")] + fn is_symlink_file(&self) -> bool; +} + +#[unstable(feature = "windows_file_type_ext", issue = "0")] +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 `dst` path will be a file symbolic link pointing to the `src` diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 7e3b16558d4..082d4689c7b 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -534,6 +534,9 @@ impl FileType { pub fn is_symlink_dir(&self) -> bool { self.is_symlink() && self.is_directory() } + pub fn is_symlink_file(&self) -> bool { + self.is_symlink() && !self.is_directory() + } fn is_directory(&self) -> bool { self.attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0 } -- cgit 1.4.1-3-g733a5 From 472dcdb4ecb3fbea4b3e2b1d5952adc1d0f6cc76 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 17 Feb 2018 20:57:00 -0500 Subject: Fix broken documentation link. --- src/libstd/sys/unix/ext/net.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 86b0f35be92..31bdc5ea1f5 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -415,7 +415,7 @@ impl UnixStream { /// method. /// /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`read`]: ../../../../std/io/trait.Write.html#tymethod.write + /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write /// [`Duration`]: ../../../../std/time/struct.Duration.html /// /// # Examples -- cgit 1.4.1-3-g733a5 From d17d645ad75c797a293ccf1fa3881853617f292c Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 18 Feb 2018 16:08:48 -0500 Subject: Add tests ensuring zero-Duration timeouts result in errors. Part of https://github.com/rust-lang/rust/issues/48311 --- src/libstd/net/tcp.rs | 20 ++++++++++++++++++++ src/libstd/net/udp.rs | 17 +++++++++++++++++ src/libstd/sys/unix/ext/net.rs | 41 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 77 insertions(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 78235ea1b4b..ee63e185ddb 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -1545,6 +1545,26 @@ mod tests { drop(listener); } + // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors + // when passed zero Durations + #[test] + fn test_timeout_zero_duration() { + let addr = next_test_ip4(); + + let listener = t!(TcpListener::bind(&addr)); + let stream = t!(TcpStream::connect(&addr)); + + let result = stream.set_write_timeout(Some(Duration::new(0, 0))); + let err = result.unwrap_err(); + assert_eq!(err.kind(), ErrorKind::InvalidInput); + + let result = stream.set_read_timeout(Some(Duration::new(0, 0))); + let err = result.unwrap_err(); + assert_eq!(err.kind(), ErrorKind::InvalidInput); + + drop(listener); + } + #[test] fn nodelay() { let addr = next_test_ip4(); diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index fc7f9205d06..4163bec000b 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -1024,6 +1024,23 @@ mod tests { assert!(start.elapsed() > Duration::from_millis(400)); } + // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors + // when passed zero Durations + #[test] + fn test_timeout_zero_duration() { + let addr = next_test_ip4(); + + let socket = t!(UdpSocket::bind(&addr)); + + let result = socket.set_write_timeout(Some(Duration::new(0, 0))); + let err = result.unwrap_err(); + assert_eq!(err.kind(), ErrorKind::InvalidInput); + + let result = socket.set_read_timeout(Some(Duration::new(0, 0))); + let err = result.unwrap_err(); + assert_eq!(err.kind(), ErrorKind::InvalidInput); + } + #[test] fn connect_send_recv() { let addr = next_test_ip4(); diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 86b0f35be92..f1bf8f240d3 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -1410,7 +1410,7 @@ impl IntoRawFd for UnixDatagram { #[cfg(all(test, not(target_os = "emscripten")))] mod test { use thread; - use io; + use io::{self, ErrorKind}; use io::prelude::*; use time::Duration; use sys_common::io::test::tmpdir; @@ -1613,6 +1613,27 @@ mod test { assert!(kind == io::ErrorKind::WouldBlock || kind == io::ErrorKind::TimedOut); } + // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors + // when passed zero Durations + #[test] + fn test_unix_stream_timeout_zero_duration() { + let dir = tmpdir(); + let socket_path = dir.path().join("sock"); + + let listener = or_panic!(UnixListener::bind(&socket_path)); + let stream = or_panic!(UnixStream::connect(&socket_path)); + + let result = stream.set_write_timeout(Some(Duration::new(0, 0))); + let err = result.unwrap_err(); + assert_eq!(err.kind(), ErrorKind::InvalidInput); + + let result = stream.set_read_timeout(Some(Duration::new(0, 0))); + let err = result.unwrap_err(); + assert_eq!(err.kind(), ErrorKind::InvalidInput); + + drop(listener); + } + #[test] fn test_unix_datagram() { let dir = tmpdir(); @@ -1712,6 +1733,24 @@ mod test { thread.join().unwrap(); } + // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors + // when passed zero Durations + #[test] + fn test_unix_datagram_timeout_zero_duration() { + let dir = tmpdir(); + let path = dir.path().join("sock"); + + let datagram = or_panic!(UnixDatagram::bind(&path)); + + let result = datagram.set_write_timeout(Some(Duration::new(0, 0))); + let err = result.unwrap_err(); + assert_eq!(err.kind(), ErrorKind::InvalidInput); + + let result = datagram.set_read_timeout(Some(Duration::new(0, 0))); + let err = result.unwrap_err(); + assert_eq!(err.kind(), ErrorKind::InvalidInput); + } + #[test] fn abstract_namespace_not_allowed() { assert!(UnixStream::connect("\0asdf").is_err()); -- cgit 1.4.1-3-g733a5 From 0700bd12d0279db22da40748d86c42b92804888a Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 18 Feb 2018 14:18:56 -0500 Subject: Clarify "It is an error to..." wording for zero-duration behaviors. Documentation fix side of https://github.com/rust-lang/rust/issues/48311. --- src/libstd/net/tcp.rs | 39 ++++++++++++++++++++--- src/libstd/net/udp.rs | 38 +++++++++++++++++++--- src/libstd/sys/unix/ext/net.rs | 71 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 134 insertions(+), 14 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 263a2c13249..53f9eaafb06 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -259,8 +259,8 @@ impl TcpStream { /// Sets the read timeout to the timeout specified. /// /// If the value specified is [`None`], then [`read`] calls will block - /// indefinitely. It is an error to pass the zero `Duration` to this - /// method. + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is + /// passed to this method. /// /// # Platform-specific behavior /// @@ -269,9 +269,11 @@ impl TcpStream { /// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`]. /// /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err /// [`read`]: ../../std/io/trait.Read.html#tymethod.read /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut + /// [`Duration`]: ../../std/time/struct.Duration.html /// /// # Examples /// @@ -282,6 +284,20 @@ impl TcpStream { /// .expect("Couldn't connect to the server..."); /// stream.set_read_timeout(None).expect("set_read_timeout call failed"); /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::net::TcpStream; + /// use std::time::Duration; + /// + /// let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); + /// let result = stream.set_read_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` #[stable(feature = "socket_timeout", since = "1.4.0")] pub fn set_read_timeout(&self, dur: Option) -> io::Result<()> { self.0.set_read_timeout(dur) @@ -290,8 +306,8 @@ impl TcpStream { /// Sets the write timeout to the timeout specified. /// /// If the value specified is [`None`], then [`write`] calls will block - /// indefinitely. It is an error to pass the zero [`Duration`] to this - /// method. + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is + /// passed to this method. /// /// # Platform-specific behavior /// @@ -300,6 +316,7 @@ impl TcpStream { /// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`]. /// /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err /// [`write`]: ../../std/io/trait.Write.html#tymethod.write /// [`Duration`]: ../../std/time/struct.Duration.html /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock @@ -314,6 +331,20 @@ impl TcpStream { /// .expect("Couldn't connect to the server..."); /// stream.set_write_timeout(None).expect("set_write_timeout call failed"); /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::net::TcpStream; + /// use std::time::Duration; + /// + /// let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); + /// let result = stream.set_write_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` #[stable(feature = "socket_timeout", since = "1.4.0")] pub fn set_write_timeout(&self, dur: Option) -> io::Result<()> { self.0.set_write_timeout(dur) diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 5e19519b88f..0a50cee6756 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -228,8 +228,8 @@ impl UdpSocket { /// Sets the read timeout to the timeout specified. /// /// If the value specified is [`None`], then [`read`] calls will block - /// indefinitely. It is an error to pass the zero [`Duration`] to this - /// method. + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is + /// passed to this method. /// /// # Platform-specific behavior /// @@ -238,6 +238,7 @@ impl UdpSocket { /// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`]. /// /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err /// [`read`]: ../../std/io/trait.Read.html#tymethod.read /// [`Duration`]: ../../std/time/struct.Duration.html /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock @@ -251,6 +252,20 @@ impl UdpSocket { /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); /// socket.set_read_timeout(None).expect("set_read_timeout call failed"); /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::net::UdpSocket; + /// use std::time::Duration; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); + /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` #[stable(feature = "socket_timeout", since = "1.4.0")] pub fn set_read_timeout(&self, dur: Option) -> io::Result<()> { self.0.set_read_timeout(dur) @@ -259,8 +274,8 @@ impl UdpSocket { /// Sets the write timeout to the timeout specified. /// /// If the value specified is [`None`], then [`write`] calls will block - /// indefinitely. It is an error to pass the zero [`Duration`] to this - /// method. + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is + /// passed to this method. /// /// # Platform-specific behavior /// @@ -269,6 +284,7 @@ impl UdpSocket { /// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`]. /// /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err /// [`write`]: ../../std/io/trait.Write.html#tymethod.write /// [`Duration`]: ../../std/time/struct.Duration.html /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock @@ -282,6 +298,20 @@ impl UdpSocket { /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); /// socket.set_write_timeout(None).expect("set_write_timeout call failed"); /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::net::UdpSocket; + /// use std::time::Duration; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); + /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` #[stable(feature = "socket_timeout", since = "1.4.0")] pub fn set_write_timeout(&self, dur: Option) -> io::Result<()> { self.0.set_write_timeout(dur) diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 31bdc5ea1f5..3430512ebe8 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -387,10 +387,11 @@ impl UnixStream { /// Sets the read timeout for the socket. /// /// If the provided value is [`None`], then [`read`] calls will block - /// indefinitely. It is an error to pass the zero [`Duration`] to this + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this /// method. /// /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read /// [`Duration`]: ../../../../std/time/struct.Duration.html /// @@ -403,6 +404,20 @@ impl UnixStream { /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_RCVTIMEO) @@ -411,10 +426,11 @@ impl UnixStream { /// Sets the write timeout for the socket. /// /// If the provided value is [`None`], then [`write`] calls will block - /// indefinitely. It is an error to pass the zero [`Duration`] to this - /// method. + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is + /// passed to this method. /// /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write /// [`Duration`]: ../../../../std/time/struct.Duration.html /// @@ -427,6 +443,20 @@ impl UnixStream { /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::net::UdpSocket; + /// use std::time::Duration; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); + /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_SNDTIMEO) @@ -1250,10 +1280,11 @@ impl UnixDatagram { /// Sets the read timeout for the socket. /// /// If the provided value is [`None`], then [`recv`] and [`recv_from`] calls will - /// block indefinitely. It is an error to pass the zero [`Duration`] to this - /// method. + /// block indefinitely. An [`Err`] is returned if the zero [`Duration`] + /// is passed to this method. /// /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err /// [`recv`]: #method.recv /// [`recv_from`]: #method.recv_from /// [`Duration`]: ../../../../std/time/struct.Duration.html @@ -1267,6 +1298,20 @@ impl UnixDatagram { /// let sock = UnixDatagram::unbound().unwrap(); /// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed"); /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::os::unix::net::UnixDatagram; + /// use std::time::Duration; + /// + /// let socket = UnixDatagram::unbound().unwrap(); + /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_RCVTIMEO) @@ -1275,7 +1320,7 @@ impl UnixDatagram { /// Sets the write timeout for the socket. /// /// If the provided value is [`None`], then [`send`] and [`send_to`] calls will - /// block indefinitely. It is an error to pass the zero [`Duration`] to this + /// block indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this /// method. /// /// [`None`]: ../../../../std/option/enum.Option.html#variant.None @@ -1293,6 +1338,20 @@ impl UnixDatagram { /// sock.set_write_timeout(Some(Duration::new(1, 0))) /// .expect("set_write_timeout function failed"); /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::os::unix::net::UnixDatagram; + /// use std::time::Duration; + /// + /// let socket = UnixDatagram::unbound().unwrap(); + /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_SNDTIMEO) -- cgit 1.4.1-3-g733a5 From a554a2f5645f12cf42d311ac11bcaad594c91347 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 19 Feb 2018 08:45:45 -0500 Subject: Return error if timeout is zero-Duration on Redox. --- src/libstd/sys/redox/net/tcp.rs | 10 +++++++++- src/libstd/sys/redox/net/udp.rs | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/net/tcp.rs b/src/libstd/sys/redox/net/tcp.rs index 319965ab396..b5664908479 100644 --- a/src/libstd/sys/redox/net/tcp.rs +++ b/src/libstd/sys/redox/net/tcp.rs @@ -9,7 +9,7 @@ // except according to those terms. use cmp; -use io::{Error, ErrorKind, Result}; +use io::{self, Error, ErrorKind, Result}; use mem; use net::{SocketAddr, Shutdown}; use path::Path; @@ -130,6 +130,10 @@ impl TcpStream { pub fn set_read_timeout(&self, duration_option: Option) -> Result<()> { let file = self.0.dup(b"read_timeout")?; if let Some(duration) = duration_option { + if duration.as_secs() == 0 && duration.subsec_nanos() == 0 { + return Err(io::Error::new(io::ErrorKind::InvalidInput, + "cannot set a 0 duration timeout")); + } file.write(&TimeSpec { tv_sec: duration.as_secs() as i64, tv_nsec: duration.subsec_nanos() as i32 @@ -143,6 +147,10 @@ impl TcpStream { pub fn set_write_timeout(&self, duration_option: Option) -> Result<()> { let file = self.0.dup(b"write_timeout")?; if let Some(duration) = duration_option { + if duration.as_secs() == 0 && duration.subsec_nanos() == 0 { + return Err(io::Error::new(io::ErrorKind::InvalidInput, + "cannot set a 0 duration timeout")); + } file.write(&TimeSpec { tv_sec: duration.as_secs() as i64, tv_nsec: duration.subsec_nanos() as i32 diff --git a/src/libstd/sys/redox/net/udp.rs b/src/libstd/sys/redox/net/udp.rs index 7e7666e7ef3..2ed67bd2836 100644 --- a/src/libstd/sys/redox/net/udp.rs +++ b/src/libstd/sys/redox/net/udp.rs @@ -10,7 +10,7 @@ use cell::UnsafeCell; use cmp; -use io::{Error, ErrorKind, Result}; +use io::{self, Error, ErrorKind, Result}; use mem; use net::{SocketAddr, Ipv4Addr, Ipv6Addr}; use path::Path; @@ -179,6 +179,10 @@ impl UdpSocket { pub fn set_read_timeout(&self, duration_option: Option) -> Result<()> { let file = self.0.dup(b"read_timeout")?; if let Some(duration) = duration_option { + if duration.as_secs() == 0 && duration.subsec_nanos() == 0 { + return Err(io::Error::new(io::ErrorKind::InvalidInput, + "cannot set a 0 duration timeout")); + } file.write(&TimeSpec { tv_sec: duration.as_secs() as i64, tv_nsec: duration.subsec_nanos() as i32 @@ -192,6 +196,10 @@ impl UdpSocket { pub fn set_write_timeout(&self, duration_option: Option) -> Result<()> { let file = self.0.dup(b"write_timeout")?; if let Some(duration) = duration_option { + if duration.as_secs() == 0 && duration.subsec_nanos() == 0 { + return Err(io::Error::new(io::ErrorKind::InvalidInput, + "cannot set a 0 duration timeout")); + } file.write(&TimeSpec { tv_sec: duration.as_secs() as i64, tv_nsec: duration.subsec_nanos() as i32 -- cgit 1.4.1-3-g733a5 From 11696acd6d070a90e8dd386a3c9ae877740fb0e2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 25 Jan 2018 18:13:45 -0800 Subject: Support posix_spawn() when possible. --- src/libstd/sys/unix/process/process_unix.rs | 102 ++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index 189280a4ba9..d66c2375140 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -24,6 +24,7 @@ impl Command { -> io::Result<(Process, StdioPipes)> { use sys; + const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX"; let envp = self.capture_env(); @@ -34,6 +35,11 @@ impl Command { } let (ours, theirs) = self.setup_io(default, needs_stdin)?; + + if let Some(ret) = self.posix_spawn(&theirs, envp.as_ref())? { + return Ok((ret, ours)) + } + let (input, output) = sys::pipe::anon_pipe()?; let pid = unsafe { @@ -229,6 +235,102 @@ impl Command { libc::execvp(self.get_argv()[0], self.get_argv().as_ptr()); io::Error::last_os_error() } + + #[cfg(not(any(target_os = "linux", target_os = "macos")))] + fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>) + -> io::Result> + { + Ok(None) + } + + #[cfg(any(target_os = "linux", target_os = "macos"))] + fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>) + -> io::Result> + { + use mem; + use sys; + + if self.get_cwd().is_some() || + self.get_gid().is_some() || + self.get_uid().is_some() || + self.get_closures().len() != 0 { + return Ok(None) + } + + let mut p = Process { pid: 0, status: None }; + + struct PosixSpawnFileActions(libc::posix_spawn_file_actions_t); + + impl Drop for PosixSpawnFileActions { + fn drop(&mut self) { + unsafe { + libc::posix_spawn_file_actions_destroy(&mut self.0); + } + } + } + + struct PosixSpawnattr(libc::posix_spawnattr_t); + + impl Drop for PosixSpawnattr { + fn drop(&mut self) { + unsafe { + libc::posix_spawnattr_destroy(&mut self.0); + } + } + } + + unsafe { + let mut file_actions = PosixSpawnFileActions(mem::zeroed()); + let mut attrs = PosixSpawnattr(mem::zeroed()); + + libc::posix_spawnattr_init(&mut attrs.0); + libc::posix_spawn_file_actions_init(&mut file_actions.0); + + if let Some(fd) = stdio.stdin.fd() { + cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0, + fd, + libc::STDIN_FILENO))?; + } + if let Some(fd) = stdio.stdout.fd() { + cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0, + fd, + libc::STDOUT_FILENO))?; + } + if let Some(fd) = stdio.stderr.fd() { + cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0, + fd, + libc::STDERR_FILENO))?; + } + + let mut set: libc::sigset_t = mem::zeroed(); + cvt(libc::sigemptyset(&mut set))?; + cvt(libc::posix_spawnattr_setsigmask(&mut attrs.0, + &set))?; + cvt(libc::sigaddset(&mut set, libc::SIGPIPE))?; + cvt(libc::posix_spawnattr_setsigdefault(&mut attrs.0, + &set))?; + + let flags = libc::POSIX_SPAWN_SETSIGDEF | + libc::POSIX_SPAWN_SETSIGMASK; + cvt(libc::posix_spawnattr_setflags(&mut attrs.0, flags as _))?; + + let envp = envp.map(|c| c.as_ptr()) + .unwrap_or(sys::os::environ() as *const _); + let ret = libc::posix_spawnp( + &mut p.pid, + self.get_argv()[0], + &file_actions.0, + &attrs.0, + self.get_argv().as_ptr() as *const _, + envp as *const _, + ); + if ret == 0 { + Ok(Some(p)) + } else { + Err(io::Error::last_os_error()) + } + } + } } //////////////////////////////////////////////////////////////////////////////// -- cgit 1.4.1-3-g733a5 From f4633865d37dea15a88220e886e77839aa1fd1ba Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Mon, 26 Feb 2018 17:33:44 -0800 Subject: Avoid error for unused variables --- src/libstd/sys/unix/process/process_unix.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index d66c2375140..05b4b9b085b 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -237,7 +237,7 @@ impl Command { } #[cfg(not(any(target_os = "linux", target_os = "macos")))] - fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>) + fn posix_spawn(&mut self, _stdio: &ChildPipes, _envp: Option<&CStringArray>) -> io::Result> { Ok(None) -- cgit 1.4.1-3-g733a5 From 94630e4ca509f9b37e4c066eee94f40da12cba51 Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Mon, 26 Feb 2018 20:23:46 -0800 Subject: No need to zero when an initializer for the object is already used. --- src/libstd/sys/unix/process/process_unix.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index 05b4b9b085b..b394d5ff41a 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -280,8 +280,8 @@ impl Command { } unsafe { - let mut file_actions = PosixSpawnFileActions(mem::zeroed()); - let mut attrs = PosixSpawnattr(mem::zeroed()); + let mut file_actions = PosixSpawnFileActions(mem::uninitialized()); + let mut attrs = PosixSpawnattr(mem::uninitialized()); libc::posix_spawnattr_init(&mut attrs.0); libc::posix_spawn_file_actions_init(&mut file_actions.0); @@ -302,7 +302,7 @@ impl Command { libc::STDERR_FILENO))?; } - let mut set: libc::sigset_t = mem::zeroed(); + let mut set: libc::sigset_t = mem::uninitialized(); cvt(libc::sigemptyset(&mut set))?; cvt(libc::posix_spawnattr_setsigmask(&mut attrs.0, &set))?; -- cgit 1.4.1-3-g733a5 From 8e3fa0d3c450051d6445aa82682416eb307b2d5b Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Mon, 26 Feb 2018 23:51:19 -0800 Subject: Pass proper pointer for envp. --- src/libstd/sys/unix/process/process_unix.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index b394d5ff41a..9765ff37e9b 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -315,7 +315,7 @@ impl Command { cvt(libc::posix_spawnattr_setflags(&mut attrs.0, flags as _))?; let envp = envp.map(|c| c.as_ptr()) - .unwrap_or(sys::os::environ() as *const _); + .unwrap_or(*sys::os::environ() as *const _); let ret = libc::posix_spawnp( &mut p.pid, self.get_argv()[0], -- cgit 1.4.1-3-g733a5 From b3ecf5f57ca9d34d10ffd9d064a027ce3f4888ac Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Mon, 26 Feb 2018 23:51:39 -0800 Subject: Remove excess newline --- src/libstd/sys/unix/process/process_unix.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index 9765ff37e9b..fa66245abb6 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -24,7 +24,6 @@ impl Command { -> io::Result<(Process, StdioPipes)> { use sys; - const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX"; let envp = self.capture_env(); -- cgit 1.4.1-3-g733a5 From 85b82f254e28f5e50b25d8e096af0f01e4441ef7 Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Tue, 27 Feb 2018 14:12:52 -0800 Subject: Support posix_spawn() for FreeBSD. spawn() is expected to return an error if the specified file could not be executed. FreeBSD's posix_spawn() supports returning ENOENT/ENOEXEC if the exec() fails, which not all platforms support. This brings a very significant performance improvement for FreeBSD, involving heavy use of Command in threads, due to fork() invoking jemalloc fork handlers and causing lock contention. FreeBSD's posix_spawn() avoids this problem due to using vfork() internally. --- src/libstd/sys/unix/process/process_unix.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index fa66245abb6..c7841a861ce 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -235,14 +235,14 @@ impl Command { io::Error::last_os_error() } - #[cfg(not(any(target_os = "linux", target_os = "macos")))] + #[cfg(not(any(target_os = "freebsd")))] fn posix_spawn(&mut self, _stdio: &ChildPipes, _envp: Option<&CStringArray>) -> io::Result> { Ok(None) } - #[cfg(any(target_os = "linux", target_os = "macos"))] + #[cfg(any(target_os = "freebsd"))] fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>) -> io::Result> { -- cgit 1.4.1-3-g733a5 From a9ea876960a06f3ae00049515bf9ef706cca806b Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Wed, 28 Feb 2018 22:16:35 -0800 Subject: posix_spawn() always returns its error rather than setting errno. --- src/libstd/sys/unix/process/process_unix.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index c7841a861ce..c5dda6273ef 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -326,7 +326,7 @@ impl Command { if ret == 0 { Ok(Some(p)) } else { - Err(io::Error::last_os_error()) + Err(io::Error::from_raw_os_error(ret)) } } } -- cgit 1.4.1-3-g733a5 From 2e2d9260f9425cd700199383096d8201190737de Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Thu, 1 Mar 2018 09:17:49 -0800 Subject: posix_spawn() on OSX supports returning ENOENT. --- src/libstd/sys/unix/process/process_unix.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index c5dda6273ef..dcf0278b4aa 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -235,14 +235,14 @@ impl Command { io::Error::last_os_error() } - #[cfg(not(any(target_os = "freebsd")))] + #[cfg(not(any(target_os = "macos", target_os = "freebsd")))] fn posix_spawn(&mut self, _stdio: &ChildPipes, _envp: Option<&CStringArray>) -> io::Result> { Ok(None) } - #[cfg(any(target_os = "freebsd"))] + #[cfg(any(target_os = "macos", target_os = "freebsd"))] fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>) -> io::Result> { -- cgit 1.4.1-3-g733a5 From ef73b3ae2eac3a03f5b966a4f8b2a568e3619d51 Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Thu, 1 Mar 2018 09:18:16 -0800 Subject: Add comment explaining when posix_spawn() can be supported. --- src/libstd/sys/unix/process/process_unix.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index dcf0278b4aa..bd6a8d3f64b 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -242,6 +242,8 @@ impl Command { Ok(None) } + // Only support platforms for which posix_spawn() can return ENOENT + // directly. #[cfg(any(target_os = "macos", target_os = "freebsd"))] fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>) -> io::Result> -- cgit 1.4.1-3-g733a5 From 99b50efb6eb048297cda699ad017821822591d7a Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Fri, 2 Mar 2018 08:50:37 -0800 Subject: Use _ --- src/libstd/sys/unix/process/process_unix.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index bd6a8d3f64b..51ae0aa7315 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -236,7 +236,7 @@ impl Command { } #[cfg(not(any(target_os = "macos", target_os = "freebsd")))] - fn posix_spawn(&mut self, _stdio: &ChildPipes, _envp: Option<&CStringArray>) + fn posix_spawn(&mut self, _: &ChildPipes, _: Option<&CStringArray>) -> io::Result> { Ok(None) -- cgit 1.4.1-3-g733a5 From 5ba6b3a728fb50cd65237b8eeac2f2df05c3c77f Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Fri, 2 Mar 2018 12:50:07 -0800 Subject: Move glibc version lookup handling to sys::os and add a simpler glibc_version() --- src/libstd/sys/unix/net.rs | 33 +++++---------------------------- src/libstd/sys/unix/os.rs | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 28 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index 3f65975e608..04d9f0b06d3 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -383,12 +383,12 @@ impl IntoInner for Socket { // believe it's thread-safe). #[cfg(target_env = "gnu")] fn on_resolver_failure() { + use sys; + // If the version fails to parse, we treat it the same as "not glibc". - if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) { - if let Some(version) = parse_glibc_version(version_str) { - if version < (2, 26) { - unsafe { libc::res_init() }; - } + if let Some(version) = sys::os::glibc_version() { + if version < (2, 26) { + unsafe { libc::res_init() }; } } } @@ -396,29 +396,6 @@ fn on_resolver_failure() { #[cfg(not(target_env = "gnu"))] fn on_resolver_failure() {} -#[cfg(target_env = "gnu")] -fn glibc_version_cstr() -> Option<&'static CStr> { - weak! { - fn gnu_get_libc_version() -> *const libc::c_char - } - if let Some(f) = gnu_get_libc_version.get() { - unsafe { Some(CStr::from_ptr(f())) } - } else { - None - } -} - -// Returns Some((major, minor)) if the string is a valid "x.y" version, -// ignoring any extra dot-separated parts. Otherwise return None. -#[cfg(target_env = "gnu")] -fn parse_glibc_version(version: &str) -> Option<(usize, usize)> { - let mut parsed_ints = version.split(".").map(str::parse::).fuse(); - match (parsed_ints.next(), parsed_ints.next()) { - (Some(Ok(major)), Some(Ok(minor))) => Some((major, minor)), - _ => None - } -} - #[cfg(all(test, taget_env = "gnu"))] mod test { use super::*; diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index a46e855b4a6..4c86fddee4b 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -546,3 +546,35 @@ pub fn getpid() -> u32 { pub fn getppid() -> u32 { unsafe { libc::getppid() as u32 } } + +#[cfg(target_env = "gnu")] +pub fn glibc_version() -> Option<(usize, usize)> { + if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) { + parse_glibc_version(version_str) + } else { + None + } +} + +#[cfg(target_env = "gnu")] +fn glibc_version_cstr() -> Option<&'static CStr> { + weak! { + fn gnu_get_libc_version() -> *const libc::c_char + } + if let Some(f) = gnu_get_libc_version.get() { + unsafe { Some(CStr::from_ptr(f())) } + } else { + None + } +} + +// Returns Some((major, minor)) if the string is a valid "x.y" version, +// ignoring any extra dot-separated parts. Otherwise return None. +#[cfg(target_env = "gnu")] +fn parse_glibc_version(version: &str) -> Option<(usize, usize)> { + let mut parsed_ints = version.split(".").map(str::parse::).fuse(); + match (parsed_ints.next(), parsed_ints.next()) { + (Some(Ok(major)), Some(Ok(minor))) => Some((major, minor)), + _ => None + } +} -- cgit 1.4.1-3-g733a5 From d740083fc8981ee933dc48a6b3dcee21b82c993e Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Fri, 2 Mar 2018 13:02:38 -0800 Subject: Support posix_spawn() for Linux glibc 2.24+. The relevant support was added in https://sourceware.org/bugzilla/show_bug.cgi?id=10354#c12 --- src/libstd/sys/unix/process/process_unix.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index 51ae0aa7315..29e33ee822e 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -235,7 +235,8 @@ impl Command { io::Error::last_os_error() } - #[cfg(not(any(target_os = "macos", target_os = "freebsd")))] + #[cfg(not(any(target_os = "macos", target_os = "freebsd", + all(target_os = "linux", target_env = "gnu"))))] fn posix_spawn(&mut self, _: &ChildPipes, _: Option<&CStringArray>) -> io::Result> { @@ -244,7 +245,8 @@ impl Command { // Only support platforms for which posix_spawn() can return ENOENT // directly. - #[cfg(any(target_os = "macos", target_os = "freebsd"))] + #[cfg(any(target_os = "macos", target_os = "freebsd", + all(target_os = "linux", target_env = "gnu")))] fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>) -> io::Result> { @@ -258,6 +260,18 @@ impl Command { return Ok(None) } + // Only glibc 2.24+ posix_spawn() supports returning ENOENT directly. + #[cfg(all(target_os = "linux", target_env = "gnu"))] + { + if let Some(version) = sys::os::glibc_version() { + if version < (2, 24) { + return Ok(None) + } + } else { + return Ok(None) + } + } + let mut p = Process { pid: 0, status: None }; struct PosixSpawnFileActions(libc::posix_spawn_file_actions_t); -- cgit 1.4.1-3-g733a5 From 74c5c6e6cb0425284f57fece6fbf248e827ea06d Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 3 Mar 2018 18:29:30 -0800 Subject: Move process::ExitCode internals to sys Now begins the saga of fixing compilation errors on other platforms... --- src/libstd/process.rs | 29 ++++++++------------------- src/libstd/sys/cloudabi/shims/process.rs | 12 +++++++++++ src/libstd/sys/redox/process.rs | 13 ++++++++++++ src/libstd/sys/unix/process/mod.rs | 2 +- src/libstd/sys/unix/process/process_common.rs | 14 ++++++++++++- src/libstd/sys/wasm/process.rs | 12 +++++++++++ src/libstd/sys/windows/process.rs | 14 ++++++++++++- 7 files changed, 72 insertions(+), 24 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 5a06bf45aaa..d5ac2d19e83 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1098,38 +1098,26 @@ impl fmt::Display for ExitStatus { /// /// [RFC #1937]: https://github.com/rust-lang/rfcs/pull/1937 #[derive(Clone, Copy, Debug)] -#[unstable(feature = "process_exitcode_placeholder", issue = "43301")] -pub struct ExitCode(pub i32); +#[unstable(feature = "process_exitcode_placeholder", issue = "48711")] +pub struct ExitCode(imp::ExitCode); -#[cfg(target_arch = "wasm32")] -mod rawexit { - pub const SUCCESS: i32 = 0; - pub const FAILURE: i32 = 1; -} -#[cfg(not(target_arch = "wasm32"))] -mod rawexit { - use libc; - pub const SUCCESS: i32 = libc::EXIT_SUCCESS; - pub const FAILURE: i32 = libc::EXIT_FAILURE; -} - -#[unstable(feature = "process_exitcode_placeholder", issue = "43301")] +#[unstable(feature = "process_exitcode_placeholder", issue = "48711")] impl ExitCode { /// The canonical ExitCode for successful termination on this platform. /// /// Note that a `()`-returning `main` implicitly results in a successful /// termination, so there's no need to return this from `main` unless /// you're also returning other possible codes. - #[unstable(feature = "process_exitcode_placeholder", issue = "43301")] - pub const SUCCESS: ExitCode = ExitCode(rawexit::SUCCESS); + #[unstable(feature = "process_exitcode_placeholder", issue = "48711")] + pub const SUCCESS: ExitCode = ExitCode(imp::ExitCode::SUCCESS); /// The canonical ExitCode for unsuccessful termination on this platform. /// /// If you're only returning this and `SUCCESS` from `main`, consider /// instead returning `Err(_)` and `Ok(())` respectively, which will /// return the same codes (but will also `eprintln!` the error). - #[unstable(feature = "process_exitcode_placeholder", issue = "43301")] - pub const FAILURE: ExitCode = ExitCode(rawexit::FAILURE); + #[unstable(feature = "process_exitcode_placeholder", issue = "48711")] + pub const FAILURE: ExitCode = ExitCode(imp::ExitCode::FAILURE); } impl Child { @@ -1494,8 +1482,7 @@ impl Termination for Result { #[unstable(feature = "termination_trait_lib", issue = "43301")] impl Termination for ExitCode { fn report(self) -> i32 { - let ExitCode(code) = self; - code + self.0.as_i32() } } diff --git a/src/libstd/sys/cloudabi/shims/process.rs b/src/libstd/sys/cloudabi/shims/process.rs index 52e8c82e2b2..fcd40c15c17 100644 --- a/src/libstd/sys/cloudabi/shims/process.rs +++ b/src/libstd/sys/cloudabi/shims/process.rs @@ -126,6 +126,18 @@ impl fmt::Display for ExitStatus { } } +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct ExitCode(bool); + +impl ExitCode { + pub const SUCCESS: ExitCode = ExitCode(false); + pub const FAILURE: ExitCode = ExitCode(true); + + pub fn as_i32(&self) -> i32 { + self.0 as i32 + } +} + pub struct Process(Void); impl Process { diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index 3fd54973896..d0b94e14f54 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -13,6 +13,7 @@ use ffi::OsStr; use os::unix::ffi::OsStrExt; use fmt; use io::{self, Error, ErrorKind}; +use libc::{EXIT_SUCCESS, EXIT_FAILURE}; use path::{Path, PathBuf}; use sys::fd::FileDesc; use sys::fs::{File, OpenOptions}; @@ -480,6 +481,18 @@ impl fmt::Display for ExitStatus { } } +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct ExitCode(u8); + +impl ExitCode { + pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _); + pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _); + + pub fn as_i32(&self) -> i32 { + self.0 as i32 + } +} + /// The unique id of the process (this should never be negative). pub struct Process { pid: usize, diff --git a/src/libstd/sys/unix/process/mod.rs b/src/libstd/sys/unix/process/mod.rs index 2a331069bc2..d8ac26c45b1 100644 --- a/src/libstd/sys/unix/process/mod.rs +++ b/src/libstd/sys/unix/process/mod.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub use self::process_common::{Command, ExitStatus, Stdio, StdioPipes}; +pub use self::process_common::{Command, ExitStatus, ExitCode, Stdio, StdioPipes}; pub use self::process_inner::Process; mod process_common; diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index 7e057401fab..d0486f06a14 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -13,7 +13,7 @@ use os::unix::prelude::*; use ffi::{OsString, OsStr, CString, CStr}; use fmt; use io; -use libc::{self, c_int, gid_t, uid_t, c_char}; +use libc::{self, c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE}; use ptr; use sys::fd::FileDesc; use sys::fs::{File, OpenOptions}; @@ -393,6 +393,18 @@ impl fmt::Display for ExitStatus { } } +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct ExitCode(u8); + +impl ExitCode { + pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _); + pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _); + + pub fn as_i32(&self) -> i32 { + self.0 as i32 + } +} + #[cfg(all(test, not(target_os = "emscripten")))] mod tests { use super::*; diff --git a/src/libstd/sys/wasm/process.rs b/src/libstd/sys/wasm/process.rs index f3f5de350f1..433e9cec7c8 100644 --- a/src/libstd/sys/wasm/process.rs +++ b/src/libstd/sys/wasm/process.rs @@ -129,6 +129,18 @@ impl fmt::Display for ExitStatus { } } +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct ExitCode(bool); + +impl ExitCode { + pub const SUCCESS: ExitCode = ExitCode(false); + pub const FAILURE: ExitCode = ExitCode(true); + + pub fn as_i32(&self) -> i32 { + self.0 as i32 + } +} + pub struct Process(Void); impl Process { diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index c93179869a6..f1ab9c47609 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -18,7 +18,7 @@ use ffi::{OsString, OsStr}; use fmt; use fs; use io::{self, Error, ErrorKind}; -use libc::c_void; +use libc::{c_void, EXIT_SUCCESS, EXIT_FAILURE}; use mem; use os::windows::ffi::OsStrExt; use path::Path; @@ -408,6 +408,18 @@ impl fmt::Display for ExitStatus { } } +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct ExitCode(c::DWORD); + +impl ExitCode { + pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _); + pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _); + + pub fn as_i32(&self) -> i32 { + self.0 as i32 + } +} + fn zeroed_startupinfo() -> c::STARTUPINFO { c::STARTUPINFO { cb: 0, -- cgit 1.4.1-3-g733a5 From a185b56b7caca17c7aa9d6f702fe1b2209c82e4e Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Sun, 18 Mar 2018 23:02:06 +0900 Subject: Address review comments --- src/librustc_driver/lib.rs | 8 +++++--- src/libstd/rt.rs | 15 +++++++++++++++ src/libstd/sys/unix/thread.rs | 20 +++++++++++++++++++- src/libstd/thread/mod.rs | 8 -------- 4 files changed, 39 insertions(+), 12 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 76179723941..e39a2c2f5dc 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -1476,13 +1476,15 @@ pub fn in_rustc_thread(f: F) -> Result> } else if rlim.rlim_max < STACK_SIZE as libc::rlim_t { true } else { + std::rt::deinit_stack_guard(); rlim.rlim_cur = STACK_SIZE as libc::rlim_t; if libc::setrlimit(libc::RLIMIT_STACK, &mut rlim) != 0 { let err = io::Error::last_os_error(); - error!("in_rustc_thread: error calling setrlimit: {}", err); - true + // We have already deinited the stack. Further corruption is + // not allowed. + panic!("in_rustc_thread: error calling setrlimit: {}", err); } else { - std::thread::update_stack_guard(); + std::rt::update_stack_guard(); false } } diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index e1392762a59..8f945470b7e 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -73,3 +73,18 @@ fn lang_start { lang_start_internal(&move || main().report(), argc, argv) } + +/// Function used for reverting changes to the main stack before setrlimit(). +/// This is POSIX (non-Linux) specific and unlikely to be directly stabilized. +#[unstable(feature = "rustc_stack_internals", issue = "0")] +pub unsafe fn deinit_stack_guard() { + ::sys::thread::guard::deinit(); +} + +/// Function used for resetting the main stack guard address after setrlimit(). +/// This is POSIX specific and unlikely to be directly stabilized. +#[unstable(feature = "rustc_stack_internals", issue = "0")] +pub unsafe fn update_stack_guard() { + let main_guard = ::sys::thread::guard::init(); + ::sys_common::thread_info::reset_guard(main_guard); +} diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 72cdb9440b8..d94e11a5207 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -222,7 +222,7 @@ pub mod guard { #[cfg_attr(test, allow(dead_code))] pub mod guard { use libc; - use libc::mmap; + use libc::{mmap, munmap}; use libc::{PROT_NONE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED}; use ops::Range; use sys::os; @@ -336,6 +336,24 @@ pub mod guard { } } + pub unsafe fn deinit() { + if !cfg!(target_os = "linux") { + if let Some(mut stackaddr) = get_stack_start() { + // Ensure address is aligned. Same as above. + let remainder = (stackaddr as usize) % PAGE_SIZE; + if remainder != 0 { + stackaddr = ((stackaddr as usize) + PAGE_SIZE - remainder) + as *mut libc::c_void; + } + + // Undo the guard page mapping. + if munmap(stackaddr, PAGE_SIZE) != 0 { + panic!("unable to deallocate the guard page"); + } + } + } + } + #[cfg(any(target_os = "macos", target_os = "bitrig", target_os = "openbsd", diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index b686ddc205e..71aee673cfe 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -208,14 +208,6 @@ pub use self::local::{LocalKey, AccessError}; #[unstable(feature = "libstd_thread_internals", issue = "0")] #[doc(hidden)] pub use self::local::os::Key as __OsLocalKeyInner; -/// Function used for resetting the main stack guard address after setrlimit(). -/// This is POSIX specific and unlikely to be directly stabilized. -#[unstable(feature = "rustc_stack_internals", issue = "0")] -pub unsafe fn update_stack_guard() { - let main_guard = imp::guard::init(); - thread_info::reset_guard(main_guard); -} - //////////////////////////////////////////////////////////////////////////////// // Builder //////////////////////////////////////////////////////////////////////////////// -- cgit 1.4.1-3-g733a5 From 6212904dd800864ca20ede8690fc827a1169fa26 Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Mon, 19 Mar 2018 15:40:09 -0700 Subject: Don't use posix_spawn() if PATH was modified in the environment. The expected behavior is that the environment's PATH should be used to find the process. posix_spawn() could be used if we iterated PATH to search for the binary to execute. For now just skip posix_spawn() if PATH is modified. --- src/libstd/sys/unix/process/process_common.rs | 3 +++ src/libstd/sys/unix/process/process_unix.rs | 1 + src/libstd/sys_common/process.rs | 12 ++++++++++++ 3 files changed, 16 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index d0486f06a14..48255489dd9 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -184,6 +184,9 @@ impl Command { let maybe_env = self.env.capture_if_changed(); maybe_env.map(|env| construct_envp(env, &mut self.saw_nul)) } + pub fn env_saw_path(&self) -> bool { + self.env.have_changed_path() + } pub fn setup_io(&self, default: Stdio, needs_stdin: bool) -> io::Result<(StdioPipes, ChildPipes)> { diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index 29e33ee822e..9d6d607e3f3 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -256,6 +256,7 @@ impl Command { if self.get_cwd().is_some() || self.get_gid().is_some() || self.get_uid().is_some() || + self.env_saw_path() || self.get_closures().len() != 0 { return Ok(None) } diff --git a/src/libstd/sys_common/process.rs b/src/libstd/sys_common/process.rs index fd1a5fdb410..775491d762c 100644 --- a/src/libstd/sys_common/process.rs +++ b/src/libstd/sys_common/process.rs @@ -47,6 +47,7 @@ impl EnvKey for DefaultEnvKey {} #[derive(Clone, Debug)] pub struct CommandEnv { clear: bool, + saw_path: bool, vars: BTreeMap> } @@ -54,6 +55,7 @@ impl Default for CommandEnv { fn default() -> Self { CommandEnv { clear: false, + saw_path: false, vars: Default::default() } } @@ -108,9 +110,11 @@ impl CommandEnv { // The following functions build up changes pub fn set(&mut self, key: &OsStr, value: &OsStr) { + self.maybe_saw_path(&key); self.vars.insert(key.to_owned().into(), Some(value.to_owned())); } pub fn remove(&mut self, key: &OsStr) { + self.maybe_saw_path(&key); if self.clear { self.vars.remove(key); } else { @@ -121,4 +125,12 @@ impl CommandEnv { self.clear = true; self.vars.clear(); } + pub fn have_changed_path(&self) -> bool { + self.saw_path || self.clear + } + fn maybe_saw_path(&mut self, key: &OsStr) { + if !self.saw_path && key.to_os_string() == OsString::from("PATH") { + self.saw_path = true; + } + } } -- cgit 1.4.1-3-g733a5 From 2928c7a8a253b655132ac9f2beb4ca74540f0e14 Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Tue, 20 Mar 2018 21:22:45 +0900 Subject: Refactor the stack addr aligning code into a function --- src/libstd/sys/unix/thread.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index d94e11a5207..4364089a181 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -284,10 +284,10 @@ pub mod guard { ret } - pub unsafe fn init() -> Option { - PAGE_SIZE = os::page_size(); - - let mut stackaddr = get_stack_start()?; + // Precondition: PAGE_SIZE is initialized. + unsafe fn get_stack_start_aligned() -> Option<*mut libc::c_void> { + assert!(PAGE_SIZE != 0); + let stackaddr = get_stack_start()?; // Ensure stackaddr is page aligned! A parent process might // have reset RLIMIT_STACK to be non-page aligned. The @@ -296,10 +296,17 @@ pub mod guard { // page-aligned, calculate the fix such that stackaddr < // new_page_aligned_stackaddr < stackaddr + stacksize let remainder = (stackaddr as usize) % PAGE_SIZE; - if remainder != 0 { - stackaddr = ((stackaddr as usize) + PAGE_SIZE - remainder) - as *mut libc::c_void; - } + Some(if remainder == 0 { + stackaddr + } else { + ((stackaddr as usize) + PAGE_SIZE - remainder) as *mut libc::c_void + }) + } + + pub unsafe fn init() -> Option { + PAGE_SIZE = os::page_size(); + + let stackaddr = get_stack_start_aligned()?; if cfg!(target_os = "linux") { // Linux doesn't allocate the whole stack right away, and @@ -338,14 +345,7 @@ pub mod guard { pub unsafe fn deinit() { if !cfg!(target_os = "linux") { - if let Some(mut stackaddr) = get_stack_start() { - // Ensure address is aligned. Same as above. - let remainder = (stackaddr as usize) % PAGE_SIZE; - if remainder != 0 { - stackaddr = ((stackaddr as usize) + PAGE_SIZE - remainder) - as *mut libc::c_void; - } - + if let Some(stackaddr) = get_stack_start_aligned() { // Undo the guard page mapping. if munmap(stackaddr, PAGE_SIZE) != 0 { panic!("unable to deallocate the guard page"); -- cgit 1.4.1-3-g733a5 From c09b9f937250db0f51b705a3110f8cffdad083bb Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 17 Mar 2018 12:15:24 +0100 Subject: Deprecate the AsciiExt trait in favor of inherent methods The trait and some of its methods are stable and will remain. Some of the newer methods are unstable and can be removed later. Fixes https://github.com/rust-lang/rust/issues/39658 --- src/libcore/tests/ascii.rs | 3 --- src/libstd/ascii.rs | 17 +++++++++++++++++ src/libstd/sys/windows/process.rs | 1 - src/libstd/sys_common/wtf8.rs | 17 +++++++---------- src/test/run-pass/issue-10683.rs | 2 -- 5 files changed, 24 insertions(+), 16 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libcore/tests/ascii.rs b/src/libcore/tests/ascii.rs index 4d43067ad2c..950222dbcfa 100644 --- a/src/libcore/tests/ascii.rs +++ b/src/libcore/tests/ascii.rs @@ -9,7 +9,6 @@ // except according to those terms. use core::char::from_u32; -use std::ascii::AsciiExt; #[test] fn test_is_ascii() { @@ -143,8 +142,6 @@ macro_rules! assert_all { stringify!($what), b); } } - assert!($str.$what()); - assert!($str.as_bytes().$what()); )+ }}; ($what:ident, $($str:tt),+,) => (assert_all!($what,$($str),+)) diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 0837ff91c14..6472edb0aa7 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -52,6 +52,7 @@ pub use core::ascii::{EscapeDefault, escape_default}; /// /// [combining character]: https://en.wikipedia.org/wiki/Combining_character #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] pub trait AsciiExt { /// Container type for copied ASCII characters. #[stable(feature = "rust1", since = "1.0.0")] @@ -84,6 +85,7 @@ pub trait AsciiExt { /// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase /// [`str::to_uppercase`]: ../primitive.str.html#method.to_uppercase #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] fn to_ascii_uppercase(&self) -> Self::Owned; /// Makes a copy of the value in its ASCII lower case equivalent. @@ -104,6 +106,7 @@ pub trait AsciiExt { /// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase /// [`str::to_lowercase`]: ../primitive.str.html#method.to_lowercase #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] fn to_ascii_lowercase(&self) -> Self::Owned; /// Checks that two values are an ASCII case-insensitive match. @@ -162,6 +165,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_alphabetic(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII uppercase character: @@ -174,6 +178,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_uppercase(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII lowercase character: @@ -186,6 +191,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_lowercase(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII alphanumeric character: @@ -199,6 +205,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_alphanumeric(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII decimal digit: @@ -211,6 +218,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_digit(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII hexadecimal digit: @@ -224,6 +232,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_hexdigit(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII punctuation character: @@ -241,6 +250,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_punctuation(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII graphic character: @@ -253,6 +263,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_graphic(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII whitespace character: @@ -282,6 +293,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_whitespace(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII control character: @@ -294,6 +306,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_control(&self) -> bool { unimplemented!(); } } @@ -354,6 +367,7 @@ macro_rules! delegating_ascii_ctype_methods { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl AsciiExt for u8 { type Owned = u8; @@ -362,6 +376,7 @@ impl AsciiExt for u8 { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl AsciiExt for char { type Owned = char; @@ -370,6 +385,7 @@ impl AsciiExt for char { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl AsciiExt for [u8] { type Owned = Vec; @@ -427,6 +443,7 @@ impl AsciiExt for [u8] { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl AsciiExt for str { type Owned = String; diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index f1ab9c47609..afa8e3e1369 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -10,7 +10,6 @@ #![unstable(feature = "process_internals", issue = "0")] -use ascii::AsciiExt; use collections::BTreeMap; use env::split_paths; use env; diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 9fff8b91f96..78b2bb5fe6e 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -27,7 +27,6 @@ use core::str::next_code_point; -use ascii::*; use borrow::Cow; use char; use fmt; @@ -871,24 +870,22 @@ impl Hash for Wtf8 { } } -impl AsciiExt for Wtf8 { - type Owned = Wtf8Buf; - - fn is_ascii(&self) -> bool { +impl Wtf8 { + pub fn is_ascii(&self) -> bool { self.bytes.is_ascii() } - fn to_ascii_uppercase(&self) -> Wtf8Buf { + pub fn to_ascii_uppercase(&self) -> Wtf8Buf { Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() } } - fn to_ascii_lowercase(&self) -> Wtf8Buf { + pub fn to_ascii_lowercase(&self) -> Wtf8Buf { Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() } } - fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool { + pub fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool { self.bytes.eq_ignore_ascii_case(&other.bytes) } - fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() } - fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() } + pub fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() } + pub fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() } } #[cfg(test)] diff --git a/src/test/run-pass/issue-10683.rs b/src/test/run-pass/issue-10683.rs index eb2177202a2..d3ba477fa57 100644 --- a/src/test/run-pass/issue-10683.rs +++ b/src/test/run-pass/issue-10683.rs @@ -10,8 +10,6 @@ // pretty-expanded FIXME #23616 -use std::ascii::AsciiExt; - static NAME: &'static str = "hello world"; fn main() { -- cgit 1.4.1-3-g733a5 From 70559c54ce2a493a15f447436e281e16fc55b291 Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Thu, 22 Mar 2018 09:49:20 -0700 Subject: Command::env_saw_path() may be unused on platforms not using posix_spawn() --- src/libstd/sys/unix/process/process_common.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index 48255489dd9..b7f30600b8a 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -184,6 +184,7 @@ impl Command { let maybe_env = self.env.capture_if_changed(); maybe_env.map(|env| construct_envp(env, &mut self.saw_nul)) } + #[allow(dead_code)] pub fn env_saw_path(&self) -> bool { self.env.have_changed_path() } -- cgit 1.4.1-3-g733a5 From fdde09c70c102058feff4c9932044ae77d341d11 Mon Sep 17 00:00:00 2001 From: Daniel Kolsoi Date: Fri, 23 Mar 2018 17:01:34 -0400 Subject: Reduce scope of unsafe block in sun_path_offset --- src/libstd/sys/unix/ext/net.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index ad437658d14..ba80cbe47c8 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -51,13 +51,11 @@ use libc::MSG_NOSIGNAL; const MSG_NOSIGNAL: libc::c_int = 0x0; fn sun_path_offset() -> usize { - unsafe { - // Work with an actual instance of the type since using a null pointer is UB - let addr: libc::sockaddr_un = mem::uninitialized(); - let base = &addr as *const _ as usize; - let path = &addr.sun_path as *const _ as usize; - path - base - } + // Work with an actual instance of the type since using a null pointer is UB + let addr: libc::sockaddr_un = unsafe { mem::uninitialized() }; + let base = &addr as *const _ as usize; + let path = &addr.sun_path as *const _ as usize; + path - base } unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> { -- cgit 1.4.1-3-g733a5 From 91279904345e2ecd3f52b17339183bbe3bd11203 Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Sat, 24 Mar 2018 13:47:36 +0900 Subject: Fix build on non-Unix platforms --- src/libstd/sys/cloudabi/thread.rs | 1 + src/libstd/sys/redox/thread.rs | 1 + src/libstd/sys/unix/thread.rs | 1 + src/libstd/sys/wasm/thread.rs | 1 + src/libstd/sys/windows/thread.rs | 1 + 5 files changed, 5 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs index 78a3b82546e..a22d9053b69 100644 --- a/src/libstd/sys/cloudabi/thread.rs +++ b/src/libstd/sys/cloudabi/thread.rs @@ -118,6 +118,7 @@ pub mod guard { pub unsafe fn init() -> Option { None } + pub unsafe fn deinit() {} } fn min_stack_size(_: *const libc::pthread_attr_t) -> usize { diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs index c4719a94c7e..f20350269b7 100644 --- a/src/libstd/sys/redox/thread.rs +++ b/src/libstd/sys/redox/thread.rs @@ -91,4 +91,5 @@ pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { None } pub unsafe fn init() -> Option { None } + pub unsafe fn deinit() {} } diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 4364089a181..b9ec0d4a403 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -209,6 +209,7 @@ pub mod guard { pub type Guard = Range; pub unsafe fn current() -> Option { None } pub unsafe fn init() -> Option { None } + pub unsafe fn deinit() {} } diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs index 6a066509b49..7345843b975 100644 --- a/src/libstd/sys/wasm/thread.rs +++ b/src/libstd/sys/wasm/thread.rs @@ -46,4 +46,5 @@ pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { None } pub unsafe fn init() -> Option { None } + pub unsafe fn deinit() {} } diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 43abfbb1f64..4b3d1b586b5 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -96,4 +96,5 @@ pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { None } pub unsafe fn init() -> Option { None } + pub unsafe fn deinit() {} } -- cgit 1.4.1-3-g733a5 From d39b02c2c9e8aa472ab47ccfb5de63bc616daf62 Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Sun, 25 Mar 2018 16:08:03 +0900 Subject: Use a more conservative way to deinit stack guard --- src/libstd/sys/unix/thread.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index b9ec0d4a403..6064b55489e 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -223,8 +223,8 @@ pub mod guard { #[cfg_attr(test, allow(dead_code))] pub mod guard { use libc; - use libc::{mmap, munmap}; - use libc::{PROT_NONE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED}; + use libc::mmap; + use libc::{PROT_NONE, PROT_READ, PROT_WRITE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED}; use ops::Range; use sys::os; @@ -347,9 +347,19 @@ pub mod guard { pub unsafe fn deinit() { if !cfg!(target_os = "linux") { if let Some(stackaddr) = get_stack_start_aligned() { - // Undo the guard page mapping. - if munmap(stackaddr, PAGE_SIZE) != 0 { - panic!("unable to deallocate the guard page"); + // Remove the protection on the guard page. + // FIXME: we cannot unmap the page, because when we mmap() + // above it may be already mapped by the OS, which we can't + // detect from mmap()'s return value. If we unmap this page, + // it will lead to failure growing stack size on platforms like + // macOS. Instead, just restore the page to a writable state. + // This ain't Linux, so we probably don't need to care about + // execstack. + let result = mmap(stackaddr, PAGE_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); + + if result != stackaddr || result == MAP_FAILED { + panic!("unable to reset the guard page"); } } } -- cgit 1.4.1-3-g733a5 From 04f6692aaf78809c041ba6145bde2dcbeec9725e Mon Sep 17 00:00:00 2001 From: Diggory Blake Date: Mon, 26 Mar 2018 23:24:31 +0100 Subject: Implement `shrink_to` method on collections --- src/liballoc/binary_heap.rs | 25 ++++++++++++++++++++++++ src/liballoc/string.rs | 28 ++++++++++++++++++++++++++ src/liballoc/vec.rs | 27 ++++++++++++++++++++++++- src/liballoc/vec_deque.rs | 35 ++++++++++++++++++++++++++++++++- src/libstd/collections/hash/map.rs | 40 ++++++++++++++++++++++++++++++++++++++ src/libstd/collections/hash/set.rs | 28 ++++++++++++++++++++++++++ src/libstd/ffi/os_str.rs | 30 ++++++++++++++++++++++++++++ src/libstd/lib.rs | 1 + src/libstd/sys/redox/os_str.rs | 5 +++++ src/libstd/sys/unix/os_str.rs | 5 +++++ src/libstd/sys/wasm/os_str.rs | 5 +++++ src/libstd/sys/windows/os_str.rs | 5 +++++ src/libstd/sys_common/wtf8.rs | 5 +++++ 13 files changed, 237 insertions(+), 2 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/liballoc/binary_heap.rs b/src/liballoc/binary_heap.rs index 8aaac5d6e08..f6a666b599b 100644 --- a/src/liballoc/binary_heap.rs +++ b/src/liballoc/binary_heap.rs @@ -509,6 +509,31 @@ impl BinaryHeap { self.data.shrink_to_fit(); } + /// Discards capacity with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::BinaryHeap; + /// let mut heap: BinaryHeap = BinaryHeap::with_capacity(100); + /// + /// assert!(heap.capacity() >= 100); + /// heap.shrink_to(10); + /// assert!(heap.capacity() >= 10); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.data.shrink_to(min_capacity) + } + /// Removes the greatest item from the binary heap and returns it, or `None` if it /// is empty. /// diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index e253122ffd6..2bb60a50679 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1015,6 +1015,34 @@ impl String { self.vec.shrink_to_fit() } + /// Shrinks the capacity of this `String` with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// let mut s = String::from("foo"); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to(10); + /// assert!(s.capacity() >= 10); + /// s.shrink_to(0); + /// assert!(s.capacity() >= 3); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.vec.shrink_to(min_capacity) + } + /// Appends the given [`char`] to the end of this `String`. /// /// [`char`]: ../../std/primitive.char.html diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 953f95876be..c9c6cf1cb66 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -66,7 +66,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use core::cmp::Ordering; +use core::cmp::{self, Ordering}; use core::fmt; use core::hash::{self, Hash}; use core::intrinsics::{arith_offset, assume}; @@ -586,6 +586,31 @@ impl Vec { self.buf.shrink_to_fit(self.len); } + /// Shrinks the capacity of the vector with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3].iter().cloned()); + /// assert_eq!(vec.capacity(), 10); + /// vec.shrink_to(4); + /// assert!(vec.capacity() >= 4); + /// vec.shrink_to(0); + /// assert!(vec.capacity() >= 3); + /// ``` + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.buf.shrink_to_fit(cmp::max(self.len, min_capacity)); + } + /// Converts the vector into [`Box<[T]>`][owned slice]. /// /// Note that this will drop any excess capacity. diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs index 0658777f0a0..be6e8d0f22f 100644 --- a/src/liballoc/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -676,9 +676,42 @@ impl VecDeque { /// ``` #[stable(feature = "deque_extras_15", since = "1.5.0")] pub fn shrink_to_fit(&mut self) { + self.shrink_to(0); + } + + /// Shrinks the capacity of the `VecDeque` with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::with_capacity(15); + /// buf.extend(0..4); + /// assert_eq!(buf.capacity(), 15); + /// buf.shrink_to(6); + /// assert!(buf.capacity() >= 6); + /// buf.shrink_to(0); + /// assert!(buf.capacity() >= 4); + /// ``` + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + assert!(self.capacity() >= min_capacity, "Tried to shrink to a larger capacity"); + // +1 since the ringbuffer always leaves one space empty // len + 1 can't overflow for an existing, well-formed ringbuffer. - let target_cap = cmp::max(self.len() + 1, MINIMUM_CAPACITY + 1).next_power_of_two(); + let target_cap = cmp::max( + cmp::max(min_capacity, self.len()) + 1, + MINIMUM_CAPACITY + 1 + ).next_power_of_two(); + if target_cap < self.cap() { // There are three cases of interest: // All elements are out of desired bounds diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index b18b38ec302..169d365c0ac 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -910,6 +910,46 @@ impl HashMap } } + /// Shrinks the capacity of the map with a lower limit. It will drop + /// down no lower than the supplied limit while maintaining the internal rules + /// and possibly leaving some space in accordance with the resize policy. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::HashMap; + /// + /// let mut map: HashMap = HashMap::with_capacity(100); + /// map.insert(1, 2); + /// map.insert(3, 4); + /// assert!(map.capacity() >= 100); + /// map.shrink_to(10); + /// assert!(map.capacity() >= 10); + /// map.shrink_to(0); + /// assert!(map.capacity() >= 2); + /// ``` + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + assert!(self.capacity() >= min_capacity, "Tried to shrink to a larger capacity"); + + let new_raw_cap = self.resize_policy.raw_capacity(max(self.len(), min_capacity)); + if self.raw_capacity() != new_raw_cap { + let old_table = replace(&mut self.table, RawTable::new(new_raw_cap)); + let old_size = old_table.size(); + + // Shrink the table. Naive algorithm for resizing: + for (h, k, v) in old_table.into_iter() { + self.insert_hashed_nocheck(h, k, v); + } + + debug_assert_eq!(self.table.size(), old_size); + } + } + /// Insert a pre-hashed key-value pair, without first checking /// that there's enough room in the buckets. Returns a reference to the /// newly insert value. diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 9e63ba2717a..855563a5cb8 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -292,6 +292,34 @@ impl HashSet self.map.shrink_to_fit() } + /// Shrinks the capacity of the set with a lower limit. It will drop + /// down no lower than the supplied limit while maintaining the internal rules + /// and possibly leaving some space in accordance with the resize policy. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::HashSet; + /// + /// let mut set = HashSet::with_capacity(100); + /// set.insert(1); + /// set.insert(2); + /// assert!(set.capacity() >= 100); + /// set.shrink_to(10); + /// assert!(set.capacity() >= 10); + /// set.shrink_to(0); + /// assert!(set.capacity() >= 2); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.map.shrink_to(min_capacity) + } + /// An iterator visiting all elements in arbitrary order. /// The iterator element type is `&'a T`. /// diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 3959e8533be..7520121a8c2 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -295,6 +295,36 @@ impl OsString { self.inner.shrink_to_fit() } + /// Shrinks the capacity of the `OsString` with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::ffi::OsString; + /// + /// let mut s = OsString::from("foo"); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to(10); + /// assert!(s.capacity() >= 10); + /// s.shrink_to(0); + /// assert!(s.capacity() >= 3); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + /// Converts this `OsString` into a boxed [`OsStr`]. /// /// [`OsStr`]: struct.OsStr.html diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 0b06c5d4d65..edecf309d16 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -299,6 +299,7 @@ #![feature(raw)] #![feature(rustc_attrs)] #![feature(stdsimd)] +#![feature(shrink_to)] #![feature(slice_bytes)] #![feature(slice_concat_ext)] #![feature(slice_internals)] diff --git a/src/libstd/sys/redox/os_str.rs b/src/libstd/sys/redox/os_str.rs index 655bfdb9167..da27787babb 100644 --- a/src/libstd/sys/redox/os_str.rs +++ b/src/libstd/sys/redox/os_str.rs @@ -104,6 +104,11 @@ impl Buf { 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) } } diff --git a/src/libstd/sys/unix/os_str.rs b/src/libstd/sys/unix/os_str.rs index e0349387998..e43bc6da5f1 100644 --- a/src/libstd/sys/unix/os_str.rs +++ b/src/libstd/sys/unix/os_str.rs @@ -104,6 +104,11 @@ impl Buf { 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) } } diff --git a/src/libstd/sys/wasm/os_str.rs b/src/libstd/sys/wasm/os_str.rs index 543c22ebe18..84f560af69b 100644 --- a/src/libstd/sys/wasm/os_str.rs +++ b/src/libstd/sys/wasm/os_str.rs @@ -104,6 +104,11 @@ impl Buf { 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) } } diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs index 414c9c5418e..bcc66b9954b 100644 --- a/src/libstd/sys/windows/os_str.rs +++ b/src/libstd/sys/windows/os_str.rs @@ -113,6 +113,11 @@ impl Buf { self.inner.shrink_to_fit() } + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + #[inline] pub fn into_box(self) -> Box { unsafe { mem::transmute(self.inner.into_box()) } diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 78b2bb5fe6e..dda4e1bab3b 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -253,6 +253,11 @@ impl Wtf8Buf { self.bytes.shrink_to_fit() } + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.bytes.shrink_to(min_capacity) + } + /// Returns the number of bytes that this string buffer can hold without reallocating. #[inline] pub fn capacity(&self) -> usize { -- cgit 1.4.1-3-g733a5 From 8ecbec1dba048bf55461dbff772f18a72311ecc2 Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Wed, 28 Mar 2018 18:47:16 +0900 Subject: Use mprotect instead of mmap --- src/libstd/sys/unix/thread.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 6064b55489e..775289f393b 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -355,10 +355,9 @@ pub mod guard { // macOS. Instead, just restore the page to a writable state. // This ain't Linux, so we probably don't need to care about // execstack. - let result = mmap(stackaddr, PAGE_SIZE, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); + let result = mprotect(stackaddr, PAGE_SIZE, PROT_READ | PROT_WRITE); - if result != stackaddr || result == MAP_FAILED { + if result != 0 { panic!("unable to reset the guard page"); } } -- cgit 1.4.1-3-g733a5 From e9dcec070d6097e5a22b6658844dccd9d1f578cf Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 24 Mar 2018 22:56:07 -0400 Subject: Remove hidden `foo` functions from doc examples; use `Termination` trait. Fixes https://github.com/rust-lang/rust/issues/49233. --- src/libstd/env.rs | 14 +- src/libstd/fs.rs | 528 +++++++++++++++++----------------- src/libstd/io/buffered.rs | 219 +++++++------- src/libstd/io/mod.rs | 605 +++++++++++++++++++-------------------- src/libstd/io/stdio.rs | 106 +++---- src/libstd/io/util.rs | 15 +- src/libstd/net/mod.rs | 10 +- src/libstd/net/tcp.rs | 16 +- src/libstd/net/udp.rs | 28 +- src/libstd/os/linux/fs.rs | 238 +++++++-------- src/libstd/sys/redox/ext/fs.rs | 38 +-- src/libstd/sys/unix/ext/fs.rs | 342 +++++++++++----------- src/libstd/sys/windows/ext/fs.rs | 98 +++---- 13 files changed, 1130 insertions(+), 1127 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/env.rs b/src/libstd/env.rs index c4946b6b282..320a9f935d4 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -552,17 +552,17 @@ pub fn home_dir() -> Option { /// /// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364992(v=vs.85).aspx /// -/// ``` +/// ```no_run /// use std::env; /// use std::fs::File; /// -/// # fn foo() -> std::io::Result<()> { -/// let mut dir = env::temp_dir(); -/// dir.push("foo.txt"); +/// fn main() -> std::io::Result<()> { +/// let mut dir = env::temp_dir(); +/// dir.push("foo.txt"); /// -/// let f = File::create(dir)?; -/// # Ok(()) -/// # } +/// let f = File::create(dir)?; +/// Ok(()) +/// } /// ``` #[stable(feature = "env", since = "1.0.0")] pub fn temp_dir() -> PathBuf { diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index db52ed67d3a..46d164e31ba 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -41,11 +41,11 @@ use time::SystemTime; /// use std::fs::File; /// use std::io::prelude::*; /// -/// # fn foo() -> std::io::Result<()> { -/// let mut file = File::create("foo.txt")?; -/// file.write_all(b"Hello, world!")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let mut file = File::create("foo.txt")?; +/// file.write_all(b"Hello, world!")?; +/// Ok(()) +/// } /// ``` /// /// Read the contents of a file into a [`String`]: @@ -54,13 +54,13 @@ use time::SystemTime; /// use std::fs::File; /// use std::io::prelude::*; /// -/// # fn foo() -> std::io::Result<()> { -/// let mut file = File::open("foo.txt")?; -/// let mut contents = String::new(); -/// file.read_to_string(&mut contents)?; -/// assert_eq!(contents, "Hello, world!"); -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let mut file = File::open("foo.txt")?; +/// let mut contents = String::new(); +/// file.read_to_string(&mut contents)?; +/// assert_eq!(contents, "Hello, world!"); +/// Ok(()) +/// } /// ``` /// /// It can be more efficient to read the contents of a file with a buffered @@ -71,14 +71,14 @@ use time::SystemTime; /// use std::io::BufReader; /// use std::io::prelude::*; /// -/// # fn foo() -> std::io::Result<()> { -/// let file = File::open("foo.txt")?; -/// let mut buf_reader = BufReader::new(file); -/// let mut contents = String::new(); -/// buf_reader.read_to_string(&mut contents)?; -/// assert_eq!(contents, "Hello, world!"); -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let file = File::open("foo.txt")?; +/// let mut buf_reader = BufReader::new(file); +/// let mut contents = String::new(); +/// buf_reader.read_to_string(&mut contents)?; +/// assert_eq!(contents, "Hello, world!"); +/// Ok(()) +/// } /// ``` /// /// Note that, although read and write methods require a `&mut File`, because @@ -256,10 +256,10 @@ fn initial_buffer_size(file: &File) -> usize { /// use std::fs; /// use std::net::SocketAddr; /// -/// # fn foo() -> Result<(), Box> { -/// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?; -/// # Ok(()) -/// # } +/// fn main() -> Result<(), Box> { +/// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?; +/// Ok(()) +/// } /// ``` #[unstable(feature = "fs_read_write", issue = "46588")] pub fn read>(path: P) -> io::Result> { @@ -298,10 +298,10 @@ pub fn read>(path: P) -> io::Result> { /// use std::fs; /// use std::net::SocketAddr; /// -/// # fn foo() -> Result<(), Box> { -/// let foo: SocketAddr = fs::read_string("address.txt")?.parse()?; -/// # Ok(()) -/// # } +/// fn main() -> Result<(), Box> { +/// let foo: SocketAddr = fs::read_string("address.txt")?.parse()?; +/// Ok(()) +/// } /// ``` #[unstable(feature = "fs_read_write", issue = "46588")] pub fn read_string>(path: P) -> io::Result { @@ -329,10 +329,10 @@ pub fn read_string>(path: P) -> io::Result { /// /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::write("foo.txt", b"Lorem ipsum")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::write("foo.txt", b"Lorem ipsum")?; +/// Ok(()) +/// } /// ``` #[unstable(feature = "fs_read_write", issue = "46588")] pub fn write, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> { @@ -356,7 +356,7 @@ impl File { /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { + /// fn main() -> std::io::Result<()> { /// let mut f = File::open("foo.txt")?; /// # Ok(()) /// # } @@ -380,10 +380,10 @@ impl File { /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::create("foo.txt")?; - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let mut f = File::create("foo.txt")?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn create>(path: P) -> io::Result { @@ -401,13 +401,13 @@ impl File { /// use std::fs::File; /// use std::io::prelude::*; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::create("foo.txt")?; - /// f.write_all(b"Hello, world!")?; + /// fn main() -> std::io::Result<()> { + /// let mut f = File::create("foo.txt")?; + /// f.write_all(b"Hello, world!")?; /// - /// f.sync_all()?; - /// # Ok(()) - /// # } + /// f.sync_all()?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn sync_all(&self) -> io::Result<()> { @@ -432,13 +432,13 @@ impl File { /// use std::fs::File; /// use std::io::prelude::*; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::create("foo.txt")?; - /// f.write_all(b"Hello, world!")?; + /// fn main() -> std::io::Result<()> { + /// let mut f = File::create("foo.txt")?; + /// f.write_all(b"Hello, world!")?; /// - /// f.sync_data()?; - /// # Ok(()) - /// # } + /// f.sync_data()?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn sync_data(&self) -> io::Result<()> { @@ -466,11 +466,11 @@ impl File { /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::create("foo.txt")?; - /// f.set_len(10)?; - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let mut f = File::create("foo.txt")?; + /// f.set_len(10)?; + /// Ok(()) + /// } /// ``` /// /// Note that this method alters the content of the underlying file, even @@ -487,11 +487,11 @@ impl File { /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let metadata = f.metadata()?; - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let metadata = f.metadata()?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn metadata(&self) -> io::Result { @@ -509,11 +509,11 @@ impl File { /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut file = File::open("foo.txt")?; - /// let file_copy = file.try_clone()?; - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// let file_copy = file.try_clone()?; + /// Ok(()) + /// } /// ``` /// /// Assuming there’s a file named `foo.txt` with contents `abcdef\n`, create @@ -525,17 +525,17 @@ impl File { /// use std::io::SeekFrom; /// use std::io::prelude::*; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut file = File::open("foo.txt")?; - /// let mut file_copy = file.try_clone()?; + /// fn main() -> std::io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// let mut file_copy = file.try_clone()?; /// - /// file.seek(SeekFrom::Start(3))?; + /// file.seek(SeekFrom::Start(3))?; /// - /// let mut contents = vec![]; - /// file_copy.read_to_end(&mut contents)?; - /// assert_eq!(contents, b"def\n"); - /// # Ok(()) - /// # } + /// let mut contents = vec![]; + /// file_copy.read_to_end(&mut contents)?; + /// assert_eq!(contents, b"def\n"); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_try_clone", since = "1.9.0")] pub fn try_clone(&self) -> io::Result { @@ -562,16 +562,16 @@ impl File { /// /// # Examples /// - /// ``` - /// # 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(()) - /// # } + /// ```no_run + /// fn main() -> 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(()) + /// } /// ``` /// /// Note that this method alters the permissions of the underlying file, @@ -891,15 +891,15 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { - /// use std::fs; + /// ```no_run + /// fn main() -> std::io::Result<()> { + /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// let metadata = fs::metadata("foo.txt")?; /// - /// println!("{:?}", metadata.file_type()); - /// # Ok(()) - /// # } + /// println!("{:?}", metadata.file_type()); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type", since = "1.1.0")] pub fn file_type(&self) -> FileType { @@ -910,15 +910,15 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { - /// use std::fs; + /// ```no_run + /// fn main() -> std::io::Result<()> { + /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// let metadata = fs::metadata("foo.txt")?; /// - /// assert!(!metadata.is_dir()); - /// # Ok(()) - /// # } + /// assert!(!metadata.is_dir()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn is_dir(&self) -> bool { self.file_type().is_dir() } @@ -927,15 +927,15 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// assert!(metadata.is_file()); - /// # Ok(()) - /// # } + /// assert!(metadata.is_file()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn is_file(&self) -> bool { self.file_type().is_file() } @@ -944,15 +944,15 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// assert_eq!(0, metadata.len()); - /// # Ok(()) - /// # } + /// assert_eq!(0, metadata.len()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> u64 { self.0.size() } @@ -961,15 +961,15 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// assert!(!metadata.permissions().readonly()); - /// # Ok(()) - /// # } + /// assert!(!metadata.permissions().readonly()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn permissions(&self) -> Permissions { @@ -988,19 +988,19 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// if let Ok(time) = metadata.modified() { - /// println!("{:?}", time); - /// } else { - /// println!("Not supported on this platform"); + /// if let Ok(time) = metadata.modified() { + /// println!("{:?}", time); + /// } else { + /// println!("Not supported on this platform"); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[stable(feature = "fs_time", since = "1.10.0")] pub fn modified(&self) -> io::Result { @@ -1023,19 +1023,19 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// if let Ok(time) = metadata.accessed() { - /// println!("{:?}", time); - /// } else { - /// println!("Not supported on this platform"); + /// if let Ok(time) = metadata.accessed() { + /// println!("{:?}", time); + /// } else { + /// println!("Not supported on this platform"); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[stable(feature = "fs_time", since = "1.10.0")] pub fn accessed(&self) -> io::Result { @@ -1054,19 +1054,19 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// if let Ok(time) = metadata.created() { - /// println!("{:?}", time); - /// } else { - /// println!("Not supported on this platform"); + /// if let Ok(time) = metadata.created() { + /// println!("{:?}", time); + /// } else { + /// println!("Not supported on this platform"); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[stable(feature = "fs_time", since = "1.10.0")] pub fn created(&self) -> io::Result { @@ -1098,16 +1098,16 @@ impl Permissions { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; + /// fn main() -> std::io::Result<()> { + /// let mut f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; /// - /// assert_eq!(false, metadata.permissions().readonly()); - /// # Ok(()) - /// # } + /// assert_eq!(false, metadata.permissions().readonly()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn readonly(&self) -> bool { self.0.readonly() } @@ -1123,23 +1123,23 @@ impl Permissions { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let mut permissions = metadata.permissions(); + /// fn main() -> std::io::Result<()> { + /// let f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; + /// let mut permissions = metadata.permissions(); /// - /// permissions.set_readonly(true); + /// permissions.set_readonly(true); /// - /// // filesystem doesn't change - /// assert_eq!(false, metadata.permissions().readonly()); + /// // filesystem doesn't change + /// assert_eq!(false, metadata.permissions().readonly()); /// - /// // just this particular `permissions`. - /// assert_eq!(true, permissions.readonly()); - /// # Ok(()) - /// # } + /// // just this particular `permissions`. + /// assert_eq!(true, permissions.readonly()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn set_readonly(&mut self, readonly: bool) { @@ -1152,16 +1152,16 @@ impl FileType { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { - /// use std::fs; + /// ```no_run + /// fn main() -> std::io::Result<()> { + /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; - /// let file_type = metadata.file_type(); + /// let metadata = fs::metadata("foo.txt")?; + /// let file_type = metadata.file_type(); /// - /// assert_eq!(file_type.is_dir(), false); - /// # Ok(()) - /// # } + /// assert_eq!(file_type.is_dir(), false); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type", since = "1.1.0")] pub fn is_dir(&self) -> bool { self.0.is_dir() } @@ -1170,16 +1170,16 @@ impl FileType { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { - /// use std::fs; + /// ```no_run + /// fn main() -> std::io::Result<()> { + /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; - /// let file_type = metadata.file_type(); + /// let metadata = fs::metadata("foo.txt")?; + /// let file_type = metadata.file_type(); /// - /// assert_eq!(file_type.is_file(), true); - /// # Ok(()) - /// # } + /// assert_eq!(file_type.is_file(), true); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type", since = "1.1.0")] pub fn is_file(&self) -> bool { self.0.is_file() } @@ -1199,16 +1199,16 @@ impl FileType { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::symlink_metadata("foo.txt")?; - /// let file_type = metadata.file_type(); + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::symlink_metadata("foo.txt")?; + /// let file_type = metadata.file_type(); /// - /// assert_eq!(file_type.is_symlink(), false); - /// # Ok(()) - /// # } + /// assert_eq!(file_type.is_symlink(), false); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type", since = "1.1.0")] pub fn is_symlink(&self) -> bool { self.0.is_symlink() } @@ -1245,15 +1245,16 @@ impl DirEntry { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; - /// # fn foo() -> std::io::Result<()> { - /// for entry in fs::read_dir(".")? { - /// let dir = entry?; - /// println!("{:?}", dir.path()); + /// + /// fn main() -> std::io::Result<()> { + /// for entry in fs::read_dir(".")? { + /// let dir = entry?; + /// println!("{:?}", dir.path()); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` /// /// This prints output like: @@ -1398,13 +1399,13 @@ impl AsInner for DirEntry { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::remove_file("a.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::remove_file("a.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_file>(path: P) -> io::Result<()> { @@ -1435,14 +1436,14 @@ pub fn remove_file>(path: P) -> io::Result<()> { /// /// # Examples /// -/// ```rust -/// # fn foo() -> std::io::Result<()> { +/// ```rust,no_run /// use std::fs; /// -/// let attr = fs::metadata("/some/file/path.txt")?; -/// // inspect attr ... -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let attr = fs::metadata("/some/file/path.txt")?; +/// // inspect attr ... +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn metadata>(path: P) -> io::Result { @@ -1469,14 +1470,14 @@ pub fn metadata>(path: P) -> io::Result { /// /// # Examples /// -/// ```rust -/// # fn foo() -> std::io::Result<()> { +/// ```rust,no_run /// use std::fs; /// -/// let attr = fs::symlink_metadata("/some/file/path.txt")?; -/// // inspect attr ... -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let attr = fs::symlink_metadata("/some/file/path.txt")?; +/// // inspect attr ... +/// Ok(()) +/// } /// ``` #[stable(feature = "symlink_metadata", since = "1.1.0")] pub fn symlink_metadata>(path: P) -> io::Result { @@ -1513,13 +1514,13 @@ pub fn symlink_metadata>(path: P) -> io::Result { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::rename("a.txt", "b.txt")?; // Rename a.txt to b.txt -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::rename("a.txt", "b.txt")?; // Rename a.txt to b.txt +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> { @@ -1564,9 +1565,10 @@ pub fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> /// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::copy("foo.txt", "bar.txt")?; // Copy foo.txt to bar.txt -/// # Ok(()) } +/// fn main() -> std::io::Result<()> { +/// fs::copy("foo.txt", "bar.txt")?; // Copy foo.txt to bar.txt +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { @@ -1595,13 +1597,13 @@ pub fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::hard_link("a.txt", "b.txt")?; // Hard link a.txt to b.txt -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::hard_link("a.txt", "b.txt")?; // Hard link a.txt to b.txt +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn hard_link, Q: AsRef>(src: P, dst: Q) -> io::Result<()> { @@ -1618,13 +1620,13 @@ pub fn hard_link, Q: AsRef>(src: P, dst: Q) -> io::Result<( /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::soft_link("a.txt", "b.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::soft_link("a.txt", "b.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.1.0", @@ -1655,13 +1657,13 @@ pub fn soft_link, Q: AsRef>(src: P, dst: Q) -> io::Result<( /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// let path = fs::read_link("a.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let path = fs::read_link("a.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn read_link>(path: P) -> io::Result { @@ -1689,13 +1691,13 @@ pub fn read_link>(path: P) -> io::Result { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// let path = fs::canonicalize("../a/../foo.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let path = fs::canonicalize("../a/../foo.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "fs_canonicalize", since = "1.5.0")] pub fn canonicalize>(path: P) -> io::Result { @@ -1722,13 +1724,13 @@ pub fn canonicalize>(path: P) -> io::Result { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::create_dir("/some/dir")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::create_dir("/some/dir")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn create_dir>(path: P) -> io::Result<()> { @@ -1764,13 +1766,13 @@ pub fn create_dir>(path: P) -> io::Result<()> { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::create_dir_all("/some/dir")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::create_dir_all("/some/dir")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn create_dir_all>(path: P) -> io::Result<()> { @@ -1797,13 +1799,13 @@ pub fn create_dir_all>(path: P) -> io::Result<()> { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::remove_dir("/some/dir")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::remove_dir("/some/dir")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_dir>(path: P) -> io::Result<()> { @@ -1831,13 +1833,13 @@ pub fn remove_dir>(path: P) -> io::Result<()> { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::remove_dir_all("/some/dir")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::remove_dir_all("/some/dir")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_dir_all>(path: P) -> io::Result<()> { @@ -1917,15 +1919,15 @@ pub fn read_dir>(path: P) -> io::Result { /// /// # Examples /// -/// ``` -/// # fn foo() -> std::io::Result<()> { +/// ```no_run /// use std::fs; /// -/// let mut perms = fs::metadata("foo.txt")?.permissions(); -/// perms.set_readonly(true); -/// fs::set_permissions("foo.txt", perms)?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let mut perms = fs::metadata("foo.txt")?.permissions(); +/// perms.set_readonly(true); +/// fs::set_permissions("foo.txt", perms)?; +/// Ok(()) +/// } /// ``` #[stable(feature = "set_permissions", since = "1.1.0")] pub fn set_permissions>(path: P, perm: Permissions) diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index ccaa19acc83..cefff2f143c 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -31,20 +31,20 @@ use memchr; /// /// # Examples /// -/// ``` +/// ```no_run /// use std::io::prelude::*; /// use std::io::BufReader; /// use std::fs::File; /// -/// # fn foo() -> std::io::Result<()> { -/// let f = File::open("log.txt")?; -/// let mut reader = BufReader::new(f); +/// fn main() -> std::io::Result<()> { +/// let f = File::open("log.txt")?; +/// let mut reader = BufReader::new(f); /// -/// let mut line = String::new(); -/// let len = reader.read_line(&mut line)?; -/// println!("First line is {} bytes long", len); -/// # Ok(()) -/// # } +/// let mut line = String::new(); +/// let len = reader.read_line(&mut line)?; +/// println!("First line is {} bytes long", len); +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct BufReader { @@ -59,15 +59,15 @@ impl BufReader { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::BufReader; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f = File::open("log.txt")?; - /// let reader = BufReader::new(f); - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let f = File::open("log.txt")?; + /// let reader = BufReader::new(f); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: R) -> BufReader { @@ -80,15 +80,15 @@ impl BufReader { /// /// Creating a buffer with ten bytes of capacity: /// - /// ``` + /// ```no_run /// use std::io::BufReader; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f = File::open("log.txt")?; - /// let reader = BufReader::with_capacity(10, f); - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let f = File::open("log.txt")?; + /// let reader = BufReader::with_capacity(10, f); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(cap: usize, inner: R) -> BufReader { @@ -111,17 +111,17 @@ impl BufReader { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::BufReader; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f1 = File::open("log.txt")?; - /// let reader = BufReader::new(f1); + /// fn main() -> std::io::Result<()> { + /// let f1 = File::open("log.txt")?; + /// let reader = BufReader::new(f1); /// - /// let f2 = reader.get_ref(); - /// # Ok(()) - /// # } + /// let f2 = reader.get_ref(); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_ref(&self) -> &R { &self.inner } @@ -132,17 +132,17 @@ impl BufReader { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::BufReader; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f1 = File::open("log.txt")?; - /// let mut reader = BufReader::new(f1); + /// fn main() -> std::io::Result<()> { + /// let f1 = File::open("log.txt")?; + /// let mut reader = BufReader::new(f1); /// - /// let f2 = reader.get_mut(); - /// # Ok(()) - /// # } + /// let f2 = reader.get_mut(); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut R { &mut self.inner } @@ -150,22 +150,23 @@ impl BufReader { /// Returns `true` if there are no bytes in the internal buffer. /// /// # Examples - /// ``` + // + /// ```no_run /// # #![feature(bufreader_is_empty)] /// use std::io::BufReader; /// use std::io::BufRead; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f1 = File::open("log.txt")?; - /// let mut reader = BufReader::new(f1); - /// assert!(reader.is_empty()); + /// fn main() -> std::io::Result<()> { + /// let f1 = File::open("log.txt")?; + /// let mut reader = BufReader::new(f1); + /// assert!(reader.is_empty()); /// - /// if reader.fill_buf()?.len() > 0 { - /// assert!(!reader.is_empty()); + /// if reader.fill_buf()?.len() > 0 { + /// assert!(!reader.is_empty()); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")] #[rustc_deprecated(since = "1.26.0", reason = "use .buffer().is_empty() instead")] @@ -179,21 +180,21 @@ impl BufReader { /// /// # Examples /// - /// ``` + /// ```no_ru /// # #![feature(bufreader_buffer)] /// use std::io::{BufReader, BufRead}; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f = File::open("log.txt")?; - /// let mut reader = BufReader::new(f); - /// assert!(reader.buffer().is_empty()); + /// fn main() -> std::io::Result<()> { + /// let f = File::open("log.txt")?; + /// let mut reader = BufReader::new(f); + /// assert!(reader.buffer().is_empty()); /// - /// if reader.fill_buf()?.len() > 0 { - /// assert!(!reader.buffer().is_empty()); + /// if reader.fill_buf()?.len() > 0 { + /// assert!(!reader.buffer().is_empty()); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[unstable(feature = "bufreader_buffer", issue = "45323")] pub fn buffer(&self) -> &[u8] { @@ -206,17 +207,17 @@ impl BufReader { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::BufReader; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f1 = File::open("log.txt")?; - /// let reader = BufReader::new(f1); + /// fn main() -> std::io::Result<()> { + /// let f1 = File::open("log.txt")?; + /// let reader = BufReader::new(f1); /// - /// let f2 = reader.into_inner(); - /// # Ok(()) - /// # } + /// let f2 = reader.into_inner(); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> R { self.inner } @@ -724,34 +725,34 @@ impl fmt::Display for IntoInnerError { /// We can use `LineWriter` to write one line at a time, significantly /// reducing the number of actual writes to the file. /// -/// ``` +/// ```no_run /// use std::fs::File; /// use std::io::prelude::*; /// use std::io::LineWriter; /// -/// # fn foo() -> std::io::Result<()> { -/// let road_not_taken = b"I shall be telling this with a sigh +/// fn main() -> std::io::Result<()> { +/// let road_not_taken = b"I shall be telling this with a sigh /// Somewhere ages and ages hence: /// Two roads diverged in a wood, and I - /// I took the one less traveled by, /// And that has made all the difference."; /// -/// let file = File::create("poem.txt")?; -/// let mut file = LineWriter::new(file); +/// let file = File::create("poem.txt")?; +/// let mut file = LineWriter::new(file); /// -/// for &byte in road_not_taken.iter() { -/// file.write(&[byte]).unwrap(); -/// } +/// for &byte in road_not_taken.iter() { +/// file.write(&[byte]).unwrap(); +/// } /// -/// // let's check we did the right thing. -/// let mut file = File::open("poem.txt")?; -/// let mut contents = String::new(); +/// // let's check we did the right thing. +/// let mut file = File::open("poem.txt")?; +/// let mut contents = String::new(); /// -/// file.read_to_string(&mut contents)?; +/// file.read_to_string(&mut contents)?; /// -/// assert_eq!(contents.as_bytes(), &road_not_taken[..]); -/// # Ok(()) -/// # } +/// assert_eq!(contents.as_bytes(), &road_not_taken[..]); +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct LineWriter { @@ -764,15 +765,15 @@ impl LineWriter { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// use std::io::LineWriter; /// - /// # fn foo() -> std::io::Result<()> { - /// let file = File::create("poem.txt")?; - /// let file = LineWriter::new(file); - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let file = File::create("poem.txt")?; + /// let file = LineWriter::new(file); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: W) -> LineWriter { @@ -785,15 +786,15 @@ impl LineWriter { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// use std::io::LineWriter; /// - /// # fn foo() -> std::io::Result<()> { - /// let file = File::create("poem.txt")?; - /// let file = LineWriter::with_capacity(100, file); - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let file = File::create("poem.txt")?; + /// let file = LineWriter::with_capacity(100, file); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(cap: usize, inner: W) -> LineWriter { @@ -807,17 +808,17 @@ impl LineWriter { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// use std::io::LineWriter; /// - /// # fn foo() -> std::io::Result<()> { - /// let file = File::create("poem.txt")?; - /// let file = LineWriter::new(file); + /// fn main() -> std::io::Result<()> { + /// let file = File::create("poem.txt")?; + /// let file = LineWriter::new(file); /// - /// let reference = file.get_ref(); - /// # Ok(()) - /// # } + /// let reference = file.get_ref(); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_ref(&self) -> &W { self.inner.get_ref() } @@ -829,18 +830,18 @@ impl LineWriter { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// use std::io::LineWriter; /// - /// # fn foo() -> std::io::Result<()> { - /// let file = File::create("poem.txt")?; - /// let mut file = LineWriter::new(file); + /// fn main() -> std::io::Result<()> { + /// let file = File::create("poem.txt")?; + /// let mut file = LineWriter::new(file); /// - /// // we can use reference just like file - /// let reference = file.get_mut(); - /// # Ok(()) - /// # } + /// // we can use reference just like file + /// let reference = file.get_mut(); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } @@ -855,18 +856,18 @@ impl LineWriter { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// use std::io::LineWriter; /// - /// # fn foo() -> std::io::Result<()> { - /// let file = File::create("poem.txt")?; + /// fn main() -> std::io::Result<()> { + /// let file = File::create("poem.txt")?; /// - /// let writer: LineWriter = LineWriter::new(file); + /// let writer: LineWriter = LineWriter::new(file); /// - /// let file: File = writer.into_inner()?; - /// # Ok(()) - /// # } + /// let file: File = writer.into_inner()?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> Result>> { diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index d403bf6bfe5..63b631ace96 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -24,21 +24,21 @@ //! example, [`Read`] adds a [`read`][`Read::read`] method, which we can use on //! [`File`]s: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! use std::fs::File; //! -//! # fn foo() -> io::Result<()> { -//! let mut f = File::open("foo.txt")?; -//! let mut buffer = [0; 10]; +//! fn main() -> io::Result<()> { +//! let mut f = File::open("foo.txt")?; +//! let mut buffer = [0; 10]; //! -//! // read up to 10 bytes -//! f.read(&mut buffer)?; +//! // read up to 10 bytes +//! f.read(&mut buffer)?; //! -//! println!("The bytes: {:?}", buffer); -//! # Ok(()) -//! # } +//! println!("The bytes: {:?}", buffer); +//! Ok(()) +//! } //! ``` //! //! [`Read`] and [`Write`] are so important, implementors of the two traits have a @@ -52,25 +52,25 @@ //! how the reading happens. [`Seek`] lets you control where the next byte is //! coming from: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! use std::io::SeekFrom; //! use std::fs::File; //! -//! # fn foo() -> io::Result<()> { -//! let mut f = File::open("foo.txt")?; -//! let mut buffer = [0; 10]; +//! fn main() -> io::Result<()> { +//! let mut f = File::open("foo.txt")?; +//! let mut buffer = [0; 10]; //! -//! // skip to the last 10 bytes of the file -//! f.seek(SeekFrom::End(-10))?; +//! // skip to the last 10 bytes of the file +//! f.seek(SeekFrom::End(-10))?; //! -//! // read up to 10 bytes -//! f.read(&mut buffer)?; +//! // read up to 10 bytes +//! f.read(&mut buffer)?; //! -//! println!("The bytes: {:?}", buffer); -//! # Ok(()) -//! # } +//! println!("The bytes: {:?}", buffer); +//! Ok(()) +//! } //! ``` //! //! [`BufRead`] uses an internal buffer to provide a number of other ways to read, but @@ -87,70 +87,70 @@ //! For example, [`BufReader`] works with the [`BufRead`] trait to add extra //! methods to any reader: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! use std::io::BufReader; //! use std::fs::File; //! -//! # fn foo() -> io::Result<()> { -//! let f = File::open("foo.txt")?; -//! let mut reader = BufReader::new(f); -//! let mut buffer = String::new(); +//! fn main() -> io::Result<()> { +//! let f = File::open("foo.txt")?; +//! let mut reader = BufReader::new(f); +//! let mut buffer = String::new(); //! -//! // read a line into buffer -//! reader.read_line(&mut buffer)?; +//! // read a line into buffer +//! reader.read_line(&mut buffer)?; //! -//! println!("{}", buffer); -//! # Ok(()) -//! # } +//! println!("{}", buffer); +//! Ok(()) +//! } //! ``` //! //! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call //! to [`write`][`Write::write`]: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! use std::io::BufWriter; //! use std::fs::File; //! -//! # fn foo() -> io::Result<()> { -//! let f = File::create("foo.txt")?; -//! { -//! let mut writer = BufWriter::new(f); +//! fn main() -> io::Result<()> { +//! let f = File::create("foo.txt")?; +//! { +//! let mut writer = BufWriter::new(f); //! -//! // write a byte to the buffer -//! writer.write(&[42])?; +//! // write a byte to the buffer +//! writer.write(&[42])?; //! -//! } // the buffer is flushed once writer goes out of scope +//! } // the buffer is flushed once writer goes out of scope //! -//! # Ok(()) -//! # } +//! Ok(()) +//! } //! ``` //! //! ## Standard input and output //! //! A very common source of input is standard input: //! -//! ``` +//! ```no_run //! use std::io; //! -//! # fn foo() -> io::Result<()> { -//! let mut input = String::new(); +//! fn main() -> io::Result<()> { +//! let mut input = String::new(); //! -//! io::stdin().read_line(&mut input)?; +//! io::stdin().read_line(&mut input)?; //! -//! println!("You typed: {}", input.trim()); -//! # Ok(()) -//! # } +//! println!("You typed: {}", input.trim()); +//! Ok(()) +//! } //! ``` //! //! Note that you cannot use the [`?` operator] in functions that do not return //! a [`Result`][`Result`] (e.g. `main`). Instead, you can call [`.unwrap()`] //! or `match` on the return value to catch any possible errors: //! -//! ``` +//! ```no_run //! use std::io; //! //! let mut input = String::new(); @@ -160,14 +160,14 @@ //! //! And a very common source of output is standard output: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! -//! # fn foo() -> io::Result<()> { -//! io::stdout().write(&[42])?; -//! # Ok(()) -//! # } +//! fn main() -> io::Result<()> { +//! io::stdout().write(&[42])?; +//! Ok(()) +//! } //! ``` //! //! Of course, using [`io::stdout`] directly is less common than something like @@ -179,22 +179,21 @@ //! ways of iterating over I/O. For example, [`Lines`] is used to split over //! lines: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! use std::io::BufReader; //! use std::fs::File; //! -//! # fn foo() -> io::Result<()> { -//! let f = File::open("foo.txt")?; -//! let reader = BufReader::new(f); +//! fn main() -> io::Result<()> { +//! let f = File::open("foo.txt")?; +//! let reader = BufReader::new(f); //! -//! for line in reader.lines() { -//! println!("{}", line?); +//! for line in reader.lines() { +//! println!("{}", line?); +//! } +//! Ok(()) //! } -//! -//! # Ok(()) -//! # } //! ``` //! //! ## Functions @@ -203,13 +202,13 @@ //! features. For example, we can use three of these functions to copy everything //! from standard input to standard output: //! -//! ``` +//! ```no_run //! use std::io; //! -//! # fn foo() -> io::Result<()> { -//! io::copy(&mut io::stdin(), &mut io::stdout())?; -//! # Ok(()) -//! # } +//! fn main() -> io::Result<()> { +//! io::copy(&mut io::stdin(), &mut io::stdout())?; +//! Ok(()) +//! } //! ``` //! //! [functions-list]: #functions-1 @@ -416,47 +415,47 @@ fn read_to_end(r: &mut R, buf: &mut Vec) -> Result /// /// [`File`]s implement `Read`: /// -/// ``` -/// # use std::io; +/// ```no_run +/// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// -/// # fn foo() -> io::Result<()> { -/// let mut f = File::open("foo.txt")?; -/// let mut buffer = [0; 10]; +/// fn main() -> io::Result<()> { +/// let mut f = File::open("foo.txt")?; +/// let mut buffer = [0; 10]; /// -/// // read up to 10 bytes -/// f.read(&mut buffer)?; +/// // read up to 10 bytes +/// f.read(&mut buffer)?; /// -/// let mut buffer = vec![0; 10]; -/// // read the whole file -/// f.read_to_end(&mut buffer)?; +/// let mut buffer = vec![0; 10]; +/// // read the whole file +/// f.read_to_end(&mut buffer)?; /// -/// // read into a String, so that you don't need to do the conversion. -/// let mut buffer = String::new(); -/// f.read_to_string(&mut buffer)?; +/// // read into a String, so that you don't need to do the conversion. +/// let mut buffer = String::new(); +/// f.read_to_string(&mut buffer)?; /// -/// // and more! See the other methods for more details. -/// # Ok(()) -/// # } +/// // and more! See the other methods for more details. +/// Ok(()) +/// } /// ``` /// /// Read from [`&str`] because [`&[u8]`][slice] implements `Read`: /// -/// ``` +/// ```no_run /// # use std::io; /// use std::io::prelude::*; /// -/// # fn foo() -> io::Result<()> { -/// let mut b = "This string will be read".as_bytes(); -/// let mut buffer = [0; 10]; +/// fn main() -> io::Result<()> { +/// let mut b = "This string will be read".as_bytes(); +/// let mut buffer = [0; 10]; /// -/// // read up to 10 bytes -/// b.read(&mut buffer)?; +/// // read up to 10 bytes +/// b.read(&mut buffer)?; /// -/// // etc... it works exactly as a File does! -/// # Ok(()) -/// # } +/// // etc... it works exactly as a File does! +/// Ok(()) +/// } /// ``` /// /// [`read()`]: trait.Read.html#tymethod.read @@ -509,19 +508,19 @@ pub trait Read { /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted /// [`File`]: ../fs/struct.File.html /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = [0; 10]; + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = [0; 10]; /// - /// // read up to 10 bytes - /// f.read(&mut buffer[..])?; - /// # Ok(()) - /// # } + /// // read up to 10 bytes + /// f.read(&mut buffer[..])?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn read(&mut self, buf: &mut [u8]) -> Result; @@ -582,19 +581,19 @@ pub trait Read { /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted /// [`File`]: ../fs/struct.File.html /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = Vec::new(); + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = Vec::new(); /// - /// // read the whole file - /// f.read_to_end(&mut buffer)?; - /// # Ok(()) - /// # } + /// // read the whole file + /// f.read_to_end(&mut buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn read_to_end(&mut self, buf: &mut Vec) -> Result { @@ -621,18 +620,18 @@ pub trait Read { /// /// [file]: ../fs/struct.File.html /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = String::new(); + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = String::new(); /// - /// f.read_to_string(&mut buffer)?; - /// # Ok(()) - /// # } + /// f.read_to_string(&mut buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn read_to_string(&mut self, buf: &mut String) -> Result { @@ -683,19 +682,19 @@ pub trait Read { /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted /// [`ErrorKind::UnexpectedEof`]: ../../std/io/enum.ErrorKind.html#variant.UnexpectedEof /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = [0; 10]; + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = [0; 10]; /// - /// // read exactly 10 bytes - /// f.read_exact(&mut buffer)?; - /// # Ok(()) - /// # } + /// // read exactly 10 bytes + /// f.read_exact(&mut buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "read_exact", since = "1.6.0")] fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> { @@ -726,28 +725,28 @@ pub trait Read { /// /// [file]: ../fs/struct.File.html /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::Read; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = Vec::new(); - /// let mut other_buffer = Vec::new(); + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = Vec::new(); + /// let mut other_buffer = Vec::new(); /// - /// { - /// let reference = f.by_ref(); + /// { + /// let reference = f.by_ref(); /// - /// // read at most 5 bytes - /// reference.take(5).read_to_end(&mut buffer)?; + /// // read at most 5 bytes + /// reference.take(5).read_to_end(&mut buffer)?; /// - /// } // drop our &mut reference so we can use f again + /// } // drop our &mut reference so we can use f again /// - /// // original file still usable, read the rest - /// f.read_to_end(&mut other_buffer)?; - /// # Ok(()) - /// # } + /// // original file still usable, read the rest + /// f.read_to_end(&mut other_buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn by_ref(&mut self) -> &mut Self where Self: Sized { self } @@ -772,19 +771,19 @@ pub trait Read { /// [`Err`]: ../../std/result/enum.Result.html#variant.Err /// [`None`]: ../../std/option/enum.Option.html#variant.None /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; /// - /// for byte in f.bytes() { - /// println!("{}", byte.unwrap()); + /// for byte in f.bytes() { + /// println!("{}", byte.unwrap()); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn bytes(self) -> Bytes where Self: Sized { @@ -812,20 +811,20 @@ pub trait Read { /// [`char`]: ../../std/primitive.char.html /// [`None`]: ../../std/option/enum.Option.html#variant.None /// - /// ``` + /// ```no_run /// #![feature(io)] /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; /// - /// for c in f.chars() { - /// println!("{}", c.unwrap()); + /// for c in f.chars() { + /// println!("{}", c.unwrap()); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[unstable(feature = "io", reason = "the semantics of a partial read/write \ of where errors happen is currently \ @@ -847,23 +846,23 @@ pub trait Read { /// /// [file]: ../fs/struct.File.html /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f1 = File::open("foo.txt")?; - /// let mut f2 = File::open("bar.txt")?; + /// fn main() -> io::Result<()> { + /// let mut f1 = File::open("foo.txt")?; + /// let mut f2 = File::open("bar.txt")?; /// - /// let mut handle = f1.chain(f2); - /// let mut buffer = String::new(); + /// let mut handle = f1.chain(f2); + /// let mut buffer = String::new(); /// - /// // read the value into a String. We could use any Read method here, - /// // this is just one example. - /// handle.read_to_string(&mut buffer)?; - /// # Ok(()) - /// # } + /// // read the value into a String. We could use any Read method here, + /// // this is just one example. + /// handle.read_to_string(&mut buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn chain(self, next: R) -> Chain where Self: Sized { @@ -885,21 +884,21 @@ pub trait Read { /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok /// [`read()`]: trait.Read.html#tymethod.read /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = [0; 5]; + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = [0; 5]; /// - /// // read at most five bytes - /// let mut handle = f.take(5); + /// // read at most five bytes + /// let mut handle = f.take(5); /// - /// handle.read(&mut buffer)?; - /// # Ok(()) - /// # } + /// handle.read(&mut buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn take(self, limit: u64) -> Take where Self: Sized { @@ -974,16 +973,16 @@ impl Initializer { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::io::prelude::*; /// use std::fs::File; /// -/// # fn foo() -> std::io::Result<()> { -/// let mut buffer = File::create("foo.txt")?; +/// fn main() -> std::io::Result<()> { +/// let mut buffer = File::create("foo.txt")?; /// -/// buffer.write(b"some bytes")?; -/// # Ok(()) -/// # } +/// buffer.write(b"some bytes")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[doc(spotlight)] @@ -1022,17 +1021,17 @@ pub trait Write { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = File::create("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; /// - /// // Writes some prefix of the byte string, not necessarily all of it. - /// buffer.write(b"some bytes")?; - /// # Ok(()) - /// # } + /// // Writes some prefix of the byte string, not necessarily all of it. + /// buffer.write(b"some bytes")?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn write(&mut self, buf: &[u8]) -> Result; @@ -1047,18 +1046,18 @@ pub trait Write { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::prelude::*; /// use std::io::BufWriter; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = BufWriter::new(File::create("foo.txt")?); + /// fn main() -> std::io::Result<()> { + /// let mut buffer = BufWriter::new(File::create("foo.txt")?); /// - /// buffer.write(b"some bytes")?; - /// buffer.flush()?; - /// # Ok(()) - /// # } + /// buffer.write(b"some bytes")?; + /// buffer.flush()?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn flush(&mut self) -> Result<()>; @@ -1082,16 +1081,16 @@ pub trait Write { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = File::create("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; /// - /// buffer.write_all(b"some bytes")?; - /// # Ok(()) - /// # } + /// buffer.write_all(b"some bytes")?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn write_all(&mut self, mut buf: &[u8]) -> Result<()> { @@ -1131,19 +1130,19 @@ pub trait Write { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = File::create("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; /// - /// // this call - /// write!(buffer, "{:.*}", 2, 1.234567)?; - /// // turns into this: - /// buffer.write_fmt(format_args!("{:.*}", 2, 1.234567))?; - /// # Ok(()) - /// # } + /// // this call + /// write!(buffer, "{:.*}", 2, 1.234567)?; + /// // turns into this: + /// buffer.write_fmt(format_args!("{:.*}", 2, 1.234567))?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()> { @@ -1187,19 +1186,19 @@ pub trait Write { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::Write; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = File::create("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; /// - /// let reference = buffer.by_ref(); + /// let reference = buffer.by_ref(); /// - /// // we can use reference just like our original buffer - /// reference.write_all(b"some bytes")?; - /// # Ok(()) - /// # } + /// // we can use reference just like our original buffer + /// reference.write_all(b"some bytes")?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn by_ref(&mut self) -> &mut Self where Self: Sized { self } @@ -1217,19 +1216,19 @@ pub trait Write { /// /// [file]: ../fs/struct.File.html /// -/// ``` +/// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// use std::io::SeekFrom; /// -/// # fn foo() -> io::Result<()> { -/// let mut f = File::open("foo.txt")?; +/// fn main() -> io::Result<()> { +/// let mut f = File::open("foo.txt")?; /// -/// // move the cursor 42 bytes from the start of the file -/// f.seek(SeekFrom::Start(42))?; -/// # Ok(()) -/// # } +/// // move the cursor 42 bytes from the start of the file +/// f.seek(SeekFrom::Start(42))?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait Seek { @@ -1320,7 +1319,7 @@ fn read_until(r: &mut R, delim: u8, buf: &mut Vec) /// /// A locked standard input implements `BufRead`: /// -/// ``` +/// ```no_run /// use std::io; /// use std::io::prelude::*; /// @@ -1342,21 +1341,21 @@ fn read_until(r: &mut R, delim: u8, buf: &mut Vec) /// [`lines`]: #method.lines /// [`Read`]: trait.Read.html /// -/// ``` +/// ```no_run /// use std::io::{self, BufReader}; /// use std::io::prelude::*; /// use std::fs::File; /// -/// # fn foo() -> io::Result<()> { -/// let f = File::open("foo.txt")?; -/// let f = BufReader::new(f); +/// fn main() -> io::Result<()> { +/// let f = File::open("foo.txt")?; +/// let f = BufReader::new(f); /// -/// for line in f.lines() { -/// println!("{}", line.unwrap()); -/// } +/// for line in f.lines() { +/// println!("{}", line.unwrap()); +/// } /// -/// # Ok(()) -/// # } +/// Ok(()) +/// } /// ``` /// #[stable(feature = "rust1", since = "1.0.0")] @@ -1383,7 +1382,7 @@ pub trait BufRead: Read { /// /// A locked standard input implements `BufRead`: /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// @@ -1645,19 +1644,19 @@ impl Chain { /// /// # Examples /// - /// ``` - /// # use std::io; + /// ```no_run + /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut foo_file = File::open("foo.txt")?; - /// let mut bar_file = File::open("bar.txt")?; + /// fn main() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; /// - /// let chain = foo_file.chain(bar_file); - /// let (foo_file, bar_file) = chain.into_inner(); - /// # Ok(()) - /// # } + /// let chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.into_inner(); + /// Ok(()) + /// } /// ``` #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn into_inner(self) -> (T, U) { @@ -1668,19 +1667,19 @@ impl Chain { /// /// # Examples /// - /// ``` - /// # use std::io; + /// ```no_run + /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut foo_file = File::open("foo.txt")?; - /// let mut bar_file = File::open("bar.txt")?; + /// fn main() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; /// - /// let chain = foo_file.chain(bar_file); - /// let (foo_file, bar_file) = chain.get_ref(); - /// # Ok(()) - /// # } + /// let chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.get_ref(); + /// Ok(()) + /// } /// ``` #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_ref(&self) -> (&T, &U) { @@ -1695,19 +1694,19 @@ impl Chain { /// /// # Examples /// - /// ``` - /// # use std::io; + /// ```no_run + /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut foo_file = File::open("foo.txt")?; - /// let mut bar_file = File::open("bar.txt")?; + /// fn main() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; /// - /// let mut chain = foo_file.chain(bar_file); - /// let (foo_file, bar_file) = chain.get_mut(); - /// # Ok(()) - /// # } + /// let mut chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.get_mut(); + /// Ok(()) + /// } /// ``` #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_mut(&mut self) -> (&mut T, &mut U) { @@ -1794,20 +1793,20 @@ impl Take { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let f = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let f = File::open("foo.txt")?; /// - /// // read at most five bytes - /// let handle = f.take(5); + /// // read at most five bytes + /// let handle = f.take(5); /// - /// println!("limit: {}", handle.limit()); - /// # Ok(()) - /// # } + /// println!("limit: {}", handle.limit()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn limit(&self) -> u64 { self.limit } @@ -1819,22 +1818,22 @@ impl Take { /// /// # Examples /// - /// ``` + /// ```no_run /// #![feature(take_set_limit)] /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let f = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let f = File::open("foo.txt")?; /// - /// // read at most five bytes - /// let mut handle = f.take(5); - /// handle.set_limit(10); + /// // read at most five bytes + /// let mut handle = f.take(5); + /// handle.set_limit(10); /// - /// assert_eq!(handle.limit(), 10); - /// # Ok(()) - /// # } + /// assert_eq!(handle.limit(), 10); + /// Ok(()) + /// } /// ``` #[unstable(feature = "take_set_limit", issue = "42781")] pub fn set_limit(&mut self, limit: u64) { @@ -1845,21 +1844,21 @@ impl Take { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut file = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; /// - /// let mut buffer = [0; 5]; - /// let mut handle = file.take(5); - /// handle.read(&mut buffer)?; + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; /// - /// let file = handle.into_inner(); - /// # Ok(()) - /// # } + /// let file = handle.into_inner(); + /// Ok(()) + /// } /// ``` #[stable(feature = "io_take_into_inner", since = "1.15.0")] pub fn into_inner(self) -> T { @@ -1870,21 +1869,21 @@ impl Take { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut file = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; /// - /// let mut buffer = [0; 5]; - /// let mut handle = file.take(5); - /// handle.read(&mut buffer)?; + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; /// - /// let file = handle.get_ref(); - /// # Ok(()) - /// # } + /// let file = handle.get_ref(); + /// Ok(()) + /// } /// ``` #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_ref(&self) -> &T { @@ -1899,21 +1898,21 @@ impl Take { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut file = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; /// - /// let mut buffer = [0; 5]; - /// let mut handle = file.take(5); - /// handle.read(&mut buffer)?; + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; /// - /// let file = handle.get_mut(); - /// # Ok(()) - /// # } + /// let file = handle.get_mut(); + /// Ok(()) + /// } /// ``` #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_mut(&mut self) -> &mut T { diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 1f73054e3be..2472bed5ba4 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -171,29 +171,29 @@ pub struct StdinLock<'a> { /// /// Using implicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Read}; /// -/// # fn foo() -> io::Result { -/// let mut buffer = String::new(); -/// io::stdin().read_to_string(&mut buffer)?; -/// # Ok(buffer) -/// # } +/// fn main() -> io::Result<()> { +/// let mut buffer = String::new(); +/// io::stdin().read_to_string(&mut buffer)?; +/// Ok(()) +/// } /// ``` /// /// Using explicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Read}; /// -/// # fn foo() -> io::Result { -/// let mut buffer = String::new(); -/// let stdin = io::stdin(); -/// let mut handle = stdin.lock(); +/// fn main() -> io::Result<()> { +/// let mut buffer = String::new(); +/// let stdin = io::stdin(); +/// let mut handle = stdin.lock(); /// -/// handle.read_to_string(&mut buffer)?; -/// # Ok(buffer) -/// # } +/// handle.read_to_string(&mut buffer)?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stdin() -> Stdin { @@ -225,17 +225,17 @@ impl Stdin { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::{self, Read}; /// - /// # fn foo() -> io::Result { - /// let mut buffer = String::new(); - /// let stdin = io::stdin(); - /// let mut handle = stdin.lock(); + /// fn main() -> io::Result<()> { + /// let mut buffer = String::new(); + /// let stdin = io::stdin(); + /// let mut handle = stdin.lock(); /// - /// handle.read_to_string(&mut buffer)?; - /// # Ok(buffer) - /// # } + /// handle.read_to_string(&mut buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StdinLock { @@ -369,29 +369,29 @@ pub struct StdoutLock<'a> { /// /// Using implicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Write}; /// -/// # fn foo() -> io::Result<()> { -/// io::stdout().write(b"hello world")?; +/// fn main() -> io::Result<()> { +/// io::stdout().write(b"hello world")?; /// -/// # Ok(()) -/// # } +/// Ok(()) +/// } /// ``` /// /// Using explicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Write}; /// -/// # fn foo() -> io::Result<()> { -/// let stdout = io::stdout(); -/// let mut handle = stdout.lock(); +/// fn main() -> io::Result<()> { +/// let stdout = io::stdout(); +/// let mut handle = stdout.lock(); /// -/// handle.write(b"hello world")?; +/// handle.write(b"hello world")?; /// -/// # Ok(()) -/// # } +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stdout() -> Stdout { @@ -419,17 +419,17 @@ impl Stdout { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::{self, Write}; /// - /// # fn foo() -> io::Result<()> { - /// let stdout = io::stdout(); - /// let mut handle = stdout.lock(); + /// fn main() -> io::Result<()> { + /// let stdout = io::stdout(); + /// let mut handle = stdout.lock(); /// - /// handle.write(b"hello world")?; + /// handle.write(b"hello world")?; /// - /// # Ok(()) - /// # } + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StdoutLock { @@ -505,29 +505,29 @@ pub struct StderrLock<'a> { /// /// Using implicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Write}; /// -/// # fn foo() -> io::Result<()> { -/// io::stderr().write(b"hello world")?; +/// fn main() -> io::Result<()> { +/// io::stderr().write(b"hello world")?; /// -/// # Ok(()) -/// # } +/// Ok(()) +/// } /// ``` /// /// Using explicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Write}; /// -/// # fn foo() -> io::Result<()> { -/// let stderr = io::stderr(); -/// let mut handle = stderr.lock(); +/// fn main() -> io::Result<()> { +/// let stderr = io::stderr(); +/// let mut handle = stderr.lock(); /// -/// handle.write(b"hello world")?; +/// handle.write(b"hello world")?; /// -/// # Ok(()) -/// # } +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stderr() -> Stderr { diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 45d281ee34a..195310a26fe 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -34,16 +34,15 @@ use mem; /// ``` /// use std::io; /// -/// # fn foo() -> io::Result<()> { -/// let mut reader: &[u8] = b"hello"; -/// let mut writer: Vec = vec![]; +/// fn main() -> io::Result<()> { +/// let mut reader: &[u8] = b"hello"; +/// let mut writer: Vec = vec![]; /// -/// io::copy(&mut reader, &mut writer)?; +/// io::copy(&mut reader, &mut writer)?; /// -/// assert_eq!(&b"hello"[..], &writer[..]); -/// # Ok(()) -/// # } -/// # foo().unwrap(); +/// assert_eq!(&b"hello"[..], &writer[..]); +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn copy(reader: &mut R, writer: &mut W) -> io::Result diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index eef043683b0..b0d5e563cb9 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -175,12 +175,12 @@ impl fmt::Debug for LookupHost { /// /// use std::net; /// -/// # fn foo() -> std::io::Result<()> { -/// for host in net::lookup_host("rust-lang.org")? { -/// println!("found address: {}", host); +/// fn main() -> std::io::Result<()> { +/// for host in net::lookup_host("rust-lang.org")? { +/// println!("found address: {}", host); +/// } +/// Ok(()) /// } -/// # Ok(()) -/// # } /// ``` #[unstable(feature = "lookup_host", reason = "unsure about the returned \ iterator and returning socket \ diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index e28ccdb766a..0f60b5b3ee4 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -72,7 +72,7 @@ pub struct TcpStream(net_imp::TcpStream); /// /// # Examples /// -/// ``` +/// ```no_run /// # use std::io; /// use std::net::{TcpListener, TcpStream}; /// @@ -80,15 +80,15 @@ pub struct TcpStream(net_imp::TcpStream); /// // ... /// } /// -/// # fn process() -> io::Result<()> { -/// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); +/// fn main() -> io::Result<()> { +/// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); /// -/// // accept connections and process them serially -/// for stream in listener.incoming() { -/// handle_client(stream?); +/// // accept connections and process them serially +/// for stream in listener.incoming() { +/// handle_client(stream?); +/// } +/// Ok(()) /// } -/// # Ok(()) -/// # } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct TcpListener(net_imp::TcpListener); diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 8e56954bea4..d25e29999cb 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -44,22 +44,22 @@ use time::Duration; /// ```no_run /// use std::net::UdpSocket; /// -/// # fn foo() -> std::io::Result<()> { -/// { -/// let mut socket = UdpSocket::bind("127.0.0.1:34254")?; +/// fn main() -> std::io::Result<()> { +/// { +/// let mut socket = UdpSocket::bind("127.0.0.1:34254")?; /// -/// // Receives a single datagram message on the socket. If `buf` is too small to hold -/// // the message, it will be cut off. -/// let mut buf = [0; 10]; -/// let (amt, src) = socket.recv_from(&mut buf)?; +/// // Receives a single datagram message on the socket. If `buf` is too small to hold +/// // the message, it will be cut off. +/// let mut buf = [0; 10]; +/// let (amt, src) = socket.recv_from(&mut buf)?; /// -/// // Redeclare `buf` as slice of the received data and send reverse data back to origin. -/// let buf = &mut buf[..amt]; -/// buf.reverse(); -/// socket.send_to(buf, &src)?; -/// # Ok(()) -/// } // the socket is closed here -/// # } +/// // Redeclare `buf` as slice of the received data and send reverse data back to origin. +/// let buf = &mut buf[..amt]; +/// buf.reverse(); +/// socket.send_to(buf, &src)?; +/// } // the socket is closed here +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct UdpSocket(net_imp::UdpSocket); diff --git a/src/libstd/os/linux/fs.rs b/src/libstd/os/linux/fs.rs index 5d37d970e89..2be2fbcb2db 100644 --- a/src/libstd/os/linux/fs.rs +++ b/src/libstd/os/linux/fs.rs @@ -32,16 +32,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let stat = meta.as_raw_stat(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let stat = meta.as_raw_stat(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] #[rustc_deprecated(since = "1.8.0", @@ -54,16 +54,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_dev()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_dev()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_dev(&self) -> u64; @@ -71,16 +71,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_ino()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ino()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_ino(&self) -> u64; @@ -88,16 +88,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_mode()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mode()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_mode(&self) -> u32; @@ -105,16 +105,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_nlink()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_nlink()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_nlink(&self) -> u64; @@ -122,16 +122,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_uid()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_uid()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_uid(&self) -> u32; @@ -139,16 +139,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_gid()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_gid()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_gid(&self) -> u32; @@ -156,16 +156,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_rdev()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_rdev()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_rdev(&self) -> u64; @@ -176,16 +176,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_size()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_size()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_size(&self) -> u64; @@ -193,16 +193,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_atime()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_atime()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_atime(&self) -> i64; @@ -210,16 +210,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_atime_nsec()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_atime_nsec()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_atime_nsec(&self) -> i64; @@ -227,16 +227,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_mtime()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mtime()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_mtime(&self) -> i64; @@ -244,16 +244,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_mtime_nsec()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mtime_nsec()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_mtime_nsec(&self) -> i64; @@ -261,16 +261,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_ctime()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ctime()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_ctime(&self) -> i64; @@ -278,16 +278,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_ctime_nsec()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ctime_nsec()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_ctime_nsec(&self) -> i64; @@ -295,16 +295,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_blksize()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_blksize()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_blksize(&self) -> u64; @@ -312,16 +312,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_blocks()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_blocks()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_blocks(&self) -> u64; diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs index 5d4edc2cf92..0f4762aa881 100644 --- a/src/libstd/sys/redox/ext/fs.rs +++ b/src/libstd/sys/redox/ext/fs.rs @@ -30,13 +30,14 @@ pub trait PermissionsExt { /// use std::fs::File; /// use std::os::redox::fs::PermissionsExt; /// - /// # fn run() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let permissions = metadata.permissions(); + /// fn main() -> std::io::Result<()> { + /// let f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; + /// let permissions = metadata.permissions(); /// - /// println!("permissions: {}", permissions.mode()); - /// # Ok(()) } + /// println!("permissions: {}", permissions.mode()); + /// Ok(()) + /// } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&self) -> u32; @@ -49,14 +50,15 @@ pub trait PermissionsExt { /// use std::fs::File; /// use std::os::redox::fs::PermissionsExt; /// - /// # fn run() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let mut permissions = metadata.permissions(); + /// fn main() -> std::io::Result<()> { + /// let f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; + /// let mut permissions = metadata.permissions(); /// - /// permissions.set_mode(0o644); // Read/write for owner and read for others. - /// assert_eq!(permissions.mode(), 0o644); - /// # Ok(()) } + /// permissions.set_mode(0o644); // Read/write for owner and read for others. + /// assert_eq!(permissions.mode(), 0o644); + /// Ok(()) + /// } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn set_mode(&mut self, mode: u32); @@ -291,13 +293,13 @@ impl FileTypeExt for fs::FileType { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::os::redox::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::symlink("a.txt", "b.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::symlink("a.txt", "b.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "symlink", since = "1.1.0")] pub fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()> diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 2e17fd58e0a..3c5b9424fb0 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -41,20 +41,20 @@ pub trait FileExt { /// /// # Examples /// - /// ``` - /// use std::os::unix::prelude::FileExt; + /// ```no_run + /// use std::io; /// use std::fs::File; + /// use std::os::unix::prelude::FileExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let mut buf = [0u8; 8]; - /// let file = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut buf = [0u8; 8]; + /// let file = File::open("foo.txt")?; /// - /// // We now read 8 bytes from the offset 10. - /// let num_bytes_read = file.read_at(&mut buf, 10)?; - /// println!("read {} bytes: {:?}", num_bytes_read, buf); - /// # Ok(()) - /// # } + /// // We now read 8 bytes from the offset 10. + /// let num_bytes_read = file.read_at(&mut buf, 10)?; + /// println!("read {} bytes: {:?}", num_bytes_read, buf); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_offset", since = "1.15.0")] fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result; @@ -78,18 +78,18 @@ pub trait FileExt { /// /// # Examples /// - /// ``` - /// use std::os::unix::prelude::FileExt; + /// ```no_run /// use std::fs::File; + /// use std::io; + /// use std::os::unix::prelude::FileExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let file = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let file = File::open("foo.txt")?; /// - /// // We now write at the offset 10. - /// file.write_at(b"sushi", 10)?; - /// # Ok(()) - /// # } + /// // We now write at the offset 10. + /// file.write_at(b"sushi", 10)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "file_offset", since = "1.15.0")] fn write_at(&self, buf: &[u8], offset: u64) -> io::Result; @@ -117,13 +117,13 @@ pub trait PermissionsExt { /// use std::fs::File; /// use std::os::unix::fs::PermissionsExt; /// - /// # fn run() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let permissions = metadata.permissions(); + /// fn main() -> std::io::Result<()> { + /// let f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; + /// let permissions = metadata.permissions(); /// - /// println!("permissions: {}", permissions.mode()); - /// # Ok(()) } + /// println!("permissions: {}", permissions.mode()); + /// Ok(()) } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&self) -> u32; @@ -136,14 +136,14 @@ pub trait PermissionsExt { /// use std::fs::File; /// use std::os::unix::fs::PermissionsExt; /// - /// # fn run() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let mut permissions = metadata.permissions(); + /// fn main() -> std::io::Result<()> { + /// let f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; + /// let mut permissions = metadata.permissions(); /// - /// permissions.set_mode(0o644); // Read/write for owner and read for others. - /// assert_eq!(permissions.mode(), 0o644); - /// # Ok(()) } + /// permissions.set_mode(0o644); // Read/write for owner and read for others. + /// assert_eq!(permissions.mode(), 0o644); + /// Ok(()) } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn set_mode(&mut self, mode: u32); @@ -260,15 +260,15 @@ pub trait MetadataExt { /// # Examples /// /// ```no_run + /// use std::io; /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let dev_id = meta.dev(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let dev_id = meta.dev(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn dev(&self) -> u64; @@ -279,13 +279,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let inode = meta.ino(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let inode = meta.ino(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn ino(&self) -> u64; @@ -296,17 +296,17 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; - /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let mode = meta.mode(); - /// let user_has_write_access = mode & 0o200; - /// let user_has_read_write_access = mode & 0o600; - /// let group_has_read_access = mode & 0o040; - /// let others_have_exec_access = mode & 0o001; - /// # Ok(()) - /// # } + /// use std::io; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let mode = meta.mode(); + /// let user_has_write_access = mode & 0o200; + /// let user_has_read_write_access = mode & 0o600; + /// let group_has_read_access = mode & 0o040; + /// let others_have_exec_access = mode & 0o001; + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn mode(&self) -> u32; @@ -317,13 +317,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let nb_hard_links = meta.nlink(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let nb_hard_links = meta.nlink(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn nlink(&self) -> u64; @@ -334,13 +334,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let user_id = meta.uid(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let user_id = meta.uid(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn uid(&self) -> u32; @@ -351,13 +351,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let group_id = meta.gid(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let group_id = meta.gid(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn gid(&self) -> u32; @@ -368,13 +368,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let device_id = meta.rdev(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let device_id = meta.rdev(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn rdev(&self) -> u64; @@ -385,13 +385,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let file_size = meta.size(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let file_size = meta.size(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn size(&self) -> u64; @@ -402,13 +402,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let last_access_time = meta.atime(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let last_access_time = meta.atime(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn atime(&self) -> i64; @@ -419,13 +419,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let nano_last_access_time = meta.atime_nsec(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let nano_last_access_time = meta.atime_nsec(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn atime_nsec(&self) -> i64; @@ -436,13 +436,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let last_modification_time = meta.mtime(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let last_modification_time = meta.mtime(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn mtime(&self) -> i64; @@ -453,13 +453,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let nano_last_modification_time = meta.mtime_nsec(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let nano_last_modification_time = meta.mtime_nsec(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn mtime_nsec(&self) -> i64; @@ -470,13 +470,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let last_status_change_time = meta.ctime(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let last_status_change_time = meta.ctime(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn ctime(&self) -> i64; @@ -487,13 +487,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let nano_last_status_change_time = meta.ctime_nsec(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let nano_last_status_change_time = meta.ctime_nsec(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn ctime_nsec(&self) -> i64; @@ -504,13 +504,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let blocksize = meta.blksize(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let blocksize = meta.blksize(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn blksize(&self) -> u64; @@ -523,13 +523,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let blocks = meta.blocks(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let blocks = meta.blocks(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn blocks(&self) -> u64; @@ -562,17 +562,17 @@ pub trait FileTypeExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; /// use std::os::unix::fs::FileTypeExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("block_device_file")?; - /// let file_type = meta.file_type(); - /// assert!(file_type.is_block_device()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("block_device_file")?; + /// let file_type = meta.file_type(); + /// assert!(file_type.is_block_device()); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type_ext", since = "1.5.0")] fn is_block_device(&self) -> bool; @@ -580,17 +580,17 @@ pub trait FileTypeExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; /// use std::os::unix::fs::FileTypeExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("char_device_file")?; - /// let file_type = meta.file_type(); - /// assert!(file_type.is_char_device()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("char_device_file")?; + /// let file_type = meta.file_type(); + /// assert!(file_type.is_char_device()); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type_ext", since = "1.5.0")] fn is_char_device(&self) -> bool; @@ -598,17 +598,17 @@ pub trait FileTypeExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; /// use std::os::unix::fs::FileTypeExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("fifo_file")?; - /// let file_type = meta.file_type(); - /// assert!(file_type.is_fifo()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("fifo_file")?; + /// let file_type = meta.file_type(); + /// assert!(file_type.is_fifo()); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type_ext", since = "1.5.0")] fn is_fifo(&self) -> bool; @@ -616,17 +616,17 @@ pub trait FileTypeExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; /// use std::os::unix::fs::FileTypeExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("unix.socket")?; - /// let file_type = meta.file_type(); - /// assert!(file_type.is_socket()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("unix.socket")?; + /// let file_type = meta.file_type(); + /// assert!(file_type.is_socket()); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type_ext", since = "1.5.0")] fn is_socket(&self) -> bool; @@ -687,13 +687,13 @@ impl DirEntryExt for fs::DirEntry { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::os::unix::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::symlink("a.txt", "b.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::symlink("a.txt", "b.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "symlink", since = "1.1.0")] pub fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()> diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index 38bf4cca851..e5cd51b6550 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -45,15 +45,15 @@ pub trait FileExt { /// use std::fs::File; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> 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(()) - /// # } + /// 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; @@ -79,14 +79,14 @@ pub trait FileExt { /// use std::fs::File; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = File::create("foo.txt")?; + /// 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(()) - /// # } + /// // 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; @@ -305,11 +305,11 @@ pub trait MetadataExt { /// use std::fs; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let attributes = metadata.file_attributes(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let attributes = metadata.file_attributes(); + /// Ok(()) + /// } /// ``` /// /// [File Attribute Constants]: @@ -335,11 +335,11 @@ pub trait MetadataExt { /// use std::fs; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let creation_time = metadata.creation_time(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let creation_time = metadata.creation_time(); + /// Ok(()) + /// } /// ``` /// /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx @@ -370,11 +370,11 @@ pub trait MetadataExt { /// use std::fs; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let last_access_time = metadata.last_access_time(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let last_access_time = metadata.last_access_time(); + /// Ok(()) + /// } /// ``` /// /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx @@ -403,11 +403,11 @@ pub trait MetadataExt { /// use std::fs; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let last_write_time = metadata.last_write_time(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let last_write_time = metadata.last_write_time(); + /// Ok(()) + /// } /// ``` /// /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx @@ -426,11 +426,11 @@ pub trait MetadataExt { /// use std::fs; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let file_size = metadata.file_size(); - /// # Ok(()) - /// # } + /// 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; @@ -473,10 +473,10 @@ impl FileTypeExt for fs::FileType { /// ```no_run /// use std::os::windows::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::symlink_file("a.txt", "b.txt")?; -/// # Ok(()) -/// # } +/// 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>(src: P, dst: Q) @@ -494,10 +494,10 @@ pub fn symlink_file, Q: AsRef>(src: P, dst: Q) /// ```no_run /// use std::os::windows::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::symlink_dir("a", "b")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::symlink_dir("a", "b")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "symlink", since = "1.1.0")] pub fn symlink_dir, Q: AsRef>(src: P, dst: Q) -- cgit 1.4.1-3-g733a5 From 7db854b36f9598e44fb4d61428d42d7769233e19 Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Tue, 3 Apr 2018 12:42:36 +0900 Subject: Fix imports --- src/libstd/sys/unix/thread.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 775289f393b..2db3d4a5744 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -223,7 +223,7 @@ pub mod guard { #[cfg_attr(test, allow(dead_code))] pub mod guard { use libc; - use libc::mmap; + use libc::{mmap, mprotect}; use libc::{PROT_NONE, PROT_READ, PROT_WRITE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED}; use ops::Range; use sys::os; -- cgit 1.4.1-3-g733a5 From 97ac479066a16d06ad4eb2cc2a4f58d1e7aa37b8 Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Tue, 3 Apr 2018 19:47:37 -0600 Subject: Stabilize parent_id() Fixes #46104 --- src/libstd/sys/unix/ext/process.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs index 60309bec6d4..7b4ec20d91f 100644 --- a/src/libstd/sys/unix/ext/process.rs +++ b/src/libstd/sys/unix/ext/process.rs @@ -193,7 +193,7 @@ impl IntoRawFd for process::ChildStderr { } /// Returns the OS-assigned process identifier associated with this process's parent. -#[unstable(feature = "unix_ppid", issue = "46104")] +#[stable(feature = "unix_ppid", since = "1.27.0")] pub fn parent_id() -> u32 { ::sys::os::getppid() } -- cgit 1.4.1-3-g733a5 From 4577da75f4badd66a337eb15da76ca836ab1ad6e Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Wed, 4 Apr 2018 19:30:46 +0900 Subject: Use box syntax instead of Box::new in Mutex::remutex on Windows The Box::new(mem::uninitialized()) pattern actually actively copies uninitialized bytes from the stack into the box, which is a waste of time. Using the box syntax instead avoids the useless copy. --- src/libstd/sys/windows/mutex.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index 85560368590..9bf9f749d4d 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -117,7 +117,7 @@ impl Mutex { 0 => {} n => return n as *mut _, } - let mut re = Box::new(ReentrantMutex::uninitialized()); + let mut re = box ReentrantMutex::uninitialized(); re.init(); let re = Box::into_raw(re); match self.lock.compare_and_swap(0, re as usize, Ordering::SeqCst) { -- cgit 1.4.1-3-g733a5 From 64ddb390efb2143f11c1583d52c78da5a290e097 Mon Sep 17 00:00:00 2001 From: memoryleak47 Date: Thu, 5 Apr 2018 13:04:00 +0200 Subject: typos --- src/libstd/lib.rs | 2 +- src/libstd/panic.rs | 2 +- src/libstd/sys/windows/pipe.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 36eb7291822..67ef47569d6 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -380,7 +380,7 @@ extern crate compiler_builtins; // During testing, this crate is not actually the "real" std library, but rather // it links to the real std library, which was compiled from this same source // code. So any lang items std defines are conditionally excluded (or else they -// wolud generate duplicate lang item errors), and any globals it defines are +// would generate duplicate lang item errors), and any globals it defines are // _not_ the globals used by "real" std. So this import, defined only during // testing gives test-std access to real-std lang items and globals. See #2912 #[cfg(test)] extern crate std as realstd; diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index 79857104b9b..28c178307a5 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -188,7 +188,7 @@ pub struct AssertUnwindSafe( // * By default everything is unwind safe // * pointers T contains mutability of some form are not unwind safe // * Unique, an owning pointer, lifts an implementation -// * Types like Mutex/RwLock which are explicilty poisoned are unwind safe +// * Types like Mutex/RwLock which are explicitly poisoned are unwind safe // * Our custom AssertUnwindSafe wrapper is indeed unwind safe #[stable(feature = "catch_unwind", since = "1.9.0")] diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index f3b1185c6ea..df1dd7401af 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -236,7 +236,7 @@ enum State { impl<'a> AsyncPipe<'a> { fn new(pipe: Handle, dst: &'a mut Vec) -> io::Result> { // Create an event which we'll use to coordinate our overlapped - // opreations, this event will be used in WaitForMultipleObjects + // operations, this event will be used in WaitForMultipleObjects // and passed as part of the OVERLAPPED handle. // // Note that we do a somewhat clever thing here by flagging the -- cgit 1.4.1-3-g733a5 From 323f8087910b0d63815003970bb8a45e3ccfdb17 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Apr 2018 11:07:19 -0700 Subject: std: Inline some Termination-related methods These were showing up in tests and in binaries but are trivially optimize-able away, so add `#[inline]` attributes so LLVM has an opportunity to optimize them out. --- src/libstd/process.rs | 2 ++ src/libstd/sys/unix/process/process_common.rs | 1 + src/libstd/sys/windows/process.rs | 1 + 3 files changed, 4 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 40bc84f4bc1..92f0406c09b 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1452,6 +1452,7 @@ pub trait Termination { #[unstable(feature = "termination_trait_lib", issue = "43301")] impl Termination for () { + #[inline] fn report(self) -> i32 { ExitCode::SUCCESS.report() } } @@ -1481,6 +1482,7 @@ impl Termination for Result { #[unstable(feature = "termination_trait_lib", issue = "43301")] impl Termination for ExitCode { + #[inline] fn report(self) -> i32 { self.0.as_i32() } diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index b7f30600b8a..6396bb3a49e 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -404,6 +404,7 @@ impl ExitCode { pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _); pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _); + #[inline] pub fn as_i32(&self) -> i32 { self.0 as i32 } diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index afa8e3e1369..bd5507e8f89 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -414,6 +414,7 @@ impl ExitCode { pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _); pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _); + #[inline] pub fn as_i32(&self) -> i32 { self.0 as i32 } -- cgit 1.4.1-3-g733a5 From 7ab31f6556c2cce433695b113f53d6275edd724d Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 10 Apr 2018 23:55:41 +0100 Subject: Prevent EPIPE causing ICEs in rustc and rustdoc --- src/librustc_driver/lib.rs | 12 ++++++++++++ src/librustdoc/lib.rs | 1 + src/libstd/sys/unix/mod.rs | 4 ++-- src/rustc/rustc.rs | 5 ++++- 4 files changed, 19 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 6f88b0aecb6..4f23c62ab06 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -548,6 +548,18 @@ fn run_compiler_impl<'a>(args: &[String], (result, Some(sess)) } +#[cfg(unix)] +pub fn set_sigpipe_handler() { + unsafe { + // Set the SIGPIPE signal handler, so that an EPIPE + // will cause rustc to terminate, as expected. + assert!(libc::signal(libc::SIGPIPE, libc::SIG_DFL) != libc::SIG_ERR); + } +} + +#[cfg(windows)] +pub fn set_sigpipe_handler() {} + // Extract output directory and file from matches. fn make_output(matches: &getopts::Matches) -> (Option, Option) { let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o)); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 42e87f88fd4..1e51f45f149 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -101,6 +101,7 @@ struct Output { pub fn main() { const STACK_SIZE: usize = 32_000_000; // 32MB + rustc_driver::set_sigpipe_handler(); env_logger::init(); let res = std::thread::Builder::new().stack_size(STACK_SIZE).spawn(move || { syntax::with_globals(move || { diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 9bdea945ea4..c1298e5040d 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -80,11 +80,11 @@ pub fn init() { reset_sigpipe(); } - #[cfg(not(any(target_os = "emscripten", target_os="fuchsia")))] + #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia")))] unsafe fn reset_sigpipe() { assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR); } - #[cfg(any(target_os = "emscripten", target_os="fuchsia"))] + #[cfg(any(target_os = "emscripten", target_os = "fuchsia"))] unsafe fn reset_sigpipe() {} } diff --git a/src/rustc/rustc.rs b/src/rustc/rustc.rs index 9fa33f911a1..c07fb41d13b 100644 --- a/src/rustc/rustc.rs +++ b/src/rustc/rustc.rs @@ -22,4 +22,7 @@ extern {} extern crate rustc_driver; -fn main() { rustc_driver::main() } +fn main() { + rustc_driver::set_sigpipe_handler(); + rustc_driver::main() +} -- cgit 1.4.1-3-g733a5 From f87d4a15a82a76e7510629173c366d084f2c02ca Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 5 Apr 2018 15:55:28 +0200 Subject: Move Utf8Lossy decoder to libcore --- src/liballoc/string.rs | 2 +- src/libcore/str/lossy.rs | 212 +++++++++++++++++++++++++++++++++++ src/libcore/str/mod.rs | 4 + src/libcore/tests/lib.rs | 2 + src/libcore/tests/str_lossy.rs | 91 +++++++++++++++ src/libstd/sys/redox/os_str.rs | 2 +- src/libstd/sys/unix/os_str.rs | 2 +- src/libstd/sys/wasm/os_str.rs | 2 +- src/libstd/sys_common/bytestring.rs | 2 +- src/libstd_unicode/Cargo.toml | 4 - src/libstd_unicode/lib.rs | 1 - src/libstd_unicode/lossy.rs | 213 ------------------------------------ src/libstd_unicode/tests/lib.rs | 15 --- src/libstd_unicode/tests/lossy.rs | 91 --------------- 14 files changed, 314 insertions(+), 329 deletions(-) create mode 100644 src/libcore/str/lossy.rs create mode 100644 src/libcore/tests/str_lossy.rs delete mode 100644 src/libstd_unicode/lossy.rs delete mode 100644 src/libstd_unicode/tests/lib.rs delete mode 100644 src/libstd_unicode/tests/lossy.rs (limited to 'src/libstd/sys') diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index b95aae02894..5f90e28cb3c 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -63,7 +63,7 @@ use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops::{self, Add, AddAssign, Index, IndexMut, RangeBounds}; use core::ptr; use core::str::pattern::Pattern; -use std_unicode::lossy; +use core::str::lossy; use std_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER}; use borrow::{Cow, ToOwned}; diff --git a/src/libcore/str/lossy.rs b/src/libcore/str/lossy.rs new file mode 100644 index 00000000000..30b7267da7c --- /dev/null +++ b/src/libcore/str/lossy.rs @@ -0,0 +1,212 @@ +// Copyright 2012-2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use char; +use str as core_str; +use fmt; +use fmt::Write; +use mem; + +/// Lossy UTF-8 string. +#[unstable(feature = "str_internals", issue = "0")] +pub struct Utf8Lossy { + bytes: [u8] +} + +impl Utf8Lossy { + pub fn from_str(s: &str) -> &Utf8Lossy { + Utf8Lossy::from_bytes(s.as_bytes()) + } + + pub fn from_bytes(bytes: &[u8]) -> &Utf8Lossy { + unsafe { mem::transmute(bytes) } + } + + pub fn chunks(&self) -> Utf8LossyChunksIter { + Utf8LossyChunksIter { source: &self.bytes } + } +} + + +/// Iterator over lossy UTF-8 string +#[unstable(feature = "str_internals", issue = "0")] +#[allow(missing_debug_implementations)] +pub struct Utf8LossyChunksIter<'a> { + source: &'a [u8], +} + +#[unstable(feature = "str_internals", issue = "0")] +#[derive(PartialEq, Eq, Debug)] +pub struct Utf8LossyChunk<'a> { + /// Sequence of valid chars. + /// Can be empty between broken UTF-8 chars. + pub valid: &'a str, + /// Single broken char, empty if none. + /// Empty iff iterator item is last. + pub broken: &'a [u8], +} + +impl<'a> Iterator for Utf8LossyChunksIter<'a> { + type Item = Utf8LossyChunk<'a>; + + fn next(&mut self) -> Option> { + if self.source.len() == 0 { + return None; + } + + const TAG_CONT_U8: u8 = 128; + fn unsafe_get(xs: &[u8], i: usize) -> u8 { + unsafe { *xs.get_unchecked(i) } + } + fn safe_get(xs: &[u8], i: usize) -> u8 { + if i >= xs.len() { 0 } else { unsafe_get(xs, i) } + } + + let mut i = 0; + while i < self.source.len() { + let i_ = i; + + let byte = unsafe_get(self.source, i); + i += 1; + + if byte < 128 { + + } else { + let w = core_str::utf8_char_width(byte); + + macro_rules! error { () => ({ + unsafe { + let r = Utf8LossyChunk { + valid: core_str::from_utf8_unchecked(&self.source[0..i_]), + broken: &self.source[i_..i], + }; + self.source = &self.source[i..]; + return Some(r); + } + })} + + match w { + 2 => { + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + error!(); + } + i += 1; + } + 3 => { + match (byte, safe_get(self.source, i)) { + (0xE0, 0xA0 ... 0xBF) => (), + (0xE1 ... 0xEC, 0x80 ... 0xBF) => (), + (0xED, 0x80 ... 0x9F) => (), + (0xEE ... 0xEF, 0x80 ... 0xBF) => (), + _ => { + error!(); + } + } + i += 1; + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + error!(); + } + i += 1; + } + 4 => { + match (byte, safe_get(self.source, i)) { + (0xF0, 0x90 ... 0xBF) => (), + (0xF1 ... 0xF3, 0x80 ... 0xBF) => (), + (0xF4, 0x80 ... 0x8F) => (), + _ => { + error!(); + } + } + i += 1; + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + error!(); + } + i += 1; + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + error!(); + } + i += 1; + } + _ => { + error!(); + } + } + } + } + + let r = Utf8LossyChunk { + valid: unsafe { core_str::from_utf8_unchecked(self.source) }, + broken: &[], + }; + self.source = &[]; + return Some(r); + } +} + + +impl fmt::Display for Utf8Lossy { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // If we're the empty string then our iterator won't actually yield + // anything, so perform the formatting manually + if self.bytes.len() == 0 { + return "".fmt(f) + } + + for Utf8LossyChunk { valid, broken } in self.chunks() { + // If we successfully decoded the whole chunk as a valid string then + // we can return a direct formatting of the string which will also + // respect various formatting flags if possible. + if valid.len() == self.bytes.len() { + assert!(broken.is_empty()); + return valid.fmt(f) + } + + f.write_str(valid)?; + if !broken.is_empty() { + f.write_char(char::REPLACEMENT_CHARACTER)?; + } + } + Ok(()) + } +} + +impl fmt::Debug for Utf8Lossy { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_char('"')?; + + for Utf8LossyChunk { valid, broken } in self.chunks() { + + // Valid part. + // Here we partially parse UTF-8 again which is suboptimal. + { + let mut from = 0; + for (i, c) in valid.char_indices() { + let esc = c.escape_debug(); + // If char needs escaping, flush backlog so far and write, else skip + if esc.len() != 1 { + f.write_str(&valid[from..i])?; + for c in esc { + f.write_char(c)?; + } + from = i + c.len_utf8(); + } + } + f.write_str(&valid[from..])?; + } + + // Broken parts of string as hex escape. + for &b in broken { + write!(f, "\\x{:02x}", b)?; + } + } + + f.write_char('"') + } +} diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 1185b7acaae..7a97d89dcf9 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -26,6 +26,10 @@ use mem; pub mod pattern; +#[unstable(feature = "str_internals", issue = "0")] +#[allow(missing_docs)] +pub mod lossy; + /// A trait to abstract the idea of creating a new instance of a type from a /// string. /// diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index c3162899bbd..149269263dc 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -33,6 +33,7 @@ #![feature(sort_internals)] #![feature(specialization)] #![feature(step_trait)] +#![feature(str_internals)] #![feature(test)] #![feature(trusted_len)] #![feature(try_trait)] @@ -68,4 +69,5 @@ mod ptr; mod result; mod slice; mod str; +mod str_lossy; mod tuple; diff --git a/src/libcore/tests/str_lossy.rs b/src/libcore/tests/str_lossy.rs new file mode 100644 index 00000000000..69e28256da9 --- /dev/null +++ b/src/libcore/tests/str_lossy.rs @@ -0,0 +1,91 @@ +// Copyright 2012-2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::str::lossy::*; + +#[test] +fn chunks() { + let mut iter = Utf8Lossy::from_bytes(b"hello").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "hello", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes("ศไทย中华Việt Nam".as_bytes()).chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "ศไทย中华Việt Nam", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"Hello\xC2 There\xFF Goodbye").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC2", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xFF", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC0", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xE6\x83", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"\xF5foo\xF5\x80bar").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF5", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF5", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"\xF1foo\xF1\x80bar\xF1\x80\x80baz").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF1", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF1\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF1\x80\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"\xF4foo\xF4\x80bar\xF4\xBFbaz").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF4", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF4\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF4", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF0", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo\u{10000}bar", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + // surrogates + let mut iter = Utf8Lossy::from_bytes(b"\xED\xA0\x80foo\xED\xBF\xBFbar").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xED", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xA0", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xED", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); +} + +#[test] +fn display() { + assert_eq!( + "Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye", + &format!("{}", Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye"))); +} + +#[test] +fn debug() { + assert_eq!( + "\"Hello\\xc0\\x80 There\\xe6\\x83 Goodbye\\u{10d4ea}\"", + &format!("{:?}", Utf8Lossy::from_bytes( + b"Hello\xC0\x80 There\xE6\x83 Goodbye\xf4\x8d\x93\xaa"))); +} diff --git a/src/libstd/sys/redox/os_str.rs b/src/libstd/sys/redox/os_str.rs index da27787babb..eb3a1ead58c 100644 --- a/src/libstd/sys/redox/os_str.rs +++ b/src/libstd/sys/redox/os_str.rs @@ -19,7 +19,7 @@ use rc::Rc; use sync::Arc; use sys_common::{AsInner, IntoInner}; use sys_common::bytestring::debug_fmt_bytestring; -use std_unicode::lossy::Utf8Lossy; +use core::str::lossy::Utf8Lossy; #[derive(Clone, Hash)] pub struct Buf { diff --git a/src/libstd/sys/unix/os_str.rs b/src/libstd/sys/unix/os_str.rs index e43bc6da5f1..01c0fb830aa 100644 --- a/src/libstd/sys/unix/os_str.rs +++ b/src/libstd/sys/unix/os_str.rs @@ -19,7 +19,7 @@ use rc::Rc; use sync::Arc; use sys_common::{AsInner, IntoInner}; use sys_common::bytestring::debug_fmt_bytestring; -use std_unicode::lossy::Utf8Lossy; +use core::str::lossy::Utf8Lossy; #[derive(Clone, Hash)] pub struct Buf { diff --git a/src/libstd/sys/wasm/os_str.rs b/src/libstd/sys/wasm/os_str.rs index 84f560af69b..e0da5bdf36c 100644 --- a/src/libstd/sys/wasm/os_str.rs +++ b/src/libstd/sys/wasm/os_str.rs @@ -19,7 +19,7 @@ use rc::Rc; use sync::Arc; use sys_common::{AsInner, IntoInner}; use sys_common::bytestring::debug_fmt_bytestring; -use std_unicode::lossy::Utf8Lossy; +use core::str::lossy::Utf8Lossy; #[derive(Clone, Hash)] pub struct Buf { diff --git a/src/libstd/sys_common/bytestring.rs b/src/libstd/sys_common/bytestring.rs index eb9cad09915..971b83938c1 100644 --- a/src/libstd/sys_common/bytestring.rs +++ b/src/libstd/sys_common/bytestring.rs @@ -11,7 +11,7 @@ #![allow(dead_code)] use fmt::{Formatter, Result, Write}; -use std_unicode::lossy::{Utf8Lossy, Utf8LossyChunk}; +use core::str::lossy::{Utf8Lossy, Utf8LossyChunk}; pub fn debug_fmt_bytestring(slice: &[u8], f: &mut Formatter) -> Result { // Writes out a valid unicode string with the correct escape sequences diff --git a/src/libstd_unicode/Cargo.toml b/src/libstd_unicode/Cargo.toml index 283070a0e2c..b1c55c2e4b6 100644 --- a/src/libstd_unicode/Cargo.toml +++ b/src/libstd_unicode/Cargo.toml @@ -9,10 +9,6 @@ path = "lib.rs" test = false bench = false -[[test]] -name = "std_unicode_tests" -path = "tests/lib.rs" - [dependencies] core = { path = "../libcore" } compiler_builtins = { path = "../rustc/compiler_builtins_shim" } diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs index cf8c101a2f9..106a2c0f0c5 100644 --- a/src/libstd_unicode/lib.rs +++ b/src/libstd_unicode/lib.rs @@ -45,7 +45,6 @@ mod tables; mod u_str; mod version; pub mod char; -pub mod lossy; #[allow(deprecated)] pub mod str { diff --git a/src/libstd_unicode/lossy.rs b/src/libstd_unicode/lossy.rs deleted file mode 100644 index cc8e93308a5..00000000000 --- a/src/libstd_unicode/lossy.rs +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright 2012-2017 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use core::str as core_str; -use core::fmt; -use core::fmt::Write; -use char; -use core::mem; - - -/// Lossy UTF-8 string. -#[unstable(feature = "str_internals", issue = "0")] -pub struct Utf8Lossy { - bytes: [u8] -} - -impl Utf8Lossy { - pub fn from_str(s: &str) -> &Utf8Lossy { - Utf8Lossy::from_bytes(s.as_bytes()) - } - - pub fn from_bytes(bytes: &[u8]) -> &Utf8Lossy { - unsafe { mem::transmute(bytes) } - } - - pub fn chunks(&self) -> Utf8LossyChunksIter { - Utf8LossyChunksIter { source: &self.bytes } - } -} - - -/// Iterator over lossy UTF-8 string -#[unstable(feature = "str_internals", issue = "0")] -#[allow(missing_debug_implementations)] -pub struct Utf8LossyChunksIter<'a> { - source: &'a [u8], -} - -#[unstable(feature = "str_internals", issue = "0")] -#[derive(PartialEq, Eq, Debug)] -pub struct Utf8LossyChunk<'a> { - /// Sequence of valid chars. - /// Can be empty between broken UTF-8 chars. - pub valid: &'a str, - /// Single broken char, empty if none. - /// Empty iff iterator item is last. - pub broken: &'a [u8], -} - -impl<'a> Iterator for Utf8LossyChunksIter<'a> { - type Item = Utf8LossyChunk<'a>; - - fn next(&mut self) -> Option> { - if self.source.len() == 0 { - return None; - } - - const TAG_CONT_U8: u8 = 128; - fn unsafe_get(xs: &[u8], i: usize) -> u8 { - unsafe { *xs.get_unchecked(i) } - } - fn safe_get(xs: &[u8], i: usize) -> u8 { - if i >= xs.len() { 0 } else { unsafe_get(xs, i) } - } - - let mut i = 0; - while i < self.source.len() { - let i_ = i; - - let byte = unsafe_get(self.source, i); - i += 1; - - if byte < 128 { - - } else { - let w = core_str::utf8_char_width(byte); - - macro_rules! error { () => ({ - unsafe { - let r = Utf8LossyChunk { - valid: core_str::from_utf8_unchecked(&self.source[0..i_]), - broken: &self.source[i_..i], - }; - self.source = &self.source[i..]; - return Some(r); - } - })} - - match w { - 2 => { - if safe_get(self.source, i) & 192 != TAG_CONT_U8 { - error!(); - } - i += 1; - } - 3 => { - match (byte, safe_get(self.source, i)) { - (0xE0, 0xA0 ... 0xBF) => (), - (0xE1 ... 0xEC, 0x80 ... 0xBF) => (), - (0xED, 0x80 ... 0x9F) => (), - (0xEE ... 0xEF, 0x80 ... 0xBF) => (), - _ => { - error!(); - } - } - i += 1; - if safe_get(self.source, i) & 192 != TAG_CONT_U8 { - error!(); - } - i += 1; - } - 4 => { - match (byte, safe_get(self.source, i)) { - (0xF0, 0x90 ... 0xBF) => (), - (0xF1 ... 0xF3, 0x80 ... 0xBF) => (), - (0xF4, 0x80 ... 0x8F) => (), - _ => { - error!(); - } - } - i += 1; - if safe_get(self.source, i) & 192 != TAG_CONT_U8 { - error!(); - } - i += 1; - if safe_get(self.source, i) & 192 != TAG_CONT_U8 { - error!(); - } - i += 1; - } - _ => { - error!(); - } - } - } - } - - let r = Utf8LossyChunk { - valid: unsafe { core_str::from_utf8_unchecked(self.source) }, - broken: &[], - }; - self.source = &[]; - return Some(r); - } -} - - -impl fmt::Display for Utf8Lossy { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // If we're the empty string then our iterator won't actually yield - // anything, so perform the formatting manually - if self.bytes.len() == 0 { - return "".fmt(f) - } - - for Utf8LossyChunk { valid, broken } in self.chunks() { - // If we successfully decoded the whole chunk as a valid string then - // we can return a direct formatting of the string which will also - // respect various formatting flags if possible. - if valid.len() == self.bytes.len() { - assert!(broken.is_empty()); - return valid.fmt(f) - } - - f.write_str(valid)?; - if !broken.is_empty() { - f.write_char(char::REPLACEMENT_CHARACTER)?; - } - } - Ok(()) - } -} - -impl fmt::Debug for Utf8Lossy { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_char('"')?; - - for Utf8LossyChunk { valid, broken } in self.chunks() { - - // Valid part. - // Here we partially parse UTF-8 again which is suboptimal. - { - let mut from = 0; - for (i, c) in valid.char_indices() { - let esc = c.escape_debug(); - // If char needs escaping, flush backlog so far and write, else skip - if esc.len() != 1 { - f.write_str(&valid[from..i])?; - for c in esc { - f.write_char(c)?; - } - from = i + c.len_utf8(); - } - } - f.write_str(&valid[from..])?; - } - - // Broken parts of string as hex escape. - for &b in broken { - write!(f, "\\x{:02x}", b)?; - } - } - - f.write_char('"') - } -} diff --git a/src/libstd_unicode/tests/lib.rs b/src/libstd_unicode/tests/lib.rs deleted file mode 100644 index 9535ec18763..00000000000 --- a/src/libstd_unicode/tests/lib.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2012-2017 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(str_internals, unicode)] - -extern crate std_unicode; - -mod lossy; diff --git a/src/libstd_unicode/tests/lossy.rs b/src/libstd_unicode/tests/lossy.rs deleted file mode 100644 index e05d0668556..00000000000 --- a/src/libstd_unicode/tests/lossy.rs +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2012-2017 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std_unicode::lossy::*; - -#[test] -fn chunks() { - let mut iter = Utf8Lossy::from_bytes(b"hello").chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "hello", broken: b"", }), iter.next()); - assert_eq!(None, iter.next()); - - let mut iter = Utf8Lossy::from_bytes("ศไทย中华Việt Nam".as_bytes()).chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "ศไทย中华Việt Nam", broken: b"", }), iter.next()); - assert_eq!(None, iter.next()); - - let mut iter = Utf8Lossy::from_bytes(b"Hello\xC2 There\xFF Goodbye").chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC2", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xFF", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"", }), iter.next()); - assert_eq!(None, iter.next()); - - let mut iter = Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye").chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC0", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xE6\x83", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"", }), iter.next()); - assert_eq!(None, iter.next()); - - let mut iter = Utf8Lossy::from_bytes(b"\xF5foo\xF5\x80bar").chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF5", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF5", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"", }), iter.next()); - assert_eq!(None, iter.next()); - - let mut iter = Utf8Lossy::from_bytes(b"\xF1foo\xF1\x80bar\xF1\x80\x80baz").chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF1", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF1\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF1\x80\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"", }), iter.next()); - assert_eq!(None, iter.next()); - - let mut iter = Utf8Lossy::from_bytes(b"\xF4foo\xF4\x80bar\xF4\xBFbaz").chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF4", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF4\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF4", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"", }), iter.next()); - assert_eq!(None, iter.next()); - - let mut iter = Utf8Lossy::from_bytes(b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar").chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF0", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "foo\u{10000}bar", broken: b"", }), iter.next()); - assert_eq!(None, iter.next()); - - // surrogates - let mut iter = Utf8Lossy::from_bytes(b"\xED\xA0\x80foo\xED\xBF\xBFbar").chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xED", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xA0", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xED", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"", }), iter.next()); - assert_eq!(None, iter.next()); -} - -#[test] -fn display() { - assert_eq!( - "Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye", - &format!("{}", Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye"))); -} - -#[test] -fn debug() { - assert_eq!( - "\"Hello\\xc0\\x80 There\\xe6\\x83 Goodbye\\u{10d4ea}\"", - &format!("{:?}", Utf8Lossy::from_bytes( - b"Hello\xC0\x80 There\xE6\x83 Goodbye\xf4\x8d\x93\xaa"))); -} -- cgit 1.4.1-3-g733a5 From 1b895d8b88413f72230fbc0f00c67328870a2e9a Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 3 Apr 2018 14:36:57 +0200 Subject: Import the `alloc` crate as `alloc_crate` in std MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … to make the name `alloc` available. --- src/libstd/collections/hash/map.rs | 4 +--- src/libstd/collections/hash/table.rs | 5 +---- src/libstd/collections/mod.rs | 10 +++++----- src/libstd/error.rs | 10 +++++----- src/libstd/heap.rs | 2 +- src/libstd/lib.rs | 18 +++++++++--------- src/libstd/sync/mod.rs | 2 +- src/libstd/sync/mpsc/mpsc_queue.rs | 3 +-- src/libstd/sync/mpsc/spsc_queue.rs | 2 +- src/libstd/sys/cloudabi/thread.rs | 2 +- src/libstd/sys/redox/thread.rs | 2 +- src/libstd/sys/unix/thread.rs | 2 +- src/libstd/sys/wasm/thread.rs | 2 +- src/libstd/sys/windows/process.rs | 2 +- src/libstd/sys/windows/thread.rs | 2 +- src/libstd/sys_common/at_exit_imp.rs | 2 +- src/libstd/sys_common/process.rs | 2 +- src/libstd/sys_common/thread.rs | 2 +- 18 files changed, 34 insertions(+), 40 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index e0b48e565d0..73a5df8dc28 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -11,15 +11,13 @@ use self::Entry::*; use self::VacantEntryState::*; -use alloc::heap::Heap; -use alloc::allocator::CollectionAllocErr; use cell::Cell; -use core::heap::Alloc; use borrow::Borrow; use cmp::max; use fmt::{self, Debug}; #[allow(deprecated)] use hash::{Hash, Hasher, BuildHasher, SipHasher13}; +use heap::{Heap, Alloc, CollectionAllocErr}; use iter::{FromIterator, FusedIterator}; use mem::{self, replace}; use ops::{Deref, Index}; diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index fa6053d3f6d..878cd82a258 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -8,17 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::heap::Heap; -use core::heap::{Alloc, Layout}; - use cmp; use hash::{BuildHasher, Hash, Hasher}; +use heap::{Heap, Alloc, Layout, CollectionAllocErr}; use marker; use mem::{align_of, size_of, needs_drop}; use mem; use ops::{Deref, DerefMut}; use ptr::{self, Unique, NonNull}; -use alloc::allocator::CollectionAllocErr; use self::BucketState::*; diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index c7ad27d8d26..9cf73824dea 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -424,13 +424,13 @@ #[doc(hidden)] pub use ops::Bound; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::{BinaryHeap, BTreeMap, BTreeSet}; +pub use alloc_crate::{BinaryHeap, BTreeMap, BTreeSet}; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::{LinkedList, VecDeque}; +pub use alloc_crate::{LinkedList, VecDeque}; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::{binary_heap, btree_map, btree_set}; +pub use alloc_crate::{binary_heap, btree_map, btree_set}; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::{linked_list, vec_deque}; +pub use alloc_crate::{linked_list, vec_deque}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::hash_map::HashMap; @@ -446,7 +446,7 @@ pub mod range { } #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] -pub use alloc::allocator::CollectionAllocErr; +pub use heap::CollectionAllocErr; mod hash; diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 3d0c96585b5..4edb897350e 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -51,13 +51,13 @@ // coherence challenge (e.g., specialization, neg impls, etc) we can // reconsider what crate these items belong in. -use alloc::allocator; use any::TypeId; use borrow::Cow; use cell; use char; use core::array; use fmt::{self, Debug, Display}; +use heap::{AllocErr, CannotReallocInPlace}; use mem::transmute; use num; use str; @@ -241,18 +241,18 @@ impl Error for ! { #[unstable(feature = "allocator_api", reason = "the precise API and guarantees it provides may be tweaked.", issue = "32838")] -impl Error for allocator::AllocErr { +impl Error for AllocErr { fn description(&self) -> &str { - allocator::AllocErr::description(self) + AllocErr::description(self) } } #[unstable(feature = "allocator_api", reason = "the precise API and guarantees it provides may be tweaked.", issue = "32838")] -impl Error for allocator::CannotReallocInPlace { +impl Error for CannotReallocInPlace { fn description(&self) -> &str { - allocator::CannotReallocInPlace::description(self) + CannotReallocInPlace::description(self) } } diff --git a/src/libstd/heap.rs b/src/libstd/heap.rs index 2cf06018087..b42a1052c49 100644 --- a/src/libstd/heap.rs +++ b/src/libstd/heap.rs @@ -12,7 +12,7 @@ #![unstable(issue = "32838", feature = "allocator_api")] -pub use alloc::heap::Heap; +pub use alloc_crate::heap::Heap; pub use alloc_system::System; #[doc(inline)] pub use core::heap::*; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index c82d600e4a1..ef4205e7a62 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -351,7 +351,7 @@ extern crate core as __core; #[macro_use] #[macro_reexport(vec, format)] -extern crate alloc; +extern crate alloc as alloc_crate; extern crate alloc_system; #[doc(masked)] extern crate libc; @@ -437,21 +437,21 @@ pub use core::u32; #[stable(feature = "rust1", since = "1.0.0")] pub use core::u64; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::boxed; +pub use alloc_crate::boxed; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::rc; +pub use alloc_crate::rc; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::borrow; +pub use alloc_crate::borrow; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::fmt; +pub use alloc_crate::fmt; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::slice; +pub use alloc_crate::slice; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::str; +pub use alloc_crate::str; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::string; +pub use alloc_crate::string; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::vec; +pub use alloc_crate::vec; #[stable(feature = "rust1", since = "1.0.0")] pub use core::char; #[stable(feature = "i128", since = "1.26.0")] diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index 289b47b3484..642b284c6c7 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -18,7 +18,7 @@ #![stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::arc::{Arc, Weak}; +pub use alloc_crate::arc::{Arc, Weak}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::sync::atomic; diff --git a/src/libstd/sync/mpsc/mpsc_queue.rs b/src/libstd/sync/mpsc/mpsc_queue.rs index 296773d20f6..df945ac3859 100644 --- a/src/libstd/sync/mpsc/mpsc_queue.rs +++ b/src/libstd/sync/mpsc/mpsc_queue.rs @@ -23,10 +23,9 @@ pub use self::PopResult::*; -use alloc::boxed::Box; use core::ptr; use core::cell::UnsafeCell; - +use boxed::Box; use sync::atomic::{AtomicPtr, Ordering}; /// A result of the `pop` function. diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs index cc4be92276a..9482f6958b3 100644 --- a/src/libstd/sync/mpsc/spsc_queue.rs +++ b/src/libstd/sync/mpsc/spsc_queue.rs @@ -16,7 +16,7 @@ // http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue -use alloc::boxed::Box; +use boxed::Box; use core::ptr; use core::cell::UnsafeCell; diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs index a22d9053b69..5d66936b2a4 100644 --- a/src/libstd/sys/cloudabi/thread.rs +++ b/src/libstd/sys/cloudabi/thread.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::boxed::FnBox; +use boxed::FnBox; use cmp; use ffi::CStr; use io; diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs index f20350269b7..110d46ca3ab 100644 --- a/src/libstd/sys/redox/thread.rs +++ b/src/libstd/sys/redox/thread.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::boxed::FnBox; +use boxed::FnBox; use ffi::CStr; use io; use mem; diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 2db3d4a5744..9e388808030 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::boxed::FnBox; +use boxed::FnBox; use cmp; use ffi::CStr; use io; diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs index 7345843b975..728e678a2e8 100644 --- a/src/libstd/sys/wasm/thread.rs +++ b/src/libstd/sys/wasm/thread.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::boxed::FnBox; +use boxed::FnBox; use ffi::CStr; use io; use sys::{unsupported, Void}; diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index bd5507e8f89..be442f41374 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -31,7 +31,7 @@ use sys::stdio; use sys::cvt; use sys_common::{AsInner, FromInner, IntoInner}; use sys_common::process::{CommandEnv, EnvKey}; -use alloc::borrow::Borrow; +use borrow::Borrow; //////////////////////////////////////////////////////////////////////////////// // Command diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 4b3d1b586b5..b6f63303dc2 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::boxed::FnBox; +use boxed::FnBox; use io; use ffi::CStr; use mem; diff --git a/src/libstd/sys_common/at_exit_imp.rs b/src/libstd/sys_common/at_exit_imp.rs index ce6fd4cb075..26da51c9825 100644 --- a/src/libstd/sys_common/at_exit_imp.rs +++ b/src/libstd/sys_common/at_exit_imp.rs @@ -12,7 +12,7 @@ //! //! Documentation can be found on the `rt::at_exit` function. -use alloc::boxed::FnBox; +use boxed::FnBox; use ptr; use sys_common::mutex::Mutex; diff --git a/src/libstd/sys_common/process.rs b/src/libstd/sys_common/process.rs index d0c5951bd6c..ddf0ebe603e 100644 --- a/src/libstd/sys_common/process.rs +++ b/src/libstd/sys_common/process.rs @@ -14,7 +14,7 @@ use ffi::{OsStr, OsString}; use env; use collections::BTreeMap; -use alloc::borrow::Borrow; +use borrow::Borrow; pub trait EnvKey: From + Into + diff --git a/src/libstd/sys_common/thread.rs b/src/libstd/sys_common/thread.rs index f1379b6ec63..da6f58ef6bb 100644 --- a/src/libstd/sys_common/thread.rs +++ b/src/libstd/sys_common/thread.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::boxed::FnBox; +use boxed::FnBox; use env; use sync::atomic::{self, Ordering}; use sys::stack_overflow; -- cgit 1.4.1-3-g733a5 From c3a5d6b130e27d7d7587f56581247d5b08c38594 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 29 Mar 2018 14:59:13 -0700 Subject: std: Minimize size of panicking on wasm This commit applies a few code size optimizations for the wasm target to the standard library, namely around panics. We notably know that in most configurations it's impossible for us to print anything in wasm32-unknown-unknown so we can skip larger portions of panicking that are otherwise simply informative. This allows us to get quite a nice size reduction. Finally we can also tweak where the allocation happens for the `Box` that we panic with. By only allocating once unwinding starts we can reduce the size of a panicking wasm module from 44k to 350 bytes. --- src/ci/docker/wasm32-unknown/Dockerfile | 6 ++ src/libcore/panic.rs | 10 ++++ src/libpanic_abort/lib.rs | 2 +- src/libpanic_unwind/lib.rs | 12 ++-- src/libstd/lib.rs | 1 + src/libstd/panicking.rs | 88 ++++++++++++++++++++++------- src/libstd/sys/cloudabi/stdio.rs | 4 ++ src/libstd/sys/redox/stdio.rs | 4 ++ src/libstd/sys/unix/stdio.rs | 4 ++ src/libstd/sys/wasm/rwlock.rs | 4 +- src/libstd/sys/wasm/stdio.rs | 4 ++ src/libstd/sys/windows/stdio.rs | 4 ++ src/libstd/sys_common/backtrace.rs | 13 ++--- src/libstd/sys_common/mod.rs | 14 +++-- src/libstd/sys_common/thread_local.rs | 4 +- src/libstd/sys_common/util.rs | 5 +- src/libstd/thread/local.rs | 41 +++++++++++++- src/libstd/thread/mod.rs | 3 + src/test/run-make/wasm-panic-small/Makefile | 11 ++++ src/test/run-make/wasm-panic-small/foo.rs | 16 ++++++ 20 files changed, 205 insertions(+), 45 deletions(-) create mode 100644 src/test/run-make/wasm-panic-small/Makefile create mode 100644 src/test/run-make/wasm-panic-small/foo.rs (limited to 'src/libstd/sys') diff --git a/src/ci/docker/wasm32-unknown/Dockerfile b/src/ci/docker/wasm32-unknown/Dockerfile index 853923ad947..56eda548071 100644 --- a/src/ci/docker/wasm32-unknown/Dockerfile +++ b/src/ci/docker/wasm32-unknown/Dockerfile @@ -25,6 +25,12 @@ ENV RUST_CONFIGURE_ARGS \ --set build.nodejs=/node-v9.2.0-linux-x64/bin/node \ --set rust.lld +# Some run-make tests have assertions about code size, and enabling debug +# assertions in libstd causes the binary to be much bigger than it would +# otherwise normally be. We already test libstd with debug assertions in lots of +# other contexts as well +ENV NO_DEBUG_ASSERTIONS=1 + ENV SCRIPT python2.7 /checkout/x.py test --target $TARGETS \ src/test/run-make \ src/test/ui \ diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs index 1720c9d8c60..37c79f2fafe 100644 --- a/src/libcore/panic.rs +++ b/src/libcore/panic.rs @@ -251,3 +251,13 @@ impl<'a> fmt::Display for Location<'a> { write!(formatter, "{}:{}:{}", self.file, self.line, self.col) } } + +/// An internal trait used by libstd to pass data from libstd to `panic_unwind` +/// and other panic runtimes. Not intended to be stabilized any time soon, do +/// not use. +#[unstable(feature = "std_internals", issue = "0")] +#[doc(hidden)] +pub unsafe trait BoxMeUp { + fn box_me_up(&mut self) -> *mut (Any + Send); + fn get(&self) -> &(Any + Send); +} diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index 43c5bbbc618..392bf17968f 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -52,7 +52,7 @@ pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8), // now hopefully. #[no_mangle] #[rustc_std_internal_symbol] -pub unsafe extern fn __rust_start_panic(_data: usize, _vtable: usize) -> u32 { +pub unsafe extern fn __rust_start_panic(_payload: usize) -> u32 { abort(); #[cfg(any(unix, target_os = "cloudabi"))] diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 9321d6917d1..6c52c0fa10c 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -29,6 +29,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/", issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] +#![feature(allocator_api)] #![feature(alloc)] #![feature(core_intrinsics)] #![feature(lang_items)] @@ -36,6 +37,7 @@ #![feature(panic_unwind)] #![feature(raw)] #![feature(staged_api)] +#![feature(std_internals)] #![feature(unwind_attributes)] #![cfg_attr(target_env = "msvc", feature(raw))] @@ -47,9 +49,11 @@ extern crate libc; #[cfg(not(any(target_env = "msvc", all(windows, target_arch = "x86_64", target_env = "gnu"))))] extern crate unwind; +use alloc::boxed::Box; use core::intrinsics; use core::mem; use core::raw; +use core::panic::BoxMeUp; // Rust runtime's startup objects depend on these symbols, so make them public. #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))] @@ -112,9 +116,7 @@ pub unsafe extern "C" fn __rust_maybe_catch_panic(f: fn(*mut u8), // implementation. #[no_mangle] #[unwind(allowed)] -pub unsafe extern "C" fn __rust_start_panic(data: usize, vtable: usize) -> u32 { - imp::panic(mem::transmute(raw::TraitObject { - data: data as *mut (), - vtable: vtable as *mut (), - })) +pub unsafe extern "C" fn __rust_start_panic(payload: usize) -> u32 { + let payload = payload as *mut &mut BoxMeUp; + imp::panic(Box::from_raw((*payload).box_me_up())) } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index a34fcb5a7f9..dd96c57538c 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -292,6 +292,7 @@ #![feature(rand)] #![feature(raw)] #![feature(rustc_attrs)] +#![feature(std_internals)] #![feature(stdsimd)] #![feature(shrink_to)] #![feature(slice_bytes)] diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index fba3269204e..715fd45e490 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -17,6 +17,8 @@ //! * Executing a panic up to doing the actual implementation //! * Shims around "try" +use core::panic::BoxMeUp; + use io::prelude::*; use any::Any; @@ -27,7 +29,7 @@ use intrinsics; use mem; use ptr; use raw; -use sys::stdio::Stderr; +use sys::stdio::{Stderr, stderr_prints_nothing}; use sys_common::rwlock::RWLock; use sys_common::thread_info; use sys_common::util; @@ -56,7 +58,7 @@ extern { data_ptr: *mut usize, vtable_ptr: *mut usize) -> u32; #[unwind(allowed)] - fn __rust_start_panic(data: usize, vtable: usize) -> u32; + fn __rust_start_panic(payload: usize) -> u32; } #[derive(Copy, Clone)] @@ -163,6 +165,12 @@ fn default_hook(info: &PanicInfo) { #[cfg(feature = "backtrace")] use sys_common::backtrace; + // Some platforms know that printing to stderr won't ever actually print + // anything, and if that's the case we can skip everything below. + if stderr_prints_nothing() { + return + } + // If this is a double panic, make sure that we print a backtrace // for this panic. Otherwise only print it if logging is enabled. #[cfg(feature = "backtrace")] @@ -212,15 +220,15 @@ fn default_hook(info: &PanicInfo) { let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take()); match (prev, err.as_mut()) { - (Some(mut stderr), _) => { - write(&mut *stderr); - let mut s = Some(stderr); - LOCAL_STDERR.with(|slot| { - *slot.borrow_mut() = s.take(); - }); - } - (None, Some(ref mut err)) => { write(err) } - _ => {} + (Some(mut stderr), _) => { + write(&mut *stderr); + let mut s = Some(stderr); + LOCAL_STDERR.with(|slot| { + *slot.borrow_mut() = s.take(); + }); + } + (None, Some(ref mut err)) => { write(err) } + _ => {} } } @@ -344,7 +352,7 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments, let mut s = String::new(); let _ = s.write_fmt(*msg); - rust_panic_with_hook(Box::new(s), Some(msg), file_line_col) + rust_panic_with_hook(&mut PanicPayload::new(s), Some(msg), file_line_col) } /// This is the entry point of panicking for panic!() and assert!(). @@ -360,7 +368,34 @@ pub fn begin_panic(msg: M, file_line_col: &(&'static str, u32, u3 // be performed in the parent of this thread instead of the thread that's // panicking. - rust_panic_with_hook(Box::new(msg), None, file_line_col) + rust_panic_with_hook(&mut PanicPayload::new(msg), None, file_line_col) +} + +struct PanicPayload { + inner: Option, +} + +impl PanicPayload { + fn new(inner: A) -> PanicPayload { + PanicPayload { inner: Some(inner) } + } +} + +unsafe impl BoxMeUp for PanicPayload { + fn box_me_up(&mut self) -> *mut (Any + Send) { + let data = match self.inner.take() { + Some(a) => Box::new(a) as Box, + None => Box::new(()), + }; + Box::into_raw(data) + } + + fn get(&self) -> &(Any + Send) { + match self.inner { + Some(ref a) => a, + None => &(), + } + } } /// Executes the primary logic for a panic, including checking for recursive @@ -369,9 +404,7 @@ pub fn begin_panic(msg: M, file_line_col: &(&'static str, u32, u3 /// This is the entry point or panics from libcore, formatted panics, and /// `Box` panics. Here we'll verify that we're not panicking recursively, /// run panic hooks, and then delegate to the actual implementation of panics. -#[inline(never)] -#[cold] -fn rust_panic_with_hook(payload: Box, +fn rust_panic_with_hook(payload: &mut BoxMeUp, message: Option<&fmt::Arguments>, file_line_col: &(&'static str, u32, u32)) -> ! { let (file, line, col) = *file_line_col; @@ -391,7 +424,7 @@ fn rust_panic_with_hook(payload: Box, unsafe { let info = PanicInfo::internal_constructor( - &*payload, + payload.get(), message, Location::internal_constructor(file, line, col), ); @@ -419,16 +452,29 @@ fn rust_panic_with_hook(payload: Box, /// Shim around rust_panic. Called by resume_unwind. pub fn update_count_then_panic(msg: Box) -> ! { update_panic_count(1); - rust_panic(msg) + + struct RewrapBox(Box); + + unsafe impl BoxMeUp for RewrapBox { + fn box_me_up(&mut self) -> *mut (Any + Send) { + Box::into_raw(mem::replace(&mut self.0, Box::new(()))) + } + + fn get(&self) -> &(Any + Send) { + &*self.0 + } + } + + rust_panic(&mut RewrapBox(msg)) } /// A private no-mangle function on which to slap yer breakpoints. #[no_mangle] #[allow(private_no_mangle_fns)] // yes we get it, but we like breakpoints -pub fn rust_panic(msg: Box) -> ! { +pub fn rust_panic(mut msg: &mut BoxMeUp) -> ! { let code = unsafe { - let obj = mem::transmute::<_, raw::TraitObject>(msg); - __rust_start_panic(obj.data as usize, obj.vtable as usize) + let obj = &mut msg as *mut &mut BoxMeUp; + __rust_start_panic(obj as usize) }; rtabort!("failed to initiate panic, error {}", code) } diff --git a/src/libstd/sys/cloudabi/stdio.rs b/src/libstd/sys/cloudabi/stdio.rs index 9519a926471..1d7344f921c 100644 --- a/src/libstd/sys/cloudabi/stdio.rs +++ b/src/libstd/sys/cloudabi/stdio.rs @@ -77,3 +77,7 @@ pub fn is_ebadf(err: &io::Error) -> bool { } pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; + +pub fn stderr_prints_nothing() -> bool { + false +} diff --git a/src/libstd/sys/redox/stdio.rs b/src/libstd/sys/redox/stdio.rs index 3abb094ac34..7a4d11b0ecb 100644 --- a/src/libstd/sys/redox/stdio.rs +++ b/src/libstd/sys/redox/stdio.rs @@ -75,3 +75,7 @@ pub fn is_ebadf(err: &io::Error) -> bool { } pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; + +pub fn stderr_prints_nothing() -> bool { + false +} diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs index e9b3d4affc7..87ba2aef4f1 100644 --- a/src/libstd/sys/unix/stdio.rs +++ b/src/libstd/sys/unix/stdio.rs @@ -75,3 +75,7 @@ pub fn is_ebadf(err: &io::Error) -> bool { } pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; + +pub fn stderr_prints_nothing() -> bool { + false +} diff --git a/src/libstd/sys/wasm/rwlock.rs b/src/libstd/sys/wasm/rwlock.rs index 8b06f541674..6516010af47 100644 --- a/src/libstd/sys/wasm/rwlock.rs +++ b/src/libstd/sys/wasm/rwlock.rs @@ -30,7 +30,7 @@ impl RWLock { if *mode >= 0 { *mode += 1; } else { - panic!("rwlock locked for writing"); + rtabort!("rwlock locked for writing"); } } @@ -51,7 +51,7 @@ impl RWLock { if *mode == 0 { *mode = -1; } else { - panic!("rwlock locked for reading") + rtabort!("rwlock locked for reading") } } diff --git a/src/libstd/sys/wasm/stdio.rs b/src/libstd/sys/wasm/stdio.rs index beb19c0ed2c..023f29576a2 100644 --- a/src/libstd/sys/wasm/stdio.rs +++ b/src/libstd/sys/wasm/stdio.rs @@ -69,3 +69,7 @@ pub const STDIN_BUF_SIZE: usize = 0; pub fn is_ebadf(_err: &io::Error) -> bool { true } + +pub fn stderr_prints_nothing() -> bool { + !cfg!(feature = "wasm_syscall") +} diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index b43df20bddd..81b89da21d3 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -227,3 +227,7 @@ pub fn is_ebadf(err: &io::Error) -> bool { // idea is that on windows we use a slightly smaller buffer that's // been seen to be acceptable. pub const STDIN_BUF_SIZE: usize = 8 * 1024; + +pub fn stderr_prints_nothing() -> bool { + false +} diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 1955f3ec9a2..20109d2d0d5 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -139,10 +139,10 @@ pub fn __rust_begin_short_backtrace(f: F) -> T /// Controls how the backtrace should be formatted. #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum PrintFormat { - /// Show all the frames with absolute path for files. - Full = 2, /// Show only relevant data from the backtrace. - Short = 3, + Short = 2, + /// Show all the frames with absolute path for files. + Full = 3, } // For now logging is turned off by default, and this function checks to see @@ -150,11 +150,10 @@ pub enum PrintFormat { pub fn log_enabled() -> Option { static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(0); match ENABLED.load(Ordering::SeqCst) { - 0 => {}, + 0 => {} 1 => return None, - 2 => return Some(PrintFormat::Full), - 3 => return Some(PrintFormat::Short), - _ => unreachable!(), + 2 => return Some(PrintFormat::Short), + _ => return Some(PrintFormat::Full), } let val = match env::var_os("RUST_BACKTRACE") { diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index 27504d374dd..d0c4d6a7737 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -28,6 +28,16 @@ use sync::Once; use sys; +macro_rules! rtabort { + ($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*))) +} + +macro_rules! rtassert { + ($e:expr) => (if !$e { + rtabort!(concat!("assertion failed: ", stringify!($e))); + }) +} + pub mod at_exit_imp; #[cfg(feature = "backtrace")] pub mod backtrace; @@ -101,10 +111,6 @@ pub fn at_exit(f: F) -> Result<(), ()> { if at_exit_imp::push(Box::new(f)) {Ok(())} else {Err(())} } -macro_rules! rtabort { - ($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*))) -} - /// One-time runtime cleanup. pub fn cleanup() { static CLEANUP: Once = Once::new(); diff --git a/src/libstd/sys_common/thread_local.rs b/src/libstd/sys_common/thread_local.rs index a4aa3d96d25..d0d6224de0a 100644 --- a/src/libstd/sys_common/thread_local.rs +++ b/src/libstd/sys_common/thread_local.rs @@ -169,7 +169,7 @@ impl StaticKey { self.key.store(key, Ordering::SeqCst); } INIT_LOCK.unlock(); - assert!(key != 0); + rtassert!(key != 0); return key } @@ -190,7 +190,7 @@ impl StaticKey { imp::destroy(key1); key2 }; - assert!(key != 0); + rtassert!(key != 0); match self.key.compare_and_swap(0, key as usize, Ordering::SeqCst) { // The CAS succeeded, so we've created the actual key 0 => key as usize, diff --git a/src/libstd/sys_common/util.rs b/src/libstd/sys_common/util.rs index a391c7cc6ef..a373e980b97 100644 --- a/src/libstd/sys_common/util.rs +++ b/src/libstd/sys_common/util.rs @@ -10,10 +10,13 @@ use fmt; use io::prelude::*; -use sys::stdio::Stderr; +use sys::stdio::{Stderr, stderr_prints_nothing}; use thread; pub fn dumb_print(args: fmt::Arguments) { + if stderr_prints_nothing() { + return + } let _ = Stderr::new().map(|mut stderr| stderr.write_fmt(args)); } diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 99479bc56ef..40d3280baa6 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -172,12 +172,16 @@ macro_rules! __thread_local_inner { &'static $crate::cell::UnsafeCell< $crate::option::Option<$t>>> { + #[cfg(target_arch = "wasm32")] + static __KEY: $crate::thread::__StaticLocalKeyInner<$t> = + $crate::thread::__StaticLocalKeyInner::new(); + #[thread_local] - #[cfg(target_thread_local)] + #[cfg(all(target_thread_local, not(target_arch = "wasm32")))] static __KEY: $crate::thread::__FastLocalKeyInner<$t> = $crate::thread::__FastLocalKeyInner::new(); - #[cfg(not(target_thread_local))] + #[cfg(all(not(target_thread_local), not(target_arch = "wasm32")))] static __KEY: $crate::thread::__OsLocalKeyInner<$t> = $crate::thread::__OsLocalKeyInner::new(); @@ -295,6 +299,39 @@ impl LocalKey { } } +/// On some platforms like wasm32 there's no threads, so no need to generate +/// thread locals and we can instead just use plain statics! +#[doc(hidden)] +#[cfg(target_arch = "wasm32")] +pub mod statik { + use cell::UnsafeCell; + use fmt; + + pub struct Key { + inner: UnsafeCell>, + } + + unsafe impl ::marker::Sync for Key { } + + impl fmt::Debug for Key { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Key { .. }") + } + } + + impl Key { + pub const fn new() -> Key { + Key { + inner: UnsafeCell::new(None), + } + } + + pub unsafe fn get(&self) -> Option<&'static UnsafeCell>> { + Some(&*(&self.inner as *const _)) + } + } +} + #[doc(hidden)] #[cfg(target_thread_local)] pub mod fast { diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 71aee673cfe..1b976b79b4c 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -202,6 +202,9 @@ pub use self::local::{LocalKey, AccessError}; // where fast TLS was not available; end-user code is compiled with fast TLS // where available, but both are needed. +#[unstable(feature = "libstd_thread_internals", issue = "0")] +#[cfg(target_arch = "wasm32")] +#[doc(hidden)] pub use self::local::statik::Key as __StaticLocalKeyInner; #[unstable(feature = "libstd_thread_internals", issue = "0")] #[cfg(target_thread_local)] #[doc(hidden)] pub use self::local::fast::Key as __FastLocalKeyInner; diff --git a/src/test/run-make/wasm-panic-small/Makefile b/src/test/run-make/wasm-panic-small/Makefile new file mode 100644 index 00000000000..a11fba23595 --- /dev/null +++ b/src/test/run-make/wasm-panic-small/Makefile @@ -0,0 +1,11 @@ +-include ../../run-make-fulldeps/tools.mk + +ifeq ($(TARGET),wasm32-unknown-unknown) +all: + $(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown + wc -c < $(TMPDIR)/foo.wasm + [ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "1024" ] +else +all: +endif + diff --git a/src/test/run-make/wasm-panic-small/foo.rs b/src/test/run-make/wasm-panic-small/foo.rs new file mode 100644 index 00000000000..9654d5f7c09 --- /dev/null +++ b/src/test/run-make/wasm-panic-small/foo.rs @@ -0,0 +1,16 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "cdylib"] + +#[no_mangle] +pub fn foo() { + panic!("test"); +} -- cgit 1.4.1-3-g733a5 From 182d99cfd1a551b9daa3d7f6896775278fb2962e Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 9 Apr 2018 17:44:28 -0700 Subject: Add doc links to `std::os` extension traits Add documentation links to the original type for various OS-specific extension traits and normalize the language for introducing such traits. Also, remove some outdated comments around the extension trait definitions. --- src/libstd/os/android/fs.rs | 4 +++- src/libstd/os/bitrig/fs.rs | 4 +++- src/libstd/os/dragonfly/fs.rs | 4 +++- src/libstd/os/emscripten/fs.rs | 4 +++- src/libstd/os/freebsd/fs.rs | 4 +++- src/libstd/os/fuchsia/fs.rs | 4 +++- src/libstd/os/haiku/fs.rs | 4 +++- src/libstd/os/ios/fs.rs | 4 +++- src/libstd/os/linux/fs.rs | 4 +++- src/libstd/os/macos/fs.rs | 4 +++- src/libstd/os/netbsd/fs.rs | 4 +++- src/libstd/os/openbsd/fs.rs | 4 +++- src/libstd/os/solaris/fs.rs | 4 +++- src/libstd/sys/redox/ext/ffi.rs | 10 +++++++--- src/libstd/sys/redox/ext/fs.rs | 36 ++++++++++++++++++++++++----------- src/libstd/sys/redox/ext/process.rs | 10 +++++++--- src/libstd/sys/redox/ext/thread.rs | 6 ++++-- src/libstd/sys/unix/ext/ffi.rs | 8 ++++++-- src/libstd/sys/unix/ext/fs.rs | 33 ++++++++++++++++++-------------- src/libstd/sys/unix/ext/process.rs | 8 ++++++-- src/libstd/sys/unix/ext/thread.rs | 4 +++- src/libstd/sys/windows/ext/ffi.rs | 8 ++++++-- src/libstd/sys/windows/ext/fs.rs | 20 ++++++++++--------- src/libstd/sys/windows/ext/process.rs | 8 ++++++-- 24 files changed, 139 insertions(+), 64 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/os/android/fs.rs b/src/libstd/os/android/fs.rs index a51b4655985..5899dc688e2 100644 --- a/src/libstd/os/android/fs.rs +++ b/src/libstd/os/android/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::android::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/bitrig/fs.rs b/src/libstd/os/bitrig/fs.rs index e4f1c9432f3..24caf326ab0 100644 --- a/src/libstd/os/bitrig/fs.rs +++ b/src/libstd/os/bitrig/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::bitrig::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/dragonfly/fs.rs b/src/libstd/os/dragonfly/fs.rs index db672e56435..6aea450774f 100644 --- a/src/libstd/os/dragonfly/fs.rs +++ b/src/libstd/os/dragonfly/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::dragonfly::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/emscripten/fs.rs b/src/libstd/os/emscripten/fs.rs index 8056ce4fdc4..e0e197dc122 100644 --- a/src/libstd/os/emscripten/fs.rs +++ b/src/libstd/os/emscripten/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::emscripten::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/freebsd/fs.rs b/src/libstd/os/freebsd/fs.rs index 2f17d2f7409..5f24cd636d5 100644 --- a/src/libstd/os/freebsd/fs.rs +++ b/src/libstd/os/freebsd/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::freebsd::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/fuchsia/fs.rs b/src/libstd/os/fuchsia/fs.rs index d22f9a628bd..16802576356 100644 --- a/src/libstd/os/fuchsia/fs.rs +++ b/src/libstd/os/fuchsia/fs.rs @@ -13,7 +13,9 @@ use fs::Metadata; use sys_common::AsInner; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { #[stable(feature = "metadata_ext2", since = "1.8.0")] diff --git a/src/libstd/os/haiku/fs.rs b/src/libstd/os/haiku/fs.rs index 54f8ea1b71b..453136e0ac8 100644 --- a/src/libstd/os/haiku/fs.rs +++ b/src/libstd/os/haiku/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::haiku::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/ios/fs.rs b/src/libstd/os/ios/fs.rs index 275daf3d3a0..296ce69ff43 100644 --- a/src/libstd/os/ios/fs.rs +++ b/src/libstd/os/ios/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::ios::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/linux/fs.rs b/src/libstd/os/linux/fs.rs index 2be2fbcb2db..76fb10da850 100644 --- a/src/libstd/os/linux/fs.rs +++ b/src/libstd/os/linux/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::linux::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/macos/fs.rs b/src/libstd/os/macos/fs.rs index 12b44901d03..0b14c05cb55 100644 --- a/src/libstd/os/macos/fs.rs +++ b/src/libstd/os/macos/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::macos::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/netbsd/fs.rs b/src/libstd/os/netbsd/fs.rs index cd7d5fafd1c..e9cad33fee6 100644 --- a/src/libstd/os/netbsd/fs.rs +++ b/src/libstd/os/netbsd/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::netbsd::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/openbsd/fs.rs b/src/libstd/os/openbsd/fs.rs index cc812fcf12c..0f6b83b6e32 100644 --- a/src/libstd/os/openbsd/fs.rs +++ b/src/libstd/os/openbsd/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::openbsd::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/os/solaris/fs.rs b/src/libstd/os/solaris/fs.rs index 5dc43d03a86..19dce1ba34c 100644 --- a/src/libstd/os/solaris/fs.rs +++ b/src/libstd/os/solaris/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::solaris::raw; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Gain a reference to the underlying `stat` structure which contains diff --git a/src/libstd/sys/redox/ext/ffi.rs b/src/libstd/sys/redox/ext/ffi.rs index d59b4fc0b70..060edbd22e4 100644 --- a/src/libstd/sys/redox/ext/ffi.rs +++ b/src/libstd/sys/redox/ext/ffi.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Unix-specific extension to the primitives in the `std::ffi` module +//! Redox-specific extension to the primitives in the `std::ffi` module. #![stable(feature = "rust1", since = "1.0.0")] @@ -17,7 +17,9 @@ use mem; use sys::os_str::Buf; use sys_common::{FromInner, IntoInner, AsInner}; -/// Unix-specific extensions to `OsString`. +/// Redox-specific extensions to [`ffi::OsString`]. +/// +/// [`ffi::OsString`]: ../../../../std/ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStringExt { /// Creates an `OsString` from a byte vector. @@ -39,7 +41,9 @@ impl OsStringExt for OsString { } } -/// Unix-specific extensions to `OsStr`. +/// Redox-specific extensions to [`ffi::OsStr`]. +/// +/// [`ffi::OsStr`]: ../../../../std/ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStrExt { #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs index 0f4762aa881..b39c6f5d022 100644 --- a/src/libstd/sys/redox/ext/fs.rs +++ b/src/libstd/sys/redox/ext/fs.rs @@ -18,7 +18,9 @@ use path::Path; use sys; use sys_common::{FromInner, AsInner, AsInnerMut}; -/// Redox-specific extensions to `Permissions` +/// Redox-specific extensions to [`fs::Permissions`]. +/// +/// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html #[stable(feature = "fs_ext", since = "1.1.0")] pub trait PermissionsExt { /// Returns the underlying raw `mode_t` bits that are the standard Redox @@ -95,7 +97,9 @@ impl PermissionsExt for Permissions { } } -/// Redox-specific extensions to `OpenOptions` +/// Redox-specific extensions to [`fs::OpenOptions`]. +/// +/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html #[stable(feature = "fs_ext", since = "1.1.0")] pub trait OpenOptionsExt { /// Sets the mode bits that a new file will be created with. @@ -163,13 +167,9 @@ impl OpenOptionsExt for OpenOptions { } } -// Hm, why are there casts here to the returned type, shouldn't the types always -// be the same? Right you are! Turns out, however, on android at least the types -// in the raw `stat` structure are not the same as the types being returned. Who -// knew! -// -// As a result to make sure this compiles for all platforms we do the manual -// casts and rely on manual lowering to `stat` if the raw type is desired. +/// Redox-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { #[stable(feature = "metadata_ext", since = "1.1.0")] @@ -204,6 +204,13 @@ pub trait MetadataExt { fn blocks(&self) -> u64; } +// Hm, why are there casts here to the returned type, shouldn't the types always +// be the same? Right you are! Turns out, however, on android at least the types +// in the raw `stat` structure are not the same as the types being returned. Who +// knew! +// +// As a result to make sure this compiles for all platforms we do the manual +// casts and rely on manual lowering to `stat` if the raw type is desired. #[stable(feature = "metadata_ext", since = "1.1.0")] impl MetadataExt for fs::Metadata { fn dev(&self) -> u64 { @@ -253,7 +260,12 @@ impl MetadataExt for fs::Metadata { } } -/// Add special Redox types (block/char device, fifo and socket) +/// Redox-specific extensions for [`fs::FileType`]. +/// +/// Adds support for special Unix file types such as block/character devices, +/// pipes, and sockets. +/// +/// [`fs::FileType`]: ../../../../std/fs/struct.FileType.html #[stable(feature = "file_type_ext", since = "1.5.0")] pub trait FileTypeExt { /// Returns whether this file type is a block device. @@ -307,8 +319,10 @@ pub fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()> sys::fs::symlink(src.as_ref(), dst.as_ref()) } +/// Redox-specific extensions to [`fs::DirBuilder`]. +/// +/// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html #[stable(feature = "dir_builder", since = "1.6.0")] -/// An extension trait for `fs::DirBuilder` for Redox-specific options. pub trait DirBuilderExt { /// Sets the mode to create new directories with. This option defaults to /// 0o777. diff --git a/src/libstd/sys/redox/ext/process.rs b/src/libstd/sys/redox/ext/process.rs index e68e180acf1..608740a5cf7 100644 --- a/src/libstd/sys/redox/ext/process.rs +++ b/src/libstd/sys/redox/ext/process.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Unix-specific extensions to primitives in the `std::process` module. +//! Redox-specific extensions to primitives in the `std::process` module. #![stable(feature = "rust1", since = "1.0.0")] @@ -18,7 +18,9 @@ use process; use sys; use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner}; -/// Unix-specific extensions to the `std::process::Command` builder +/// Redox-specific extensions to the [`process::Command`] builder. +/// +/// [`process::Command`]: ../../../../std/process/struct.Command.html #[stable(feature = "rust1", since = "1.0.0")] pub trait CommandExt { /// Sets the child process's user id. This translates to a @@ -107,7 +109,9 @@ impl CommandExt for process::Command { } } -/// Unix-specific extensions to `std::process::ExitStatus` +/// Redox-specific extensions to [`process::ExitStatus`]. +/// +/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html #[stable(feature = "rust1", since = "1.0.0")] pub trait ExitStatusExt { /// Creates a new `ExitStatus` from the raw underlying `i32` return value of diff --git a/src/libstd/sys/redox/ext/thread.rs b/src/libstd/sys/redox/ext/thread.rs index 52be2ccd9f9..71ff0d46b91 100644 --- a/src/libstd/sys/redox/ext/thread.rs +++ b/src/libstd/sys/redox/ext/thread.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Unix-specific extensions to primitives in the `std::thread` module. +//! Redox-specific extensions to primitives in the `std::thread` module. #![stable(feature = "thread_extensions", since = "1.9.0")] @@ -19,7 +19,9 @@ use thread::JoinHandle; #[allow(deprecated)] pub type RawPthread = usize; -/// Unix-specific extensions to `std::thread::JoinHandle` +/// Redox-specific extensions to [`thread::JoinHandle`]. +/// +/// [`thread::JoinHandle`]: ../../../../std/thread/struct.JoinHandle.html #[stable(feature = "thread_extensions", since = "1.9.0")] pub trait JoinHandleExt { /// Extracts the raw pthread_t without taking ownership diff --git a/src/libstd/sys/unix/ext/ffi.rs b/src/libstd/sys/unix/ext/ffi.rs index fb9984ccbdd..3103ad0416e 100644 --- a/src/libstd/sys/unix/ext/ffi.rs +++ b/src/libstd/sys/unix/ext/ffi.rs @@ -17,7 +17,9 @@ use mem; use sys::os_str::Buf; use sys_common::{FromInner, IntoInner, AsInner}; -/// Unix-specific extensions to `OsString`. +/// Unix-specific extensions to [`ffi::OsString`]. +/// +/// [`ffi::OsString`]: ../../../../std/ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStringExt { /// Creates an [`OsString`] from a byte vector. @@ -66,7 +68,9 @@ impl OsStringExt for OsString { } } -/// Unix-specific extensions to `OsStr`. +/// Unix-specific extensions to [`ffi::OsStr`]. +/// +/// [`ffi::OsStr`]: ../../../../std/ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStrExt { #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 3c5b9424fb0..844e0106df0 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -20,9 +20,9 @@ use sys; use sys_common::{FromInner, AsInner, AsInnerMut}; use sys::platform::fs::MetadataExt as UnixMetadataExt; -/// Unix-specific extensions to [`File`]. +/// Unix-specific extensions to [`fs::File`]. /// -/// [`File`]: ../../../../std/fs/struct.File.html +/// [`fs::File`]: ../../../../std/fs/struct.File.html #[stable(feature = "file_offset", since = "1.15.0")] pub trait FileExt { /// Reads a number of bytes starting from a given offset. @@ -105,7 +105,9 @@ impl FileExt for fs::File { } } -/// Unix-specific extensions to `Permissions` +/// Unix-specific extensions to [`fs::Permissions`]. +/// +/// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html #[stable(feature = "fs_ext", since = "1.1.0")] pub trait PermissionsExt { /// Returns the underlying raw `st_mode` bits that contain the standard @@ -180,7 +182,9 @@ impl PermissionsExt for Permissions { } } -/// Unix-specific extensions to `OpenOptions` +/// Unix-specific extensions to [`fs::OpenOptions`]. +/// +/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html #[stable(feature = "fs_ext", since = "1.1.0")] pub trait OpenOptionsExt { /// Sets the mode bits that a new file will be created with. @@ -246,13 +250,9 @@ impl OpenOptionsExt for OpenOptions { } } -// Hm, why are there casts here to the returned type, shouldn't the types always -// be the same? Right you are! Turns out, however, on android at least the types -// in the raw `stat` structure are not the same as the types being returned. Who -// knew! -// -// As a result to make sure this compiles for all platforms we do the manual -// casts and rely on manual lowering to `stat` if the raw type is desired. +/// Unix-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Returns the ID of the device containing the file. @@ -555,7 +555,12 @@ impl MetadataExt for fs::Metadata { fn blocks(&self) -> u64 { self.st_blocks() } } -/// Add support for special unix types (block/char device, fifo and socket). +/// Unix-specific extensions for [`fs::FileType`]. +/// +/// Adds support for special Unix file types such as block/character devices, +/// pipes, and sockets. +/// +/// [`fs::FileType`]: ../../../../std/fs/struct.FileType.html #[stable(feature = "file_type_ext", since = "1.5.0")] pub trait FileTypeExt { /// Returns whether this file type is a block device. @@ -701,10 +706,10 @@ pub fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()> sys::fs::symlink(src.as_ref(), dst.as_ref()) } -#[stable(feature = "dir_builder", since = "1.6.0")] -/// An extension trait for [`fs::DirBuilder`] for unix-specific options. +/// Unix-specific extensions to [`fs::DirBuilder`]. /// /// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html +#[stable(feature = "dir_builder", since = "1.6.0")] pub trait DirBuilderExt { /// Sets the mode to create new directories with. This option defaults to /// 0o777. diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs index 7b4ec20d91f..21630ae9746 100644 --- a/src/libstd/sys/unix/ext/process.rs +++ b/src/libstd/sys/unix/ext/process.rs @@ -18,7 +18,9 @@ use process; use sys; use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner}; -/// Unix-specific extensions to the `std::process::Command` builder +/// Unix-specific extensions to the [`process::Command`] builder. +/// +/// [`process::Command`]: ../../../../std/process/struct.Command.html #[stable(feature = "rust1", since = "1.0.0")] pub trait CommandExt { /// Sets the child process's user id. This translates to a @@ -117,7 +119,9 @@ impl CommandExt for process::Command { } } -/// Unix-specific extensions to `std::process::ExitStatus` +/// Unix-specific extensions to [`process::ExitStatus`]. +/// +/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html #[stable(feature = "rust1", since = "1.0.0")] pub trait ExitStatusExt { /// Creates a new `ExitStatus` from the raw underlying `i32` return value of diff --git a/src/libstd/sys/unix/ext/thread.rs b/src/libstd/sys/unix/ext/thread.rs index fe2a48764dc..8dadf29945c 100644 --- a/src/libstd/sys/unix/ext/thread.rs +++ b/src/libstd/sys/unix/ext/thread.rs @@ -21,7 +21,9 @@ use thread::JoinHandle; #[allow(deprecated)] pub type RawPthread = pthread_t; -/// Unix-specific extensions to `std::thread::JoinHandle` +/// Unix-specific extensions to [`thread::JoinHandle`]. +/// +/// [`thread::JoinHandle`]: ../../../../std/thread/struct.JoinHandle.html #[stable(feature = "thread_extensions", since = "1.9.0")] pub trait JoinHandleExt { /// Extracts the raw pthread_t without taking ownership diff --git a/src/libstd/sys/windows/ext/ffi.rs b/src/libstd/sys/windows/ext/ffi.rs index d6b8896ac09..b3f7635efd3 100644 --- a/src/libstd/sys/windows/ext/ffi.rs +++ b/src/libstd/sys/windows/ext/ffi.rs @@ -76,7 +76,9 @@ use sys_common::{FromInner, AsInner}; #[stable(feature = "rust1", since = "1.0.0")] pub use sys_common::wtf8::EncodeWide; -/// Windows-specific extensions to `OsString`. +/// Windows-specific extensions to [`ffi::OsString`]. +/// +/// [`ffi::OsString`]: ../../../../std/ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStringExt { /// Creates an `OsString` from a potentially ill-formed UTF-16 slice of @@ -109,7 +111,9 @@ impl OsStringExt for OsString { } } -/// Windows-specific extensions to `OsStr`. +/// Windows-specific extensions to [`ffi::OsStr`]. +/// +/// [`ffi::OsStr`]: ../../../../std/ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStrExt { /// Re-encodes an `OsStr` as a wide character sequence, i.e. potentially diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index e5cd51b6550..5daeb5282cd 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -18,9 +18,9 @@ use path::Path; use sys; use sys_common::{AsInnerMut, AsInner}; -/// Windows-specific extensions to [`File`]. +/// Windows-specific extensions to [`fs::File`]. /// -/// [`File`]: ../../../fs/struct.File.html +/// [`fs::File`]: ../../../fs/struct.File.html #[stable(feature = "file_offset", since = "1.15.0")] pub trait FileExt { /// Seeks to a given position and reads a number of bytes. @@ -103,9 +103,9 @@ impl FileExt for fs::File { } } -/// Windows-specific extensions to [`OpenOptions`]. +/// Windows-specific extensions to [`fs::OpenOptions`]. /// -/// [`OpenOptions`]: ../../../fs/struct.OpenOptions.html +/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html #[stable(feature = "open_options_ext", since = "1.10.0")] pub trait OpenOptionsExt { /// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`] @@ -281,13 +281,12 @@ impl OpenOptionsExt for OpenOptions { } } -/// Extension methods for [`fs::Metadata`] to access the raw fields contained -/// within. +/// Windows-specific extensions to [`fs::Metadata`]. /// /// The data members that this trait exposes correspond to the members /// of the [`BY_HANDLE_FILE_INFORMATION`] structure. /// -/// [`fs::Metadata`]: ../../../fs/struct.Metadata.html +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html /// [`BY_HANDLE_FILE_INFORMATION`]: /// https://msdn.microsoft.com/en-us/library/windows/desktop/aa363788.aspx #[stable(feature = "metadata_ext", since = "1.1.0")] @@ -445,8 +444,11 @@ impl MetadataExt for Metadata { fn file_size(&self) -> u64 { self.as_inner().size() } } -/// Add support for the Windows specific fact that a symbolic link knows whether it is a file -/// or directory. +/// Windows-specific extensions to [`fs::FileType`]. +/// +/// On Windows, a symbolic link knows whether it is a file or directory. +/// +/// [`fs::FileType`]: ../../../../std/fs/struct.FileType.html #[unstable(feature = "windows_file_type_ext", issue = "0")] pub trait FileTypeExt { /// Returns whether this file type is a symbolic link that is also a directory. diff --git a/src/libstd/sys/windows/ext/process.rs b/src/libstd/sys/windows/ext/process.rs index 759f055c4b1..a02bcbe0c87 100644 --- a/src/libstd/sys/windows/ext/process.rs +++ b/src/libstd/sys/windows/ext/process.rs @@ -82,7 +82,9 @@ impl IntoRawHandle for process::ChildStderr { } } -/// Windows-specific extensions to `std::process::ExitStatus` +/// Windows-specific extensions to [`process::ExitStatus`]. +/// +/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html #[stable(feature = "exit_status_from", since = "1.12.0")] pub trait ExitStatusExt { /// Creates a new `ExitStatus` from the raw underlying `u32` return value of @@ -98,7 +100,9 @@ impl ExitStatusExt for process::ExitStatus { } } -/// Windows-specific extensions to the `std::process::Command` builder +/// Windows-specific extensions to the [`process::Command`] builder. +/// +/// [`process::Command`]: ../../../../std/process/struct.Command.html #[stable(feature = "windows_process_extensions", since = "1.16.0")] pub trait CommandExt { /// Sets the [process creation flags][1] to be passed to `CreateProcess`. -- cgit 1.4.1-3-g733a5 From d5bee64df400126279e71562352936d5e4d14433 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 10 Apr 2018 17:03:07 -0700 Subject: Prefer unprefixed paths for well known structs --- src/libstd/sys/redox/ext/ffi.rs | 8 ++++---- src/libstd/sys/redox/ext/fs.rs | 4 ++-- src/libstd/sys/redox/ext/process.rs | 2 +- src/libstd/sys/unix/ext/ffi.rs | 8 ++++---- src/libstd/sys/unix/ext/fs.rs | 8 ++++---- src/libstd/sys/windows/ext/ffi.rs | 8 ++++---- src/libstd/sys/windows/ext/fs.rs | 8 ++++---- 7 files changed, 23 insertions(+), 23 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/ffi.rs b/src/libstd/sys/redox/ext/ffi.rs index 060edbd22e4..cd88c8f46b3 100644 --- a/src/libstd/sys/redox/ext/ffi.rs +++ b/src/libstd/sys/redox/ext/ffi.rs @@ -17,9 +17,9 @@ use mem; use sys::os_str::Buf; use sys_common::{FromInner, IntoInner, AsInner}; -/// Redox-specific extensions to [`ffi::OsString`]. +/// Redox-specific extensions to [`OsString`]. /// -/// [`ffi::OsString`]: ../../../../std/ffi/struct.OsString.html +/// [`OsString`]: ../../../../std/ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStringExt { /// Creates an `OsString` from a byte vector. @@ -41,9 +41,9 @@ impl OsStringExt for OsString { } } -/// Redox-specific extensions to [`ffi::OsStr`]. +/// Redox-specific extensions to [`OsStr`]. /// -/// [`ffi::OsStr`]: ../../../../std/ffi/struct.OsStr.html +/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStrExt { #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs index b39c6f5d022..c1dba6edda4 100644 --- a/src/libstd/sys/redox/ext/fs.rs +++ b/src/libstd/sys/redox/ext/fs.rs @@ -260,12 +260,12 @@ impl MetadataExt for fs::Metadata { } } -/// Redox-specific extensions for [`fs::FileType`]. +/// Redox-specific extensions for [`FileType`]. /// /// Adds support for special Unix file types such as block/character devices, /// pipes, and sockets. /// -/// [`fs::FileType`]: ../../../../std/fs/struct.FileType.html +/// [`FileType`]: ../../../../std/fs/struct.FileType.html #[stable(feature = "file_type_ext", since = "1.5.0")] pub trait FileTypeExt { /// Returns whether this file type is a block device. diff --git a/src/libstd/sys/redox/ext/process.rs b/src/libstd/sys/redox/ext/process.rs index 608740a5cf7..cfb6d5fc703 100644 --- a/src/libstd/sys/redox/ext/process.rs +++ b/src/libstd/sys/redox/ext/process.rs @@ -18,7 +18,7 @@ use process; use sys; use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner}; -/// Redox-specific extensions to the [`process::Command`] builder. +/// Redox-specific extensions to the [`process::Command`] builder, /// /// [`process::Command`]: ../../../../std/process/struct.Command.html #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/unix/ext/ffi.rs b/src/libstd/sys/unix/ext/ffi.rs index 3103ad0416e..8347145db5a 100644 --- a/src/libstd/sys/unix/ext/ffi.rs +++ b/src/libstd/sys/unix/ext/ffi.rs @@ -17,9 +17,9 @@ use mem; use sys::os_str::Buf; use sys_common::{FromInner, IntoInner, AsInner}; -/// Unix-specific extensions to [`ffi::OsString`]. +/// Unix-specific extensions to [`OsString`]. /// -/// [`ffi::OsString`]: ../../../../std/ffi/struct.OsString.html +/// [`OsString`]: ../../../../std/ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStringExt { /// Creates an [`OsString`] from a byte vector. @@ -68,9 +68,9 @@ impl OsStringExt for OsString { } } -/// Unix-specific extensions to [`ffi::OsStr`]. +/// Unix-specific extensions to [`OsStr`]. /// -/// [`ffi::OsStr`]: ../../../../std/ffi/struct.OsStr.html +/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStrExt { #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 844e0106df0..4e981012669 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -20,9 +20,9 @@ use sys; use sys_common::{FromInner, AsInner, AsInnerMut}; use sys::platform::fs::MetadataExt as UnixMetadataExt; -/// Unix-specific extensions to [`fs::File`]. +/// Unix-specific extensions to [`File`]. /// -/// [`fs::File`]: ../../../../std/fs/struct.File.html +/// [`File`]: ../../../../std/fs/struct.File.html #[stable(feature = "file_offset", since = "1.15.0")] pub trait FileExt { /// Reads a number of bytes starting from a given offset. @@ -555,12 +555,12 @@ impl MetadataExt for fs::Metadata { fn blocks(&self) -> u64 { self.st_blocks() } } -/// Unix-specific extensions for [`fs::FileType`]. +/// Unix-specific extensions for [`FileType`]. /// /// Adds support for special Unix file types such as block/character devices, /// pipes, and sockets. /// -/// [`fs::FileType`]: ../../../../std/fs/struct.FileType.html +/// [`FileType`]: ../../../../std/fs/struct.FileType.html #[stable(feature = "file_type_ext", since = "1.5.0")] pub trait FileTypeExt { /// Returns whether this file type is a block device. diff --git a/src/libstd/sys/windows/ext/ffi.rs b/src/libstd/sys/windows/ext/ffi.rs index b3f7635efd3..98d43552489 100644 --- a/src/libstd/sys/windows/ext/ffi.rs +++ b/src/libstd/sys/windows/ext/ffi.rs @@ -76,9 +76,9 @@ use sys_common::{FromInner, AsInner}; #[stable(feature = "rust1", since = "1.0.0")] pub use sys_common::wtf8::EncodeWide; -/// Windows-specific extensions to [`ffi::OsString`]. +/// Windows-specific extensions to [`OsString`]. /// -/// [`ffi::OsString`]: ../../../../std/ffi/struct.OsString.html +/// [`OsString`]: ../../../../std/ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStringExt { /// Creates an `OsString` from a potentially ill-formed UTF-16 slice of @@ -111,9 +111,9 @@ impl OsStringExt for OsString { } } -/// Windows-specific extensions to [`ffi::OsStr`]. +/// Windows-specific extensions to [`OsStr`]. /// -/// [`ffi::OsStr`]: ../../../../std/ffi/struct.OsStr.html +/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStrExt { /// Re-encodes an `OsStr` as a wide character sequence, i.e. potentially diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index 5daeb5282cd..78c9e95a055 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -18,9 +18,9 @@ use path::Path; use sys; use sys_common::{AsInnerMut, AsInner}; -/// Windows-specific extensions to [`fs::File`]. +/// Windows-specific extensions to [`File`]. /// -/// [`fs::File`]: ../../../fs/struct.File.html +/// [`File`]: ../../../fs/struct.File.html #[stable(feature = "file_offset", since = "1.15.0")] pub trait FileExt { /// Seeks to a given position and reads a number of bytes. @@ -444,11 +444,11 @@ impl MetadataExt for Metadata { fn file_size(&self) -> u64 { self.as_inner().size() } } -/// Windows-specific extensions to [`fs::FileType`]. +/// Windows-specific extensions to [`FileType`]. /// /// On Windows, a symbolic link knows whether it is a file or directory. /// -/// [`fs::FileType`]: ../../../../std/fs/struct.FileType.html +/// [`FileType`]: ../../../../std/fs/struct.FileType.html #[unstable(feature = "windows_file_type_ext", issue = "0")] pub trait FileTypeExt { /// Returns whether this file type is a symbolic link that is also a directory. -- cgit 1.4.1-3-g733a5 From c7f3621f0e9e6ca617ff5debc634e1e16d0a662f Mon Sep 17 00:00:00 2001 From: Nicholas Rishel Date: Fri, 16 Feb 2018 15:41:24 -0500 Subject: The prior check causes abstract unix domain sockets to return unnamed on Android. Signed-off-by: Nicholas Rishel --- src/libstd/sys/unix/ext/net.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index ba80cbe47c8..2010b0218db 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -214,7 +214,7 @@ impl SocketAddr { let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses - if len == 0 || (cfg!(not(target_os = "linux")) && self.addr.sun_path[0] == 0) { + if len == 0 || (cfg!(not(any(target_os = "linux", target_os = "android"))) && self.addr.sun_path[0] == 0) { AddressKind::Unnamed } else if self.addr.sun_path[0] == 0 { AddressKind::Abstract(&path[1..len]) -- cgit 1.4.1-3-g733a5 From da6142c81057342d8d6686ae4078995aab73b5bc Mon Sep 17 00:00:00 2001 From: Nicholas Rishel Date: Thu, 19 Apr 2018 17:27:05 -0400 Subject: Rustfmt result (for relevant changes) to satisfy Travis line length check. Signed-off-by: Nicholas Rishel --- src/libstd/sys/unix/ext/net.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 2010b0218db..e277b1aa7b5 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -214,7 +214,10 @@ impl SocketAddr { let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses - if len == 0 || (cfg!(not(any(target_os = "linux", target_os = "android"))) && self.addr.sun_path[0] == 0) { + if len == 0 + || (cfg!(not(any(target_os = "linux", target_os = "android"))) + && self.addr.sun_path[0] == 0) + { AddressKind::Unnamed } else if self.addr.sun_path[0] == 0 { AddressKind::Abstract(&path[1..len]) -- cgit 1.4.1-3-g733a5 From 7c2304ddc6d716883415ac883f02256db6318644 Mon Sep 17 00:00:00 2001 From: Martin Husemann Date: Mon, 30 Apr 2018 08:04:53 +0200 Subject: Map the stack guard page with max protection on NetBSD On NetBSD the initial mmap() protection of a mapping can not be made less restrictive with mprotect(). So when mapping a stack guard page, use the maximum protection we ever want to use, then mprotect() it to the permission we want it to have initially. --- src/libstd/sys/unix/thread.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 9e388808030..f32016ce1d6 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -326,11 +326,23 @@ pub mod guard { // Reallocate the last page of the stack. // This ensures SIGBUS will be raised on // stack overflow. - let result = mmap(stackaddr, PAGE_SIZE, PROT_NONE, - MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); + if cfg!(target_os = "netbsd") { + let result = mmap(stackaddr, PAGE_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); + if result != stackaddr || result == MAP_FAILED { + panic!("failed to allocate a guard page"); + } + let result = mprotect(stackaddr, PAGE_SIZE, 0); - if result != stackaddr || result == MAP_FAILED { - panic!("failed to allocate a guard page"); + if result != 0 { + panic!("unable to protect the guard page"); + } + } else { + let result = mmap(stackaddr, PAGE_SIZE, PROT_NONE, + MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); + if result != stackaddr || result == MAP_FAILED { + panic!("failed to allocate a guard page"); + } } let guardaddr = stackaddr as usize; -- cgit 1.4.1-3-g733a5 From 244e24a312925779f6c62ce7d6b315fa2c120a7c Mon Sep 17 00:00:00 2001 From: Martin Husemann Date: Wed, 2 May 2018 10:00:33 +0200 Subject: Add comments and unify guard page setup. While currently only NetBSD seems to be affected, all systems implementing PAX MPROTECT in strict mode need this treatment, and it does not hurt others. --- src/libstd/sys/unix/thread.rs | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index f32016ce1d6..7fdecc9c0c0 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -326,23 +326,20 @@ pub mod guard { // Reallocate the last page of the stack. // This ensures SIGBUS will be raised on // stack overflow. - if cfg!(target_os = "netbsd") { - let result = mmap(stackaddr, PAGE_SIZE, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); - if result != stackaddr || result == MAP_FAILED { - panic!("failed to allocate a guard page"); - } - let result = mprotect(stackaddr, PAGE_SIZE, 0); + // Systems which enforce strict PAX MPROTECT do not allow + // to mprotect() a mapping with less restrictive permissions + // than the initial mmap() used, so we mmap() here with + // read/write permissions and only then mprotect() it to + // no permissions at all. See issue #50313. + let result = mmap(stackaddr, PAGE_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); + if result != stackaddr || result == MAP_FAILED { + panic!("failed to allocate a guard page"); + } - if result != 0 { - panic!("unable to protect the guard page"); - } - } else { - let result = mmap(stackaddr, PAGE_SIZE, PROT_NONE, - MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); - if result != stackaddr || result == MAP_FAILED { - panic!("failed to allocate a guard page"); - } + let result = mprotect(stackaddr, PAGE_SIZE, PROT_NONE); + if result != 0 { + panic!("failed to protect the guard page"); } let guardaddr = stackaddr as usize; -- cgit 1.4.1-3-g733a5 From e333725664c45874262ecb11e511c17cfd4672f0 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Wed, 9 May 2018 01:41:44 +0200 Subject: use fmt::Result where applicable --- src/librustc/ich/fingerprint.rs | 2 +- src/librustc_data_structures/control_flow_graph/dominators/mod.rs | 4 ++-- src/librustc_data_structures/owning_ref/mod.rs | 6 +++--- src/librustc_errors/lib.rs | 4 ++-- src/librustc_mir/borrow_check/nll/region_infer/mod.rs | 2 +- src/librustc_mir/transform/elaborate_drops.rs | 2 +- src/librustdoc/html/render.rs | 4 ++-- src/libstd/path.rs | 2 +- src/libstd/sys/redox/syscall/error.rs | 4 ++-- src/libstd/sys_common/wtf8.rs | 4 ++-- src/libsyntax_ext/format_foreign.rs | 2 +- src/test/run-pass/atomic-print.rs | 2 +- src/test/run-pass/union/union-trait-impl.rs | 2 +- 13 files changed, 20 insertions(+), 20 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/librustc/ich/fingerprint.rs b/src/librustc/ich/fingerprint.rs index a7adf28c481..f56f4e12e7a 100644 --- a/src/librustc/ich/fingerprint.rs +++ b/src/librustc/ich/fingerprint.rs @@ -67,7 +67,7 @@ impl Fingerprint { } impl ::std::fmt::Display for Fingerprint { - fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { write!(formatter, "{:x}-{:x}", self.0, self.1) } } diff --git a/src/librustc_data_structures/control_flow_graph/dominators/mod.rs b/src/librustc_data_structures/control_flow_graph/dominators/mod.rs index dc487f1162c..54407658e6c 100644 --- a/src/librustc_data_structures/control_flow_graph/dominators/mod.rs +++ b/src/librustc_data_structures/control_flow_graph/dominators/mod.rs @@ -175,7 +175,7 @@ impl DominatorTree { } impl fmt::Debug for DominatorTree { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&DominatorTreeNode { tree: self, node: self.root, @@ -190,7 +190,7 @@ struct DominatorTreeNode<'tree, Node: Idx> { } impl<'tree, Node: Idx> fmt::Debug for DominatorTreeNode<'tree, Node> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let subtrees: Vec<_> = self.tree .children(self.node) .iter() diff --git a/src/librustc_data_structures/owning_ref/mod.rs b/src/librustc_data_structures/owning_ref/mod.rs index c466b8f8ad1..aa113fac9fb 100644 --- a/src/librustc_data_structures/owning_ref/mod.rs +++ b/src/librustc_data_structures/owning_ref/mod.rs @@ -1002,7 +1002,7 @@ impl Debug for OwningRef where O: Debug, T: Debug, { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "OwningRef {{ owner: {:?}, reference: {:?} }}", self.owner(), @@ -1014,7 +1014,7 @@ impl Debug for OwningRefMut where O: Debug, T: Debug, { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "OwningRefMut {{ owner: {:?}, reference: {:?} }}", self.owner(), @@ -1047,7 +1047,7 @@ unsafe impl Sync for OwningRefMut where O: Sync, for<'a> (&'a mut T): Sync {} impl Debug for Erased { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "",) } } diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index c2b442e9497..fd90e1cbe08 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -232,7 +232,7 @@ impl FatalError { } impl fmt::Display for FatalError { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "parser fatal error") } } @@ -249,7 +249,7 @@ impl error::Error for FatalError { pub struct ExplicitBug; impl fmt::Display for ExplicitBug { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "parser internal bug") } } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index 4d1f3e2b430..57b8824191f 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -1185,7 +1185,7 @@ impl<'tcx> RegionDefinition<'tcx> { } impl fmt::Debug for Constraint { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!( formatter, "({:?}: {:?} @ {:?}) due to {:?}", diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 5397d18cdd7..79252e7654b 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -174,7 +174,7 @@ struct Elaborator<'a, 'b: 'a, 'tcx: 'b> { } impl<'a, 'b, 'tcx> fmt::Debug for Elaborator<'a, 'b, 'tcx> { - fn fmt(&self, _f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { Ok(()) } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 21de2db1dfe..fe9fc3ddd68 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2579,7 +2579,7 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, } fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter, - implementor_dups: &FxHashMap<&str, (DefId, bool)>) -> Result<(), fmt::Error> { + implementor_dups: &FxHashMap<&str, (DefId, bool)>) -> fmt::Result { write!(w, "
  • ")?; // If there's already another implementor that has the same abbridged name, use the // full path, for example in `std::iter::ExactSizeIterator` @@ -2612,7 +2612,7 @@ fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter, fn render_impls(cx: &Context, w: &mut fmt::Formatter, traits: &[&&Impl], - containing_item: &clean::Item) -> Result<(), fmt::Error> { + containing_item: &clean::Item) -> fmt::Result { for i in traits { let did = i.trait_did().unwrap(); let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods); diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 696711a70d4..5d35a786173 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1460,7 +1460,7 @@ impl> iter::Extend

    for PathBuf { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for PathBuf { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, formatter) } } diff --git a/src/libstd/sys/redox/syscall/error.rs b/src/libstd/sys/redox/syscall/error.rs index d8d78d55016..1ef79547431 100644 --- a/src/libstd/sys/redox/syscall/error.rs +++ b/src/libstd/sys/redox/syscall/error.rs @@ -48,13 +48,13 @@ impl Error { } impl fmt::Debug for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(self.text()) } } impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(self.text()) } } diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index fe7e058091e..14a2555adf9 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -56,7 +56,7 @@ pub struct CodePoint { /// Example: `U+1F4A9` impl fmt::Debug for CodePoint { #[inline] - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "U+{:04X}", self.value) } } @@ -144,7 +144,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) -> Result<(), fmt::Error> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, formatter) } } diff --git a/src/libsyntax_ext/format_foreign.rs b/src/libsyntax_ext/format_foreign.rs index e95c6f2e124..2b8603c75a5 100644 --- a/src/libsyntax_ext/format_foreign.rs +++ b/src/libsyntax_ext/format_foreign.rs @@ -989,7 +989,7 @@ mod strcursor { } impl<'a> std::fmt::Debug for StrCursor<'a> { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { write!(fmt, "StrCursor({:?} | {:?})", self.slice_before(), self.slice_after()) } } diff --git a/src/test/run-pass/atomic-print.rs b/src/test/run-pass/atomic-print.rs index 914b89dfb4d..2d478e954e7 100644 --- a/src/test/run-pass/atomic-print.rs +++ b/src/test/run-pass/atomic-print.rs @@ -15,7 +15,7 @@ use std::{env, fmt, process, sync, thread}; struct SlowFmt(u32); impl fmt::Debug for SlowFmt { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { thread::sleep_ms(3); self.0.fmt(f) } diff --git a/src/test/run-pass/union/union-trait-impl.rs b/src/test/run-pass/union/union-trait-impl.rs index 1cdaff2cab7..c1e408cc02a 100644 --- a/src/test/run-pass/union/union-trait-impl.rs +++ b/src/test/run-pass/union/union-trait-impl.rs @@ -15,7 +15,7 @@ union U { } impl fmt::Display for U { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { unsafe { write!(f, "Oh hai {}", self.a) } } } -- cgit 1.4.1-3-g733a5 From 5d015e1366d4c54f86d02638e2de3c89c43af481 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Sat, 12 May 2018 02:31:38 +0200 Subject: Do not silently truncate offsets for `read_at`/`write_at` on emscripten Generate an IO error if the offset is out of bounds for the system call. --- src/libstd/sys/unix/fd.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index 5dafc3251e7..67546d06b4e 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -75,8 +75,15 @@ impl FileDesc { unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: usize, offset: i64) -> io::Result { + use convert::TryInto; use libc::pread64; - cvt(pread64(fd, buf, count, offset as i32)) + // pread64 on emscripten actually takes a 32 bit offset + if let Ok(o) = offset.try_into() { + cvt(pread64(fd, buf, count, o)) + } else { + Err(io::Error::new(io::ErrorKind::InvalidInput, + "cannot pread >2GB")) + } } #[cfg(not(any(target_os = "android", target_os = "emscripten")))] @@ -116,8 +123,15 @@ impl FileDesc { unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: usize, offset: i64) -> io::Result { + use convert::TryInto; use libc::pwrite64; - cvt(pwrite64(fd, buf, count, offset as i32)) + // pwrite64 on emscripten actually takes a 32 bit offset + if let Ok(o) = offset.try_into() { + cvt(pwrite64(fd, buf, count, o)) + } else { + Err(io::Error::new(io::ErrorKind::InvalidInput, + "cannot pwrite >2GB")) + } } #[cfg(not(any(target_os = "android", target_os = "emscripten")))] -- cgit 1.4.1-3-g733a5 From 56f505e6c650106cb2328145f8f51ff4c9459124 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Mon, 14 May 2018 03:23:10 +0200 Subject: read2: Use inner function instead of closure --- src/libstd/sys/unix/pipe.rs | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index ec9b6f17dca..0a5dccdddda 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -100,24 +100,6 @@ pub fn read2(p1: AnonPipe, // wait for either pipe to become readable using `poll` cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?; - // Read as much as we can from each pipe, ignoring EWOULDBLOCK or - // EAGAIN. If we hit EOF, then this will happen because the underlying - // reader will return Ok(0), in which case we'll see `Ok` ourselves. In - // this case we flip the other fd back into blocking mode and read - // whatever's leftover on that file descriptor. - let read = |fd: &FileDesc, dst: &mut Vec| { - match fd.read_to_end(dst) { - Ok(_) => Ok(true), - Err(e) => { - if e.raw_os_error() == Some(libc::EWOULDBLOCK) || - e.raw_os_error() == Some(libc::EAGAIN) { - Ok(false) - } else { - Err(e) - } - } - } - }; if fds[0].revents != 0 && read(&p1, v1)? { p2.set_nonblocking(false)?; return p2.read_to_end(v2).map(|_| ()); @@ -127,4 +109,23 @@ pub fn read2(p1: AnonPipe, return p1.read_to_end(v1).map(|_| ()); } } + + // Read as much as we can from each pipe, ignoring EWOULDBLOCK or + // EAGAIN. If we hit EOF, then this will happen because the underlying + // reader will return Ok(0), in which case we'll see `Ok` ourselves. In + // this case we flip the other fd back into blocking mode and read + // whatever's leftover on that file descriptor. + fn read(fd: &FileDesc, dst: &mut Vec) -> Result { + match fd.read_to_end(dst) { + Ok(_) => Ok(true), + Err(e) => { + if e.raw_os_error() == Some(libc::EWOULDBLOCK) || + e.raw_os_error() == Some(libc::EAGAIN) { + Ok(false) + } else { + Err(e) + } + } + } + } } -- cgit 1.4.1-3-g733a5 From 6d1da8232997af4b785486329f01995440818920 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 14 May 2018 13:20:39 +0200 Subject: Don't unconditionally set CLOEXEC twice on every fd we open on Linux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, every `open64` was accompanied by a `ioctl(…, FIOCLEX)`, because some old Linux version would ignore the `O_CLOEXEC` flag we pass to the `open64` function. Now, we check whether the `CLOEXEC` flag is set on the first file we open – if it is, we won't do extra syscalls for every opened file. If it is not set, we fall back to the old behavior of unconditionally calling `ioctl(…, FIOCLEX)` on newly opened files. On old Linuxes, this amounts to one extra syscall per process, namely the `fcntl(…, F_GETFD)` call to check the `CLOEXEC` flag. On new Linuxes, this reduces the number of syscalls per opened file by one, except for the first file, where it does the same number of syscalls as before (`fcntl(…, F_GETFD)` to check the flag instead of `ioctl(…, FIOCLEX)` to set it). --- src/libstd/sys/unix/fd.rs | 7 +++++++ src/libstd/sys/unix/fs.rs | 41 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 4 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index 5dafc3251e7..72272d0581a 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -140,6 +140,13 @@ impl FileDesc { } } + #[cfg(target_os = "linux")] + pub fn get_cloexec(&self) -> io::Result { + unsafe { + Ok((cvt(libc::fcntl(self.fd, libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) + } + } + #[cfg(not(any(target_env = "newlib", target_os = "solaris", target_os = "emscripten", diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index a1ca839dc18..77968ffdedf 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -441,15 +441,48 @@ impl File { // Currently the standard library supports Linux 2.6.18 which did not // have the O_CLOEXEC flag (passed above). If we're running on an older - // Linux kernel then the flag is just ignored by the OS, so we continue - // to explicitly ask for a CLOEXEC fd here. + // Linux kernel then the flag is just ignored by the OS. After we open + // the first file, we check whether it has CLOEXEC set. If it doesn't, + // we will explicitly ask for a CLOEXEC fd for every further file we + // open, if it does, we will skip that step. // // The CLOEXEC flag, however, is supported on versions of macOS/BSD/etc // that we support, so we only do this on Linux currently. - if cfg!(target_os = "linux") { - fd.set_cloexec()?; + #[cfg(target_os = "linux")] + fn ensure_cloexec(fd: &FileDesc) -> io::Result<()> { + use sync::atomic::{AtomicUsize, Ordering}; + + const OPEN_CLOEXEC_UNKNOWN: usize = 0; + const OPEN_CLOEXEC_SUPPORTED: usize = 1; + const OPEN_CLOEXEC_NOTSUPPORTED: usize = 2; + static OPEN_CLOEXEC: AtomicUsize = AtomicUsize::new(OPEN_CLOEXEC_UNKNOWN); + + let need_to_set; + match OPEN_CLOEXEC.load(Ordering::Relaxed) { + OPEN_CLOEXEC_UNKNOWN => { + need_to_set = !fd.get_cloexec()?; + OPEN_CLOEXEC.store(if need_to_set { + OPEN_CLOEXEC_NOTSUPPORTED + } else { + OPEN_CLOEXEC_SUPPORTED + }, Ordering::Relaxed); + }, + OPEN_CLOEXEC_SUPPORTED => need_to_set = false, + OPEN_CLOEXEC_NOTSUPPORTED => need_to_set = true, + _ => unreachable!(), + } + if need_to_set { + fd.set_cloexec()?; + } + Ok(()) + } + + #[cfg(not(target_os = "linux"))] + fn ensure_cloexec(_: &FileDesc) -> io::Result<()> { + Ok(()) } + ensure_cloexec(&fd)?; Ok(File(fd)) } -- cgit 1.4.1-3-g733a5 From 834ef9f08ae3429a05dead80237bb4bd04769895 Mon Sep 17 00:00:00 2001 From: Nicolas Koch Date: Tue, 15 May 2018 15:25:09 +0200 Subject: fs: use copy_file_range on linux --- src/libstd/sys/unix/fs.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index a1ca839dc18..b9f0f39bbe2 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -761,6 +761,7 @@ pub fn canonicalize(p: &Path) -> io::Result { Ok(PathBuf::from(OsString::from_vec(buf))) } +#[cfg(not(target_os = "linux"))] pub fn copy(from: &Path, to: &Path) -> io::Result { use fs::{File, set_permissions}; if !from.is_file() { @@ -776,3 +777,69 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { set_permissions(to, perm)?; Ok(ret) } + +#[cfg(target_os = "linux")] +pub fn copy(from: &Path, to: &Path) -> io::Result { + use fs::{File, set_permissions}; + + unsafe fn copy_file_range( + fd_in: libc::c_int, + off_in: *mut libc::loff_t, + fd_out: libc::c_int, + off_out: *mut libc::loff_t, + len: libc::size_t, + flags: libc::c_uint, + ) -> libc::c_long { + libc::syscall( + libc::SYS_copy_file_range, + fd_in, + off_in, + fd_out, + off_out, + len, + flags, + ) + } + + if !from.is_file() { + return Err(Error::new(ErrorKind::InvalidInput, + "the source path is not an existing regular file")) + } + + let mut reader = File::open(from)?; + let mut writer = File::create(to)?; + let (perm, len) = { + let metadata = reader.metadata()?; + (metadata.permissions(), metadata.size()) + }; + + let mut written = 0u64; + while written < len { + let copy_result = unsafe { + cvt(copy_file_range(reader.as_raw_fd(), + ptr::null_mut(), + writer.as_raw_fd(), + ptr::null_mut(), + len as usize, + 0) + ) + }; + match copy_result { + Ok(ret) => written += ret as u64, + Err(err) => { + match err.raw_os_error() { + Some(os_err) if os_err == libc::ENOSYS || os_err == libc::EXDEV => { + // Either kernel is too old or the files are not mounted on the same fs. + // Try again with fallback method + let ret = io::copy(&mut reader, &mut writer)?; + set_permissions(to, perm)?; + return Ok(ret) + }, + _ => return Err(err), + } + } + } + } + set_permissions(to, perm)?; + Ok(written) +} -- cgit 1.4.1-3-g733a5 From 00ec3cf2a0449f41bd3cb873bc9b2cf1b6241095 Mon Sep 17 00:00:00 2001 From: Nicolas Koch Date: Wed, 16 May 2018 10:17:06 +0200 Subject: Use copy_file_range on android also --- src/libstd/sys/unix/fs.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index b9f0f39bbe2..42dc7b83da9 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -761,7 +761,7 @@ pub fn canonicalize(p: &Path) -> io::Result { Ok(PathBuf::from(OsString::from_vec(buf))) } -#[cfg(not(target_os = "linux"))] +#[cfg(not(any(target_os = "linux", target_os = "android")))] pub fn copy(from: &Path, to: &Path) -> io::Result { use fs::{File, set_permissions}; if !from.is_file() { @@ -778,7 +778,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { Ok(ret) } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] pub fn copy(from: &Path, to: &Path) -> io::Result { use fs::{File, set_permissions}; @@ -812,7 +812,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { let metadata = reader.metadata()?; (metadata.permissions(), metadata.size()) }; - + let mut written = 0u64; while written < len { let copy_result = unsafe { -- cgit 1.4.1-3-g733a5 From b605923cc83a444f6be52542b891d31b00c87662 Mon Sep 17 00:00:00 2001 From: Nicolas Koch Date: Wed, 16 May 2018 10:21:34 +0200 Subject: Add clarifying comment about offset argument --- src/libstd/sys/unix/fs.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 42dc7b83da9..0649a147ea3 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -816,6 +816,8 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { let mut written = 0u64; while written < len { let copy_result = unsafe { + // We actually don't have to adjust the offsets, + // because copy_file_range adjusts the file offset automatically cvt(copy_file_range(reader.as_raw_fd(), ptr::null_mut(), writer.as_raw_fd(), -- cgit 1.4.1-3-g733a5 From f4c2825c8f80eae6ef18eb3fa30464a18a588e0f Mon Sep 17 00:00:00 2001 From: Nicolas Koch Date: Wed, 16 May 2018 10:27:14 +0200 Subject: Adjust len in every iteration --- src/libstd/sys/unix/fs.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 0649a147ea3..c9d187f2ff2 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -815,6 +815,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { let mut written = 0u64; while written < len { + let bytes_to_copy = len - written; let copy_result = unsafe { // We actually don't have to adjust the offsets, // because copy_file_range adjusts the file offset automatically @@ -822,7 +823,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { ptr::null_mut(), writer.as_raw_fd(), ptr::null_mut(), - len as usize, + bytes_to_copy as usize, 0) ) }; -- cgit 1.4.1-3-g733a5 From a5e2942861324493c2cc5a32cb1473e656857b98 Mon Sep 17 00:00:00 2001 From: Nicolas Koch Date: Wed, 16 May 2018 10:35:19 +0200 Subject: Fix large file copies on 32 bit platforms --- src/libstd/sys/unix/fs.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index c9d187f2ff2..d8739d65326 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -815,7 +815,11 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { let mut written = 0u64; while written < len { - let bytes_to_copy = len - written; + let bytes_to_copy = if len - written > usize::max_value() as u64 { + usize::max_value() + } else { + (len - written) as usize + }; let copy_result = unsafe { // We actually don't have to adjust the offsets, // because copy_file_range adjusts the file offset automatically @@ -823,7 +827,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { ptr::null_mut(), writer.as_raw_fd(), ptr::null_mut(), - bytes_to_copy as usize, + bytes_to_copy, 0) ) }; -- cgit 1.4.1-3-g733a5 From 09d03bc245b27728c9cdd4976114506ae20208a7 Mon Sep 17 00:00:00 2001 From: Nicolas Koch Date: Thu, 17 May 2018 14:10:14 +0200 Subject: Store ENOSYS in a global to avoid unnecessary system calls --- src/libstd/sys/unix/fs.rs | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index d8739d65326..8412540934e 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -781,6 +781,11 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { #[cfg(any(target_os = "linux", target_os = "android"))] pub fn copy(from: &Path, to: &Path) -> io::Result { use fs::{File, set_permissions}; + use sync::atomic::{AtomicBool, Ordering}; + + // Kernel prior to 4.5 don't have copy_file_range + // We store the availability in a global to avoid unneccessary syscalls + static HAS_COPY_FILE_RANGE: AtomicBool = AtomicBool::new(true); unsafe fn copy_file_range( fd_in: libc::c_int, @@ -820,16 +825,26 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { } else { (len - written) as usize }; - let copy_result = unsafe { - // We actually don't have to adjust the offsets, - // because copy_file_range adjusts the file offset automatically - cvt(copy_file_range(reader.as_raw_fd(), - ptr::null_mut(), - writer.as_raw_fd(), - ptr::null_mut(), - bytes_to_copy, - 0) - ) + let copy_result = if HAS_COPY_FILE_RANGE.load(Ordering::Relaxed) { + let copy_result = unsafe { + // We actually don't have to adjust the offsets, + // because copy_file_range adjusts the file offset automatically + cvt(copy_file_range(reader.as_raw_fd(), + ptr::null_mut(), + writer.as_raw_fd(), + ptr::null_mut(), + bytes_to_copy, + 0) + ) + }; + if let Err(ref copy_err) = copy_result { + if let Some(libc::ENOSYS) = copy_err.raw_os_error() { + HAS_COPY_FILE_RANGE.store(false, Ordering::Relaxed); + } + } + copy_result + } else { + Err(io::Error::from_raw_os_error(libc::ENOSYS)) }; match copy_result { Ok(ret) => written += ret as u64, -- cgit 1.4.1-3-g733a5 From 3f392abdfb2ec0f436352d349eedd5f6707bf817 Mon Sep 17 00:00:00 2001 From: Nicolas Koch Date: Thu, 24 May 2018 14:51:59 +0200 Subject: Implement suggestions from the PR - Move loading of atomic bool outside the loop - Add comment about TryFrom for future improvement --- src/libstd/sys/unix/fs.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 8412540934e..6624c48cbe0 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -818,14 +818,16 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { (metadata.permissions(), metadata.size()) }; + let has_copy_file_range = HAS_COPY_FILE_RANGE.load(Ordering::Relaxed); let mut written = 0u64; while written < len { + // TODO should ideally use TryFrom let bytes_to_copy = if len - written > usize::max_value() as u64 { usize::max_value() } else { (len - written) as usize }; - let copy_result = if HAS_COPY_FILE_RANGE.load(Ordering::Relaxed) { + let copy_result = if has_copy_file_range { let copy_result = unsafe { // We actually don't have to adjust the offsets, // because copy_file_range adjusts the file offset automatically -- cgit 1.4.1-3-g733a5 From 3b271eb039d22a4b31caed29a2aac0a9ac604902 Mon Sep 17 00:00:00 2001 From: Nicolas Koch Date: Mon, 28 May 2018 17:19:42 +0200 Subject: Use FIXME instead of TODO; Move bytes_to_copy calculation inside if branch --- src/libstd/sys/unix/fs.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 6624c48cbe0..56075c5e8d0 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -821,13 +821,14 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { let has_copy_file_range = HAS_COPY_FILE_RANGE.load(Ordering::Relaxed); let mut written = 0u64; while written < len { - // TODO should ideally use TryFrom - let bytes_to_copy = if len - written > usize::max_value() as u64 { - usize::max_value() - } else { - (len - written) as usize - }; let copy_result = if has_copy_file_range { + // FIXME: should ideally use TryFrom + let bytes_to_copy = if len - written > usize::max_value() as u64 { + usize::max_value() + } else { + (len - written) as usize + }; + let copy_result = unsafe { // We actually don't have to adjust the offsets, // because copy_file_range adjusts the file offset automatically -- cgit 1.4.1-3-g733a5 From c7d6a0130b6b76b65982916198e7de2b348f9718 Mon Sep 17 00:00:00 2001 From: Nicolas Koch Date: Tue, 29 May 2018 23:42:42 +0200 Subject: Fix additional nits: - compute bytes_to_copy more elegantly - add assert that written is 0 in fallback case --- src/libstd/sys/unix/fs.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 56075c5e8d0..38f1ac472fa 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -780,6 +780,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { #[cfg(any(target_os = "linux", target_os = "android"))] pub fn copy(from: &Path, to: &Path) -> io::Result { + use cmp; use fs::{File, set_permissions}; use sync::atomic::{AtomicBool, Ordering}; @@ -822,13 +823,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { let mut written = 0u64; while written < len { let copy_result = if has_copy_file_range { - // FIXME: should ideally use TryFrom - let bytes_to_copy = if len - written > usize::max_value() as u64 { - usize::max_value() - } else { - (len - written) as usize - }; - + let bytes_to_copy = cmp::min(len - written, usize::max_value() as u64) as usize; let copy_result = unsafe { // We actually don't have to adjust the offsets, // because copy_file_range adjusts the file offset automatically @@ -856,6 +851,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { Some(os_err) if os_err == libc::ENOSYS || os_err == libc::EXDEV => { // Either kernel is too old or the files are not mounted on the same fs. // Try again with fallback method + assert_eq!(written, 0); let ret = io::copy(&mut reader, &mut writer)?; set_permissions(to, perm)?; return Ok(ret) -- cgit 1.4.1-3-g733a5 From 9b6940d0b46284f24410050e9bfde0a9ab08d0fb Mon Sep 17 00:00:00 2001 From: Nicolas Koch Date: Wed, 30 May 2018 06:33:54 +0200 Subject: fs: copy: Use File::set_permissions instead of fs::set_permissions We already got the open file descriptor at this point. Don't make the kernel resolve the path again. --- src/libstd/sys/unix/fs.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 889d21cad65..9d0d3779057 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -807,14 +807,14 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { let perm = reader.metadata()?.permissions(); let ret = io::copy(&mut reader, &mut writer)?; - set_permissions(to, perm)?; + writer.set_permissions(perm)?; Ok(ret) } #[cfg(any(target_os = "linux", target_os = "android"))] pub fn copy(from: &Path, to: &Path) -> io::Result { use cmp; - use fs::{File, set_permissions}; + use fs::File; use sync::atomic::{AtomicBool, Ordering}; // Kernel prior to 4.5 don't have copy_file_range @@ -886,7 +886,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { // Try again with fallback method assert_eq!(written, 0); let ret = io::copy(&mut reader, &mut writer)?; - set_permissions(to, perm)?; + writer.set_permissions(perm)?; return Ok(ret) }, _ => return Err(err), @@ -894,6 +894,6 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { } } } - set_permissions(to, perm)?; + writer.set_permissions(perm)?; Ok(written) } -- cgit 1.4.1-3-g733a5 From c5ee3b6df1db2c4410b0e8d7a80a2885cf5628f1 Mon Sep 17 00:00:00 2001 From: Nicolas Koch Date: Wed, 30 May 2018 12:09:20 +0200 Subject: Remobve unused import --- src/libstd/sys/unix/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 9d0d3779057..758286fce6c 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -796,7 +796,7 @@ pub fn canonicalize(p: &Path) -> io::Result { #[cfg(not(any(target_os = "linux", target_os = "android")))] pub fn copy(from: &Path, to: &Path) -> io::Result { - use fs::{File, set_permissions}; + use fs::File; if !from.is_file() { return Err(Error::new(ErrorKind::InvalidInput, "the source path is not an existing regular file")) -- cgit 1.4.1-3-g733a5 From cb2a0d61adb47b530f8922c9ae3c816cbbf062c5 Mon Sep 17 00:00:00 2001 From: Guillaume Girol Date: Thu, 24 May 2018 23:50:28 +0200 Subject: std::fs::DirEntry.metadata(): use fstatat instead of lstat when possible --- src/libstd/sys/unix/fs.rs | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 889d21cad65..007511a992b 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -25,6 +25,8 @@ use sys_common::{AsInner, FromInner}; #[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "l4re"))] use libc::{stat64, fstat64, lstat64, off64_t, ftruncate64, lseek64, dirent64, readdir64_r, open64}; +#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))] +use libc::{fstatat, dirfd}; #[cfg(target_os = "android")] use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, lseek64, dirent as dirent64, open as open64}; @@ -48,11 +50,15 @@ pub struct FileAttr { stat: stat64, } -pub struct ReadDir { +// all DirEntry's will have a reference to this struct +struct InnerReadDir { dirp: Dir, - root: Arc, + root: PathBuf, } +#[derive(Clone)] +pub struct ReadDir(Arc); + struct Dir(*mut libc::DIR); unsafe impl Send for Dir {} @@ -60,8 +66,8 @@ unsafe impl Sync for Dir {} pub struct DirEntry { entry: dirent64, - root: Arc, - // We need to store an owned copy of the directory name + dir: ReadDir, + // We need to store an owned copy of the entry name // on Solaris and Fuchsia because a) it uses a zero-length // array to store the name, b) its lifetime between readdir // calls is not guaranteed. @@ -207,7 +213,7 @@ impl fmt::Debug for ReadDir { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame. // Thus the result will be e g 'ReadDir("/home")' - fmt::Debug::fmt(&*self.root, f) + fmt::Debug::fmt(&*self.0.root, f) } } @@ -240,7 +246,7 @@ impl Iterator for ReadDir { entry: *entry_ptr, name: ::slice::from_raw_parts(name as *const u8, namelen as usize).to_owned().into_boxed_slice(), - root: self.root.clone() + dir: self.clone() }; if ret.name_bytes() != b"." && ret.name_bytes() != b".." { return Some(Ok(ret)) @@ -254,11 +260,11 @@ impl Iterator for ReadDir { unsafe { let mut ret = DirEntry { entry: mem::zeroed(), - root: self.root.clone() + dir: self.clone(), }; let mut entry_ptr = ptr::null_mut(); loop { - if readdir64_r(self.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 { + if readdir64_r(self.0.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 { return Some(Err(Error::last_os_error())) } if entry_ptr.is_null() { @@ -281,13 +287,27 @@ impl Drop for Dir { impl DirEntry { pub fn path(&self) -> PathBuf { - self.root.join(OsStr::from_bytes(self.name_bytes())) + self.dir.0.root.join(OsStr::from_bytes(self.name_bytes())) } pub fn file_name(&self) -> OsString { OsStr::from_bytes(self.name_bytes()).to_os_string() } + #[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))] + pub fn metadata(&self) -> io::Result { + let fd = cvt(unsafe {dirfd(self.dir.0.dirp.0)})?; + let mut stat: stat64 = unsafe { mem::zeroed() }; + cvt(unsafe { + fstatat(fd, + self.entry.d_name.as_ptr(), + &mut stat as *mut _ as *mut _, + libc::AT_SYMLINK_NOFOLLOW) + })?; + Ok(FileAttr { stat: stat }) + } + + #[cfg(not(any(target_os = "linux", target_os = "emscripten", target_os = "android")))] pub fn metadata(&self) -> io::Result { lstat(&self.path()) } @@ -664,14 +684,15 @@ impl fmt::Debug for File { } pub fn readdir(p: &Path) -> io::Result { - let root = Arc::new(p.to_path_buf()); + let root = p.to_path_buf(); let p = cstr(p)?; unsafe { let ptr = libc::opendir(p.as_ptr()); if ptr.is_null() { Err(Error::last_os_error()) } else { - Ok(ReadDir { dirp: Dir(ptr), root: root }) + let inner = InnerReadDir { dirp: Dir(ptr), root }; + Ok(ReadDir(Arc::new(inner))) } } } -- cgit 1.4.1-3-g733a5 From 8dec03b71af22a160803c241b6812b8e54ee9671 Mon Sep 17 00:00:00 2001 From: Guillaume Girol Date: Thu, 31 May 2018 19:18:58 +0200 Subject: libstd/sys/unix/fs.rs: fix compilation on fuchsia --- src/libstd/sys/unix/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 007511a992b..c4d94259bd6 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -229,7 +229,7 @@ impl Iterator for ReadDir { // is safe to use in threaded applications and it is generally preferred // over the readdir_r(3C) function. super::os::set_errno(0); - let entry_ptr = libc::readdir(self.dirp.0); + let entry_ptr = libc::readdir(self.0.dirp.0); if entry_ptr.is_null() { // NULL can mean either the end is reached or an error occurred. // So we had to clear errno beforehand to check for an error now. -- cgit 1.4.1-3-g733a5 From 95e2bf253d864c5e14ad000ffa2040ce85916056 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Thu, 31 May 2018 22:05:36 +0200 Subject: Fix confusing error message for sub_instant When subtracting an Instant from another, the function will panick when `RHS > self`, but the error message confusingly displays a different error: ```rust let i = Instant::now(); let other = Instant::now(); if other > i { println!("{:?}", i - other); } ``` This results in a panic: ``` thread 'test_instant' panicked at 'other was less than the current instant', libstd/sys/unix/time.rs:292:17 ``` --- src/libstd/sys/unix/time.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index 83127935909..f7459cb55d5 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -289,7 +289,7 @@ mod inner { pub fn sub_instant(&self, other: &Instant) -> Duration { self.t.sub_timespec(&other.t).unwrap_or_else(|_| { - panic!("other was less than the current instant") + panic!("other was greater than the current instant") }) } -- cgit 1.4.1-3-g733a5 From 2c3eff99f0cc0bb460f9068c553e5d029e7b7ec3 Mon Sep 17 00:00:00 2001 From: Nicolas Koch Date: Fri, 1 Jun 2018 09:32:20 +0200 Subject: fs: copy: Add EPERM to fallback error conditions Fixes #51266 --- src/libstd/sys/unix/fs.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index c4092dcd388..774340388e1 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -890,8 +890,11 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { ) }; if let Err(ref copy_err) = copy_result { - if let Some(libc::ENOSYS) = copy_err.raw_os_error() { - HAS_COPY_FILE_RANGE.store(false, Ordering::Relaxed); + match copy_err.raw_os_error() { + Some(libc::ENOSYS) | Some(libc::EPERM) => { + HAS_COPY_FILE_RANGE.store(false, Ordering::Relaxed); + } + _ => {} } } copy_result @@ -902,9 +905,13 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { Ok(ret) => written += ret as u64, Err(err) => { match err.raw_os_error() { - Some(os_err) if os_err == libc::ENOSYS || os_err == libc::EXDEV => { - // Either kernel is too old or the files are not mounted on the same fs. - // Try again with fallback method + Some(os_err) if os_err == libc::ENOSYS + || os_err == libc::EXDEV + || os_err == libc::EPERM => { + // Try fallback io::copy if either: + // - Kernel version is < 4.5 (ENOSYS) + // - Files are mounted on different fs (EXDEV) + // - copy_file_range is disallowed, for example by seccomp (EPERM) assert_eq!(written, 0); let ret = io::copy(&mut reader, &mut writer)?; writer.set_permissions(perm)?; -- cgit 1.4.1-3-g733a5 From 33c4b37d00985f8f12796ef1b0b8ff97a4f3db99 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Mon, 4 Jun 2018 08:58:55 +0200 Subject: Clarify error phrase in `sub_instant` function Uses the same wording as [`src/libstd/sys/windows/time.rs`][1]. 1: https://github.com/avdv/rust/blob/95e2bf253d864c5e14ad000ffa2040ce85916056/src/libstd/sys/windows/time.rs#L65 --- src/libstd/sys/redox/time.rs | 2 +- src/libstd/sys/unix/time.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/time.rs b/src/libstd/sys/redox/time.rs index cf798500b7f..5c491115c55 100644 --- a/src/libstd/sys/redox/time.rs +++ b/src/libstd/sys/redox/time.rs @@ -144,7 +144,7 @@ impl Instant { pub fn sub_instant(&self, other: &Instant) -> Duration { self.t.sub_timespec(&other.t).unwrap_or_else(|_| { - panic!("other was less than the current instant") + panic!("specified instant was later than self") }) } diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index f7459cb55d5..89786eb2a6c 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -289,7 +289,7 @@ mod inner { pub fn sub_instant(&self, other: &Instant) -> Duration { self.t.sub_timespec(&other.t).unwrap_or_else(|_| { - panic!("other was greater than the current instant") + panic!("specified instant was later than self") }) } -- cgit 1.4.1-3-g733a5 From 0c6cd26aecb7aec3407014c4b0ece7e6278631c4 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Fri, 1 Jun 2018 12:58:30 -0700 Subject: [fuchsia] Migrate from launchpad to fdio_spawn_etc fdio_spawn_etc is the preferred way of creating processes on Fuchsia now. --- src/libstd/build.rs | 1 - src/libstd/sys/unix/process/process_fuchsia.rs | 75 +++++++++-------------- src/libstd/sys/unix/process/zircon.rs | 85 +++++++------------------- 3 files changed, 51 insertions(+), 110 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/build.rs b/src/libstd/build.rs index c34877d369c..c001e4e8ceb 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -74,7 +74,6 @@ fn main() { } println!("cargo:rustc-link-lib=zircon"); println!("cargo:rustc-link-lib=fdio"); - println!("cargo:rustc-link-lib=launchpad"); // for std::process } else if target.contains("cloudabi") { if cfg!(feature = "backtrace") { println!("cargo:rustc-link-lib=unwind"); diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs index 06c0540fec0..fa48001179e 100644 --- a/src/libstd/sys/unix/process/process_fuchsia.rs +++ b/src/libstd/sys/unix/process/process_fuchsia.rs @@ -56,68 +56,49 @@ impl Command { -> io::Result { use sys::process::zircon::*; - let job_handle = zx_job_default(); let envp = match maybe_envp { Some(envp) => envp.as_ptr(), None => ptr::null(), }; - // To make sure launchpad_destroy gets called on the launchpad if this function fails - struct LaunchpadDestructor(*mut launchpad_t); - impl Drop for LaunchpadDestructor { - fn drop(&mut self) { unsafe { launchpad_destroy(self.0); } } - } - - // Duplicate the job handle - let mut job_copy: zx_handle_t = ZX_HANDLE_INVALID; - zx_cvt(zx_handle_duplicate(job_handle, ZX_RIGHT_SAME_RIGHTS, &mut job_copy))?; - // Create a launchpad - let mut launchpad: *mut launchpad_t = ptr::null_mut(); - zx_cvt(launchpad_create(job_copy, self.get_argv()[0], &mut launchpad))?; - let launchpad_destructor = LaunchpadDestructor(launchpad); - - // Set the process argv - zx_cvt(launchpad_set_args(launchpad, self.get_argv().len() as i32 - 1, - self.get_argv().as_ptr()))?; - // Setup the environment vars - zx_cvt(launchpad_set_environ(launchpad, envp))?; - zx_cvt(launchpad_add_vdso_vmo(launchpad))?; - // Load the executable - zx_cvt(launchpad_elf_load(launchpad, launchpad_vmo_from_file(self.get_argv()[0])))?; - zx_cvt(launchpad_load_vdso(launchpad, ZX_HANDLE_INVALID))?; - zx_cvt(launchpad_clone(launchpad, LP_CLONE_FDIO_NAMESPACE | LP_CLONE_FDIO_CWD))?; + let transfer_or_clone = |opt_fd, target_fd| if let Some(local_fd) = opt_fd { + fdio_spawn_action_t { + action: FDIO_SPAWN_ACTION_TRANSFER_FD, + local_fd, + target_fd, + ..Default::default() + } + } else { + fdio_spawn_action_t { + action: FDIO_SPAWN_ACTION_CLONE_FD, + local_fd: target_fd, + target_fd, + ..Default::default() + } + }; // Clone stdin, stdout, and stderr - if let Some(fd) = stdio.stdin.fd() { - zx_cvt(launchpad_transfer_fd(launchpad, fd, 0))?; - } else { - zx_cvt(launchpad_clone_fd(launchpad, 0, 0))?; - } - if let Some(fd) = stdio.stdout.fd() { - zx_cvt(launchpad_transfer_fd(launchpad, fd, 1))?; - } else { - zx_cvt(launchpad_clone_fd(launchpad, 1, 1))?; - } - if let Some(fd) = stdio.stderr.fd() { - zx_cvt(launchpad_transfer_fd(launchpad, fd, 2))?; - } else { - zx_cvt(launchpad_clone_fd(launchpad, 2, 2))?; - } + let action1 = transfer_or_clone(stdio.stdin.fd(), 0); + let action2 = transfer_or_clone(stdio.stdout.fd(), 1); + let action3 = transfer_or_clone(stdio.stderr.fd(), 2); + let actions = [action1, action2, action3]; - // We don't want FileDesc::drop to be called on any stdio. It would close their fds. The - // fds will be closed once the child process finishes. + // We don't want FileDesc::drop to be called on any stdio. fdio_spawn_etc + // always consumes transferred file descriptors. mem::forget(stdio); for callback in self.get_closures().iter_mut() { callback()?; } - // `launchpad_go` destroys the launchpad, so we must not - mem::forget(launchpad_destructor); - let mut process_handle: zx_handle_t = 0; - let mut err_msg: *const libc::c_char = ptr::null(); - zx_cvt(launchpad_go(launchpad, &mut process_handle, &mut err_msg))?; + zx_cvt(fdio_spawn_etc( + 0, + FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC | FDIO_SPAWN_CLONE_NAMESPACE, + self.get_argv()[0], self.get_argv().as_ptr(), envp, 3, actions.as_ptr(), + &mut process_handle, + ptr::null_mut(), + ))?; // FIXME: See if we want to do something with that err_msg Ok(process_handle) diff --git a/src/libstd/sys/unix/process/zircon.rs b/src/libstd/sys/unix/process/zircon.rs index 90864e6ef3f..a06c73ee263 100644 --- a/src/libstd/sys/unix/process/zircon.rs +++ b/src/libstd/sys/unix/process/zircon.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(non_camel_case_types)] +#![allow(non_camel_case_types, unused)] use convert::TryInto; use io; @@ -117,75 +117,36 @@ extern { avail: *mut size_t) -> zx_status_t; } -// From `enum special_handles` in system/ulib/launchpad/launchpad.c -// HND_LOADER_SVC = 0 -// HND_EXEC_VMO = 1 -// HND_SEGMENTS_VMAR = 2 -const HND_SPECIAL_COUNT: c_int = 3; - +#[derive(Default)] #[repr(C)] -pub struct launchpad_t { - argc: u32, - envc: u32, - args: *const c_char, - args_len: size_t, - env: *const c_char, - env_len: size_t, - - handles: *mut zx_handle_t, - handles_info: *mut u32, - handle_count: size_t, - handle_alloc: size_t, - - entry: zx_vaddr_t, - base: zx_vaddr_t, - vdso_base: zx_vaddr_t, - - stack_size: size_t, - - special_handles: [zx_handle_t; HND_SPECIAL_COUNT as usize], - loader_message: bool, +pub struct fdio_spawn_action_t { + pub action: u32, + pub reserved0: u32, + pub local_fd: i32, + pub target_fd: i32, + pub reserved1: u64, } extern { - pub fn launchpad_create(job: zx_handle_t, name: *const c_char, - lp: *mut *mut launchpad_t) -> zx_status_t; - - pub fn launchpad_go(lp: *mut launchpad_t, - proc_handle: *mut zx_handle_t, - err_msg: *mut *const c_char) -> zx_status_t; - - pub fn launchpad_destroy(lp: *mut launchpad_t); - - pub fn launchpad_set_args(lp: *mut launchpad_t, argc: c_int, - argv: *const *const c_char) -> zx_status_t; - - pub fn launchpad_set_environ(lp: *mut launchpad_t, envp: *const *const c_char) -> zx_status_t; - - pub fn launchpad_clone(lp: *mut launchpad_t, what: u32) -> zx_status_t; - - pub fn launchpad_clone_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> zx_status_t; - - pub fn launchpad_transfer_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> zx_status_t; - - pub fn launchpad_elf_load(lp: *mut launchpad_t, vmo: zx_handle_t) -> zx_status_t; - - pub fn launchpad_add_vdso_vmo(lp: *mut launchpad_t) -> zx_status_t; + pub fn fdio_spawn_etc(job: zx_handle_t, flags: u32, path: *const c_char, + argv: *const *const c_char, envp: *const *const c_char, + action_count: u64, actions: *const fdio_spawn_action_t, + process: *mut zx_handle_t, err_msg: *mut c_char) -> zx_status_t; +} - pub fn launchpad_load_vdso(lp: *mut launchpad_t, vmo: zx_handle_t) -> zx_status_t; +// fdio_spawn_etc flags - pub fn launchpad_vmo_from_file(filename: *const c_char) -> zx_handle_t; -} +pub const FDIO_SPAWN_CLONE_JOB: u32 = 0x0001; +pub const FDIO_SPAWN_CLONE_LDSVC: u32 = 0x0002; +pub const FDIO_SPAWN_CLONE_NAMESPACE: u32 = 0x0004; +pub const FDIO_SPAWN_CLONE_STDIO: u32 = 0x0008; +pub const FDIO_SPAWN_CLONE_ENVIRON: u32 = 0x0010; +pub const FDIO_SPAWN_CLONE_ALL: u32 = 0xFFFF; -// Launchpad clone constants +// fdio_spawn_etc actions -pub const LP_CLONE_FDIO_NAMESPACE: u32 = 0x0001; -pub const LP_CLONE_FDIO_CWD: u32 = 0x0002; -// LP_CLONE_FDIO_STDIO = 0x0004 -// LP_CLONE_FDIO_ALL = 0x00FF -// LP_CLONE_ENVIRON = 0x0100 -// LP_CLONE_DEFAULT_JOB = 0x0200 -// LP_CLONE_ALL = 0xFFFF +pub const FDIO_SPAWN_ACTION_CLONE_FD: u32 = 0x0001; +pub const FDIO_SPAWN_ACTION_TRANSFER_FD: u32 = 0x0002; // Errors -- cgit 1.4.1-3-g733a5 From af75314ecdbc5564f300467e732fdb5c923a873a Mon Sep 17 00:00:00 2001 From: sharkdp Date: Tue, 12 Jun 2018 21:03:27 +0200 Subject: Fix possibly endless loop in ReadDir iterator Certain directories in `/proc` can cause the `ReadDir` iterator to loop indefinitely. We get an error code (22) when calling libc's `readdir_r` on these directories, but `entry_ptr` is `NULL` at the same time, signalling the end of the directory stream. This change introduces an internal state to the iterator such that the `Some(Err(..))` value will only be returned once when calling `next`. Subsequent calls will return `None`. fixes #50619 --- src/libstd/sys/unix/fs.rs | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 774340388e1..6579fee14d8 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -57,7 +57,10 @@ struct InnerReadDir { } #[derive(Clone)] -pub struct ReadDir(Arc); +pub struct ReadDir { + inner: Arc, + end_of_stream: bool, +} struct Dir(*mut libc::DIR); @@ -213,7 +216,7 @@ impl fmt::Debug for ReadDir { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame. // Thus the result will be e g 'ReadDir("/home")' - fmt::Debug::fmt(&*self.0.root, f) + fmt::Debug::fmt(&*self.inner.root, f) } } @@ -229,7 +232,7 @@ impl Iterator for ReadDir { // is safe to use in threaded applications and it is generally preferred // over the readdir_r(3C) function. super::os::set_errno(0); - let entry_ptr = libc::readdir(self.0.dirp.0); + let entry_ptr = libc::readdir(self.inner.dirp.0); if entry_ptr.is_null() { // NULL can mean either the end is reached or an error occurred. // So we had to clear errno beforehand to check for an error now. @@ -257,6 +260,10 @@ impl Iterator for ReadDir { #[cfg(not(any(target_os = "solaris", target_os = "fuchsia")))] fn next(&mut self) -> Option> { + if self.end_of_stream { + return None; + } + unsafe { let mut ret = DirEntry { entry: mem::zeroed(), @@ -264,7 +271,14 @@ impl Iterator for ReadDir { }; let mut entry_ptr = ptr::null_mut(); loop { - if readdir64_r(self.0.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 { + if readdir64_r(self.inner.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 { + if entry_ptr.is_null() { + // We encountered an error (which will be returned in this iteration), but + // we also reached the end of the directory stream. The `end_of_stream` + // flag is enabled to make sure that we return `None` in the next iteration + // (instead of looping forever) + self.end_of_stream = true; + } return Some(Err(Error::last_os_error())) } if entry_ptr.is_null() { @@ -287,7 +301,7 @@ impl Drop for Dir { impl DirEntry { pub fn path(&self) -> PathBuf { - self.dir.0.root.join(OsStr::from_bytes(self.name_bytes())) + self.dir.inner.root.join(OsStr::from_bytes(self.name_bytes())) } pub fn file_name(&self) -> OsString { @@ -296,7 +310,7 @@ impl DirEntry { #[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))] pub fn metadata(&self) -> io::Result { - let fd = cvt(unsafe {dirfd(self.dir.0.dirp.0)})?; + let fd = cvt(unsafe {dirfd(self.dir.inner.dirp.0)})?; let mut stat: stat64 = unsafe { mem::zeroed() }; cvt(unsafe { fstatat(fd, @@ -692,7 +706,10 @@ pub fn readdir(p: &Path) -> io::Result { Err(Error::last_os_error()) } else { let inner = InnerReadDir { dirp: Dir(ptr), root }; - Ok(ReadDir(Arc::new(inner))) + Ok(ReadDir{ + inner: Arc::new(inner), + end_of_stream: false, + }) } } } -- cgit 1.4.1-3-g733a5 From 231c61a76bba716ad0a7d571f64825d57be2a75e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 13 Jun 2018 22:28:21 +0200 Subject: Add missing allow_missing_docs --- src/libstd/sys/windows/ext/mod.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/ext/mod.rs b/src/libstd/sys/windows/ext/mod.rs index 4b458d293bc..1f10609f32c 100644 --- a/src/libstd/sys/windows/ext/mod.rs +++ b/src/libstd/sys/windows/ext/mod.rs @@ -18,6 +18,7 @@ #![stable(feature = "rust1", since = "1.0.0")] #![doc(cfg(windows))] +#![allow(missing_docs)] pub mod ffi; pub mod fs; -- cgit 1.4.1-3-g733a5 From 8f0909c9792f01fff4ff8196194d99f59d7e3682 Mon Sep 17 00:00:00 2001 From: Chris Cesare Date: Thu, 14 Jun 2018 11:39:28 -0400 Subject: Removed two unused variables --- src/libstd/sys/redox/os.rs | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs index 480765b77a0..5822216779b 100644 --- a/src/libstd/sys/redox/os.rs +++ b/src/libstd/sys/redox/os.rs @@ -30,9 +30,6 @@ use sys_common::mutex::Mutex; use sys::{cvt, fd, syscall}; use vec; -const TMPBUF_SZ: usize = 128; -static ENV_LOCK: Mutex = Mutex::new(); - extern { #[link_name = "__errno_location"] fn errno_location() -> *mut i32; -- cgit 1.4.1-3-g733a5 From 6a03884ce99df2002ddaa1155de65384f7767cd5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 15 Jun 2018 10:00:57 +0200 Subject: Fix issue on unix --- src/libstd/sys/unix/ext/mod.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/ext/mod.rs b/src/libstd/sys/unix/ext/mod.rs index c221f7c8cfe..88e4237f8e2 100644 --- a/src/libstd/sys/unix/ext/mod.rs +++ b/src/libstd/sys/unix/ext/mod.rs @@ -35,6 +35,7 @@ #![stable(feature = "rust1", since = "1.0.0")] #![doc(cfg(unix))] +#![allow(missing_docs)] pub mod io; pub mod ffi; -- cgit 1.4.1-3-g733a5 From b81da278623d9dcda1776008612bd42e1922e9c3 Mon Sep 17 00:00:00 2001 From: "NODA, Kai" Date: Sat, 9 Jun 2018 21:13:04 +0800 Subject: libstd: add an RAII utility for sys_common::mutex::Mutex Signed-off-by: NODA, Kai --- src/libstd/io/lazy.rs | 21 +++++++++++---------- src/libstd/sync/mutex.rs | 4 ++-- src/libstd/sys/redox/args.rs | 16 ++++++---------- src/libstd/sys/unix/args.rs | 14 +++++--------- src/libstd/sys/unix/os.rs | 26 +++++++++----------------- src/libstd/sys_common/at_exit_imp.rs | 27 ++++++++++++++------------- src/libstd/sys_common/mutex.rs | 26 ++++++++++++++++++++++++-- src/libstd/sys_common/thread_local.rs | 3 +-- src/libstd/thread/mod.rs | 5 +---- 9 files changed, 73 insertions(+), 69 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/io/lazy.rs b/src/libstd/io/lazy.rs index 9cef4e3cdf1..d357966be92 100644 --- a/src/libstd/io/lazy.rs +++ b/src/libstd/io/lazy.rs @@ -20,6 +20,9 @@ pub struct Lazy { init: fn() -> Arc, } +#[inline] +const fn done() -> *mut Arc { 1_usize as *mut _ } + unsafe impl Sync for Lazy {} impl Lazy { @@ -33,17 +36,15 @@ impl Lazy { pub fn get(&'static self) -> Option> { unsafe { - self.lock.lock(); + let _guard = self.lock.lock(); let ptr = self.ptr.get(); - let ret = if ptr.is_null() { + if ptr.is_null() { Some(self.init()) - } else if ptr as usize == 1 { + } else if ptr == done() { None } else { Some((*ptr).clone()) - }; - self.lock.unlock(); - return ret + } } } @@ -53,10 +54,10 @@ impl Lazy { // the at exit handler). Otherwise we just return the freshly allocated // `Arc`. let registered = sys_common::at_exit(move || { - self.lock.lock(); - let ptr = self.ptr.get(); - self.ptr.set(1 as *mut _); - self.lock.unlock(); + let ptr = { + let _guard = self.lock.lock(); + self.ptr.replace(done()) + }; drop(Box::from_raw(ptr)) }); let ret = (self.init)(); diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index f3503b0b3a6..e5a410644b9 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -227,7 +227,7 @@ impl Mutex { #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> LockResult> { unsafe { - self.inner.lock(); + self.inner.raw_lock(); MutexGuard::new(self) } } @@ -454,7 +454,7 @@ impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> { fn drop(&mut self) { unsafe { self.__lock.poison.done(&self.__poison); - self.__lock.inner.unlock(); + self.__lock.inner.raw_unlock(); } } } diff --git a/src/libstd/sys/redox/args.rs b/src/libstd/sys/redox/args.rs index 59ae2a74a6d..556ed77372e 100644 --- a/src/libstd/sys/redox/args.rs +++ b/src/libstd/sys/redox/args.rs @@ -73,17 +73,15 @@ mod imp { CStr::from_ptr(*argv.offset(i) as *const libc::c_char).to_bytes().to_vec() }).collect(); - LOCK.lock(); + let _guard = LOCK.lock(); let ptr = get_global_ptr(); assert!((*ptr).is_none()); (*ptr) = Some(box args); - LOCK.unlock(); } pub unsafe fn cleanup() { - LOCK.lock(); + let _guard = LOCK.lock(); *get_global_ptr() = None; - LOCK.unlock(); } pub fn args() -> Args { @@ -96,16 +94,14 @@ mod imp { fn clone() -> Option>> { unsafe { - LOCK.lock(); + let _guard = LOCK.lock(); let ptr = get_global_ptr(); - let ret = (*ptr).as_ref().map(|s| (**s).clone()); - LOCK.unlock(); - return ret + (*ptr).as_ref().map(|s| (**s).clone()) } } - fn get_global_ptr() -> *mut Option>>> { - unsafe { mem::transmute(&GLOBAL_ARGS_PTR) } + unsafe fn get_global_ptr() -> *mut Option>>> { + mem::transmute(&GLOBAL_ARGS_PTR) } } diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs index e1c7ffc19e5..dc1dba6f2f9 100644 --- a/src/libstd/sys/unix/args.rs +++ b/src/libstd/sys/unix/args.rs @@ -82,17 +82,15 @@ mod imp { static LOCK: Mutex = Mutex::new(); pub unsafe fn init(argc: isize, argv: *const *const u8) { - LOCK.lock(); + let _guard = LOCK.lock(); ARGC = argc; ARGV = argv; - LOCK.unlock(); } pub unsafe fn cleanup() { - LOCK.lock(); + let _guard = LOCK.lock(); ARGC = 0; ARGV = ptr::null(); - LOCK.unlock(); } pub fn args() -> Args { @@ -104,13 +102,11 @@ mod imp { fn clone() -> Vec { unsafe { - LOCK.lock(); - let ret = (0..ARGC).map(|i| { + let _guard = LOCK.lock(); + (0..ARGC).map(|i| { let cstr = CStr::from_ptr(*ARGV.offset(i) as *const libc::c_char); OsStringExt::from_vec(cstr.to_bytes().to_vec()) - }).collect(); - LOCK.unlock(); - return ret + }).collect() } } } diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 4c86fddee4b..82d05f78850 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -409,10 +409,9 @@ pub unsafe fn environ() -> *mut *const *const c_char { /// environment variables of the current process. pub fn env() -> Env { unsafe { - ENV_LOCK.lock(); + let _guard = ENV_LOCK.lock(); let mut environ = *environ(); if environ == ptr::null() { - ENV_LOCK.unlock(); panic!("os::env() failure getting env string from OS: {}", io::Error::last_os_error()); } @@ -423,12 +422,10 @@ pub fn env() -> Env { } environ = environ.offset(1); } - let ret = Env { + return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData, - }; - ENV_LOCK.unlock(); - return ret + } } fn parse(input: &[u8]) -> Option<(OsString, OsString)> { @@ -452,15 +449,14 @@ pub fn getenv(k: &OsStr) -> io::Result> { // always None as well let k = CString::new(k.as_bytes())?; unsafe { - ENV_LOCK.lock(); + let _guard = ENV_LOCK.lock(); let s = libc::getenv(k.as_ptr()) as *const libc::c_char; let ret = if s.is_null() { None } else { Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec())) }; - ENV_LOCK.unlock(); - return Ok(ret) + Ok(ret) } } @@ -469,10 +465,8 @@ pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { let v = CString::new(v.as_bytes())?; unsafe { - ENV_LOCK.lock(); - let ret = cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ()); - ENV_LOCK.unlock(); - return ret + let _guard = ENV_LOCK.lock(); + cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ()) } } @@ -480,10 +474,8 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> { let nbuf = CString::new(n.as_bytes())?; unsafe { - ENV_LOCK.lock(); - let ret = cvt(libc::unsetenv(nbuf.as_ptr())).map(|_| ()); - ENV_LOCK.unlock(); - return ret + let _guard = ENV_LOCK.lock(); + cvt(libc::unsetenv(nbuf.as_ptr())).map(|_| ()) } } diff --git a/src/libstd/sys_common/at_exit_imp.rs b/src/libstd/sys_common/at_exit_imp.rs index 26da51c9825..d268d9ad6f9 100644 --- a/src/libstd/sys_common/at_exit_imp.rs +++ b/src/libstd/sys_common/at_exit_imp.rs @@ -14,6 +14,7 @@ use boxed::FnBox; use ptr; +use mem; use sys_common::mutex::Mutex; type Queue = Vec>; @@ -25,6 +26,8 @@ type Queue = Vec>; static LOCK: Mutex = Mutex::new(); static mut QUEUE: *mut Queue = ptr::null_mut(); +const DONE: *mut Queue = 1_usize as *mut _; + // The maximum number of times the cleanup routines will be run. While running // the at_exit closures new ones may be registered, and this count is the number // of times the new closures will be allowed to register successfully. After @@ -35,7 +38,7 @@ unsafe fn init() -> bool { if QUEUE.is_null() { let state: Box = box Vec::new(); QUEUE = Box::into_raw(state); - } else if QUEUE as usize == 1 { + } else if QUEUE == DONE { // can't re-init after a cleanup return false } @@ -44,18 +47,18 @@ unsafe fn init() -> bool { } pub fn cleanup() { - for i in 0..ITERS { + for i in 1..=ITERS { unsafe { - LOCK.lock(); - let queue = QUEUE; - QUEUE = if i == ITERS - 1 {1} else {0} as *mut _; - LOCK.unlock(); + let queue = { + let _guard = LOCK.lock(); + mem::replace(&mut QUEUE, if i == ITERS { DONE } else { ptr::null_mut() }) + }; // make sure we're not recursively cleaning up - assert!(queue as usize != 1); + assert!(queue != DONE); // If we never called init, not need to cleanup! - if queue as usize != 0 { + if !queue.is_null() { let queue: Box = Box::from_raw(queue); for to_run in *queue { to_run(); @@ -66,15 +69,13 @@ pub fn cleanup() { } pub fn push(f: Box) -> bool { - let mut ret = true; unsafe { - LOCK.lock(); + let _guard = LOCK.lock(); if init() { (*QUEUE).push(f); + true } else { - ret = false; + false } - LOCK.unlock(); } - ret } diff --git a/src/libstd/sys_common/mutex.rs b/src/libstd/sys_common/mutex.rs index d1a738770d3..608355b7d70 100644 --- a/src/libstd/sys_common/mutex.rs +++ b/src/libstd/sys_common/mutex.rs @@ -37,7 +37,15 @@ impl Mutex { /// Behavior is undefined if the mutex has been moved between this and any /// previous function call. #[inline] - pub unsafe fn lock(&self) { self.0.lock() } + pub unsafe fn raw_lock(&self) { self.0.lock() } + + /// Calls raw_lock() and then returns an RAII guard to guarantee the mutex + /// will be unlocked. + #[inline] + pub unsafe fn lock(&self) -> MutexGuard { + self.raw_lock(); + MutexGuard(&self.0) + } /// Attempts to lock the mutex without blocking, returning whether it was /// successfully acquired or not. @@ -51,8 +59,11 @@ impl Mutex { /// /// Behavior is undefined if the current thread does not actually hold the /// mutex. + /// + /// Consider switching from the pair of raw_lock() and raw_unlock() to + /// lock() whenever possible. #[inline] - pub unsafe fn unlock(&self) { self.0.unlock() } + pub unsafe fn raw_unlock(&self) { self.0.unlock() } /// Deallocates all resources associated with this mutex. /// @@ -64,3 +75,14 @@ impl Mutex { // not meant to be exported to the outside world, just the containing module pub fn raw(mutex: &Mutex) -> &imp::Mutex { &mutex.0 } + +#[must_use] +/// A simple RAII utility for the above Mutex without the poisoning semantics. +pub struct MutexGuard<'a>(&'a imp::Mutex); + +impl<'a> Drop for MutexGuard<'a> { + #[inline] + fn drop(&mut self) { + unsafe { self.0.unlock(); } + } +} diff --git a/src/libstd/sys_common/thread_local.rs b/src/libstd/sys_common/thread_local.rs index d0d6224de0a..75f6b9ac7fd 100644 --- a/src/libstd/sys_common/thread_local.rs +++ b/src/libstd/sys_common/thread_local.rs @@ -162,13 +162,12 @@ impl StaticKey { // we just simplify the whole branch. if imp::requires_synchronized_create() { static INIT_LOCK: Mutex = Mutex::new(); - INIT_LOCK.lock(); + let _guard = INIT_LOCK.lock(); let mut key = self.key.load(Ordering::SeqCst); if key == 0 { key = imp::create(self.dtor) as usize; self.key.store(key, Ordering::SeqCst); } - INIT_LOCK.unlock(); rtassert!(key != 0); return key } diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 1b976b79b4c..1dacf99b64b 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -935,20 +935,17 @@ impl ThreadId { static mut COUNTER: u64 = 0; unsafe { - GUARD.lock(); + let _guard = GUARD.lock(); // If we somehow use up all our bits, panic so that we're not // covering up subtle bugs of IDs being reused. if COUNTER == ::u64::MAX { - GUARD.unlock(); panic!("failed to generate unique thread ID: bitspace exhausted"); } let id = COUNTER; COUNTER += 1; - GUARD.unlock(); - ThreadId(id) } } -- cgit 1.4.1-3-g733a5 From 03a40b31a74d62923ab616bb64e24c7f90ef3daf Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Tue, 19 Jun 2018 09:46:51 -0700 Subject: Update zx_cprng_draw_new on Fuchsia Fuchsia is changing the semantics for zx_cprng_draw and zx_cprng_draw_new is a temporary name for the new semantics. --- src/libstd/sys/unix/rand.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index caa18945765..3f7f0671490 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -183,15 +183,14 @@ mod imp { mod imp { #[link(name = "zircon")] extern { - fn zx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32; + fn zx_cprng_draw_new(buffer: *mut u8, len: usize) -> i32; } fn getrandom(buf: &mut [u8]) -> Result { unsafe { - let mut actual = 0; - let status = zx_cprng_draw(buf.as_mut_ptr(), buf.len(), &mut actual); + let status = zx_cprng_draw_new(buf.as_mut_ptr(), buf.len()); if status == 0 { - Ok(actual) + Ok(buf.len()) } else { Err(status) } -- cgit 1.4.1-3-g733a5 From d259f4364738d911128d6e8ad863d0066733a343 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 20 Jun 2018 00:04:59 +0200 Subject: Fix doc build on unknown windows target --- src/libstd/sys/mod.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs index 1231898ed7e..b5bf4044be4 100644 --- a/src/libstd/sys/mod.rs +++ b/src/libstd/sys/mod.rs @@ -67,6 +67,7 @@ cfg_if! { // (missing things in `libc` which is empty) so just omit everything // with an empty module #[unstable(issue = "0", feature = "std_internals")] + #[allow(missing_docs)] pub mod unix_ext {} } else { // On other platforms like Windows document the bare bones of unix @@ -80,6 +81,7 @@ cfg_if! { cfg_if! { if #[cfg(windows)] { // On windows we'll just be documenting what's already available + #[allow(missing_docs)] pub use self::ext as windows_ext; } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32"))] { // On CloudABI and wasm right now the shim below doesn't compile, so -- cgit 1.4.1-3-g733a5 From 3c6c18d095b7cdafadffcc7ae3c39b037e4e793d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Jun 2018 20:38:29 +0200 Subject: Add missing \[allow(missing_docs)\] --- src/libstd/sys/mod.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs index b5bf4044be4..c44db3b1072 100644 --- a/src/libstd/sys/mod.rs +++ b/src/libstd/sys/mod.rs @@ -87,6 +87,7 @@ cfg_if! { // On CloudABI and wasm right now the shim below doesn't compile, so // just omit it #[unstable(issue = "0", feature = "std_internals")] + #[allow(missing_docs)] pub mod windows_ext {} } else { // On all other platforms (aka linux/osx/etc) then pull in a "minimal" -- cgit 1.4.1-3-g733a5 From 65d31d726940fe87f95f497323de7473da51f229 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 25 Jun 2018 11:42:27 -0700 Subject: Use fstatat64 where available --- src/libstd/sys/unix/fs.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 774340388e1..6949e22c58f 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -25,10 +25,12 @@ use sys_common::{AsInner, FromInner}; #[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "l4re"))] use libc::{stat64, fstat64, lstat64, off64_t, ftruncate64, lseek64, dirent64, readdir64_r, open64}; +#[cfg(any(target_os = "linux", target_os = "emscripten"))] +use libc::fstatat64; #[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))] -use libc::{fstatat, dirfd}; +use libc::dirfd; #[cfg(target_os = "android")] -use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, lseek64, +use libc::{stat as stat64, fstat as fstat64, fstatat as fstatat64, lstat as lstat64, lseek64, dirent as dirent64, open as open64}; #[cfg(not(any(target_os = "linux", target_os = "emscripten", @@ -299,10 +301,7 @@ impl DirEntry { let fd = cvt(unsafe {dirfd(self.dir.0.dirp.0)})?; let mut stat: stat64 = unsafe { mem::zeroed() }; cvt(unsafe { - fstatat(fd, - self.entry.d_name.as_ptr(), - &mut stat as *mut _ as *mut _, - libc::AT_SYMLINK_NOFOLLOW) + fstatat64(fd, self.entry.d_name.as_ptr(), &mut stat, libc::AT_SYMLINK_NOFOLLOW) })?; Ok(FileAttr { stat: stat }) } -- cgit 1.4.1-3-g733a5 From 490f49fd2ab15ae25a6ffeae2de8f667a521f19d Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 25 Jun 2018 12:34:33 -0700 Subject: Remove unnecessary stat64 pointer casts In effect, these just casted `&mut stat64` to `*mut stat64`, twice. That's harmless, but it masked a problem when this was copied to new code calling `fstatat`, which takes a pointer to `struct stat`. That will be fixed by #51785, but let's remove the unnecessary casts here too. --- src/libstd/sys/unix/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 774340388e1..93e2f4425b6 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -787,7 +787,7 @@ pub fn stat(p: &Path) -> io::Result { let p = cstr(p)?; let mut stat: stat64 = unsafe { mem::zeroed() }; cvt(unsafe { - stat64(p.as_ptr(), &mut stat as *mut _ as *mut _) + stat64(p.as_ptr(), &mut stat) })?; Ok(FileAttr { stat: stat }) } @@ -796,7 +796,7 @@ pub fn lstat(p: &Path) -> io::Result { let p = cstr(p)?; let mut stat: stat64 = unsafe { mem::zeroed() }; cvt(unsafe { - lstat64(p.as_ptr(), &mut stat as *mut _ as *mut _) + lstat64(p.as_ptr(), &mut stat) })?; Ok(FileAttr { stat: stat }) } -- cgit 1.4.1-3-g733a5 From 7015dfd1b9cfc02cd1f6dc30cd88b106211a3921 Mon Sep 17 00:00:00 2001 From: Dror Levin Date: Tue, 26 Jun 2018 13:29:36 +0300 Subject: Add read_exact_at and write_all_at methods to FileExt on unix --- src/libstd/sys/unix/ext/fs.rs | 127 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 4e981012669..4c2cea0d32c 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -59,6 +59,78 @@ pub trait FileExt { #[stable(feature = "file_offset", since = "1.15.0")] fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result; + /// Reads the exact number of byte required to fill `buf` from the given offset. + /// + /// The offset is relative to the start of the file and thus independent + /// from the current cursor. + /// + /// The current file cursor is not affected by this function. + /// + /// Similar to [`Read::read_exact`] but uses [`read_at`] instead of `read`. + /// + /// [`Read::read_exact`]: ../../../../std/io/trait.Read.html#method.read_exact + /// [`read_at`]: #tymethod.read_at + /// + /// # Errors + /// + /// If this function encounters an error of the kind + /// [`ErrorKind::Interrupted`] then the error is ignored and the operation + /// will continue. + /// + /// If this function encounters an "end of file" before completely filling + /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`]. + /// The contents of `buf` are unspecified in this case. + /// + /// If any other read error is encountered then this function immediately + /// returns. The contents of `buf` are unspecified in this case. + /// + /// If this function returns an error, it is unspecified how many bytes it + /// has read, but it will never read more than would be necessary to + /// completely fill the buffer. + /// + /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted + /// [`ErrorKind::UnexpectedEof`]: ../../../../std/io/enum.ErrorKind.html#variant.UnexpectedEof + /// + /// # Examples + /// + /// ```no_run + /// #![feature(rw_exact_all_at)] + /// use std::io; + /// use std::fs::File; + /// use std::os::unix::prelude::FileExt; + /// + /// fn main() -> io::Result<()> { + /// let mut buf = [0u8; 8]; + /// let file = File::open("foo.txt")?; + /// + /// // We now read exactly 8 bytes from the offset 10. + /// file.read_exact_at(&mut buf, 10)?; + /// println!("read {} bytes: {:?}", buf.len(), buf); + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "rw_exact_all_at", issue = "0")] + fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> { + while !buf.is_empty() { + match self.read_at(buf, offset) { + Ok(0) => break, + Ok(n) => { + let tmp = buf; + buf = &mut tmp[n..]; + offset += n as u64; + } + Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} + Err(e) => return Err(e), + } + } + if !buf.is_empty() { + Err(io::Error::new(io::ErrorKind::UnexpectedEof, + "failed to fill whole buffer")) + } else { + Ok(()) + } + } + /// Writes a number of bytes starting from a given offset. /// /// Returns the number of bytes written. @@ -93,6 +165,61 @@ pub trait FileExt { /// ``` #[stable(feature = "file_offset", since = "1.15.0")] fn write_at(&self, buf: &[u8], offset: u64) -> io::Result; + + /// Attempts to write an entire buffer starting from a given offset. + /// + /// The offset is relative to the start of the file and thus independent + /// from the current cursor. + /// + /// The current file cursor is not affected by this function. + /// + /// This method will continuously call [`write_at`] until there is no more data + /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is + /// returned. This method will not return until the entire buffer has been + /// successfully written or such an error occurs. The first error that is + /// not of [`ErrorKind::Interrupted`] kind generated from this method will be + /// returned. + /// + /// # Errors + /// + /// This function will return the first error of + /// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns. + /// + /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted + /// [`write_at`]: #tymethod.write_at + /// + /// # Examples + /// + /// ```no_run + /// #![feature(rw_exact_all_at)] + /// use std::fs::File; + /// use std::io; + /// use std::os::unix::prelude::FileExt; + /// + /// fn main() -> io::Result<()> { + /// let file = File::open("foo.txt")?; + /// + /// // We now write at the offset 10. + /// file.write_all_at(b"sushi", 10)?; + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "rw_exact_all_at", issue = "0")] + fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> { + while !buf.is_empty() { + match self.write_at(buf, offset) { + Ok(0) => return Err(io::Error::new(io::ErrorKind::WriteZero, + "failed to write whole buffer")), + Ok(n) => { + buf = &buf[n..]; + offset += n as u64 + } + Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} + Err(e) => return Err(e), + } + } + Ok(()) + } } #[stable(feature = "file_offset", since = "1.15.0")] -- cgit 1.4.1-3-g733a5 From 2394549af5fafa0eb7e52ff291970be5b35af7cf Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Thu, 14 Jun 2018 08:42:13 +0200 Subject: Unix sockets on redox! --- src/libstd/sys/redox/ext/mod.rs | 1 + src/libstd/sys/redox/ext/net.rs | 728 ++++++++++++++++++++++++++++++++++++++++ src/libstd/sys/redox/fd.rs | 5 +- 3 files changed, 733 insertions(+), 1 deletion(-) create mode 100644 src/libstd/sys/redox/ext/net.rs (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/mod.rs b/src/libstd/sys/redox/ext/mod.rs index 9fd8d6c9186..cb2c75ae0bf 100644 --- a/src/libstd/sys/redox/ext/mod.rs +++ b/src/libstd/sys/redox/ext/mod.rs @@ -33,6 +33,7 @@ pub mod ffi; pub mod fs; pub mod io; +pub mod net; pub mod process; pub mod thread; diff --git a/src/libstd/sys/redox/ext/net.rs b/src/libstd/sys/redox/ext/net.rs new file mode 100644 index 00000000000..78ed8194088 --- /dev/null +++ b/src/libstd/sys/redox/ext/net.rs @@ -0,0 +1,728 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![stable(feature = "unix_socket", since = "1.10.0")] + +//! Unix-specific networking functionality + +use fmt; +use io::{self, Error, ErrorKind, Initializer}; +use net::Shutdown; +use os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd}; +use path::Path; +use time::Duration; +use sys::{cvt, fd::FileDesc, syscall}; + +/// An address associated with a Unix socket. +/// +/// # Examples +/// +/// ``` +/// use std::os::unix::net::UnixListener; +/// +/// let socket = match UnixListener::bind("/tmp/sock") { +/// Ok(sock) => sock, +/// Err(e) => { +/// println!("Couldn't bind: {:?}", e); +/// return +/// } +/// }; +/// let addr = socket.local_addr().expect("Couldn't get local address"); +/// ``` +#[stable(feature = "unix_socket", since = "1.10.0")] +#[derive(Clone)] +pub struct SocketAddr; + +impl SocketAddr { + /// Returns the contents of this address if it is a `pathname` address. + /// + /// # Examples + /// + /// With a pathname: + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// use std::path::Path; + /// + /// let socket = UnixListener::bind("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock"))); + /// ``` + /// + /// Without a pathname: + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// + /// let socket = UnixDatagram::unbound().unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.as_pathname(), None); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn as_pathname(&self) -> Option<&Path> { + None + } +} +#[stable(feature = "unix_socket", since = "1.10.0")] +impl fmt::Debug for SocketAddr { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "SocketAddr") + } +} + +/// A Unix stream socket. +/// +/// # Examples +/// +/// ```no_run +/// use std::os::unix::net::UnixStream; +/// use std::io::prelude::*; +/// +/// let mut stream = UnixStream::connect("/path/to/my/socket").unwrap(); +/// stream.write_all(b"hello world").unwrap(); +/// let mut response = String::new(); +/// stream.read_to_string(&mut response).unwrap(); +/// println!("{}", response); +/// ``` +#[stable(feature = "unix_socket", since = "1.10.0")] +pub struct UnixStream(FileDesc); + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl fmt::Debug for UnixStream { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut builder = fmt.debug_struct("UnixStream"); + builder.field("fd", &self.0.raw()); + if let Ok(addr) = self.local_addr() { + builder.field("local", &addr); + } + if let Ok(addr) = self.peer_addr() { + builder.field("peer", &addr); + } + builder.finish() + } +} + +impl UnixStream { + /// Connects to the socket named by `path`. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = match UnixStream::connect("/tmp/sock") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return + /// } + /// }; + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn connect>(path: P) -> io::Result { + if let Some(s) = path.as_ref().to_str() { + cvt(syscall::open(format!("chan:{}", s), syscall::O_CLOEXEC)) + .map(FileDesc::new) + .map(UnixStream) + } else { + Err(Error::new(ErrorKind::Other, "UnixStream::connect: non-utf8 paths not supported on redox")) + } + } + + /// Creates an unnamed pair of connected sockets. + /// + /// Returns two `UnixStream`s which are connected to each other. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let (sock1, sock2) = match UnixStream::pair() { + /// Ok((sock1, sock2)) => (sock1, sock2), + /// Err(e) => { + /// println!("Couldn't create a pair of sockets: {:?}", e); + /// return + /// } + /// }; + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn pair() -> io::Result<(UnixStream, UnixStream)> { + let server = cvt(syscall::open("chan:", syscall::O_CREAT | syscall::O_CLOEXEC)).map(FileDesc::new)?; + let client = server.duplicate_path(b"connect")?; + let stream = server.duplicate_path(b"listen")?; + Ok((UnixStream(client), UnixStream(stream))) + } + + /// Creates a new independently owned handle to the underlying socket. + /// + /// The returned `UnixStream` is a reference to the same stream that this + /// object references. Both handles will read and write the same stream of + /// data, and options set on one stream will be propagated to the other + /// stream. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn try_clone(&self) -> io::Result { + self.0.duplicate().map(UnixStream) + } + + /// Returns the socket address of the local half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn local_addr(&self) -> io::Result { + Err(Error::new(ErrorKind::Other, "UnixStream::local_addr unimplemented on redox")) + } + + /// Returns the socket address of the remote half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let addr = socket.peer_addr().expect("Couldn't get peer address"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn peer_addr(&self) -> io::Result { + Err(Error::new(ErrorKind::Other, "UnixStream::peer_addr unimplemented on redox")) + } + + /// Sets the read timeout for the socket. + /// + /// If the provided value is [`None`], then [`read`] calls will block + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err + /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read + /// [`Duration`]: ../../../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn set_read_timeout(&self, _timeout: Option) -> io::Result<()> { + Err(Error::new(ErrorKind::Other, "UnixStream::set_read_timeout unimplemented on redox")) + } + + /// Sets the write timeout for the socket. + /// + /// If the provided value is [`None`], then [`write`] calls will block + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is + /// passed to this method. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err + /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write + /// [`Duration`]: ../../../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); + /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::net::UdpSocket; + /// use std::time::Duration; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); + /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn set_write_timeout(&self, _timeout: Option) -> io::Result<()> { + Err(Error::new(ErrorKind::Other, "UnixStream::set_write_timeout unimplemented on redox")) + } + + /// Returns the read timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn read_timeout(&self) -> io::Result> { + Err(Error::new(ErrorKind::Other, "UnixStream::read_timeout unimplemented on redox")) + } + + /// Returns the write timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); + /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn write_timeout(&self) -> io::Result> { + Err(Error::new(ErrorKind::Other, "UnixStream::write_timeout unimplemented on redox")) + } + + /// Moves the socket into or out of nonblocking mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.0.set_nonblocking(nonblocking) + } + + /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// if let Ok(Some(err)) = socket.take_error() { + /// println!("Got error: {:?}", err); + /// } + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn take_error(&self) -> io::Result> { + Err(Error::new(ErrorKind::Other, "UnixStream::take_error unimplemented on redox")) + } + + /// Shuts down the read, write, or both halves of this connection. + /// + /// This function will cause all pending and future I/O calls on the + /// specified portions to immediately return with an appropriate value + /// (see the documentation of [`Shutdown`]). + /// + /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::net::Shutdown; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { + Err(Error::new(ErrorKind::Other, "UnixStream::shutdown unimplemented on redox")) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl io::Read for UnixStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + io::Read::read(&mut &*self, buf) + } + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl<'a> io::Read for &'a UnixStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.0.read(buf) + } + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl io::Write for UnixStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + io::Write::write(&mut &*self, buf) + } + + fn flush(&mut self) -> io::Result<()> { + io::Write::flush(&mut &*self) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl<'a> io::Write for &'a UnixStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl AsRawFd for UnixStream { + fn as_raw_fd(&self) -> RawFd { + self.0.raw() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl FromRawFd for UnixStream { + unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { + UnixStream(FileDesc::new(fd)) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl IntoRawFd for UnixStream { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw() + } +} + +/// A structure representing a Unix domain socket server. +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// use std::os::unix::net::{UnixStream, UnixListener}; +/// +/// fn handle_client(stream: UnixStream) { +/// // ... +/// } +/// +/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); +/// +/// // accept connections and process them, spawning a new thread for each one +/// for stream in listener.incoming() { +/// match stream { +/// Ok(stream) => { +/// /* connection succeeded */ +/// thread::spawn(|| handle_client(stream)); +/// } +/// Err(err) => { +/// /* connection failed */ +/// break; +/// } +/// } +/// } +/// ``` +#[stable(feature = "unix_socket", since = "1.10.0")] +pub struct UnixListener(FileDesc); + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl fmt::Debug for UnixListener { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut builder = fmt.debug_struct("UnixListener"); + builder.field("fd", &self.0.raw()); + if let Ok(addr) = self.local_addr() { + builder.field("local", &addr); + } + builder.finish() + } +} + +impl UnixListener { + /// Creates a new `UnixListener` bound to the specified socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = match UnixListener::bind("/path/to/the/socket") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return + /// } + /// }; + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn bind>(path: P) -> io::Result { + if let Some(s) = path.as_ref().to_str() { + cvt(syscall::open(format!("chan:{}", s), syscall::O_CREAT | syscall::O_CLOEXEC)) + .map(FileDesc::new) + .map(UnixListener) + } else { + Err(Error::new(ErrorKind::Other, "UnixListener::bind: non-utf8 paths not supported on redox")) + } + } + + /// Accepts a new incoming connection to this listener. + /// + /// This function will block the calling thread until a new Unix connection + /// is established. When established, the corresponding [`UnixStream`] and + /// the remote peer's address will be returned. + /// + /// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// match listener.accept() { + /// Ok((socket, addr)) => println!("Got a client: {:?}", addr), + /// Err(e) => println!("accept function failed: {:?}", e), + /// } + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { + self.0.duplicate_path(b"listen").map(|fd| (UnixStream(fd), SocketAddr)) + } + + /// Creates a new independently owned handle to the underlying socket. + /// + /// The returned `UnixListener` is a reference to the same socket that this + /// object references. Both handles can be used to accept incoming + /// connections and options set on one listener will affect the other. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// let listener_copy = listener.try_clone().expect("try_clone failed"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn try_clone(&self) -> io::Result { + self.0.duplicate().map(UnixListener) + } + + /// Returns the local socket address of this listener. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// let addr = listener.local_addr().expect("Couldn't get local address"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn local_addr(&self) -> io::Result { + Err(Error::new(ErrorKind::Other, "UnixListener::local_addr unimplemented on redox")) + } + + /// Moves the socket into or out of nonblocking mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.0.set_nonblocking(nonblocking) + } + + /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/tmp/sock").unwrap(); + /// + /// if let Ok(Some(err)) = listener.take_error() { + /// println!("Got error: {:?}", err); + /// } + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn take_error(&self) -> io::Result> { + Err(Error::new(ErrorKind::Other, "UnixListener::take_error unimplemented on redox")) + } + + /// Returns an iterator over incoming connections. + /// + /// The iterator will never return [`None`] and will also not yield the + /// peer's [`SocketAddr`] structure. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`SocketAddr`]: struct.SocketAddr.html + /// + /// # Examples + /// + /// ```no_run + /// use std::thread; + /// use std::os::unix::net::{UnixStream, UnixListener}; + /// + /// fn handle_client(stream: UnixStream) { + /// // ... + /// } + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// for stream in listener.incoming() { + /// match stream { + /// Ok(stream) => { + /// thread::spawn(|| handle_client(stream)); + /// } + /// Err(err) => { + /// break; + /// } + /// } + /// } + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn incoming<'a>(&'a self) -> Incoming<'a> { + Incoming { listener: self } + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl AsRawFd for UnixListener { + fn as_raw_fd(&self) -> RawFd { + self.0.raw() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl FromRawFd for UnixListener { + unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { + UnixListener(FileDesc::new(fd)) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl IntoRawFd for UnixListener { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl<'a> IntoIterator for &'a UnixListener { + type Item = io::Result; + type IntoIter = Incoming<'a>; + + fn into_iter(self) -> Incoming<'a> { + self.incoming() + } +} + +/// An iterator over incoming connections to a [`UnixListener`]. +/// +/// It will never return [`None`]. +/// +/// [`None`]: ../../../../std/option/enum.Option.html#variant.None +/// [`UnixListener`]: struct.UnixListener.html +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// use std::os::unix::net::{UnixStream, UnixListener}; +/// +/// fn handle_client(stream: UnixStream) { +/// // ... +/// } +/// +/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); +/// +/// for stream in listener.incoming() { +/// match stream { +/// Ok(stream) => { +/// thread::spawn(|| handle_client(stream)); +/// } +/// Err(err) => { +/// break; +/// } +/// } +/// } +/// ``` +#[derive(Debug)] +#[stable(feature = "unix_socket", since = "1.10.0")] +pub struct Incoming<'a> { + listener: &'a UnixListener, +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl<'a> Iterator for Incoming<'a> { + type Item = io::Result; + + fn next(&mut self) -> Option> { + Some(self.listener.accept().map(|s| s.0)) + } + + fn size_hint(&self) -> (usize, Option) { + (usize::max_value(), None) + } +} diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs index ba7bbdc657f..e04e2791b23 100644 --- a/src/libstd/sys/redox/fd.rs +++ b/src/libstd/sys/redox/fd.rs @@ -47,7 +47,10 @@ impl FileDesc { } pub fn duplicate(&self) -> io::Result { - let new_fd = cvt(syscall::dup(self.fd, &[]))?; + self.duplicate_path(&[]) + } + pub fn duplicate_path(&self, path: &[u8]) -> io::Result { + let new_fd = cvt(syscall::dup(self.fd, path))?; Ok(FileDesc::new(new_fd)) } -- cgit 1.4.1-3-g733a5 From 3b866b0ea44a27e8fa1f7bedabb42c92b670d467 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Thu, 14 Jun 2018 11:17:08 +0200 Subject: Make UnixStream::take_error return None on redox --- src/libstd/sys/redox/ext/net.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/net.rs b/src/libstd/sys/redox/ext/net.rs index 78ed8194088..abfbfaa8dbb 100644 --- a/src/libstd/sys/redox/ext/net.rs +++ b/src/libstd/sys/redox/ext/net.rs @@ -352,7 +352,7 @@ impl UnixStream { /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn take_error(&self) -> io::Result> { - Err(Error::new(ErrorKind::Other, "UnixStream::take_error unimplemented on redox")) + Ok(None) } /// Shuts down the read, write, or both halves of this connection. @@ -373,7 +373,7 @@ impl UnixStream { /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { + pub fn shutdown(&self, _how: Shutdown) -> io::Result<()> { Err(Error::new(ErrorKind::Other, "UnixStream::shutdown unimplemented on redox")) } } @@ -607,7 +607,7 @@ impl UnixListener { /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn take_error(&self) -> io::Result> { - Err(Error::new(ErrorKind::Other, "UnixListener::take_error unimplemented on redox")) + Ok(None) } /// Returns an iterator over incoming connections. -- cgit 1.4.1-3-g733a5 From 419500710d40d49eadc2dbea37aa83a64b2bf6d3 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Thu, 14 Jun 2018 16:24:01 +0200 Subject: Trim all lines to 100 --- src/libstd/sys/redox/ext/net.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/net.rs b/src/libstd/sys/redox/ext/net.rs index abfbfaa8dbb..21c3903e623 100644 --- a/src/libstd/sys/redox/ext/net.rs +++ b/src/libstd/sys/redox/ext/net.rs @@ -132,7 +132,10 @@ impl UnixStream { .map(FileDesc::new) .map(UnixStream) } else { - Err(Error::new(ErrorKind::Other, "UnixStream::connect: non-utf8 paths not supported on redox")) + Err(Error::new( + ErrorKind::Other, + "UnixStream::connect: non-utf8 paths not supported on redox" + )) } } @@ -155,7 +158,8 @@ impl UnixStream { /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn pair() -> io::Result<(UnixStream, UnixStream)> { - let server = cvt(syscall::open("chan:", syscall::O_CREAT | syscall::O_CLOEXEC)).map(FileDesc::new)?; + let server = cvt(syscall::open("chan:", syscall::O_CREAT | syscall::O_CLOEXEC)) + .map(FileDesc::new)?; let client = server.duplicate_path(b"connect")?; let stream = server.duplicate_path(b"listen")?; Ok((UnixStream(client), UnixStream(stream))) @@ -511,7 +515,10 @@ impl UnixListener { .map(FileDesc::new) .map(UnixListener) } else { - Err(Error::new(ErrorKind::Other, "UnixListener::bind: non-utf8 paths not supported on redox")) + Err(Error::new( + ErrorKind::Other, + "UnixListener::bind: non-utf8 paths not supported on redox" + )) } } -- cgit 1.4.1-3-g733a5 From c5977e3ea7e7c4f901e6c089294e0986373d41f8 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Thu, 14 Jun 2018 18:21:21 +0200 Subject: Custom feature gate (I think?) --- src/libstd/sys/redox/ext/net.rs | 80 ++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 40 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/net.rs b/src/libstd/sys/redox/ext/net.rs index 21c3903e623..b95f0dd02f1 100644 --- a/src/libstd/sys/redox/ext/net.rs +++ b/src/libstd/sys/redox/ext/net.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![stable(feature = "unix_socket", since = "1.10.0")] +#![stable(feature = "unix_socket_redox", since = "1.27.0")] //! Unix-specific networking functionality @@ -36,7 +36,7 @@ use sys::{cvt, fd::FileDesc, syscall}; /// }; /// let addr = socket.local_addr().expect("Couldn't get local address"); /// ``` -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] #[derive(Clone)] pub struct SocketAddr; @@ -65,12 +65,12 @@ impl SocketAddr { /// let addr = socket.local_addr().expect("Couldn't get local address"); /// assert_eq!(addr.as_pathname(), None); /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn as_pathname(&self) -> Option<&Path> { None } } -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl fmt::Debug for SocketAddr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "SocketAddr") @@ -91,10 +91,10 @@ impl fmt::Debug for SocketAddr { /// stream.read_to_string(&mut response).unwrap(); /// println!("{}", response); /// ``` -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] pub struct UnixStream(FileDesc); -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl fmt::Debug for UnixStream { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut builder = fmt.debug_struct("UnixStream"); @@ -125,7 +125,7 @@ impl UnixStream { /// } /// }; /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn connect>(path: P) -> io::Result { if let Some(s) = path.as_ref().to_str() { cvt(syscall::open(format!("chan:{}", s), syscall::O_CLOEXEC)) @@ -156,7 +156,7 @@ impl UnixStream { /// } /// }; /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn pair() -> io::Result<(UnixStream, UnixStream)> { let server = cvt(syscall::open("chan:", syscall::O_CREAT | syscall::O_CLOEXEC)) .map(FileDesc::new)?; @@ -180,7 +180,7 @@ impl UnixStream { /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UnixStream) } @@ -195,7 +195,7 @@ impl UnixStream { /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// let addr = socket.local_addr().expect("Couldn't get local address"); /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn local_addr(&self) -> io::Result { Err(Error::new(ErrorKind::Other, "UnixStream::local_addr unimplemented on redox")) } @@ -210,7 +210,7 @@ impl UnixStream { /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// let addr = socket.peer_addr().expect("Couldn't get peer address"); /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn peer_addr(&self) -> io::Result { Err(Error::new(ErrorKind::Other, "UnixStream::peer_addr unimplemented on redox")) } @@ -249,7 +249,7 @@ impl UnixStream { /// let err = result.unwrap_err(); /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn set_read_timeout(&self, _timeout: Option) -> io::Result<()> { Err(Error::new(ErrorKind::Other, "UnixStream::set_read_timeout unimplemented on redox")) } @@ -288,7 +288,7 @@ impl UnixStream { /// let err = result.unwrap_err(); /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn set_write_timeout(&self, _timeout: Option) -> io::Result<()> { Err(Error::new(ErrorKind::Other, "UnixStream::set_write_timeout unimplemented on redox")) } @@ -305,7 +305,7 @@ impl UnixStream { /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0))); /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn read_timeout(&self) -> io::Result> { Err(Error::new(ErrorKind::Other, "UnixStream::read_timeout unimplemented on redox")) } @@ -322,7 +322,7 @@ impl UnixStream { /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0))); /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn write_timeout(&self) -> io::Result> { Err(Error::new(ErrorKind::Other, "UnixStream::write_timeout unimplemented on redox")) } @@ -337,7 +337,7 @@ impl UnixStream { /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } @@ -354,7 +354,7 @@ impl UnixStream { /// println!("Got error: {:?}", err); /// } /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn take_error(&self) -> io::Result> { Ok(None) } @@ -376,13 +376,13 @@ impl UnixStream { /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn shutdown(&self, _how: Shutdown) -> io::Result<()> { Err(Error::new(ErrorKind::Other, "UnixStream::shutdown unimplemented on redox")) } } -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl io::Read for UnixStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { io::Read::read(&mut &*self, buf) @@ -394,7 +394,7 @@ impl io::Read for UnixStream { } } -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl<'a> io::Read for &'a UnixStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) @@ -406,7 +406,7 @@ impl<'a> io::Read for &'a UnixStream { } } -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl io::Write for UnixStream { fn write(&mut self, buf: &[u8]) -> io::Result { io::Write::write(&mut &*self, buf) @@ -417,7 +417,7 @@ impl io::Write for UnixStream { } } -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl<'a> io::Write for &'a UnixStream { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) @@ -428,21 +428,21 @@ impl<'a> io::Write for &'a UnixStream { } } -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl AsRawFd for UnixStream { fn as_raw_fd(&self) -> RawFd { self.0.raw() } } -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl FromRawFd for UnixStream { unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { UnixStream(FileDesc::new(fd)) } } -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl IntoRawFd for UnixStream { fn into_raw_fd(self) -> RawFd { self.0.into_raw() @@ -477,10 +477,10 @@ impl IntoRawFd for UnixStream { /// } /// } /// ``` -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] pub struct UnixListener(FileDesc); -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl fmt::Debug for UnixListener { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut builder = fmt.debug_struct("UnixListener"); @@ -508,7 +508,7 @@ impl UnixListener { /// } /// }; /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn bind>(path: P) -> io::Result { if let Some(s) = path.as_ref().to_str() { cvt(syscall::open(format!("chan:{}", s), syscall::O_CREAT | syscall::O_CLOEXEC)) @@ -542,7 +542,7 @@ impl UnixListener { /// Err(e) => println!("accept function failed: {:?}", e), /// } /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { self.0.duplicate_path(b"listen").map(|fd| (UnixStream(fd), SocketAddr)) } @@ -562,7 +562,7 @@ impl UnixListener { /// /// let listener_copy = listener.try_clone().expect("try_clone failed"); /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UnixListener) } @@ -578,7 +578,7 @@ impl UnixListener { /// /// let addr = listener.local_addr().expect("Couldn't get local address"); /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn local_addr(&self) -> io::Result { Err(Error::new(ErrorKind::Other, "UnixListener::local_addr unimplemented on redox")) } @@ -594,7 +594,7 @@ impl UnixListener { /// /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } @@ -612,7 +612,7 @@ impl UnixListener { /// println!("Got error: {:?}", err); /// } /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn take_error(&self) -> io::Result> { Ok(None) } @@ -648,34 +648,34 @@ impl UnixListener { /// } /// } /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] + #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn incoming<'a>(&'a self) -> Incoming<'a> { Incoming { listener: self } } } -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl AsRawFd for UnixListener { fn as_raw_fd(&self) -> RawFd { self.0.raw() } } -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl FromRawFd for UnixListener { unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { UnixListener(FileDesc::new(fd)) } } -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl IntoRawFd for UnixListener { fn into_raw_fd(self) -> RawFd { self.0.into_raw() } } -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl<'a> IntoIterator for &'a UnixListener { type Item = io::Result; type IntoIter = Incoming<'a>; @@ -716,12 +716,12 @@ impl<'a> IntoIterator for &'a UnixListener { /// } /// ``` #[derive(Debug)] -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] pub struct Incoming<'a> { listener: &'a UnixListener, } -#[stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl<'a> Iterator for Incoming<'a> { type Item = io::Result; -- cgit 1.4.1-3-g733a5 From 2161254d8a211e9e5caecf259ac9fbcad6479030 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Mon, 18 Jun 2018 06:30:38 +0200 Subject: Make feature unstable --- src/libstd/sys/redox/ext/net.rs | 41 +---------------------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/net.rs b/src/libstd/sys/redox/ext/net.rs index b95f0dd02f1..396a140fa1b 100644 --- a/src/libstd/sys/redox/ext/net.rs +++ b/src/libstd/sys/redox/ext/net.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![stable(feature = "unix_socket_redox", since = "1.27.0")] +#![unstable(feature = "unix_socket_redox", reason = "new feature", issue="51553")] //! Unix-specific networking functionality @@ -36,7 +36,6 @@ use sys::{cvt, fd::FileDesc, syscall}; /// }; /// let addr = socket.local_addr().expect("Couldn't get local address"); /// ``` -#[stable(feature = "unix_socket_redox", since = "1.27.0")] #[derive(Clone)] pub struct SocketAddr; @@ -65,12 +64,10 @@ impl SocketAddr { /// let addr = socket.local_addr().expect("Couldn't get local address"); /// assert_eq!(addr.as_pathname(), None); /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn as_pathname(&self) -> Option<&Path> { None } } -#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl fmt::Debug for SocketAddr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "SocketAddr") @@ -91,10 +88,8 @@ impl fmt::Debug for SocketAddr { /// stream.read_to_string(&mut response).unwrap(); /// println!("{}", response); /// ``` -#[stable(feature = "unix_socket_redox", since = "1.27.0")] pub struct UnixStream(FileDesc); -#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl fmt::Debug for UnixStream { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut builder = fmt.debug_struct("UnixStream"); @@ -125,7 +120,6 @@ impl UnixStream { /// } /// }; /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn connect>(path: P) -> io::Result { if let Some(s) = path.as_ref().to_str() { cvt(syscall::open(format!("chan:{}", s), syscall::O_CLOEXEC)) @@ -156,7 +150,6 @@ impl UnixStream { /// } /// }; /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn pair() -> io::Result<(UnixStream, UnixStream)> { let server = cvt(syscall::open("chan:", syscall::O_CREAT | syscall::O_CLOEXEC)) .map(FileDesc::new)?; @@ -180,7 +173,6 @@ impl UnixStream { /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UnixStream) } @@ -195,7 +187,6 @@ impl UnixStream { /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// let addr = socket.local_addr().expect("Couldn't get local address"); /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn local_addr(&self) -> io::Result { Err(Error::new(ErrorKind::Other, "UnixStream::local_addr unimplemented on redox")) } @@ -210,7 +201,6 @@ impl UnixStream { /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// let addr = socket.peer_addr().expect("Couldn't get peer address"); /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn peer_addr(&self) -> io::Result { Err(Error::new(ErrorKind::Other, "UnixStream::peer_addr unimplemented on redox")) } @@ -249,7 +239,6 @@ impl UnixStream { /// let err = result.unwrap_err(); /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn set_read_timeout(&self, _timeout: Option) -> io::Result<()> { Err(Error::new(ErrorKind::Other, "UnixStream::set_read_timeout unimplemented on redox")) } @@ -288,7 +277,6 @@ impl UnixStream { /// let err = result.unwrap_err(); /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn set_write_timeout(&self, _timeout: Option) -> io::Result<()> { Err(Error::new(ErrorKind::Other, "UnixStream::set_write_timeout unimplemented on redox")) } @@ -305,7 +293,6 @@ impl UnixStream { /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0))); /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn read_timeout(&self) -> io::Result> { Err(Error::new(ErrorKind::Other, "UnixStream::read_timeout unimplemented on redox")) } @@ -322,7 +309,6 @@ impl UnixStream { /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0))); /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn write_timeout(&self) -> io::Result> { Err(Error::new(ErrorKind::Other, "UnixStream::write_timeout unimplemented on redox")) } @@ -337,7 +323,6 @@ impl UnixStream { /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } @@ -354,7 +339,6 @@ impl UnixStream { /// println!("Got error: {:?}", err); /// } /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn take_error(&self) -> io::Result> { Ok(None) } @@ -376,13 +360,11 @@ impl UnixStream { /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn shutdown(&self, _how: Shutdown) -> io::Result<()> { Err(Error::new(ErrorKind::Other, "UnixStream::shutdown unimplemented on redox")) } } -#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl io::Read for UnixStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { io::Read::read(&mut &*self, buf) @@ -394,7 +376,6 @@ impl io::Read for UnixStream { } } -#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl<'a> io::Read for &'a UnixStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) @@ -406,7 +387,6 @@ impl<'a> io::Read for &'a UnixStream { } } -#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl io::Write for UnixStream { fn write(&mut self, buf: &[u8]) -> io::Result { io::Write::write(&mut &*self, buf) @@ -417,7 +397,6 @@ impl io::Write for UnixStream { } } -#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl<'a> io::Write for &'a UnixStream { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) @@ -428,21 +407,18 @@ impl<'a> io::Write for &'a UnixStream { } } -#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl AsRawFd for UnixStream { fn as_raw_fd(&self) -> RawFd { self.0.raw() } } -#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl FromRawFd for UnixStream { unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { UnixStream(FileDesc::new(fd)) } } -#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl IntoRawFd for UnixStream { fn into_raw_fd(self) -> RawFd { self.0.into_raw() @@ -477,10 +453,8 @@ impl IntoRawFd for UnixStream { /// } /// } /// ``` -#[stable(feature = "unix_socket_redox", since = "1.27.0")] pub struct UnixListener(FileDesc); -#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl fmt::Debug for UnixListener { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut builder = fmt.debug_struct("UnixListener"); @@ -508,7 +482,6 @@ impl UnixListener { /// } /// }; /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn bind>(path: P) -> io::Result { if let Some(s) = path.as_ref().to_str() { cvt(syscall::open(format!("chan:{}", s), syscall::O_CREAT | syscall::O_CLOEXEC)) @@ -542,7 +515,6 @@ impl UnixListener { /// Err(e) => println!("accept function failed: {:?}", e), /// } /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { self.0.duplicate_path(b"listen").map(|fd| (UnixStream(fd), SocketAddr)) } @@ -562,7 +534,6 @@ impl UnixListener { /// /// let listener_copy = listener.try_clone().expect("try_clone failed"); /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UnixListener) } @@ -578,7 +549,6 @@ impl UnixListener { /// /// let addr = listener.local_addr().expect("Couldn't get local address"); /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn local_addr(&self) -> io::Result { Err(Error::new(ErrorKind::Other, "UnixListener::local_addr unimplemented on redox")) } @@ -594,7 +564,6 @@ impl UnixListener { /// /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } @@ -612,7 +581,6 @@ impl UnixListener { /// println!("Got error: {:?}", err); /// } /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn take_error(&self) -> io::Result> { Ok(None) } @@ -648,34 +616,29 @@ impl UnixListener { /// } /// } /// ``` - #[stable(feature = "unix_socket_redox", since = "1.27.0")] pub fn incoming<'a>(&'a self) -> Incoming<'a> { Incoming { listener: self } } } -#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl AsRawFd for UnixListener { fn as_raw_fd(&self) -> RawFd { self.0.raw() } } -#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl FromRawFd for UnixListener { unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { UnixListener(FileDesc::new(fd)) } } -#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl IntoRawFd for UnixListener { fn into_raw_fd(self) -> RawFd { self.0.into_raw() } } -#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl<'a> IntoIterator for &'a UnixListener { type Item = io::Result; type IntoIter = Incoming<'a>; @@ -716,12 +679,10 @@ impl<'a> IntoIterator for &'a UnixListener { /// } /// ``` #[derive(Debug)] -#[stable(feature = "unix_socket_redox", since = "1.27.0")] pub struct Incoming<'a> { listener: &'a UnixListener, } -#[stable(feature = "unix_socket_redox", since = "1.27.0")] impl<'a> Iterator for Incoming<'a> { type Item = io::Result; -- cgit 1.4.1-3-g733a5 From 4286ad7f0d3e1c39ac31205e43011e29b1486dcf Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Mon, 18 Jun 2018 07:15:59 +0200 Subject: Disallow constructing SocketAddr from third-party code --- src/libstd/sys/redox/ext/net.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/net.rs b/src/libstd/sys/redox/ext/net.rs index 396a140fa1b..2ae7803378e 100644 --- a/src/libstd/sys/redox/ext/net.rs +++ b/src/libstd/sys/redox/ext/net.rs @@ -37,7 +37,7 @@ use sys::{cvt, fd::FileDesc, syscall}; /// let addr = socket.local_addr().expect("Couldn't get local address"); /// ``` #[derive(Clone)] -pub struct SocketAddr; +pub struct SocketAddr(()); impl SocketAddr { /// Returns the contents of this address if it is a `pathname` address. @@ -516,7 +516,7 @@ impl UnixListener { /// } /// ``` pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { - self.0.duplicate_path(b"listen").map(|fd| (UnixStream(fd), SocketAddr)) + self.0.duplicate_path(b"listen").map(|fd| (UnixStream(fd), SocketAddr(()))) } /// Creates a new independently owned handle to the underlying socket. -- cgit 1.4.1-3-g733a5 From 4bebd24fcaa2a16ee9afcf51a7baca2a4b98b230 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Mon, 18 Jun 2018 07:23:51 +0200 Subject: Remove functions that always error --- src/libstd/sys/redox/ext/net.rs | 181 ---------------------------------------- 1 file changed, 181 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/net.rs b/src/libstd/sys/redox/ext/net.rs index 2ae7803378e..0dab7db9a93 100644 --- a/src/libstd/sys/redox/ext/net.rs +++ b/src/libstd/sys/redox/ext/net.rs @@ -94,12 +94,6 @@ impl fmt::Debug for UnixStream { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut builder = fmt.debug_struct("UnixStream"); builder.field("fd", &self.0.raw()); - if let Ok(addr) = self.local_addr() { - builder.field("local", &addr); - } - if let Ok(addr) = self.peer_addr() { - builder.field("peer", &addr); - } builder.finish() } } @@ -177,142 +171,6 @@ impl UnixStream { self.0.duplicate().map(UnixStream) } - /// Returns the socket address of the local half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// ``` - pub fn local_addr(&self) -> io::Result { - Err(Error::new(ErrorKind::Other, "UnixStream::local_addr unimplemented on redox")) - } - - /// Returns the socket address of the remote half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let addr = socket.peer_addr().expect("Couldn't get peer address"); - /// ``` - pub fn peer_addr(&self) -> io::Result { - Err(Error::new(ErrorKind::Other, "UnixStream::peer_addr unimplemented on redox")) - } - - /// Sets the read timeout for the socket. - /// - /// If the provided value is [`None`], then [`read`] calls will block - /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method. - /// - /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err - /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read - /// [`Duration`]: ../../../../std/time/struct.Duration.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); - /// ``` - /// - /// An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method: - /// - /// ```no_run - /// use std::io; - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); - /// let err = result.unwrap_err(); - /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) - /// ``` - pub fn set_read_timeout(&self, _timeout: Option) -> io::Result<()> { - Err(Error::new(ErrorKind::Other, "UnixStream::set_read_timeout unimplemented on redox")) - } - - /// Sets the write timeout for the socket. - /// - /// If the provided value is [`None`], then [`write`] calls will block - /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is - /// passed to this method. - /// - /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err - /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write - /// [`Duration`]: ../../../../std/time/struct.Duration.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); - /// ``` - /// - /// An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method: - /// - /// ```no_run - /// use std::io; - /// use std::net::UdpSocket; - /// use std::time::Duration; - /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); - /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); - /// let err = result.unwrap_err(); - /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) - /// ``` - pub fn set_write_timeout(&self, _timeout: Option) -> io::Result<()> { - Err(Error::new(ErrorKind::Other, "UnixStream::set_write_timeout unimplemented on redox")) - } - - /// Returns the read timeout of this socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); - /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0))); - /// ``` - pub fn read_timeout(&self) -> io::Result> { - Err(Error::new(ErrorKind::Other, "UnixStream::read_timeout unimplemented on redox")) - } - - /// Returns the write timeout of this socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); - /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0))); - /// ``` - pub fn write_timeout(&self) -> io::Result> { - Err(Error::new(ErrorKind::Other, "UnixStream::write_timeout unimplemented on redox")) - } - /// Moves the socket into or out of nonblocking mode. /// /// # Examples @@ -342,27 +200,6 @@ impl UnixStream { pub fn take_error(&self) -> io::Result> { Ok(None) } - - /// Shuts down the read, write, or both halves of this connection. - /// - /// This function will cause all pending and future I/O calls on the - /// specified portions to immediately return with an appropriate value - /// (see the documentation of [`Shutdown`]). - /// - /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::net::Shutdown; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); - /// ``` - pub fn shutdown(&self, _how: Shutdown) -> io::Result<()> { - Err(Error::new(ErrorKind::Other, "UnixStream::shutdown unimplemented on redox")) - } } impl io::Read for UnixStream { @@ -459,9 +296,6 @@ impl fmt::Debug for UnixListener { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut builder = fmt.debug_struct("UnixListener"); builder.field("fd", &self.0.raw()); - if let Ok(addr) = self.local_addr() { - builder.field("local", &addr); - } builder.finish() } } @@ -538,21 +372,6 @@ impl UnixListener { self.0.duplicate().map(UnixListener) } - /// Returns the local socket address of this listener. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// let addr = listener.local_addr().expect("Couldn't get local address"); - /// ``` - pub fn local_addr(&self) -> io::Result { - Err(Error::new(ErrorKind::Other, "UnixListener::local_addr unimplemented on redox")) - } - /// Moves the socket into or out of nonblocking mode. /// /// # Examples -- cgit 1.4.1-3-g733a5 From c86a7a01e27f78474ff5ce2fe7f88aa2cb14caad Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Tue, 26 Jun 2018 08:23:16 +0200 Subject: Mention redox' behavior in doc comments --- src/libstd/sys/redox/ext/net.rs | 6 ++++++ src/libstd/sys/unix/ext/net.rs | 6 ++++++ 2 files changed, 12 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/net.rs b/src/libstd/sys/redox/ext/net.rs index 0dab7db9a93..2d791fa75cf 100644 --- a/src/libstd/sys/redox/ext/net.rs +++ b/src/libstd/sys/redox/ext/net.rs @@ -197,6 +197,9 @@ impl UnixStream { /// println!("Got error: {:?}", err); /// } /// ``` + /// + /// # Platform specific + /// On Redox this always returns None. pub fn take_error(&self) -> io::Result> { Ok(None) } @@ -400,6 +403,9 @@ impl UnixListener { /// println!("Got error: {:?}", err); /// } /// ``` + /// + /// # Platform specific + /// On Redox this always returns None. pub fn take_error(&self) -> io::Result> { Ok(None) } diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index e277b1aa7b5..55f43ccd7db 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -524,6 +524,9 @@ impl UnixStream { /// println!("Got error: {:?}", err); /// } /// ``` + /// + /// # Platform specific + /// On Redox this always returns None. #[stable(feature = "unix_socket", since = "1.10.0")] pub fn take_error(&self) -> io::Result> { self.0.take_error() @@ -846,6 +849,9 @@ impl UnixListener { /// println!("Got error: {:?}", err); /// } /// ``` + /// + /// # Platform specific + /// On Redox this always returns None. #[stable(feature = "unix_socket", since = "1.10.0")] pub fn take_error(&self) -> io::Result> { self.0.take_error() -- cgit 1.4.1-3-g733a5 From 916f7c864a1da3bb822a282a9f7386c78bdc2c69 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Tue, 26 Jun 2018 19:21:55 +0200 Subject: Revert "Remove functions that always error" This reverts commit 21d09b983de87fec2e98832f4c30b52f12d6342f. --- src/libstd/sys/redox/ext/net.rs | 181 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/net.rs b/src/libstd/sys/redox/ext/net.rs index 2d791fa75cf..d29d28c8427 100644 --- a/src/libstd/sys/redox/ext/net.rs +++ b/src/libstd/sys/redox/ext/net.rs @@ -94,6 +94,12 @@ impl fmt::Debug for UnixStream { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut builder = fmt.debug_struct("UnixStream"); builder.field("fd", &self.0.raw()); + if let Ok(addr) = self.local_addr() { + builder.field("local", &addr); + } + if let Ok(addr) = self.peer_addr() { + builder.field("peer", &addr); + } builder.finish() } } @@ -171,6 +177,142 @@ impl UnixStream { self.0.duplicate().map(UnixStream) } + /// Returns the socket address of the local half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// ``` + pub fn local_addr(&self) -> io::Result { + Err(Error::new(ErrorKind::Other, "UnixStream::local_addr unimplemented on redox")) + } + + /// Returns the socket address of the remote half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let addr = socket.peer_addr().expect("Couldn't get peer address"); + /// ``` + pub fn peer_addr(&self) -> io::Result { + Err(Error::new(ErrorKind::Other, "UnixStream::peer_addr unimplemented on redox")) + } + + /// Sets the read timeout for the socket. + /// + /// If the provided value is [`None`], then [`read`] calls will block + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err + /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read + /// [`Duration`]: ../../../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` + pub fn set_read_timeout(&self, _timeout: Option) -> io::Result<()> { + Err(Error::new(ErrorKind::Other, "UnixStream::set_read_timeout unimplemented on redox")) + } + + /// Sets the write timeout for the socket. + /// + /// If the provided value is [`None`], then [`write`] calls will block + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is + /// passed to this method. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err + /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write + /// [`Duration`]: ../../../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); + /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::net::UdpSocket; + /// use std::time::Duration; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); + /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` + pub fn set_write_timeout(&self, _timeout: Option) -> io::Result<()> { + Err(Error::new(ErrorKind::Other, "UnixStream::set_write_timeout unimplemented on redox")) + } + + /// Returns the read timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` + pub fn read_timeout(&self) -> io::Result> { + Err(Error::new(ErrorKind::Other, "UnixStream::read_timeout unimplemented on redox")) + } + + /// Returns the write timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); + /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` + pub fn write_timeout(&self) -> io::Result> { + Err(Error::new(ErrorKind::Other, "UnixStream::write_timeout unimplemented on redox")) + } + /// Moves the socket into or out of nonblocking mode. /// /// # Examples @@ -203,6 +345,27 @@ impl UnixStream { pub fn take_error(&self) -> io::Result> { Ok(None) } + + /// Shuts down the read, write, or both halves of this connection. + /// + /// This function will cause all pending and future I/O calls on the + /// specified portions to immediately return with an appropriate value + /// (see the documentation of [`Shutdown`]). + /// + /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::net::Shutdown; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); + /// ``` + pub fn shutdown(&self, _how: Shutdown) -> io::Result<()> { + Err(Error::new(ErrorKind::Other, "UnixStream::shutdown unimplemented on redox")) + } } impl io::Read for UnixStream { @@ -299,6 +462,9 @@ impl fmt::Debug for UnixListener { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut builder = fmt.debug_struct("UnixListener"); builder.field("fd", &self.0.raw()); + if let Ok(addr) = self.local_addr() { + builder.field("local", &addr); + } builder.finish() } } @@ -375,6 +541,21 @@ impl UnixListener { self.0.duplicate().map(UnixListener) } + /// Returns the local socket address of this listener. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// let addr = listener.local_addr().expect("Couldn't get local address"); + /// ``` + pub fn local_addr(&self) -> io::Result { + Err(Error::new(ErrorKind::Other, "UnixListener::local_addr unimplemented on redox")) + } + /// Moves the socket into or out of nonblocking mode. /// /// # Examples -- cgit 1.4.1-3-g733a5 From a4e190546c9aaa06630577adb7310a8674bbac06 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Wed, 27 Jun 2018 10:11:46 +0200 Subject: Horrible attempt at cleaning things up that probably just made it worse --- src/libstd/sys/redox/ext/mod.rs | 1 + src/libstd/sys/redox/ext/net.rs | 705 +------------------------- src/libstd/sys/redox/ext/unixsocket.rs | 250 ++++++++++ src/libstd/sys/unix/ext/mod.rs | 1 + src/libstd/sys/unix/ext/net.rs | 869 +-------------------------------- src/libstd/sys/unix/ext/unixsocket.rs | 366 ++++++++++++++ src/libstd/sys_common/mod.rs | 1 + src/libstd/sys_common/unixsocket.rs | 704 ++++++++++++++++++++++++++ 8 files changed, 1348 insertions(+), 1549 deletions(-) create mode 100644 src/libstd/sys/redox/ext/unixsocket.rs create mode 100644 src/libstd/sys/unix/ext/unixsocket.rs create mode 100644 src/libstd/sys_common/unixsocket.rs (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/mod.rs b/src/libstd/sys/redox/ext/mod.rs index cb2c75ae0bf..c86b5d78524 100644 --- a/src/libstd/sys/redox/ext/mod.rs +++ b/src/libstd/sys/redox/ext/mod.rs @@ -36,6 +36,7 @@ pub mod io; pub mod net; pub mod process; pub mod thread; +pub(crate) mod unixsocket; /// A prelude for conveniently writing platform-specific code. /// diff --git a/src/libstd/sys/redox/ext/net.rs b/src/libstd/sys/redox/ext/net.rs index d29d28c8427..eb256885155 100644 --- a/src/libstd/sys/redox/ext/net.rs +++ b/src/libstd/sys/redox/ext/net.rs @@ -1,702 +1,3 @@ -// Copyright 2016 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![unstable(feature = "unix_socket_redox", reason = "new feature", issue="51553")] - -//! Unix-specific networking functionality - -use fmt; -use io::{self, Error, ErrorKind, Initializer}; -use net::Shutdown; -use os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd}; -use path::Path; -use time::Duration; -use sys::{cvt, fd::FileDesc, syscall}; - -/// An address associated with a Unix socket. -/// -/// # Examples -/// -/// ``` -/// use std::os::unix::net::UnixListener; -/// -/// let socket = match UnixListener::bind("/tmp/sock") { -/// Ok(sock) => sock, -/// Err(e) => { -/// println!("Couldn't bind: {:?}", e); -/// return -/// } -/// }; -/// let addr = socket.local_addr().expect("Couldn't get local address"); -/// ``` -#[derive(Clone)] -pub struct SocketAddr(()); - -impl SocketAddr { - /// Returns the contents of this address if it is a `pathname` address. - /// - /// # Examples - /// - /// With a pathname: - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// use std::path::Path; - /// - /// let socket = UnixListener::bind("/tmp/sock").unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock"))); - /// ``` - /// - /// Without a pathname: - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// - /// let socket = UnixDatagram::unbound().unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.as_pathname(), None); - /// ``` - pub fn as_pathname(&self) -> Option<&Path> { - None - } -} -impl fmt::Debug for SocketAddr { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "SocketAddr") - } -} - -/// A Unix stream socket. -/// -/// # Examples -/// -/// ```no_run -/// use std::os::unix::net::UnixStream; -/// use std::io::prelude::*; -/// -/// let mut stream = UnixStream::connect("/path/to/my/socket").unwrap(); -/// stream.write_all(b"hello world").unwrap(); -/// let mut response = String::new(); -/// stream.read_to_string(&mut response).unwrap(); -/// println!("{}", response); -/// ``` -pub struct UnixStream(FileDesc); - -impl fmt::Debug for UnixStream { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut builder = fmt.debug_struct("UnixStream"); - builder.field("fd", &self.0.raw()); - if let Ok(addr) = self.local_addr() { - builder.field("local", &addr); - } - if let Ok(addr) = self.peer_addr() { - builder.field("peer", &addr); - } - builder.finish() - } -} - -impl UnixStream { - /// Connects to the socket named by `path`. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = match UnixStream::connect("/tmp/sock") { - /// Ok(sock) => sock, - /// Err(e) => { - /// println!("Couldn't connect: {:?}", e); - /// return - /// } - /// }; - /// ``` - pub fn connect>(path: P) -> io::Result { - if let Some(s) = path.as_ref().to_str() { - cvt(syscall::open(format!("chan:{}", s), syscall::O_CLOEXEC)) - .map(FileDesc::new) - .map(UnixStream) - } else { - Err(Error::new( - ErrorKind::Other, - "UnixStream::connect: non-utf8 paths not supported on redox" - )) - } - } - - /// Creates an unnamed pair of connected sockets. - /// - /// Returns two `UnixStream`s which are connected to each other. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let (sock1, sock2) = match UnixStream::pair() { - /// Ok((sock1, sock2)) => (sock1, sock2), - /// Err(e) => { - /// println!("Couldn't create a pair of sockets: {:?}", e); - /// return - /// } - /// }; - /// ``` - pub fn pair() -> io::Result<(UnixStream, UnixStream)> { - let server = cvt(syscall::open("chan:", syscall::O_CREAT | syscall::O_CLOEXEC)) - .map(FileDesc::new)?; - let client = server.duplicate_path(b"connect")?; - let stream = server.duplicate_path(b"listen")?; - Ok((UnixStream(client), UnixStream(stream))) - } - - /// Creates a new independently owned handle to the underlying socket. - /// - /// The returned `UnixStream` is a reference to the same stream that this - /// object references. Both handles will read and write the same stream of - /// data, and options set on one stream will be propagated to the other - /// stream. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); - /// ``` - pub fn try_clone(&self) -> io::Result { - self.0.duplicate().map(UnixStream) - } - - /// Returns the socket address of the local half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// ``` - pub fn local_addr(&self) -> io::Result { - Err(Error::new(ErrorKind::Other, "UnixStream::local_addr unimplemented on redox")) - } - - /// Returns the socket address of the remote half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let addr = socket.peer_addr().expect("Couldn't get peer address"); - /// ``` - pub fn peer_addr(&self) -> io::Result { - Err(Error::new(ErrorKind::Other, "UnixStream::peer_addr unimplemented on redox")) - } - - /// Sets the read timeout for the socket. - /// - /// If the provided value is [`None`], then [`read`] calls will block - /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method. - /// - /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err - /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read - /// [`Duration`]: ../../../../std/time/struct.Duration.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); - /// ``` - /// - /// An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method: - /// - /// ```no_run - /// use std::io; - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); - /// let err = result.unwrap_err(); - /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) - /// ``` - pub fn set_read_timeout(&self, _timeout: Option) -> io::Result<()> { - Err(Error::new(ErrorKind::Other, "UnixStream::set_read_timeout unimplemented on redox")) - } - - /// Sets the write timeout for the socket. - /// - /// If the provided value is [`None`], then [`write`] calls will block - /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is - /// passed to this method. - /// - /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err - /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write - /// [`Duration`]: ../../../../std/time/struct.Duration.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); - /// ``` - /// - /// An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method: - /// - /// ```no_run - /// use std::io; - /// use std::net::UdpSocket; - /// use std::time::Duration; - /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); - /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); - /// let err = result.unwrap_err(); - /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) - /// ``` - pub fn set_write_timeout(&self, _timeout: Option) -> io::Result<()> { - Err(Error::new(ErrorKind::Other, "UnixStream::set_write_timeout unimplemented on redox")) - } - - /// Returns the read timeout of this socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); - /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0))); - /// ``` - pub fn read_timeout(&self) -> io::Result> { - Err(Error::new(ErrorKind::Other, "UnixStream::read_timeout unimplemented on redox")) - } - - /// Returns the write timeout of this socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); - /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0))); - /// ``` - pub fn write_timeout(&self) -> io::Result> { - Err(Error::new(ErrorKind::Other, "UnixStream::write_timeout unimplemented on redox")) - } - - /// Moves the socket into or out of nonblocking mode. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); - /// ``` - pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - self.0.set_nonblocking(nonblocking) - } - - /// Returns the value of the `SO_ERROR` option. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// if let Ok(Some(err)) = socket.take_error() { - /// println!("Got error: {:?}", err); - /// } - /// ``` - /// - /// # Platform specific - /// On Redox this always returns None. - pub fn take_error(&self) -> io::Result> { - Ok(None) - } - - /// Shuts down the read, write, or both halves of this connection. - /// - /// This function will cause all pending and future I/O calls on the - /// specified portions to immediately return with an appropriate value - /// (see the documentation of [`Shutdown`]). - /// - /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::net::Shutdown; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); - /// ``` - pub fn shutdown(&self, _how: Shutdown) -> io::Result<()> { - Err(Error::new(ErrorKind::Other, "UnixStream::shutdown unimplemented on redox")) - } -} - -impl io::Read for UnixStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - io::Read::read(&mut &*self, buf) - } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } -} - -impl<'a> io::Read for &'a UnixStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) - } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } -} - -impl io::Write for UnixStream { - fn write(&mut self, buf: &[u8]) -> io::Result { - io::Write::write(&mut &*self, buf) - } - - fn flush(&mut self) -> io::Result<()> { - io::Write::flush(&mut &*self) - } -} - -impl<'a> io::Write for &'a UnixStream { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.0.write(buf) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -impl AsRawFd for UnixStream { - fn as_raw_fd(&self) -> RawFd { - self.0.raw() - } -} - -impl FromRawFd for UnixStream { - unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { - UnixStream(FileDesc::new(fd)) - } -} - -impl IntoRawFd for UnixStream { - fn into_raw_fd(self) -> RawFd { - self.0.into_raw() - } -} - -/// A structure representing a Unix domain socket server. -/// -/// # Examples -/// -/// ```no_run -/// use std::thread; -/// use std::os::unix::net::{UnixStream, UnixListener}; -/// -/// fn handle_client(stream: UnixStream) { -/// // ... -/// } -/// -/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); -/// -/// // accept connections and process them, spawning a new thread for each one -/// for stream in listener.incoming() { -/// match stream { -/// Ok(stream) => { -/// /* connection succeeded */ -/// thread::spawn(|| handle_client(stream)); -/// } -/// Err(err) => { -/// /* connection failed */ -/// break; -/// } -/// } -/// } -/// ``` -pub struct UnixListener(FileDesc); - -impl fmt::Debug for UnixListener { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut builder = fmt.debug_struct("UnixListener"); - builder.field("fd", &self.0.raw()); - if let Ok(addr) = self.local_addr() { - builder.field("local", &addr); - } - builder.finish() - } -} - -impl UnixListener { - /// Creates a new `UnixListener` bound to the specified socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = match UnixListener::bind("/path/to/the/socket") { - /// Ok(sock) => sock, - /// Err(e) => { - /// println!("Couldn't connect: {:?}", e); - /// return - /// } - /// }; - /// ``` - pub fn bind>(path: P) -> io::Result { - if let Some(s) = path.as_ref().to_str() { - cvt(syscall::open(format!("chan:{}", s), syscall::O_CREAT | syscall::O_CLOEXEC)) - .map(FileDesc::new) - .map(UnixListener) - } else { - Err(Error::new( - ErrorKind::Other, - "UnixListener::bind: non-utf8 paths not supported on redox" - )) - } - } - - /// Accepts a new incoming connection to this listener. - /// - /// This function will block the calling thread until a new Unix connection - /// is established. When established, the corresponding [`UnixStream`] and - /// the remote peer's address will be returned. - /// - /// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// match listener.accept() { - /// Ok((socket, addr)) => println!("Got a client: {:?}", addr), - /// Err(e) => println!("accept function failed: {:?}", e), - /// } - /// ``` - pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { - self.0.duplicate_path(b"listen").map(|fd| (UnixStream(fd), SocketAddr(()))) - } - - /// Creates a new independently owned handle to the underlying socket. - /// - /// The returned `UnixListener` is a reference to the same socket that this - /// object references. Both handles can be used to accept incoming - /// connections and options set on one listener will affect the other. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// let listener_copy = listener.try_clone().expect("try_clone failed"); - /// ``` - pub fn try_clone(&self) -> io::Result { - self.0.duplicate().map(UnixListener) - } - - /// Returns the local socket address of this listener. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// let addr = listener.local_addr().expect("Couldn't get local address"); - /// ``` - pub fn local_addr(&self) -> io::Result { - Err(Error::new(ErrorKind::Other, "UnixListener::local_addr unimplemented on redox")) - } - - /// Moves the socket into or out of nonblocking mode. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); - /// ``` - pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - self.0.set_nonblocking(nonblocking) - } - - /// Returns the value of the `SO_ERROR` option. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/tmp/sock").unwrap(); - /// - /// if let Ok(Some(err)) = listener.take_error() { - /// println!("Got error: {:?}", err); - /// } - /// ``` - /// - /// # Platform specific - /// On Redox this always returns None. - pub fn take_error(&self) -> io::Result> { - Ok(None) - } - - /// Returns an iterator over incoming connections. - /// - /// The iterator will never return [`None`] and will also not yield the - /// peer's [`SocketAddr`] structure. - /// - /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`SocketAddr`]: struct.SocketAddr.html - /// - /// # Examples - /// - /// ```no_run - /// use std::thread; - /// use std::os::unix::net::{UnixStream, UnixListener}; - /// - /// fn handle_client(stream: UnixStream) { - /// // ... - /// } - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// for stream in listener.incoming() { - /// match stream { - /// Ok(stream) => { - /// thread::spawn(|| handle_client(stream)); - /// } - /// Err(err) => { - /// break; - /// } - /// } - /// } - /// ``` - pub fn incoming<'a>(&'a self) -> Incoming<'a> { - Incoming { listener: self } - } -} - -impl AsRawFd for UnixListener { - fn as_raw_fd(&self) -> RawFd { - self.0.raw() - } -} - -impl FromRawFd for UnixListener { - unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { - UnixListener(FileDesc::new(fd)) - } -} - -impl IntoRawFd for UnixListener { - fn into_raw_fd(self) -> RawFd { - self.0.into_raw() - } -} - -impl<'a> IntoIterator for &'a UnixListener { - type Item = io::Result; - type IntoIter = Incoming<'a>; - - fn into_iter(self) -> Incoming<'a> { - self.incoming() - } -} - -/// An iterator over incoming connections to a [`UnixListener`]. -/// -/// It will never return [`None`]. -/// -/// [`None`]: ../../../../std/option/enum.Option.html#variant.None -/// [`UnixListener`]: struct.UnixListener.html -/// -/// # Examples -/// -/// ```no_run -/// use std::thread; -/// use std::os::unix::net::{UnixStream, UnixListener}; -/// -/// fn handle_client(stream: UnixStream) { -/// // ... -/// } -/// -/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); -/// -/// for stream in listener.incoming() { -/// match stream { -/// Ok(stream) => { -/// thread::spawn(|| handle_client(stream)); -/// } -/// Err(err) => { -/// break; -/// } -/// } -/// } -/// ``` -#[derive(Debug)] -pub struct Incoming<'a> { - listener: &'a UnixListener, -} - -impl<'a> Iterator for Incoming<'a> { - type Item = io::Result; - - fn next(&mut self) -> Option> { - Some(self.listener.accept().map(|s| s.0)) - } - - fn size_hint(&self) -> (usize, Option) { - (usize::max_value(), None) - } -} +#![stable(feature = "unix_socket", since = "1.10.0")] +#[stable(feature = "unix_socket", since = "1.10.0")] +pub use sys_common::unixsocket::*; diff --git a/src/libstd/sys/redox/ext/unixsocket.rs b/src/libstd/sys/redox/ext/unixsocket.rs new file mode 100644 index 00000000000..78ca0f16af4 --- /dev/null +++ b/src/libstd/sys/redox/ext/unixsocket.rs @@ -0,0 +1,250 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![stable(feature = "unix_socket", since = "1.10.0")] + +use fmt; +use io::{self, Error, ErrorKind, Initializer}; +use net::Shutdown; +use os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd}; +use path::Path; +use time::Duration; +use sys::{cvt, fd::FileDesc, syscall}; + +#[stable(feature = "unix_socket", since = "1.10.0")] +#[derive(Clone)] +pub(crate) struct SocketAddr(()); + +impl SocketAddr { + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn as_pathname(&self) -> Option<&Path> { + None + } +} +#[stable(feature = "unix_socket", since = "1.10.0")] +impl fmt::Debug for SocketAddr { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "SocketAddr") + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +pub(crate) struct UnixStream(FileDesc); + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl fmt::Debug for UnixStream { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut builder = fmt.debug_struct("UnixStream"); + builder.field("fd", &self.0.raw()); + if let Ok(addr) = self.local_addr() { + builder.field("local", &addr); + } + if let Ok(addr) = self.peer_addr() { + builder.field("peer", &addr); + } + builder.finish() + } +} + +impl UnixStream { + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn connect(path: &Path) -> io::Result { + if let Some(s) = path.to_str() { + cvt(syscall::open(format!("chan:{}", s), syscall::O_CLOEXEC)) + .map(FileDesc::new) + .map(UnixStream) + } else { + Err(Error::new( + ErrorKind::Other, + "UnixStream::connect: non-utf8 paths not supported on redox" + )) + } + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn pair() -> io::Result<(UnixStream, UnixStream)> { + let server = cvt(syscall::open("chan:", syscall::O_CREAT | syscall::O_CLOEXEC)) + .map(FileDesc::new)?; + let client = server.duplicate_path(b"connect")?; + let stream = server.duplicate_path(b"listen")?; + Ok((UnixStream(client), UnixStream(stream))) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn try_clone(&self) -> io::Result { + self.0.duplicate().map(UnixStream) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn local_addr(&self) -> io::Result { + Err(Error::new(ErrorKind::Other, "UnixStream::local_addr unimplemented on redox")) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn peer_addr(&self) -> io::Result { + Err(Error::new(ErrorKind::Other, "UnixStream::peer_addr unimplemented on redox")) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn set_read_timeout(&self, _timeout: Option) -> io::Result<()> { + Err(Error::new(ErrorKind::Other, "UnixStream::set_read_timeout unimplemented on redox")) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn set_write_timeout(&self, _timeout: Option) -> io::Result<()> { + Err(Error::new(ErrorKind::Other, "UnixStream::set_write_timeout unimplemented on redox")) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn read_timeout(&self) -> io::Result> { + Err(Error::new(ErrorKind::Other, "UnixStream::read_timeout unimplemented on redox")) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn write_timeout(&self) -> io::Result> { + Err(Error::new(ErrorKind::Other, "UnixStream::write_timeout unimplemented on redox")) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.0.set_nonblocking(nonblocking) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn take_error(&self) -> io::Result> { + Ok(None) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn shutdown(&self, _how: Shutdown) -> io::Result<()> { + Err(Error::new(ErrorKind::Other, "UnixStream::shutdown unimplemented on redox")) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl<'a> io::Read for &'a UnixStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.0.read(buf) + } + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl<'a> io::Write for &'a UnixStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl AsRawFd for UnixStream { + fn as_raw_fd(&self) -> RawFd { + self.0.raw() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl FromRawFd for UnixStream { + unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { + UnixStream(FileDesc::new(fd)) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl IntoRawFd for UnixStream { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +pub(crate) struct UnixListener(FileDesc); + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl fmt::Debug for UnixListener { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut builder = fmt.debug_struct("UnixListener"); + builder.field("fd", &self.0.raw()); + if let Ok(addr) = self.local_addr() { + builder.field("local", &addr); + } + builder.finish() + } +} + +impl UnixListener { + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn bind(path: &Path) -> io::Result { + if let Some(s) = path.to_str() { + cvt(syscall::open(format!("chan:{}", s), syscall::O_CREAT | syscall::O_CLOEXEC)) + .map(FileDesc::new) + .map(UnixListener) + } else { + Err(Error::new( + ErrorKind::Other, + "UnixListener::bind: non-utf8 paths not supported on redox" + )) + } + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { + self.0.duplicate_path(b"listen").map(|fd| (UnixStream(fd), SocketAddr(()))) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn try_clone(&self) -> io::Result { + self.0.duplicate().map(UnixListener) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn local_addr(&self) -> io::Result { + Err(Error::new(ErrorKind::Other, "UnixListener::local_addr unimplemented on redox")) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.0.set_nonblocking(nonblocking) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub(crate) fn take_error(&self) -> io::Result> { + Ok(None) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl AsRawFd for UnixListener { + fn as_raw_fd(&self) -> RawFd { + self.0.raw() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl FromRawFd for UnixListener { + unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { + UnixListener(FileDesc::new(fd)) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl IntoRawFd for UnixListener { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw() + } +} diff --git a/src/libstd/sys/unix/ext/mod.rs b/src/libstd/sys/unix/ext/mod.rs index 88e4237f8e2..b7a1b45e9b7 100644 --- a/src/libstd/sys/unix/ext/mod.rs +++ b/src/libstd/sys/unix/ext/mod.rs @@ -44,6 +44,7 @@ pub mod process; pub mod raw; pub mod thread; pub mod net; +pub(crate) mod unixsocket; /// A prelude for conveniently writing platform-specific code. /// diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 55f43ccd7db..77bca85fe88 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -25,32 +25,34 @@ mod libc { pub struct sockaddr_un; } -use ascii; -use ffi::OsStr; use fmt; -use io::{self, Initializer}; +use io; use mem; use net::{self, Shutdown}; use os::unix::ffi::OsStrExt; use os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd}; use path::Path; use time::Duration; -use sys::{self, cvt}; +use sys::ext::unixsocket as inner; use sys::net::Socket; +use sys::{self, cvt}; use sys_common::{self, AsInner, FromInner, IntoInner}; +#[stable(feature = "unix_socket", since = "1.10.0")] +pub use sys_common::unixsocket::*; + #[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"))] -use libc::MSG_NOSIGNAL; +pub(crate) 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")))] -const MSG_NOSIGNAL: libc::c_int = 0x0; +pub(crate) const MSG_NOSIGNAL: libc::c_int = 0x0; -fn sun_path_offset() -> usize { +pub(crate) fn sun_path_offset() -> usize { // Work with an actual instance of the type since using a null pointer is UB let addr: libc::sockaddr_un = unsafe { mem::uninitialized() }; let base = &addr as *const _ as usize; @@ -58,7 +60,7 @@ fn sun_path_offset() -> usize { path - base } -unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> { +pub(crate) unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> { let mut addr: libc::sockaddr_un = mem::zeroed(); addr.sun_family = libc::AF_UNIX as libc::sa_family_t; @@ -87,557 +89,22 @@ unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::sockl Ok((addr, len as libc::socklen_t)) } -enum AddressKind<'a> { - Unnamed, - Pathname(&'a Path), - Abstract(&'a [u8]), -} - -/// An address associated with a Unix socket. -/// -/// # Examples -/// -/// ``` -/// use std::os::unix::net::UnixListener; -/// -/// let socket = match UnixListener::bind("/tmp/sock") { -/// Ok(sock) => sock, -/// Err(e) => { -/// println!("Couldn't bind: {:?}", e); -/// return -/// } -/// }; -/// let addr = socket.local_addr().expect("Couldn't get local address"); -/// ``` -#[derive(Clone)] -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct SocketAddr { - addr: libc::sockaddr_un, - len: libc::socklen_t, -} - -impl SocketAddr { - fn new(f: F) -> io::Result - where F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int - { - unsafe { - let mut addr: libc::sockaddr_un = mem::zeroed(); - let mut len = mem::size_of::() as libc::socklen_t; - cvt(f(&mut addr as *mut _ as *mut _, &mut len))?; - SocketAddr::from_parts(addr, len) - } - } - - fn from_parts(addr: libc::sockaddr_un, mut len: libc::socklen_t) -> io::Result { - if len == 0 { - // When there is a datagram from unnamed unix socket - // linux returns zero bytes of address - len = sun_path_offset() as libc::socklen_t; // i.e. zero-length address - } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t { - return Err(io::Error::new(io::ErrorKind::InvalidInput, - "file descriptor did not correspond to a Unix socket")); - } - - Ok(SocketAddr { - addr, - len, - }) - } - - /// Returns true if and only if the address is unnamed. - /// - /// # Examples - /// - /// A named address: - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let socket = UnixListener::bind("/tmp/sock").unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.is_unnamed(), false); - /// ``` - /// - /// An unnamed address: - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// - /// let socket = UnixDatagram::unbound().unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.is_unnamed(), true); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn is_unnamed(&self) -> bool { - if let AddressKind::Unnamed = self.address() { - true - } else { - false - } - } - - /// Returns the contents of this address if it is a `pathname` address. - /// - /// # Examples - /// - /// With a pathname: - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// use std::path::Path; - /// - /// let socket = UnixListener::bind("/tmp/sock").unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock"))); - /// ``` - /// - /// Without a pathname: - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// - /// let socket = UnixDatagram::unbound().unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.as_pathname(), None); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn as_pathname(&self) -> Option<&Path> { - if let AddressKind::Pathname(path) = self.address() { - Some(path) - } else { - None - } - } - - fn address<'a>(&'a self) -> AddressKind<'a> { - let len = self.len as usize - sun_path_offset(); - let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; - - // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses - if len == 0 - || (cfg!(not(any(target_os = "linux", target_os = "android"))) - && self.addr.sun_path[0] == 0) - { - AddressKind::Unnamed - } else if self.addr.sun_path[0] == 0 { - AddressKind::Abstract(&path[1..len]) - } else { - AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref()) - } - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for SocketAddr { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match self.address() { - AddressKind::Unnamed => write!(fmt, "(unnamed)"), - AddressKind::Abstract(name) => write!(fmt, "{} (abstract)", AsciiEscaped(name)), - AddressKind::Pathname(path) => write!(fmt, "{:?} (pathname)", path), - } - } -} - -struct AsciiEscaped<'a>(&'a [u8]); - -impl<'a> fmt::Display for AsciiEscaped<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "\"")?; - for byte in self.0.iter().cloned().flat_map(ascii::escape_default) { - write!(fmt, "{}", byte as char)?; - } - write!(fmt, "\"") - } -} - -/// A Unix stream socket. -/// -/// # Examples -/// -/// ```no_run -/// use std::os::unix::net::UnixStream; -/// use std::io::prelude::*; -/// -/// let mut stream = UnixStream::connect("/path/to/my/socket").unwrap(); -/// stream.write_all(b"hello world").unwrap(); -/// let mut response = String::new(); -/// stream.read_to_string(&mut response).unwrap(); -/// println!("{}", response); -/// ``` -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct UnixStream(Socket); - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for UnixStream { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut builder = fmt.debug_struct("UnixStream"); - builder.field("fd", self.0.as_inner()); - if let Ok(addr) = self.local_addr() { - builder.field("local", &addr); - } - if let Ok(addr) = self.peer_addr() { - builder.field("peer", &addr); - } - builder.finish() - } -} - -impl UnixStream { - /// Connects to the socket named by `path`. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = match UnixStream::connect("/tmp/sock") { - /// Ok(sock) => sock, - /// Err(e) => { - /// println!("Couldn't connect: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn connect>(path: P) -> io::Result { - fn inner(path: &Path) -> io::Result { - unsafe { - let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; - let (addr, len) = sockaddr_un(path)?; - - cvt(libc::connect(*inner.as_inner(), &addr as *const _ as *const _, len))?; - Ok(UnixStream(inner)) - } - } - inner(path.as_ref()) - } - - /// Creates an unnamed pair of connected sockets. - /// - /// Returns two `UnixStream`s which are connected to each other. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let (sock1, sock2) = match UnixStream::pair() { - /// Ok((sock1, sock2)) => (sock1, sock2), - /// Err(e) => { - /// println!("Couldn't create a pair of sockets: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn pair() -> io::Result<(UnixStream, UnixStream)> { - let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?; - Ok((UnixStream(i1), UnixStream(i2))) - } - - /// Creates a new independently owned handle to the underlying socket. - /// - /// The returned `UnixStream` is a reference to the same stream that this - /// object references. Both handles will read and write the same stream of - /// data, and options set on one stream will be propagated to the other - /// stream. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn try_clone(&self) -> io::Result { - self.0.duplicate().map(UnixStream) - } - - /// Returns the socket address of the local half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn local_addr(&self) -> io::Result { - SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) - } - - /// Returns the socket address of the remote half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let addr = socket.peer_addr().expect("Couldn't get peer address"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn peer_addr(&self) -> io::Result { - SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) - } - - /// Sets the read timeout for the socket. - /// - /// If the provided value is [`None`], then [`read`] calls will block - /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method. - /// - /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err - /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read - /// [`Duration`]: ../../../../std/time/struct.Duration.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); - /// ``` - /// - /// An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method: - /// - /// ```no_run - /// use std::io; - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); - /// let err = result.unwrap_err(); - /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { - self.0.set_timeout(timeout, libc::SO_RCVTIMEO) - } - - /// Sets the write timeout for the socket. - /// - /// If the provided value is [`None`], then [`write`] calls will block - /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is - /// passed to this method. - /// - /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err - /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write - /// [`Duration`]: ../../../../std/time/struct.Duration.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); - /// ``` - /// - /// An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method: - /// - /// ```no_run - /// use std::io; - /// use std::net::UdpSocket; - /// use std::time::Duration; - /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); - /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); - /// let err = result.unwrap_err(); - /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { - self.0.set_timeout(timeout, libc::SO_SNDTIMEO) - } - - /// Returns the read timeout of this socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); - /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0))); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn read_timeout(&self) -> io::Result> { - self.0.timeout(libc::SO_RCVTIMEO) - } - - /// Returns the write timeout of this socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); - /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0))); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn write_timeout(&self) -> io::Result> { - self.0.timeout(libc::SO_SNDTIMEO) - } - - /// Moves the socket into or out of nonblocking mode. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - self.0.set_nonblocking(nonblocking) - } - - /// Returns the value of the `SO_ERROR` option. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// if let Ok(Some(err)) = socket.take_error() { - /// println!("Got error: {:?}", err); - /// } - /// ``` - /// - /// # Platform specific - /// On Redox this always returns None. - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn take_error(&self) -> io::Result> { - self.0.take_error() - } - - /// Shuts down the read, write, or both halves of this connection. - /// - /// This function will cause all pending and future I/O calls on the - /// specified portions to immediately return with an appropriate value - /// (see the documentation of [`Shutdown`]). - /// - /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::net::Shutdown; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { - self.0.shutdown(how) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl io::Read for UnixStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - io::Read::read(&mut &*self, buf) - } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> io::Read for &'a UnixStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) - } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl io::Write for UnixStream { - fn write(&mut self, buf: &[u8]) -> io::Result { - io::Write::write(&mut &*self, buf) - } - - fn flush(&mut self) -> io::Result<()> { - io::Write::flush(&mut &*self) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> io::Write for &'a UnixStream { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.0.write(buf) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl AsRawFd for UnixStream { - fn as_raw_fd(&self) -> RawFd { - *self.0.as_inner() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl FromRawFd for UnixStream { - unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { - UnixStream(Socket::from_inner(fd)) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl IntoRawFd for UnixStream { - fn into_raw_fd(self) -> RawFd { - self.0.into_inner() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "into_raw_os", since = "1.4.0")] impl AsRawFd for net::TcpStream { fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } } -#[stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "into_raw_os", since = "1.4.0")] impl AsRawFd for net::TcpListener { fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } } -#[stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "into_raw_os", since = "1.4.0")] impl AsRawFd for net::UdpSocket { fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } } -#[stable(feature = "from_raw_os", since = "1.1.0")] +#[stable(feature = "into_raw_os", since = "1.4.0")] impl FromRawFd for net::TcpStream { unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream { let socket = sys::net::Socket::from_inner(fd); @@ -645,7 +112,7 @@ impl FromRawFd for net::TcpStream { } } -#[stable(feature = "from_raw_os", since = "1.1.0")] +#[stable(feature = "into_raw_os", since = "1.4.0")] impl FromRawFd for net::TcpListener { unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener { let socket = sys::net::Socket::from_inner(fd); @@ -653,7 +120,7 @@ impl FromRawFd for net::TcpListener { } } -#[stable(feature = "from_raw_os", since = "1.1.0")] +#[stable(feature = "into_raw_os", since = "1.4.0")] impl FromRawFd for net::UdpSocket { unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket { let socket = sys::net::Socket::from_inner(fd); @@ -680,300 +147,6 @@ impl IntoRawFd for net::UdpSocket { } } -/// A structure representing a Unix domain socket server. -/// -/// # Examples -/// -/// ```no_run -/// use std::thread; -/// use std::os::unix::net::{UnixStream, UnixListener}; -/// -/// fn handle_client(stream: UnixStream) { -/// // ... -/// } -/// -/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); -/// -/// // accept connections and process them, spawning a new thread for each one -/// for stream in listener.incoming() { -/// match stream { -/// Ok(stream) => { -/// /* connection succeeded */ -/// thread::spawn(|| handle_client(stream)); -/// } -/// Err(err) => { -/// /* connection failed */ -/// break; -/// } -/// } -/// } -/// ``` -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct UnixListener(Socket); - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for UnixListener { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut builder = fmt.debug_struct("UnixListener"); - builder.field("fd", self.0.as_inner()); - if let Ok(addr) = self.local_addr() { - builder.field("local", &addr); - } - builder.finish() - } -} - -impl UnixListener { - /// Creates a new `UnixListener` bound to the specified socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = match UnixListener::bind("/path/to/the/socket") { - /// Ok(sock) => sock, - /// Err(e) => { - /// println!("Couldn't connect: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn bind>(path: P) -> io::Result { - fn inner(path: &Path) -> io::Result { - unsafe { - let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; - let (addr, len) = sockaddr_un(path)?; - - cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len as _))?; - cvt(libc::listen(*inner.as_inner(), 128))?; - - Ok(UnixListener(inner)) - } - } - inner(path.as_ref()) - } - - /// Accepts a new incoming connection to this listener. - /// - /// This function will block the calling thread until a new Unix connection - /// is established. When established, the corresponding [`UnixStream`] and - /// the remote peer's address will be returned. - /// - /// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// match listener.accept() { - /// Ok((socket, addr)) => println!("Got a client: {:?}", addr), - /// Err(e) => println!("accept function failed: {:?}", e), - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { - let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() }; - let mut len = mem::size_of_val(&storage) as libc::socklen_t; - let sock = self.0.accept(&mut storage as *mut _ as *mut _, &mut len)?; - let addr = SocketAddr::from_parts(storage, len)?; - Ok((UnixStream(sock), addr)) - } - - /// Creates a new independently owned handle to the underlying socket. - /// - /// The returned `UnixListener` is a reference to the same socket that this - /// object references. Both handles can be used to accept incoming - /// connections and options set on one listener will affect the other. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// let listener_copy = listener.try_clone().expect("try_clone failed"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn try_clone(&self) -> io::Result { - self.0.duplicate().map(UnixListener) - } - - /// Returns the local socket address of this listener. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// let addr = listener.local_addr().expect("Couldn't get local address"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn local_addr(&self) -> io::Result { - SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) - } - - /// Moves the socket into or out of nonblocking mode. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - self.0.set_nonblocking(nonblocking) - } - - /// Returns the value of the `SO_ERROR` option. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/tmp/sock").unwrap(); - /// - /// if let Ok(Some(err)) = listener.take_error() { - /// println!("Got error: {:?}", err); - /// } - /// ``` - /// - /// # Platform specific - /// On Redox this always returns None. - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn take_error(&self) -> io::Result> { - self.0.take_error() - } - - /// Returns an iterator over incoming connections. - /// - /// The iterator will never return [`None`] and will also not yield the - /// peer's [`SocketAddr`] structure. - /// - /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`SocketAddr`]: struct.SocketAddr.html - /// - /// # Examples - /// - /// ```no_run - /// use std::thread; - /// use std::os::unix::net::{UnixStream, UnixListener}; - /// - /// fn handle_client(stream: UnixStream) { - /// // ... - /// } - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// for stream in listener.incoming() { - /// match stream { - /// Ok(stream) => { - /// thread::spawn(|| handle_client(stream)); - /// } - /// Err(err) => { - /// break; - /// } - /// } - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn incoming<'a>(&'a self) -> Incoming<'a> { - Incoming { listener: self } - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl AsRawFd for UnixListener { - fn as_raw_fd(&self) -> RawFd { - *self.0.as_inner() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl FromRawFd for UnixListener { - unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { - UnixListener(Socket::from_inner(fd)) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl IntoRawFd for UnixListener { - fn into_raw_fd(self) -> RawFd { - self.0.into_inner() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> IntoIterator for &'a UnixListener { - type Item = io::Result; - type IntoIter = Incoming<'a>; - - fn into_iter(self) -> Incoming<'a> { - self.incoming() - } -} - -/// An iterator over incoming connections to a [`UnixListener`]. -/// -/// It will never return [`None`]. -/// -/// [`None`]: ../../../../std/option/enum.Option.html#variant.None -/// [`UnixListener`]: struct.UnixListener.html -/// -/// # Examples -/// -/// ```no_run -/// use std::thread; -/// use std::os::unix::net::{UnixStream, UnixListener}; -/// -/// fn handle_client(stream: UnixStream) { -/// // ... -/// } -/// -/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); -/// -/// for stream in listener.incoming() { -/// match stream { -/// Ok(stream) => { -/// thread::spawn(|| handle_client(stream)); -/// } -/// Err(err) => { -/// break; -/// } -/// } -/// } -/// ``` -#[derive(Debug)] -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct Incoming<'a> { - listener: &'a UnixListener, -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> Iterator for Incoming<'a> { - type Item = io::Result; - - fn next(&mut self) -> Option> { - Some(self.listener.accept().map(|s| s.0)) - } - - fn size_hint(&self) -> (usize, Option) { - (usize::max_value(), None) - } -} - /// A Unix datagram socket. /// /// # Examples @@ -1150,7 +323,8 @@ impl UnixDatagram { /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn local_addr(&self) -> io::Result { - SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) + inner::SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) + .map(SocketAddr) } /// Returns the address of this socket's peer. @@ -1171,7 +345,8 @@ impl UnixDatagram { /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn peer_addr(&self) -> io::Result { - SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) + inner::SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) + .map(SocketAddr) } /// Receives data from the socket. @@ -1194,7 +369,7 @@ impl UnixDatagram { #[stable(feature = "unix_socket", since = "1.10.0")] pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { let mut count = 0; - let addr = SocketAddr::new(|addr, len| { + let addr = SocketAddr(inner::SocketAddr::new(|addr, len| { unsafe { count = libc::recvfrom(*self.0.as_inner(), buf.as_mut_ptr() as *mut _, @@ -1210,7 +385,7 @@ impl UnixDatagram { -1 } } - })?; + })?); Ok((count as usize, addr)) } diff --git a/src/libstd/sys/unix/ext/unixsocket.rs b/src/libstd/sys/unix/ext/unixsocket.rs new file mode 100644 index 00000000000..f6996ecd66f --- /dev/null +++ b/src/libstd/sys/unix/ext/unixsocket.rs @@ -0,0 +1,366 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![stable(feature = "unix_socket", since = "1.10.0")] + +//! Unix-specific networking functionality + +#[cfg(unix)] +use libc; + +// FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here? +#[cfg(not(unix))] +mod libc { + pub use libc::c_int; + pub type socklen_t = u32; + pub struct sockaddr; + #[derive(Clone)] + pub struct sockaddr_un; +} + +use ascii; +use ffi::OsStr; +use fmt; +use io::{self, Initializer}; +use mem; +use net::Shutdown; +use os::unix::ffi::OsStrExt; +use os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd}; +use path::Path; +use time::Duration; +use sys::cvt; +use sys::net::Socket; +use sys::ext::net::*; +use sys_common::{AsInner, FromInner, IntoInner}; + +enum AddressKind<'a> { + Unnamed, + Pathname(&'a Path), + Abstract(&'a [u8]), +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +#[derive(Clone)] +pub struct SocketAddr { + addr: libc::sockaddr_un, + len: libc::socklen_t, +} + +impl SocketAddr { + pub(crate) fn new(f: F) -> io::Result + where F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int + { + unsafe { + let mut addr: libc::sockaddr_un = mem::zeroed(); + let mut len = mem::size_of::() as libc::socklen_t; + cvt(f(&mut addr as *mut _ as *mut _, &mut len))?; + SocketAddr::from_parts(addr, len) + } + } + + pub(crate) fn from_parts(addr: libc::sockaddr_un, mut len: libc::socklen_t) -> io::Result { + if len == 0 { + // When there is a datagram from unnamed unix socket + // linux returns zero bytes of address + len = sun_path_offset() as libc::socklen_t; // i.e. zero-length address + } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t { + return Err(io::Error::new(io::ErrorKind::InvalidInput, + "file descriptor did not correspond to a Unix socket")); + } + + Ok(SocketAddr { + addr, + len, + }) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn is_unnamed(&self) -> bool { + if let AddressKind::Unnamed = self.address() { + true + } else { + false + } + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn as_pathname(&self) -> Option<&Path> { + if let AddressKind::Pathname(path) = self.address() { + Some(path) + } else { + None + } + } + + fn address<'a>(&'a self) -> AddressKind<'a> { + let len = self.len as usize - sun_path_offset(); + let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; + + // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses + if len == 0 + || (cfg!(not(any(target_os = "linux", target_os = "android"))) + && self.addr.sun_path[0] == 0) + { + AddressKind::Unnamed + } else if self.addr.sun_path[0] == 0 { + AddressKind::Abstract(&path[1..len]) + } else { + AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref()) + } + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl fmt::Debug for SocketAddr { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match self.address() { + AddressKind::Unnamed => write!(fmt, "(unnamed)"), + AddressKind::Abstract(name) => write!(fmt, "{} (abstract)", AsciiEscaped(name)), + AddressKind::Pathname(path) => write!(fmt, "{:?} (pathname)", path), + } + } +} + +struct AsciiEscaped<'a>(&'a [u8]); + +impl<'a> fmt::Display for AsciiEscaped<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "\"")?; + for byte in self.0.iter().cloned().flat_map(ascii::escape_default) { + write!(fmt, "{}", byte as char)?; + } + write!(fmt, "\"") + } +} + +/// A Unix stream socket. +/// +/// # Examples +/// +/// ```no_run +/// use std::os::unix::net::UnixStream; +/// use std::io::prelude::*; +/// +/// let mut stream = UnixStream::connect("/path/to/my/socket").unwrap(); +/// stream.write_all(b"hello world").unwrap(); +/// let mut response = String::new(); +/// stream.read_to_string(&mut response).unwrap(); +/// println!("{}", response); +/// ``` +#[stable(feature = "unix_socket", since = "1.10.0")] +pub struct UnixStream(Socket); + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl fmt::Debug for UnixStream { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut builder = fmt.debug_struct("UnixStream"); + builder.field("fd", self.0.as_inner()); + if let Ok(addr) = self.local_addr() { + builder.field("local", &addr); + } + if let Ok(addr) = self.peer_addr() { + builder.field("peer", &addr); + } + builder.finish() + } +} + +impl UnixStream { + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn connect(path: &Path) -> io::Result { + unsafe { + let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; + let (addr, len) = sockaddr_un(path)?; + + cvt(libc::connect(*inner.as_inner(), &addr as *const _ as *const _, len))?; + Ok(UnixStream(inner)) + } + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn pair() -> io::Result<(UnixStream, UnixStream)> { + let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?; + Ok((UnixStream(i1), UnixStream(i2))) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn try_clone(&self) -> io::Result { + self.0.duplicate().map(UnixStream) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn local_addr(&self) -> io::Result { + SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn peer_addr(&self) -> io::Result { + SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { + self.0.set_timeout(timeout, libc::SO_RCVTIMEO) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { + self.0.set_timeout(timeout, libc::SO_SNDTIMEO) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn read_timeout(&self) -> io::Result> { + self.0.timeout(libc::SO_RCVTIMEO) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn write_timeout(&self) -> io::Result> { + self.0.timeout(libc::SO_SNDTIMEO) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.0.set_nonblocking(nonblocking) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn take_error(&self) -> io::Result> { + self.0.take_error() + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { + self.0.shutdown(how) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl<'a> io::Read for &'a UnixStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.0.read(buf) + } + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl<'a> io::Write for &'a UnixStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl AsRawFd for UnixStream { + fn as_raw_fd(&self) -> RawFd { + *self.0.as_inner() + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl FromRawFd for UnixStream { + unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { + UnixStream(Socket::from_inner(fd)) + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawFd for UnixStream { + fn into_raw_fd(self) -> RawFd { + self.0.into_inner() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +pub struct UnixListener(Socket); + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl fmt::Debug for UnixListener { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut builder = fmt.debug_struct("UnixListener"); + builder.field("fd", self.0.as_inner()); + if let Ok(addr) = self.local_addr() { + builder.field("local", &addr); + } + builder.finish() + } +} + +impl UnixListener { + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn bind(path: &Path) -> io::Result { + unsafe { + let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; + let (addr, len) = sockaddr_un(path)?; + + cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len as _))?; + cvt(libc::listen(*inner.as_inner(), 128))?; + + Ok(UnixListener(inner)) + } + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { + let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() }; + let mut len = mem::size_of_val(&storage) as libc::socklen_t; + let sock = self.0.accept(&mut storage as *mut _ as *mut _, &mut len)?; + let addr = SocketAddr::from_parts(storage, len)?; + Ok((UnixStream(sock), addr)) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn try_clone(&self) -> io::Result { + self.0.duplicate().map(UnixListener) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn local_addr(&self) -> io::Result { + SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.0.set_nonblocking(nonblocking) + } + + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn take_error(&self) -> io::Result> { + self.0.take_error() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl AsRawFd for UnixListener { + fn as_raw_fd(&self) -> RawFd { + *self.0.as_inner() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl FromRawFd for UnixListener { + unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { + UnixListener(Socket::from_inner(fd)) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl IntoRawFd for UnixListener { + fn into_raw_fd(self) -> RawFd { + self.0.into_inner() + } +} diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index d0c4d6a7737..7fb273826cc 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -54,6 +54,7 @@ pub mod util; pub mod wtf8; pub mod bytestring; pub mod process; +pub mod unixsocket; cfg_if! { if #[cfg(any(target_os = "cloudabi", target_os = "l4re", target_os = "redox"))] { diff --git a/src/libstd/sys_common/unixsocket.rs b/src/libstd/sys_common/unixsocket.rs new file mode 100644 index 00000000000..96037d6c5d9 --- /dev/null +++ b/src/libstd/sys_common/unixsocket.rs @@ -0,0 +1,704 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![cfg(any(all(unix, not(target_os = "emscripten")), target_os = "redox"))] +#![stable(feature = "unix_socket", since = "1.10.0")] + +//! Unix-specific networking functionality + +use fmt; +use io::{self, Initializer}; +use net::Shutdown; +use os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd}; +use path::Path; +use time::Duration; + +use sys::ext::unixsocket as inner; + +/// An address associated with a Unix socket. +/// +/// # Examples +/// +/// ``` +/// use std::os::unix::net::UnixListener; +/// +/// let socket = match UnixListener::bind("/tmp/sock") { +/// Ok(sock) => sock, +/// Err(e) => { +/// println!("Couldn't bind: {:?}", e); +/// return +/// } +/// }; +/// let addr = socket.local_addr().expect("Couldn't get local address"); +/// ``` +#[stable(feature = "unix_socket", since = "1.10.0")] +#[derive(Clone)] +pub struct SocketAddr(pub(crate) inner::SocketAddr); + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl fmt::Debug for SocketAddr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.0) + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawFd for UnixStream { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw_fd() + } +} +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl AsRawFd for UnixStream { + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } +} +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl FromRawFd for UnixStream { + unsafe fn from_raw_fd(fd: RawFd) -> Self { + UnixStream(inner::UnixStream::from_raw_fd(fd)) + } +} +#[stable(feature = "unix_socket", since = "1.10.0")] +impl io::Read for UnixStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + io::Read::read(&mut &self.0, buf) + } + + #[inline] + unsafe fn initializer(&self) -> Initializer { + io::Read::initializer(&&self.0) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl<'a> io::Read for &'a UnixStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + io::Read::read(&mut &self.0, buf) + } + + #[inline] + unsafe fn initializer(&self) -> Initializer { + io::Read::initializer(&&self.0) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl io::Write for UnixStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + io::Write::write(&mut &self.0, buf) + } + + fn flush(&mut self) -> io::Result<()> { + io::Write::flush(&mut &self.0) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl<'a> io::Write for &'a UnixStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + io::Write::write(&mut &self.0, buf) + } + + fn flush(&mut self) -> io::Result<()> { + io::Write::flush(&mut &self.0) + } +} + +impl SocketAddr { + /// Returns the contents of this address if it is a `pathname` address. + /// + /// # Examples + /// + /// With a pathname: + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// use std::path::Path; + /// + /// let socket = UnixListener::bind("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock"))); + /// ``` + /// + /// Without a pathname: + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// + /// let socket = UnixDatagram::unbound().unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.as_pathname(), None); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn as_pathname(&self) -> Option<&Path> { + self.0.as_pathname() + } +} + +/// A Unix stream socket. +/// +/// # Examples +/// +/// ```no_run +/// use std::os::unix::net::UnixStream; +/// use std::io::prelude::*; +/// +/// let mut stream = UnixStream::connect("/path/to/my/socket").unwrap(); +/// stream.write_all(b"hello world").unwrap(); +/// let mut response = String::new(); +/// stream.read_to_string(&mut response).unwrap(); +/// println!("{}", response); +/// ``` +#[stable(feature = "unix_socket", since = "1.10.0")] +pub struct UnixStream(inner::UnixStream); + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl fmt::Debug for UnixStream { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.0) + } +} + +impl UnixStream { + /// Connects to the socket named by `path`. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = match UnixStream::connect("/tmp/sock") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return + /// } + /// }; + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn connect>(path: P) -> io::Result { + inner::UnixStream::connect(path.as_ref()).map(UnixStream) + } + + /// Creates an unnamed pair of connected sockets. + /// + /// Returns two `UnixStream`s which are connected to each other. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let (sock1, sock2) = match UnixStream::pair() { + /// Ok((sock1, sock2)) => (sock1, sock2), + /// Err(e) => { + /// println!("Couldn't create a pair of sockets: {:?}", e); + /// return + /// } + /// }; + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn pair() -> io::Result<(UnixStream, UnixStream)> { + inner::UnixStream::pair().map(|(s1, s2)| (UnixStream(s1), UnixStream(s2))) + } + + /// Creates a new independently owned handle to the underlying socket. + /// + /// The returned `UnixStream` is a reference to the same stream that this + /// object references. Both handles will read and write the same stream of + /// data, and options set on one stream will be propagated to the other + /// stream. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn try_clone(&self) -> io::Result { + self.0.try_clone().map(UnixStream) + } + + /// Returns the socket address of the local half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn local_addr(&self) -> io::Result { + self.0.local_addr().map(SocketAddr) + } + + /// Returns the socket address of the remote half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let addr = socket.peer_addr().expect("Couldn't get peer address"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn peer_addr(&self) -> io::Result { + self.0.peer_addr().map(SocketAddr) + } + + /// Sets the read timeout for the socket. + /// + /// If the provided value is [`None`], then [`read`] calls will block + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err + /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read + /// [`Duration`]: ../../../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { + self.0.set_read_timeout(timeout) + } + + /// Sets the write timeout for the socket. + /// + /// If the provided value is [`None`], then [`write`] calls will block + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is + /// passed to this method. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err + /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write + /// [`Duration`]: ../../../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); + /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::net::UdpSocket; + /// use std::time::Duration; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); + /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { + self.0.set_write_timeout(timeout) + } + + /// Returns the read timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn read_timeout(&self) -> io::Result> { + self.0.read_timeout() + } + + /// Returns the write timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); + /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn write_timeout(&self) -> io::Result> { + self.0.write_timeout() + } + + /// Moves the socket into or out of nonblocking mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.0.set_nonblocking(nonblocking) + } + + /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// if let Ok(Some(err)) = socket.take_error() { + /// println!("Got error: {:?}", err); + /// } + /// ``` + /// + /// # Platform specific + /// On Redox this always returns None. + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn take_error(&self) -> io::Result> { + self.0.take_error() + } + + /// Shuts down the read, write, or both halves of this connection. + /// + /// This function will cause all pending and future I/O calls on the + /// specified portions to immediately return with an appropriate value + /// (see the documentation of [`Shutdown`]). + /// + /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::net::Shutdown; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { + self.0.shutdown(how) + } +} + +/// A structure representing a Unix domain socket server. +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// use std::os::unix::net::{UnixStream, UnixListener}; +/// +/// pub fn handle_client(stream: UnixStream) { +/// // ... +/// } +/// +/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); +/// +/// // accept connections and process them, spawning a new thread for each one +/// for stream in listener.incoming() { +/// match stream { +/// Ok(stream) => { +/// /* connection succeeded */ +/// thread::spawn(|| handle_client(stream)); +/// } +/// Err(err) => { +/// /* connection failed */ +/// break; +/// } +/// } +/// } +/// ``` +#[stable(feature = "unix_socket", since = "1.10.0")] +pub struct UnixListener(inner::UnixListener); + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl fmt::Debug for UnixListener { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.0) + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawFd for UnixListener { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw_fd() + } +} +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl AsRawFd for UnixListener { + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } +} +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl FromRawFd for UnixListener { + unsafe fn from_raw_fd(fd: RawFd) -> Self { + UnixListener(inner::UnixListener::from_raw_fd(fd)) + } +} + +impl UnixListener { + /// Creates a new `UnixListener` bound to the specified socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = match UnixListener::bind("/path/to/the/socket") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return + /// } + /// }; + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn bind>(path: P) -> io::Result { + inner::UnixListener::bind(path.as_ref()).map(UnixListener) + } + + /// Accepts a new incoming connection to this listener. + /// + /// This function will block the calling thread until a new Unix connection + /// is established. When established, the corresponding [`UnixStream`] and + /// the remote peer's address will be returned. + /// + /// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// match listener.accept() { + /// Ok((socket, addr)) => println!("Got a client: {:?}", addr), + /// Err(e) => println!("accept function failed: {:?}", e), + /// } + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { + self.0.accept().map(|(s, a)| (UnixStream(s), SocketAddr(a))) + } + + /// Creates a new independently owned handle to the underlying socket. + /// + /// The returned `UnixListener` is a reference to the same socket that this + /// object references. Both handles can be used to accept incoming + /// connections and options set on one listener will affect the other. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// let listener_copy = listener.try_clone().expect("try_clone failed"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn try_clone(&self) -> io::Result { + self.0.try_clone().map(UnixListener) + } + + /// Returns the local socket address of this listener. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// let addr = listener.local_addr().expect("Couldn't get local address"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn local_addr(&self) -> io::Result { + self.0.local_addr().map(SocketAddr) + } + + /// Moves the socket into or out of nonblocking mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.0.set_nonblocking(nonblocking) + } + + /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/tmp/sock").unwrap(); + /// + /// if let Ok(Some(err)) = listener.take_error() { + /// println!("Got error: {:?}", err); + /// } + /// ``` + /// + /// # Platform specific + /// On Redox this always returns None. + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn take_error(&self) -> io::Result> { + self.0.take_error() + } + + /// Returns an iterator over incoming connections. + /// + /// The iterator will never return [`None`] and will also not yield the + /// peer's [`SocketAddr`] structure. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`SocketAddr`]: struct.SocketAddr.html + /// + /// # Examples + /// + /// ```no_run + /// use std::thread; + /// use std::os::unix::net::{UnixStream, UnixListener}; + /// + /// pub fn handle_client(stream: UnixStream) { + /// // ... + /// } + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// for stream in listener.incoming() { + /// match stream { + /// Ok(stream) => { + /// thread::spawn(|| handle_client(stream)); + /// } + /// Err(err) => { + /// break; + /// } + /// } + /// } + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn incoming<'a>(&'a self) -> Incoming<'a> { + Incoming { listener: self } + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl<'a> IntoIterator for &'a UnixListener { + type Item = io::Result; + type IntoIter = Incoming<'a>; + + fn into_iter(self) -> Incoming<'a> { + self.incoming() + } +} + +/// An iterator over incoming connections to a [`UnixListener`]. +/// +/// It will never return [`None`]. +/// +/// [`None`]: ../../../../std/option/enum.Option.html#variant.None +/// [`UnixListener`]: struct.UnixListener.html +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// use std::os::unix::net::{UnixStream, UnixListener}; +/// +/// pub fn handle_client(stream: UnixStream) { +/// // ... +/// } +/// +/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); +/// +/// for stream in listener.incoming() { +/// match stream { +/// Ok(stream) => { +/// thread::spawn(|| handle_client(stream)); +/// } +/// Err(err) => { +/// break; +/// } +/// } +/// } +/// ``` +#[stable(feature = "unix_socket", since = "1.10.0")] +#[derive(Debug)] +pub struct Incoming<'a> { + listener: &'a UnixListener, +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl<'a> Iterator for Incoming<'a> { + type Item = io::Result; + + fn next(&mut self) -> Option> { + Some(self.listener.accept().map(|s| s.0)) + } + + fn size_hint(&self) -> (usize, Option) { + (usize::max_value(), None) + } +} -- cgit 1.4.1-3-g733a5 From 79bf00f4063793b3828001a845f6111d628c3349 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Wed, 27 Jun 2018 14:52:08 +0200 Subject: Fix tidy checks --- src/libstd/sys/redox/ext/net.rs | 10 ++++++++++ src/libstd/sys/unix/ext/net.rs | 10 ++++++---- src/libstd/sys/unix/ext/unixsocket.rs | 4 +++- src/libstd/sys_common/mod.rs | 4 +++- src/libstd/sys_common/unixsocket.rs | 1 - 5 files changed, 22 insertions(+), 7 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/net.rs b/src/libstd/sys/redox/ext/net.rs index eb256885155..16eec67fb87 100644 --- a/src/libstd/sys/redox/ext/net.rs +++ b/src/libstd/sys/redox/ext/net.rs @@ -1,3 +1,13 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #![stable(feature = "unix_socket", since = "1.10.0")] #[stable(feature = "unix_socket", since = "1.10.0")] pub use sys_common::unixsocket::*; diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 77bca85fe88..9251871baf6 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -323,8 +323,9 @@ impl UnixDatagram { /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn local_addr(&self) -> io::Result { - inner::SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) - .map(SocketAddr) + inner::SocketAddr::new(|addr, len| unsafe { + libc::getsockname(*self.0.as_inner(), addr, len) + }).map(SocketAddr) } /// Returns the address of this socket's peer. @@ -345,8 +346,9 @@ impl UnixDatagram { /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn peer_addr(&self) -> io::Result { - inner::SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) - .map(SocketAddr) + inner::SocketAddr::new(|addr, len| unsafe { + libc::getsockname(*self.0.as_inner(), addr, len) + }).map(SocketAddr) } /// Receives data from the socket. diff --git a/src/libstd/sys/unix/ext/unixsocket.rs b/src/libstd/sys/unix/ext/unixsocket.rs index f6996ecd66f..7b52a5fcf0d 100644 --- a/src/libstd/sys/unix/ext/unixsocket.rs +++ b/src/libstd/sys/unix/ext/unixsocket.rs @@ -65,7 +65,9 @@ impl SocketAddr { } } - pub(crate) fn from_parts(addr: libc::sockaddr_un, mut len: libc::socklen_t) -> io::Result { + pub(crate) fn from_parts(addr: libc::sockaddr_un, mut len: libc::socklen_t) + -> io::Result + { if len == 0 { // When there is a datagram from unnamed unix socket // linux returns zero bytes of address diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index 7fb273826cc..89f5fd79f40 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -54,7 +54,9 @@ pub mod util; pub mod wtf8; pub mod bytestring; pub mod process; -pub mod unixsocket; + +#[cfg(any(all(unix, not(target_os = "emscripten")), target_os = "redox"))] +pub(crate) mod unixsocket; cfg_if! { if #[cfg(any(target_os = "cloudabi", target_os = "l4re", target_os = "redox"))] { diff --git a/src/libstd/sys_common/unixsocket.rs b/src/libstd/sys_common/unixsocket.rs index 96037d6c5d9..286e0e9f37f 100644 --- a/src/libstd/sys_common/unixsocket.rs +++ b/src/libstd/sys_common/unixsocket.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![cfg(any(all(unix, not(target_os = "emscripten")), target_os = "redox"))] #![stable(feature = "unix_socket", since = "1.10.0")] //! Unix-specific networking functionality -- cgit 1.4.1-3-g733a5 From a9f7cc3b4968d1ec5a8bc857a83ea7ade33fffa8 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Wed, 27 Jun 2018 08:56:19 -0700 Subject: [fuchsia] Update zx_cprng_draw to target semantics This change is the final step in improving the semantics of zx_cprng_draw. Now the syscall always generates the requested number of bytes. If the syscall would have failed to generate the requested number of bytes, the syscall either terminates the entire operating system or terminates the calling process, depending on whether the error is a result of the kernel misbehaving or the userspace program misbehaving. --- src/libstd/sys/unix/rand.rs | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index 3f7f0671490..01c0ada4ffb 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -183,34 +183,10 @@ mod imp { mod imp { #[link(name = "zircon")] extern { - fn zx_cprng_draw_new(buffer: *mut u8, len: usize) -> i32; - } - - fn getrandom(buf: &mut [u8]) -> Result { - unsafe { - let status = zx_cprng_draw_new(buf.as_mut_ptr(), buf.len()); - if status == 0 { - Ok(buf.len()) - } else { - Err(status) - } - } + fn zx_cprng_draw(buffer: *mut u8, len: usize); } pub fn fill_bytes(v: &mut [u8]) { - let mut buf = v; - while !buf.is_empty() { - let ret = getrandom(buf); - match ret { - Err(err) => { - panic!("kernel zx_cprng_draw call failed! (returned {}, buf.len() {})", - err, buf.len()) - } - Ok(actual) => { - let move_buf = buf; - buf = &mut move_buf[(actual as usize)..]; - } - } - } + unsafe { zx_cprng_draw(v.as_mut_ptr(), v.len()) } } } -- cgit 1.4.1-3-g733a5 From c98631075748d19c1dce3768fdff9918e8f1492a Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Wed, 27 Jun 2018 18:37:44 +0200 Subject: Add is_unnamed on redox --- src/libstd/sys/redox/ext/unixsocket.rs | 48 ++++++++++++++++++---------------- src/libstd/sys/unix/ext/unixsocket.rs | 6 +++-- src/libstd/sys_common/unixsocket.rs | 28 ++++++++++++++++++++ 3 files changed, 58 insertions(+), 24 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/unixsocket.rs b/src/libstd/sys/redox/ext/unixsocket.rs index 78ca0f16af4..be37575145a 100644 --- a/src/libstd/sys/redox/ext/unixsocket.rs +++ b/src/libstd/sys/redox/ext/unixsocket.rs @@ -20,11 +20,15 @@ use sys::{cvt, fd::FileDesc, syscall}; #[stable(feature = "unix_socket", since = "1.10.0")] #[derive(Clone)] -pub(crate) struct SocketAddr(()); +pub struct SocketAddr(()); impl SocketAddr { #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn as_pathname(&self) -> Option<&Path> { + pub fn is_unnamed(&self) -> bool { + false + } + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn as_pathname(&self) -> Option<&Path> { None } } @@ -36,7 +40,7 @@ impl fmt::Debug for SocketAddr { } #[stable(feature = "unix_socket", since = "1.10.0")] -pub(crate) struct UnixStream(FileDesc); +pub struct UnixStream(FileDesc); #[stable(feature = "unix_socket", since = "1.10.0")] impl fmt::Debug for UnixStream { @@ -55,7 +59,7 @@ impl fmt::Debug for UnixStream { impl UnixStream { #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn connect(path: &Path) -> io::Result { + pub fn connect(path: &Path) -> io::Result { if let Some(s) = path.to_str() { cvt(syscall::open(format!("chan:{}", s), syscall::O_CLOEXEC)) .map(FileDesc::new) @@ -69,7 +73,7 @@ impl UnixStream { } #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn pair() -> io::Result<(UnixStream, UnixStream)> { + pub fn pair() -> io::Result<(UnixStream, UnixStream)> { let server = cvt(syscall::open("chan:", syscall::O_CREAT | syscall::O_CLOEXEC)) .map(FileDesc::new)?; let client = server.duplicate_path(b"connect")?; @@ -78,52 +82,52 @@ impl UnixStream { } #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn try_clone(&self) -> io::Result { + pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UnixStream) } #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn local_addr(&self) -> io::Result { + pub fn local_addr(&self) -> io::Result { Err(Error::new(ErrorKind::Other, "UnixStream::local_addr unimplemented on redox")) } #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn peer_addr(&self) -> io::Result { + pub fn peer_addr(&self) -> io::Result { Err(Error::new(ErrorKind::Other, "UnixStream::peer_addr unimplemented on redox")) } #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn set_read_timeout(&self, _timeout: Option) -> io::Result<()> { + pub fn set_read_timeout(&self, _timeout: Option) -> io::Result<()> { Err(Error::new(ErrorKind::Other, "UnixStream::set_read_timeout unimplemented on redox")) } #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn set_write_timeout(&self, _timeout: Option) -> io::Result<()> { + pub fn set_write_timeout(&self, _timeout: Option) -> io::Result<()> { Err(Error::new(ErrorKind::Other, "UnixStream::set_write_timeout unimplemented on redox")) } #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn read_timeout(&self) -> io::Result> { + pub fn read_timeout(&self) -> io::Result> { Err(Error::new(ErrorKind::Other, "UnixStream::read_timeout unimplemented on redox")) } #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn write_timeout(&self) -> io::Result> { + pub fn write_timeout(&self) -> io::Result> { Err(Error::new(ErrorKind::Other, "UnixStream::write_timeout unimplemented on redox")) } #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn take_error(&self) -> io::Result> { + pub fn take_error(&self) -> io::Result> { Ok(None) } #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn shutdown(&self, _how: Shutdown) -> io::Result<()> { + pub fn shutdown(&self, _how: Shutdown) -> io::Result<()> { Err(Error::new(ErrorKind::Other, "UnixStream::shutdown unimplemented on redox")) } } @@ -173,7 +177,7 @@ impl IntoRawFd for UnixStream { } #[stable(feature = "unix_socket", since = "1.10.0")] -pub(crate) struct UnixListener(FileDesc); +pub struct UnixListener(FileDesc); #[stable(feature = "unix_socket", since = "1.10.0")] impl fmt::Debug for UnixListener { @@ -189,7 +193,7 @@ impl fmt::Debug for UnixListener { impl UnixListener { #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn bind(path: &Path) -> io::Result { + pub fn bind(path: &Path) -> io::Result { if let Some(s) = path.to_str() { cvt(syscall::open(format!("chan:{}", s), syscall::O_CREAT | syscall::O_CLOEXEC)) .map(FileDesc::new) @@ -203,27 +207,27 @@ impl UnixListener { } #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { + pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { self.0.duplicate_path(b"listen").map(|fd| (UnixStream(fd), SocketAddr(()))) } #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn try_clone(&self) -> io::Result { + pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UnixListener) } #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn local_addr(&self) -> io::Result { + pub fn local_addr(&self) -> io::Result { Err(Error::new(ErrorKind::Other, "UnixListener::local_addr unimplemented on redox")) } #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } #[stable(feature = "unix_socket", since = "1.10.0")] - pub(crate) fn take_error(&self) -> io::Result> { + pub fn take_error(&self) -> io::Result> { Ok(None) } } diff --git a/src/libstd/sys/unix/ext/unixsocket.rs b/src/libstd/sys/unix/ext/unixsocket.rs index 7b52a5fcf0d..124555141a3 100644 --- a/src/libstd/sys/unix/ext/unixsocket.rs +++ b/src/libstd/sys/unix/ext/unixsocket.rs @@ -54,7 +54,8 @@ pub struct SocketAddr { } impl SocketAddr { - pub(crate) fn new(f: F) -> io::Result + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn new(f: F) -> io::Result where F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int { unsafe { @@ -65,7 +66,8 @@ impl SocketAddr { } } - pub(crate) fn from_parts(addr: libc::sockaddr_un, mut len: libc::socklen_t) + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn from_parts(addr: libc::sockaddr_un, mut len: libc::socklen_t) -> io::Result { if len == 0 { diff --git a/src/libstd/sys_common/unixsocket.rs b/src/libstd/sys_common/unixsocket.rs index 286e0e9f37f..c7d71ae6790 100644 --- a/src/libstd/sys_common/unixsocket.rs +++ b/src/libstd/sys_common/unixsocket.rs @@ -113,6 +113,34 @@ impl<'a> io::Write for &'a UnixStream { } impl SocketAddr { + /// Returns true if and only if the address is unnamed. + /// + /// # Examples + /// + /// A named address: + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let socket = UnixListener::bind("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.is_unnamed(), false); + /// ``` + /// + /// An unnamed address: + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// + /// let socket = UnixDatagram::unbound().unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.is_unnamed(), true); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn is_unnamed(&self) -> bool { + self.0.is_unnamed() + } + /// Returns the contents of this address if it is a `pathname` address. /// /// # Examples -- cgit 1.4.1-3-g733a5 From d39c66bf4ff2b49957edadf10afcc4050c3fc60b Mon Sep 17 00:00:00 2001 From: moxian Date: Tue, 8 May 2018 06:19:55 +0000 Subject: Add a fallback for stacktrace printing for older Windows versions. PR #47252 switched stack inspection functions of dbghelp.dll to their newer alternatives that also capture inlined context. Unfortunately, said new alternatives are not present in older dbghelp.dll versions. In particular Windows 7 at the time of writing has dbghelp.dll version 6.1.7601 from 2010, that lacks StackWalkEx and friends. Fixes #50138 --- src/libstd/sys/windows/backtrace/mod.rs | 170 +++++++++++---- src/libstd/sys/windows/backtrace/printing/msvc.rs | 253 ++++++++++++++++------ src/libstd/sys/windows/c.rs | 16 ++ 3 files changed, 331 insertions(+), 108 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs index 82498ad4d58..8e879e0f49e 100644 --- a/src/libstd/sys/windows/backtrace/mod.rs +++ b/src/libstd/sys/windows/backtrace/mod.rs @@ -48,24 +48,21 @@ pub mod gnu; pub use self::printing::{resolve_symname, foreach_symbol_fileline}; -pub fn unwind_backtrace(frames: &mut [Frame]) - -> io::Result<(usize, BacktraceContext)> -{ +pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> { let dbghelp = DynamicLibrary::open("dbghelp.dll")?; // Fetch the symbols necessary from dbghelp.dll let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn)?; let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn)?; - let StackWalkEx = sym!(dbghelp, "StackWalkEx", StackWalkExFn)?; + // StackWalkEx might not be present and we'll fall back to StackWalk64 + let ResStackWalkEx = sym!(dbghelp, "StackWalkEx", StackWalkExFn); + let ResStackWalk64 = sym!(dbghelp, "StackWalk64", StackWalk64Fn); // Allocate necessary structures for doing the stack walk let process = unsafe { c::GetCurrentProcess() }; let thread = unsafe { c::GetCurrentThread() }; let mut context: c::CONTEXT = unsafe { mem::zeroed() }; unsafe { c::RtlCaptureContext(&mut context) }; - let mut frame: c::STACKFRAME_EX = unsafe { mem::zeroed() }; - frame.StackFrameSize = mem::size_of_val(&frame) as c::DWORD; - let image = init_frame(&mut frame, &context); let backtrace_context = BacktraceContext { handle: process, @@ -76,49 +73,139 @@ pub fn unwind_backtrace(frames: &mut [Frame]) // Initialize this process's symbols let ret = unsafe { SymInitialize(process, ptr::null_mut(), c::TRUE) }; if ret != c::TRUE { - return Ok((0, backtrace_context)) + return Ok((0, backtrace_context)); } // And now that we're done with all the setup, do the stack walking! - let mut i = 0; - unsafe { - while i < frames.len() && - StackWalkEx(image, process, thread, &mut frame, &mut context, - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - 0) == c::TRUE - { - let addr = (frame.AddrPC.Offset - 1) as *const u8; - - frames[i] = Frame { - symbol_addr: addr, - exact_position: addr, - inline_context: frame.InlineFrameContext, - }; - i += 1; + match (ResStackWalkEx, ResStackWalk64) { + (Ok(StackWalkEx), _) => { + let mut frame: c::STACKFRAME_EX = unsafe { mem::zeroed() }; + frame.StackFrameSize = mem::size_of_val(&frame) as c::DWORD; + let image = init_frame_ex(&mut frame, &context); + + let mut i = 0; + unsafe { + while i < frames.len() + && StackWalkEx( + image, + process, + thread, + &mut frame, + &mut context, + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + 0, + ) == c::TRUE + { + let addr = (frame.AddrPC.Offset - 1) as *const u8; + + frames[i] = Frame { + symbol_addr: addr, + exact_position: addr, + inline_context: frame.InlineFrameContext, + }; + i += 1; + } + } + + Ok((i, backtrace_context)) } + (_, Ok(StackWalk64)) => { + let mut frame: c::STACKFRAME64 = unsafe { mem::zeroed() }; + let image = init_frame_64(&mut frame, &context); + + // Start from -1 to avoid printing this stack frame, which will + // always be exactly the same. + let mut i = 0; + unsafe { + while i < frames.len() + && StackWalk64( + image, + process, + thread, + &mut frame, + &mut context, + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ) == c::TRUE + { + let addr = frame.AddrPC.Offset; + if addr == frame.AddrReturn.Offset || addr == 0 || frame.AddrReturn.Offset == 0 + { + break; + } + + frames[i] = Frame { + symbol_addr: (addr - 1) as *const u8, + exact_position: (addr - 1) as *const u8, + inline_context: 0, + }; + i += 1; + } + } + + Ok((i, backtrace_context)) + } + (Err(e), _) => Err(e), } - - Ok((i, backtrace_context)) } -type SymInitializeFn = - unsafe extern "system" fn(c::HANDLE, *mut c_void, - c::BOOL) -> c::BOOL; -type SymCleanupFn = - unsafe extern "system" fn(c::HANDLE) -> c::BOOL; +type SymInitializeFn = unsafe extern "system" fn(c::HANDLE, *mut c_void, c::BOOL) -> c::BOOL; +type SymCleanupFn = unsafe extern "system" fn(c::HANDLE) -> c::BOOL; + +type StackWalkExFn = unsafe extern "system" fn( + c::DWORD, + c::HANDLE, + c::HANDLE, + *mut c::STACKFRAME_EX, + *mut c::CONTEXT, + *mut c_void, + *mut c_void, + *mut c_void, + *mut c_void, + c::DWORD, +) -> c::BOOL; + +type StackWalk64Fn = unsafe extern "system" fn( + c::DWORD, + c::HANDLE, + c::HANDLE, + *mut c::STACKFRAME64, + *mut c::CONTEXT, + *mut c_void, + *mut c_void, + *mut c_void, + *mut c_void, +) -> c::BOOL; -type StackWalkExFn = - unsafe extern "system" fn(c::DWORD, c::HANDLE, c::HANDLE, - *mut c::STACKFRAME_EX, *mut c::CONTEXT, - *mut c_void, *mut c_void, - *mut c_void, *mut c_void, c::DWORD) -> c::BOOL; +#[cfg(target_arch = "x86")] +fn init_frame_ex(frame: &mut c::STACKFRAME_EX, ctx: &c::CONTEXT) -> c::DWORD { + frame.AddrPC.Offset = ctx.Eip as u64; + frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat; + frame.AddrStack.Offset = ctx.Esp as u64; + frame.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat; + frame.AddrFrame.Offset = ctx.Ebp as u64; + frame.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat; + c::IMAGE_FILE_MACHINE_I386 +} + +#[cfg(target_arch = "x86_64")] +fn init_frame_ex(frame: &mut c::STACKFRAME_EX, ctx: &c::CONTEXT) -> c::DWORD { + frame.AddrPC.Offset = ctx.Rip as u64; + frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat; + frame.AddrStack.Offset = ctx.Rsp as u64; + frame.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat; + frame.AddrFrame.Offset = ctx.Rbp as u64; + frame.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat; + c::IMAGE_FILE_MACHINE_AMD64 +} #[cfg(target_arch = "x86")] -fn init_frame(frame: &mut c::STACKFRAME_EX, - ctx: &c::CONTEXT) -> c::DWORD { +fn init_frame_64(frame: &mut c::STACKFRAME64, ctx: &c::CONTEXT) -> c::DWORD { frame.AddrPC.Offset = ctx.Eip as u64; frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat; frame.AddrStack.Offset = ctx.Esp as u64; @@ -129,8 +216,7 @@ fn init_frame(frame: &mut c::STACKFRAME_EX, } #[cfg(target_arch = "x86_64")] -fn init_frame(frame: &mut c::STACKFRAME_EX, - ctx: &c::CONTEXT) -> c::DWORD { +fn init_frame_64(frame: &mut c::STACKFRAME64, ctx: &c::CONTEXT) -> c::DWORD { frame.AddrPC.Offset = ctx.Rip as u64; frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat; frame.AddrStack.Offset = ctx.Rsp as u64; diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs index 967df1c8a2d..e26d95a4f9d 100644 --- a/src/libstd/sys/windows/backtrace/printing/msvc.rs +++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs @@ -10,88 +10,209 @@ use ffi::CStr; use io; -use libc::{c_ulong, c_char}; +use libc::{c_char, c_ulong}; use mem; -use sys::c; use sys::backtrace::BacktraceContext; +use sys::c; use sys_common::backtrace::Frame; type SymFromInlineContextFn = - unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, - *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL; -type SymGetLineFromInlineContextFn = - unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, - u64, *mut c::DWORD, *mut c::IMAGEHLP_LINE64) -> c::BOOL; + unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL; +type SymFromInlineContextFn = + unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL; +type SymGetLineFromInlineContextFn = unsafe extern "system" fn( + c::HANDLE, + u64, + c::ULONG, + u64, + *mut c::DWORD, + *mut c::IMAGEHLP_LINE64, +) -> c::BOOL; + +type SymFromAddrFn = + unsafe extern "system" fn(c::HANDLE, u64, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL; +type SymGetLineFromAddr64Fn = + unsafe extern "system" fn(c::HANDLE, u64, *mut u32, *mut c::IMAGEHLP_LINE64) -> c::BOOL; /// Converts a pointer to symbol to its string value. -pub fn resolve_symname(frame: Frame, - callback: F, - context: &BacktraceContext) -> io::Result<()> - where F: FnOnce(Option<&str>) -> io::Result<()> +pub fn resolve_symname(frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()> +where + F: FnOnce(Option<&str>) -> io::Result<()>, { - let SymFromInlineContext = sym!(&context.dbghelp, - "SymFromInlineContext", - SymFromInlineContextFn)?; + match ( + sym!( + &context.dbghelp, + "SymFromInlineContext", + SymFromInlineContextFn + ), + sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn), + ) { + (Ok(SymFromInlineContext), _) => unsafe { + let mut info: c::SYMBOL_INFO = mem::zeroed(); + info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; + // the struct size in C. the value is different to + // `size_of::() - MAX_SYM_NAME + 1` (== 81) + // due to struct alignment. + info.SizeOfStruct = 88; - unsafe { - let mut info: c::SYMBOL_INFO = mem::zeroed(); - info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; - // the struct size in C. the value is different to - // `size_of::() - MAX_SYM_NAME + 1` (== 81) - // due to struct alignment. - info.SizeOfStruct = 88; + let mut displacement = 0u64; + let ret = SymFromInlineContext( + context.handle, + frame.symbol_addr as u64, + frame.inline_context, + &mut displacement, + &mut info, + ); + let valid_range = + if ret == c::TRUE && frame.symbol_addr as usize >= info.Address as usize { + if info.Size != 0 { + (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize + } else { + true + } + } else { + false + }; + let symname = if valid_range { + let ptr = info.Name.as_ptr() as *const c_char; + CStr::from_ptr(ptr).to_str().ok() + } else { + None + }; + callback(symname) +{ + match ( + sym!( + &context.dbghelp, + "SymFromInlineContext", + SymFromInlineContextFn + ), + sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn), + ) { + (Ok(SymFromInlineContext), _) => unsafe { + let mut info: c::SYMBOL_INFO = mem::zeroed(); + info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; + // the struct size in C. the value is different to + // `size_of::() - MAX_SYM_NAME + 1` (== 81) + // due to struct alignment. + info.SizeOfStruct = 88; - let mut displacement = 0u64; - let ret = SymFromInlineContext(context.handle, - frame.symbol_addr as u64, - frame.inline_context, - &mut displacement, - &mut info); - let valid_range = if ret == c::TRUE && - frame.symbol_addr as usize >= info.Address as usize { - if info.Size != 0 { - (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize + let mut displacement = 0u64; + let ret = SymFromInlineContext( + context.handle, + frame.symbol_addr as u64, + frame.inline_context, + &mut displacement, + &mut info, + ); + let valid_range = + if ret == c::TRUE && frame.symbol_addr as usize >= info.Address as usize { + if info.Size != 0 { + (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize + } else { + true + } + } else { + false + }; + let symname = if valid_range { + let ptr = info.Name.as_ptr() as *const c_char; + CStr::from_ptr(ptr).to_str().ok() } else { - true - } - } else { - false - }; - let symname = if valid_range { - let ptr = info.Name.as_ptr() as *const c_char; - CStr::from_ptr(ptr).to_str().ok() - } else { - None - }; - callback(symname) + None + }; + callback(symname) + }, + (_, Ok(SymFromAddr)) => unsafe { + } else { + None + }; + callback(symname) + }, + (_, Ok(SymFromAddr)) => unsafe { + let mut info: c::SYMBOL_INFO = mem::zeroed(); + info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; + // the struct size in C. the value is different to + // `size_of::() - MAX_SYM_NAME + 1` (== 81) + // due to struct alignment. + info.SizeOfStruct = 88; + + let mut displacement = 0u64; + let ret = SymFromAddr( + context.handle, + frame.symbol_addr as u64, + &mut displacement, + &mut info, + ); + + let symname = if ret == c::TRUE { + let ptr = info.Name.as_ptr() as *const c_char; + CStr::from_ptr(ptr).to_str().ok() + } else { + None + }; + callback(symname) + }, + (Err(e), _) => Err(e), } } -pub fn foreach_symbol_fileline(frame: Frame, - mut f: F, - context: &BacktraceContext) - -> io::Result - where F: FnMut(&[u8], u32) -> io::Result<()> +pub fn foreach_symbol_fileline( + frame: Frame, + mut f: F, + context: &BacktraceContext, +) -> io::Result +where + F: FnMut(&[u8], u32) -> io::Result<()>, { - let SymGetLineFromInlineContext = sym!(&context.dbghelp, - "SymGetLineFromInlineContext", - SymGetLineFromInlineContextFn)?; + match ( + sym!( + &context.dbghelp, + "SymGetLineFromInlineContext", + SymGetLineFromInlineContextFn + ), + sym!( + &context.dbghelp, + "SymGetLineFromAddr64", + SymGetLineFromAddr64Fn + ), + ) { + (Ok(SymGetLineFromInlineContext), _) => unsafe { + let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); + line.SizeOfStruct = ::mem::size_of::() as u32; - unsafe { - let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); - line.SizeOfStruct = ::mem::size_of::() as u32; + let mut displacement = 0u32; + let ret = SymGetLineFromInlineContext( + context.handle, + frame.exact_position as u64, + frame.inline_context, + 0, + &mut displacement, + &mut line, + ); + if ret == c::TRUE { + let name = CStr::from_ptr(line.Filename).to_bytes(); + f(name, line.LineNumber as u32)?; + } + Ok(false) + }, + (_, Ok(SymGetLineFromAddr64)) => unsafe { + let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); + line.SizeOfStruct = ::mem::size_of::() as u32; - let mut displacement = 0u32; - let ret = SymGetLineFromInlineContext(context.handle, - frame.exact_position as u64, - frame.inline_context, - 0, - &mut displacement, - &mut line); - if ret == c::TRUE { - let name = CStr::from_ptr(line.Filename).to_bytes(); - f(name, line.LineNumber as u32)?; - } - Ok(false) + let mut displacement = 0u32; + let ret = SymGetLineFromAddr64( + context.handle, + frame.exact_position as u64, + &mut displacement, + &mut line, + ); + if ret == c::TRUE { + let name = CStr::from_ptr(line.Filename).to_bytes(); + f(name, line.LineNumber as u32)?; + } + Ok(false) + }, + (Err(e), _) => Err(e), } } diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 6d929f21365..30aba2f400f 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -635,6 +635,22 @@ pub struct STACKFRAME_EX { pub InlineFrameContext: DWORD, } +#[repr(C)] +#[cfg(feature = "backtrace")] +pub struct STACKFRAME64 { + pub AddrPC: ADDRESS64, + pub AddrReturn: ADDRESS64, + pub AddrFrame: ADDRESS64, + pub AddrStack: ADDRESS64, + pub AddrBStore: ADDRESS64, + pub FuncTableEntry: *mut c_void, + pub Params: [u64; 4], + pub Far: BOOL, + pub Virtual: BOOL, + pub Reserved: [u64; 3], + pub KdHelp: KDHELP64, +} + #[repr(C)] #[cfg(feature = "backtrace")] pub struct KDHELP64 { -- cgit 1.4.1-3-g733a5 From 3245a475ab92b5ab77cf69e336279420c86a83eb Mon Sep 17 00:00:00 2001 From: moxian Date: Sun, 13 May 2018 04:38:43 +0000 Subject: Split separate stackwalk variants into their own functions .. rather than having them be one giant match statement. --- src/libstd/sys/windows/backtrace/mod.rs | 194 ++++++++++------- src/libstd/sys/windows/backtrace/printing/msvc.rs | 248 +++++++++++----------- 2 files changed, 238 insertions(+), 204 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs index 8e879e0f49e..884ec4e9fad 100644 --- a/src/libstd/sys/windows/backtrace/mod.rs +++ b/src/libstd/sys/windows/backtrace/mod.rs @@ -46,7 +46,7 @@ mod printing; #[path = "backtrace_gnu.rs"] pub mod gnu; -pub use self::printing::{resolve_symname, foreach_symbol_fileline}; +pub use self::printing::{foreach_symbol_fileline, resolve_symname}; pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> { let dbghelp = DynamicLibrary::open("dbghelp.dll")?; @@ -54,19 +54,30 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon // Fetch the symbols necessary from dbghelp.dll let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn)?; let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn)?; + + // enum for holding the StackWalk function. Different from StackWalkVariant + // below, since there's no need to pass the function itself into + // the BacktraceContext + enum sw_fn_local { + SWExFn(StackWalkExFn), + SW64Fn(StackWalk64Fn), + } // StackWalkEx might not be present and we'll fall back to StackWalk64 - let ResStackWalkEx = sym!(dbghelp, "StackWalkEx", StackWalkExFn); - let ResStackWalk64 = sym!(dbghelp, "StackWalk64", StackWalk64Fn); + let (StackWalkFn, variant) = + sym!(dbghelp, "StackWalkEx", StackWalkExFn) + .map(|f| (sw_fn_local::SWExFn(f), StackWalkVariant::StackWalkEx)) + .or_else(|_| + sym!(dbghelp, "StackWalk64", StackWalk64Fn) + .map(|f| (sw_fn_local::SW64Fn(f), StackWalkVariant::StackWalk64)) + )?; // Allocate necessary structures for doing the stack walk let process = unsafe { c::GetCurrentProcess() }; - let thread = unsafe { c::GetCurrentThread() }; - let mut context: c::CONTEXT = unsafe { mem::zeroed() }; - unsafe { c::RtlCaptureContext(&mut context) }; let backtrace_context = BacktraceContext { handle: process, SymCleanup, + StackWalkVariant: variant, dbghelp, }; @@ -77,81 +88,102 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon } // And now that we're done with all the setup, do the stack walking! - match (ResStackWalkEx, ResStackWalk64) { - (Ok(StackWalkEx), _) => { - let mut frame: c::STACKFRAME_EX = unsafe { mem::zeroed() }; - frame.StackFrameSize = mem::size_of_val(&frame) as c::DWORD; - let image = init_frame_ex(&mut frame, &context); - - let mut i = 0; - unsafe { - while i < frames.len() - && StackWalkEx( - image, - process, - thread, - &mut frame, - &mut context, - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - 0, - ) == c::TRUE - { - let addr = (frame.AddrPC.Offset - 1) as *const u8; - - frames[i] = Frame { - symbol_addr: addr, - exact_position: addr, - inline_context: frame.InlineFrameContext, - }; - i += 1; - } - } + match StackWalkFn { + sw_fn_local::SWExFn(f) => set_frames_ex(f, frames, backtrace_context, process), + sw_fn_local::SW64Fn(f) => set_frames_64(f, frames, backtrace_context, process), + } +} - Ok((i, backtrace_context)) +fn set_frames_ex( + StackWalkEx: StackWalkExFn, + frames: &mut [Frame], + backtrace_context: BacktraceContext, + process: c::HANDLE, +) -> io::Result<(usize, BacktraceContext)> { + let thread = unsafe { c::GetCurrentProcess() }; + let mut context: c::CONTEXT = unsafe { mem::zeroed() }; + unsafe { c::RtlCaptureContext(&mut context) }; + + let mut frame: c::STACKFRAME_EX = unsafe { mem::zeroed() }; + frame.StackFrameSize = mem::size_of_val(&frame) as c::DWORD; + let image = init_frame_ex(&mut frame, &context); + + let mut i = 0; + unsafe { + while i < frames.len() + && StackWalkEx( + image, + process, + thread, + &mut frame, + &mut context, + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + 0, + ) == c::TRUE + { + let addr = (frame.AddrPC.Offset - 1) as *const u8; + + frames[i] = Frame { + symbol_addr: addr, + exact_position: addr, + inline_context: frame.InlineFrameContext, + }; + i += 1; } - (_, Ok(StackWalk64)) => { - let mut frame: c::STACKFRAME64 = unsafe { mem::zeroed() }; - let image = init_frame_64(&mut frame, &context); - - // Start from -1 to avoid printing this stack frame, which will - // always be exactly the same. - let mut i = 0; - unsafe { - while i < frames.len() - && StackWalk64( - image, - process, - thread, - &mut frame, - &mut context, - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ) == c::TRUE - { - let addr = frame.AddrPC.Offset; - if addr == frame.AddrReturn.Offset || addr == 0 || frame.AddrReturn.Offset == 0 - { - break; - } - - frames[i] = Frame { - symbol_addr: (addr - 1) as *const u8, - exact_position: (addr - 1) as *const u8, - inline_context: 0, - }; - i += 1; - } + } + + Ok((i, backtrace_context)) +} + +fn set_frames_64( + StackWalk64: StackWalk64Fn, + frames: &mut [Frame], + backtrace_context: BacktraceContext, + process: c::HANDLE, +) -> io::Result<(usize, BacktraceContext)> { + let thread = unsafe { c::GetCurrentProcess() }; + let mut context: c::CONTEXT = unsafe { mem::zeroed() }; + unsafe { c::RtlCaptureContext(&mut context) }; + + let mut frame: c::STACKFRAME64 = unsafe { mem::zeroed() }; + let image = init_frame_64(&mut frame, &context); + + // Start from -1 to avoid printing this stack frame, which will + // always be exactly the same. + let mut i = 0; + unsafe { + while i < frames.len() + && StackWalk64( + image, + process, + thread, + &mut frame, + &mut context, + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ) == c::TRUE + { + let addr = frame.AddrPC.Offset; + if addr == frame.AddrReturn.Offset || addr == 0 || frame.AddrReturn.Offset == 0 + { + break; } - Ok((i, backtrace_context)) + frames[i] = Frame { + symbol_addr: (addr - 1) as *const u8, + exact_position: (addr - 1) as *const u8, + inline_context: 0, + }; + i += 1; } - (Err(e), _) => Err(e), } + + Ok((i, backtrace_context)) } type SymInitializeFn = unsafe extern "system" fn(c::HANDLE, *mut c_void, c::BOOL) -> c::BOOL; @@ -226,16 +258,26 @@ fn init_frame_64(frame: &mut c::STACKFRAME64, ctx: &c::CONTEXT) -> c::DWORD { c::IMAGE_FILE_MACHINE_AMD64 } +enum StackWalkVariant { + StackWalkEx, + StackWalk64, +} + + pub struct BacktraceContext { handle: c::HANDLE, SymCleanup: SymCleanupFn, // Only used in printing for msvc and not gnu #[allow(dead_code)] + StackWalkVariant: StackWalkVariant, + #[allow(dead_code)] dbghelp: DynamicLibrary, } impl Drop for BacktraceContext { fn drop(&mut self) { - unsafe { (self.SymCleanup)(self.handle); } + unsafe { + (self.SymCleanup)(self.handle); + } } } diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs index e26d95a4f9d..9d7accb7ad7 100644 --- a/src/libstd/sys/windows/backtrace/printing/msvc.rs +++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs @@ -13,11 +13,10 @@ use io; use libc::{c_char, c_ulong}; use mem; use sys::backtrace::BacktraceContext; +use sys::backtrace::StackWalkVariant; use sys::c; use sys_common::backtrace::Frame; -type SymFromInlineContextFn = - unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL; type SymFromInlineContextFn = unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL; type SymGetLineFromInlineContextFn = unsafe extern "system" fn( @@ -39,57 +38,26 @@ pub fn resolve_symname(frame: Frame, callback: F, context: &BacktraceContext) where F: FnOnce(Option<&str>) -> io::Result<()>, { - match ( - sym!( - &context.dbghelp, - "SymFromInlineContext", - SymFromInlineContextFn - ), - sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn), - ) { - (Ok(SymFromInlineContext), _) => unsafe { - let mut info: c::SYMBOL_INFO = mem::zeroed(); - info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; - // the struct size in C. the value is different to - // `size_of::() - MAX_SYM_NAME + 1` (== 81) - // due to struct alignment. - info.SizeOfStruct = 88; + match context.StackWalkVariant { + StackWalkVariant::StackWalkEx => { + let SymFromInlineContext = + sym!(&context.dbghelp, "SymFromInlineContext",SymFromInlineContextFn)?; + resolve_symname_from_inline_context(SymFromInlineContext, frame, callback, context) + }, + StackWalkVariant::StackWalk64 => { + let SymFromAddr = sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn)?; + resolve_symname_from_addr(SymFromAddr, frame, callback, context) + } + } +} - let mut displacement = 0u64; - let ret = SymFromInlineContext( - context.handle, - frame.symbol_addr as u64, - frame.inline_context, - &mut displacement, - &mut info, - ); - let valid_range = - if ret == c::TRUE && frame.symbol_addr as usize >= info.Address as usize { - if info.Size != 0 { - (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize - } else { - true - } - } else { - false - }; - let symname = if valid_range { - let ptr = info.Name.as_ptr() as *const c_char; - CStr::from_ptr(ptr).to_str().ok() - } else { - None - }; - callback(symname) +fn resolve_symname_from_inline_context( + SymFromInlineContext: SymFromInlineContextFn, + frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()> +where + F: FnOnce(Option<&str>) -> io::Result<()>, { - match ( - sym!( - &context.dbghelp, - "SymFromInlineContext", - SymFromInlineContextFn - ), - sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn), - ) { - (Ok(SymFromInlineContext), _) => unsafe { + unsafe { let mut info: c::SYMBOL_INFO = mem::zeroed(); info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; // the struct size in C. the value is different to @@ -122,42 +90,69 @@ where None }; callback(symname) - }, - (_, Ok(SymFromAddr)) => unsafe { - } else { - None - }; - callback(symname) - }, - (_, Ok(SymFromAddr)) => unsafe { - let mut info: c::SYMBOL_INFO = mem::zeroed(); - info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; - // the struct size in C. the value is different to - // `size_of::() - MAX_SYM_NAME + 1` (== 81) - // due to struct alignment. - info.SizeOfStruct = 88; + } +} - let mut displacement = 0u64; - let ret = SymFromAddr( - context.handle, - frame.symbol_addr as u64, - &mut displacement, - &mut info, - ); +fn resolve_symname_from_addr( + SymFromAddr: SymFromAddrFn, + frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()> +where + F: FnOnce(Option<&str>) -> io::Result<()>, +{ + unsafe { + let mut info: c::SYMBOL_INFO = mem::zeroed(); + info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; + // the struct size in C. the value is different to + // `size_of::() - MAX_SYM_NAME + 1` (== 81) + // due to struct alignment. + info.SizeOfStruct = 88; - let symname = if ret == c::TRUE { - let ptr = info.Name.as_ptr() as *const c_char; - CStr::from_ptr(ptr).to_str().ok() - } else { - None - }; - callback(symname) - }, - (Err(e), _) => Err(e), + let mut displacement = 0u64; + let ret = SymFromAddr( + context.handle, + frame.symbol_addr as u64, + &mut displacement, + &mut info, + ); + + let symname = if ret == c::TRUE { + let ptr = info.Name.as_ptr() as *const c_char; + CStr::from_ptr(ptr).to_str().ok() + } else { + None + }; + callback(symname) } } pub fn foreach_symbol_fileline( + frame: Frame, + f: F, + context: &BacktraceContext, +) -> io::Result +where + F: FnMut(&[u8], u32) -> io::Result<()>, +{ + match context.StackWalkVariant { + StackWalkVariant::StackWalkEx => { + let SymGetLineFromInlineContext = + sym!(&context.dbghelp, "SymGetLineFromInlineContext", + SymGetLineFromInlineContextFn)?; + foreach_symbol_fileline_ex(SymGetLineFromInlineContext, + frame, f, context) + }, + StackWalkVariant::StackWalk64 => { + let SymGetLineFromAddr64 = + sym!(&context.dbghelp, "SymGetLineFromAddr64", + SymGetLineFromAddr64Fn)?; + foreach_symbol_fileline_64(SymGetLineFromAddr64, + frame, f, context) + } + } +} + +fn foreach_symbol_fileline_ex( + SymGetLineFromInlineContext: SymGetLineFromInlineContextFn, frame: Frame, mut f: F, context: &BacktraceContext, @@ -165,54 +160,51 @@ pub fn foreach_symbol_fileline( where F: FnMut(&[u8], u32) -> io::Result<()>, { - match ( - sym!( - &context.dbghelp, - "SymGetLineFromInlineContext", - SymGetLineFromInlineContextFn - ), - sym!( - &context.dbghelp, - "SymGetLineFromAddr64", - SymGetLineFromAddr64Fn - ), - ) { - (Ok(SymGetLineFromInlineContext), _) => unsafe { - let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); - line.SizeOfStruct = ::mem::size_of::() as u32; + unsafe { + let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); + line.SizeOfStruct = ::mem::size_of::() as u32; - let mut displacement = 0u32; - let ret = SymGetLineFromInlineContext( - context.handle, - frame.exact_position as u64, - frame.inline_context, - 0, - &mut displacement, - &mut line, - ); - if ret == c::TRUE { - let name = CStr::from_ptr(line.Filename).to_bytes(); - f(name, line.LineNumber as u32)?; - } - Ok(false) - }, - (_, Ok(SymGetLineFromAddr64)) => unsafe { - let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); - line.SizeOfStruct = ::mem::size_of::() as u32; + let mut displacement = 0u32; + let ret = SymGetLineFromInlineContext( + context.handle, + frame.exact_position as u64, + frame.inline_context, + 0, + &mut displacement, + &mut line, + ); + if ret == c::TRUE { + let name = CStr::from_ptr(line.Filename).to_bytes(); + f(name, line.LineNumber as u32)?; + } + Ok(false) + } +} - let mut displacement = 0u32; - let ret = SymGetLineFromAddr64( - context.handle, - frame.exact_position as u64, - &mut displacement, - &mut line, - ); - if ret == c::TRUE { - let name = CStr::from_ptr(line.Filename).to_bytes(); - f(name, line.LineNumber as u32)?; - } - Ok(false) - }, - (Err(e), _) => Err(e), +fn foreach_symbol_fileline_64( + SymGetLineFromAddr64: SymGetLineFromAddr64Fn, + frame: Frame, + mut f: F, + context: &BacktraceContext, +) -> io::Result +where + F: FnMut(&[u8], u32) -> io::Result<()>, +{ + unsafe { + let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); + line.SizeOfStruct = ::mem::size_of::() as u32; + + let mut displacement = 0u32; + let ret = SymGetLineFromAddr64( + context.handle, + frame.exact_position as u64, + &mut displacement, + &mut line, + ); + if ret == c::TRUE { + let name = CStr::from_ptr(line.Filename).to_bytes(); + f(name, line.LineNumber as u32)?; + } + Ok(false) } } -- cgit 1.4.1-3-g733a5 From c0b280f5f594fc6ff34ddcf35aa26cc46a073808 Mon Sep 17 00:00:00 2001 From: moxian Date: Sun, 13 May 2018 08:41:24 +0000 Subject: Load backtrace-related functions only once .. and pass them around in BacktraceContext. --- src/libstd/sys/windows/backtrace/mod.rs | 45 +++++++++-------- src/libstd/sys/windows/backtrace/printing/mod.rs | 14 ++++++ src/libstd/sys/windows/backtrace/printing/msvc.rs | 59 +++++++++++++++-------- 3 files changed, 77 insertions(+), 41 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs index 884ec4e9fad..23bb4ab6dfe 100644 --- a/src/libstd/sys/windows/backtrace/mod.rs +++ b/src/libstd/sys/windows/backtrace/mod.rs @@ -47,6 +47,7 @@ mod printing; pub mod gnu; pub use self::printing::{foreach_symbol_fileline, resolve_symname}; +use self::printing::{load_printing_fns_ex, load_printing_fns_64}; pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> { let dbghelp = DynamicLibrary::open("dbghelp.dll")?; @@ -55,21 +56,23 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn)?; let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn)?; - // enum for holding the StackWalk function. Different from StackWalkVariant - // below, since there's no need to pass the function itself into - // the BacktraceContext - enum sw_fn_local { - SWExFn(StackWalkExFn), - SW64Fn(StackWalk64Fn), - } + // StackWalkEx might not be present and we'll fall back to StackWalk64 - let (StackWalkFn, variant) = - sym!(dbghelp, "StackWalkEx", StackWalkExFn) - .map(|f| (sw_fn_local::SWExFn(f), StackWalkVariant::StackWalkEx)) - .or_else(|_| - sym!(dbghelp, "StackWalk64", StackWalk64Fn) - .map(|f| (sw_fn_local::SW64Fn(f), StackWalkVariant::StackWalk64)) - )?; + let sw_var = match sym!(dbghelp, "StackWalkEx", StackWalkExFn) { + Ok(StackWalkEx) => + StackWalkVariant::StackWalkEx( + StackWalkEx, + load_printing_fns_ex(&dbghelp)?, + ), + Err(e) => match sym!(dbghelp, "StackWalk64", StackWalk64Fn) { + Ok(StackWalk64) => + StackWalkVariant::StackWalk64( + StackWalk64, + load_printing_fns_64(&dbghelp)?, + ), + Err(..) => return Err(e), + }, + }; // Allocate necessary structures for doing the stack walk let process = unsafe { c::GetCurrentProcess() }; @@ -77,7 +80,7 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon let backtrace_context = BacktraceContext { handle: process, SymCleanup, - StackWalkVariant: variant, + StackWalkVariant: sw_var, dbghelp, }; @@ -88,9 +91,9 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon } // And now that we're done with all the setup, do the stack walking! - match StackWalkFn { - sw_fn_local::SWExFn(f) => set_frames_ex(f, frames, backtrace_context, process), - sw_fn_local::SW64Fn(f) => set_frames_64(f, frames, backtrace_context, process), + match backtrace_context.StackWalkVariant { + StackWalkVariant::StackWalkEx(f, _) => set_frames_ex(f, frames, backtrace_context, process), + StackWalkVariant::StackWalk64(f, _) => set_frames_64(f, frames, backtrace_context, process), } } @@ -259,8 +262,8 @@ fn init_frame_64(frame: &mut c::STACKFRAME64, ctx: &c::CONTEXT) -> c::DWORD { } enum StackWalkVariant { - StackWalkEx, - StackWalk64, + StackWalkEx(StackWalkExFn, printing::PrintingFnsEx), + StackWalk64(StackWalk64Fn, printing::PrintingFns64), } @@ -268,8 +271,10 @@ pub struct BacktraceContext { handle: c::HANDLE, SymCleanup: SymCleanupFn, // Only used in printing for msvc and not gnu + // The gnu version is effectively a ZST dummy. #[allow(dead_code)] StackWalkVariant: StackWalkVariant, + // keeping DynamycLibrary loaded until its functions no longer needed #[allow(dead_code)] dbghelp: DynamicLibrary, } diff --git a/src/libstd/sys/windows/backtrace/printing/mod.rs b/src/libstd/sys/windows/backtrace/printing/mod.rs index 3e566f6e2bd..251d5028aea 100644 --- a/src/libstd/sys/windows/backtrace/printing/mod.rs +++ b/src/libstd/sys/windows/backtrace/printing/mod.rs @@ -15,6 +15,20 @@ mod printing; #[cfg(target_env = "gnu")] mod printing { pub use sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname}; + + // dummy functions to mirror those present in msvc version. + use sys::dynamic_lib::DynamicLibrary; + use io; + pub struct PrintingFnsEx {} + pub struct PrintingFns64 {} + pub fn load_printing_fns_ex(_: &DynamicLibrary) -> io::Result { + Ok(PrintingFnsEx{}) + } + pub fn load_printing_fns_64(_: &DynamicLibrary) -> io::Result { + Ok(PrintingFns64{}) + } } pub use self::printing::{foreach_symbol_fileline, resolve_symname}; +pub use self::printing::{load_printing_fns_ex, load_printing_fns_64, + PrintingFnsEx, PrintingFns64}; diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs index 9d7accb7ad7..9cfc2c3d352 100644 --- a/src/libstd/sys/windows/backtrace/printing/msvc.rs +++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs @@ -15,8 +15,38 @@ use mem; use sys::backtrace::BacktraceContext; use sys::backtrace::StackWalkVariant; use sys::c; +use sys::dynamic_lib::DynamicLibrary; use sys_common::backtrace::Frame; + +// Structs holding printing functions and loaders for them +// Two versions depending on whether dbghelp.dll has StackWalkEx or not +// (the former being in newer Windows versions, the older being in Win7 and before) +pub struct PrintingFnsEx { + resolve_symname: SymFromInlineContextFn, + sym_get_line: SymGetLineFromInlineContextFn, +} +pub struct PrintingFns64 { + resolve_symname: SymFromAddrFn, + sym_get_line: SymGetLineFromAddr64Fn, +} + +pub fn load_printing_fns_ex(dbghelp: &DynamicLibrary) -> io::Result { + Ok(PrintingFnsEx{ + resolve_symname: sym!(dbghelp, "SymFromInlineContext", + SymFromInlineContextFn)?, + sym_get_line: sym!(dbghelp, "SymGetLineFromInlineContext", + SymGetLineFromInlineContextFn)?, + }) +} +pub fn load_printing_fns_64(dbghelp: &DynamicLibrary) -> io::Result { + Ok(PrintingFns64{ + resolve_symname: sym!(dbghelp, "SymFromAddr", SymFromAddrFn)?, + sym_get_line: sym!(dbghelp, "SymGetLineFromAddr64", + SymGetLineFromAddr64Fn)?, + }) +} + type SymFromInlineContextFn = unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL; type SymGetLineFromInlineContextFn = unsafe extern "system" fn( @@ -39,14 +69,11 @@ where F: FnOnce(Option<&str>) -> io::Result<()>, { match context.StackWalkVariant { - StackWalkVariant::StackWalkEx => { - let SymFromInlineContext = - sym!(&context.dbghelp, "SymFromInlineContext",SymFromInlineContextFn)?; - resolve_symname_from_inline_context(SymFromInlineContext, frame, callback, context) + StackWalkVariant::StackWalkEx(_, ref fns) => { + resolve_symname_from_inline_context(fns.resolve_symname, frame, callback, context) }, - StackWalkVariant::StackWalk64 => { - let SymFromAddr = sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn)?; - resolve_symname_from_addr(SymFromAddr, frame, callback, context) + StackWalkVariant::StackWalk64(_, ref fns) => { + resolve_symname_from_addr(fns.resolve_symname, frame, callback, context) } } } @@ -134,20 +161,10 @@ where F: FnMut(&[u8], u32) -> io::Result<()>, { match context.StackWalkVariant { - StackWalkVariant::StackWalkEx => { - let SymGetLineFromInlineContext = - sym!(&context.dbghelp, "SymGetLineFromInlineContext", - SymGetLineFromInlineContextFn)?; - foreach_symbol_fileline_ex(SymGetLineFromInlineContext, - frame, f, context) - }, - StackWalkVariant::StackWalk64 => { - let SymGetLineFromAddr64 = - sym!(&context.dbghelp, "SymGetLineFromAddr64", - SymGetLineFromAddr64Fn)?; - foreach_symbol_fileline_64(SymGetLineFromAddr64, - frame, f, context) - } + StackWalkVariant::StackWalkEx(_, ref fns) => + foreach_symbol_fileline_ex(fns.sym_get_line, frame, f, context), + StackWalkVariant::StackWalk64(_, ref fns) => + foreach_symbol_fileline_64(fns.sym_get_line, frame, f, context), } } -- cgit 1.4.1-3-g733a5 From a0b15012a17594566311ea490eda243b6bd9d92b Mon Sep 17 00:00:00 2001 From: moxian Date: Fri, 18 May 2018 11:38:50 +0000 Subject: Make stackwalking generic instead of matching on enum variants. --- src/libstd/sys/windows/backtrace/mod.rs | 280 +++++++++++++++++--------------- 1 file changed, 147 insertions(+), 133 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs index 23bb4ab6dfe..7ef4e203571 100644 --- a/src/libstd/sys/windows/backtrace/mod.rs +++ b/src/libstd/sys/windows/backtrace/mod.rs @@ -47,7 +47,7 @@ mod printing; pub mod gnu; pub use self::printing::{foreach_symbol_fileline, resolve_symname}; -use self::printing::{load_printing_fns_ex, load_printing_fns_64}; +use self::printing::{load_printing_fns_64, load_printing_fns_ex}; pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> { let dbghelp = DynamicLibrary::open("dbghelp.dll")?; @@ -56,20 +56,15 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn)?; let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn)?; - // StackWalkEx might not be present and we'll fall back to StackWalk64 let sw_var = match sym!(dbghelp, "StackWalkEx", StackWalkExFn) { - Ok(StackWalkEx) => - StackWalkVariant::StackWalkEx( - StackWalkEx, - load_printing_fns_ex(&dbghelp)?, - ), + Ok(StackWalkEx) => { + StackWalkVariant::StackWalkEx(StackWalkEx, load_printing_fns_ex(&dbghelp)?) + } Err(e) => match sym!(dbghelp, "StackWalk64", StackWalk64Fn) { - Ok(StackWalk64) => - StackWalkVariant::StackWalk64( - StackWalk64, - load_printing_fns_64(&dbghelp)?, - ), + Ok(StackWalk64) => { + StackWalkVariant::StackWalk64(StackWalk64, load_printing_fns_64(&dbghelp)?) + } Err(..) => return Err(e), }, }; @@ -92,101 +87,38 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon // And now that we're done with all the setup, do the stack walking! match backtrace_context.StackWalkVariant { - StackWalkVariant::StackWalkEx(f, _) => set_frames_ex(f, frames, backtrace_context, process), - StackWalkVariant::StackWalk64(f, _) => set_frames_64(f, frames, backtrace_context, process), - } -} - -fn set_frames_ex( - StackWalkEx: StackWalkExFn, - frames: &mut [Frame], - backtrace_context: BacktraceContext, - process: c::HANDLE, -) -> io::Result<(usize, BacktraceContext)> { - let thread = unsafe { c::GetCurrentProcess() }; - let mut context: c::CONTEXT = unsafe { mem::zeroed() }; - unsafe { c::RtlCaptureContext(&mut context) }; - - let mut frame: c::STACKFRAME_EX = unsafe { mem::zeroed() }; - frame.StackFrameSize = mem::size_of_val(&frame) as c::DWORD; - let image = init_frame_ex(&mut frame, &context); + StackWalkVariant::StackWalkEx(StackWalkEx, _) => { + set_frames(StackWalkEx, frames).map(|i| (i, backtrace_context)) + } - let mut i = 0; - unsafe { - while i < frames.len() - && StackWalkEx( - image, - process, - thread, - &mut frame, - &mut context, - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - 0, - ) == c::TRUE - { - let addr = (frame.AddrPC.Offset - 1) as *const u8; - - frames[i] = Frame { - symbol_addr: addr, - exact_position: addr, - inline_context: frame.InlineFrameContext, - }; - i += 1; + StackWalkVariant::StackWalk64(StackWalk64, _) => { + set_frames(StackWalk64, frames).map(|i| (i, backtrace_context)) } } - - Ok((i, backtrace_context)) } -fn set_frames_64( - StackWalk64: StackWalk64Fn, - frames: &mut [Frame], - backtrace_context: BacktraceContext, - process: c::HANDLE, -) -> io::Result<(usize, BacktraceContext)> { +fn set_frames(StackWalk: W, frames: &mut [Frame]) -> io::Result { + let process = unsafe { c::GetCurrentProcess() }; let thread = unsafe { c::GetCurrentProcess() }; let mut context: c::CONTEXT = unsafe { mem::zeroed() }; unsafe { c::RtlCaptureContext(&mut context) }; + let mut frame = W::Item::new(); + let image = frame.init(&context); - let mut frame: c::STACKFRAME64 = unsafe { mem::zeroed() }; - let image = init_frame_64(&mut frame, &context); - - // Start from -1 to avoid printing this stack frame, which will - // always be exactly the same. let mut i = 0; - unsafe { - while i < frames.len() - && StackWalk64( - image, - process, - thread, - &mut frame, - &mut context, - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ) == c::TRUE - { - let addr = frame.AddrPC.Offset; - if addr == frame.AddrReturn.Offset || addr == 0 || frame.AddrReturn.Offset == 0 - { - break; - } - - frames[i] = Frame { - symbol_addr: (addr - 1) as *const u8, - exact_position: (addr - 1) as *const u8, - inline_context: 0, - }; - i += 1; - } + while i < frames.len() + && StackWalk.walk(image, process, thread, &mut frame, &mut context) == c::TRUE + { + let addr = frame.get_addr(); + frames[i] = Frame { + symbol_addr: addr, + exact_position: addr, + inline_context: 0, + }; + + i += 1 } - - Ok((i, backtrace_context)) + Ok(i) } type SymInitializeFn = unsafe extern "system" fn(c::HANDLE, *mut c_void, c::BOOL) -> c::BOOL; @@ -217,48 +149,131 @@ type StackWalk64Fn = unsafe extern "system" fn( *mut c_void, ) -> c::BOOL; -#[cfg(target_arch = "x86")] -fn init_frame_ex(frame: &mut c::STACKFRAME_EX, ctx: &c::CONTEXT) -> c::DWORD { - frame.AddrPC.Offset = ctx.Eip as u64; - frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat; - frame.AddrStack.Offset = ctx.Esp as u64; - frame.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat; - frame.AddrFrame.Offset = ctx.Ebp as u64; - frame.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat; - c::IMAGE_FILE_MACHINE_I386 +trait StackWalker { + type Item: StackFrame; + + fn walk(&self, c::DWORD, c::HANDLE, c::HANDLE, &mut Self::Item, &mut c::CONTEXT) -> c::BOOL; } -#[cfg(target_arch = "x86_64")] -fn init_frame_ex(frame: &mut c::STACKFRAME_EX, ctx: &c::CONTEXT) -> c::DWORD { - frame.AddrPC.Offset = ctx.Rip as u64; - frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat; - frame.AddrStack.Offset = ctx.Rsp as u64; - frame.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat; - frame.AddrFrame.Offset = ctx.Rbp as u64; - frame.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat; - c::IMAGE_FILE_MACHINE_AMD64 +impl StackWalker for StackWalkExFn { + type Item = c::STACKFRAME_EX; + fn walk( + &self, + image: c::DWORD, + process: c::HANDLE, + thread: c::HANDLE, + frame: &mut Self::Item, + context: &mut c::CONTEXT, + ) -> c::BOOL { + unsafe { + self( + image, + process, + thread, + frame, + context, + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + 0, + ) + } + } +} + +impl StackWalker for StackWalk64Fn { + type Item = c::STACKFRAME64; + fn walk( + &self, + image: c::DWORD, + process: c::HANDLE, + thread: c::HANDLE, + frame: &mut Self::Item, + context: &mut c::CONTEXT, + ) -> c::BOOL { + unsafe { + self( + image, + process, + thread, + frame, + context, + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ) + } + } +} + +trait StackFrame { + fn new() -> Self; + fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD; + fn get_addr(&self) -> *const u8; } -#[cfg(target_arch = "x86")] -fn init_frame_64(frame: &mut c::STACKFRAME64, ctx: &c::CONTEXT) -> c::DWORD { - frame.AddrPC.Offset = ctx.Eip as u64; - frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat; - frame.AddrStack.Offset = ctx.Esp as u64; - frame.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat; - frame.AddrFrame.Offset = ctx.Ebp as u64; - frame.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat; - c::IMAGE_FILE_MACHINE_I386 +impl StackFrame for c::STACKFRAME_EX { + fn new() -> c::STACKFRAME_EX { + unsafe { mem::zeroed() } + } + + #[cfg(target_arch = "x86")] + fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD { + self.AddrPC.Offset = ctx.Eip as u64; + self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat; + self.AddrStack.Offset = ctx.Esp as u64; + self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat; + self.AddrFrame.Offset = ctx.Ebp as u64; + self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat; + c::IMAGE_FILE_MACHINE_I386 + } + #[cfg(target_arch = "x86_64")] + fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD { + self.AddrPC.Offset = ctx.Rip as u64; + self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat; + self.AddrStack.Offset = ctx.Rsp as u64; + self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat; + self.AddrFrame.Offset = ctx.Rbp as u64; + self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat; + c::IMAGE_FILE_MACHINE_AMD64 + } + + fn get_addr(&self) -> *const u8 { + (self.AddrPC.Offset - 1) as *const u8 + } } -#[cfg(target_arch = "x86_64")] -fn init_frame_64(frame: &mut c::STACKFRAME64, ctx: &c::CONTEXT) -> c::DWORD { - frame.AddrPC.Offset = ctx.Rip as u64; - frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat; - frame.AddrStack.Offset = ctx.Rsp as u64; - frame.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat; - frame.AddrFrame.Offset = ctx.Rbp as u64; - frame.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat; - c::IMAGE_FILE_MACHINE_AMD64 +impl StackFrame for c::STACKFRAME64 { + fn new() -> c::STACKFRAME64 { + unsafe { mem::zeroed() } + } + + #[cfg(target_arch = "x86")] + fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD { + self.AddrPC.Offset = ctx.Eip as u64; + self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat; + self.AddrStack.Offset = ctx.Esp as u64; + self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat; + self.AddrFrame.Offset = ctx.Ebp as u64; + self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat; + c::IMAGE_FILE_MACHINE_I386 + } + #[cfg(target_arch = "x86_64")] + fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD { + self.AddrPC.Offset = ctx.Rip as u64; + self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat; + self.AddrStack.Offset = ctx.Rsp as u64; + self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat; + self.AddrFrame.Offset = ctx.Rbp as u64; + self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat; + c::IMAGE_FILE_MACHINE_AMD64 + } + + fn get_addr(&self) -> *const u8 { + (self.AddrPC.Offset - 1) as *const u8 + } } enum StackWalkVariant { @@ -266,7 +281,6 @@ enum StackWalkVariant { StackWalk64(StackWalk64Fn, printing::PrintingFns64), } - pub struct BacktraceContext { handle: c::HANDLE, SymCleanup: SymCleanupFn, -- cgit 1.4.1-3-g733a5 From 9d426ac387f2d42c998349c76ac1c2aea044e0ec Mon Sep 17 00:00:00 2001 From: moxian Date: Fri, 18 May 2018 12:33:23 +0000 Subject: Make msvc symbol extraction/printing functions generic. --- src/libstd/sys/windows/backtrace/printing/msvc.rs | 240 ++++++++++++---------- 1 file changed, 137 insertions(+), 103 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs index 9cfc2c3d352..d8f0a4d8208 100644 --- a/src/libstd/sys/windows/backtrace/printing/msvc.rs +++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs @@ -18,7 +18,6 @@ use sys::c; use sys::dynamic_lib::DynamicLibrary; use sys_common::backtrace::Frame; - // Structs holding printing functions and loaders for them // Two versions depending on whether dbghelp.dll has StackWalkEx or not // (the former being in newer Windows versions, the older being in Win7 and before) @@ -32,23 +31,29 @@ pub struct PrintingFns64 { } pub fn load_printing_fns_ex(dbghelp: &DynamicLibrary) -> io::Result { - Ok(PrintingFnsEx{ - resolve_symname: sym!(dbghelp, "SymFromInlineContext", - SymFromInlineContextFn)?, - sym_get_line: sym!(dbghelp, "SymGetLineFromInlineContext", - SymGetLineFromInlineContextFn)?, + Ok(PrintingFnsEx { + resolve_symname: sym!(dbghelp, "SymFromInlineContext", SymFromInlineContextFn)?, + sym_get_line: sym!( + dbghelp, + "SymGetLineFromInlineContext", + SymGetLineFromInlineContextFn + )?, }) } pub fn load_printing_fns_64(dbghelp: &DynamicLibrary) -> io::Result { - Ok(PrintingFns64{ + Ok(PrintingFns64 { resolve_symname: sym!(dbghelp, "SymFromAddr", SymFromAddrFn)?, - sym_get_line: sym!(dbghelp, "SymGetLineFromAddr64", - SymGetLineFromAddr64Fn)?, + sym_get_line: sym!(dbghelp, "SymGetLineFromAddr64", SymGetLineFromAddr64Fn)?, }) } +type SymFromAddrFn = + unsafe extern "system" fn(c::HANDLE, u64, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL; type SymFromInlineContextFn = unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL; + +type SymGetLineFromAddr64Fn = + unsafe extern "system" fn(c::HANDLE, u64, *mut u32, *mut c::IMAGEHLP_LINE64) -> c::BOOL; type SymGetLineFromInlineContextFn = unsafe extern "system" fn( c::HANDLE, u64, @@ -58,11 +63,6 @@ type SymGetLineFromInlineContextFn = unsafe extern "system" fn( *mut c::IMAGEHLP_LINE64, ) -> c::BOOL; -type SymFromAddrFn = - unsafe extern "system" fn(c::HANDLE, u64, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL; -type SymGetLineFromAddr64Fn = - unsafe extern "system" fn(c::HANDLE, u64, *mut u32, *mut c::IMAGEHLP_LINE64) -> c::BOOL; - /// Converts a pointer to symbol to its string value. pub fn resolve_symname(frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()> where @@ -70,61 +70,23 @@ where { match context.StackWalkVariant { StackWalkVariant::StackWalkEx(_, ref fns) => { - resolve_symname_from_inline_context(fns.resolve_symname, frame, callback, context) - }, + resolve_symname_internal(fns.resolve_symname, frame, callback, context) + } StackWalkVariant::StackWalk64(_, ref fns) => { - resolve_symname_from_addr(fns.resolve_symname, frame, callback, context) + resolve_symname_internal(fns.resolve_symname, frame, callback, context) } } } -fn resolve_symname_from_inline_context( - SymFromInlineContext: SymFromInlineContextFn, - frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()> -where - F: FnOnce(Option<&str>) -> io::Result<()>, -{ - unsafe { - let mut info: c::SYMBOL_INFO = mem::zeroed(); - info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; - // the struct size in C. the value is different to - // `size_of::() - MAX_SYM_NAME + 1` (== 81) - // due to struct alignment. - info.SizeOfStruct = 88; - - let mut displacement = 0u64; - let ret = SymFromInlineContext( - context.handle, - frame.symbol_addr as u64, - frame.inline_context, - &mut displacement, - &mut info, - ); - let valid_range = - if ret == c::TRUE && frame.symbol_addr as usize >= info.Address as usize { - if info.Size != 0 { - (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize - } else { - true - } - } else { - false - }; - let symname = if valid_range { - let ptr = info.Name.as_ptr() as *const c_char; - CStr::from_ptr(ptr).to_str().ok() - } else { - None - }; - callback(symname) - } -} - -fn resolve_symname_from_addr( - SymFromAddr: SymFromAddrFn, - frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()> +fn resolve_symname_internal( + symbol_resolver: R, + frame: Frame, + callback: F, + context: &BacktraceContext, +) -> io::Result<()> where F: FnOnce(Option<&str>) -> io::Result<()>, + R: SymbolResolver, { unsafe { let mut info: c::SYMBOL_INFO = mem::zeroed(); @@ -134,15 +96,22 @@ where // due to struct alignment. info.SizeOfStruct = 88; - let mut displacement = 0u64; - let ret = SymFromAddr( + let ret = symbol_resolver.resolve_symbol( context.handle, frame.symbol_addr as u64, - &mut displacement, + frame.inline_context, &mut info, ); - - let symname = if ret == c::TRUE { + let valid_range = if ret == c::TRUE && frame.symbol_addr as usize >= info.Address as usize { + if info.Size != 0 { + (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize + } else { + true + } + } else { + false + }; + let symname = if valid_range { let ptr = info.Name.as_ptr() as *const c_char; CStr::from_ptr(ptr).to_str().ok() } else { @@ -152,76 +121,141 @@ where } } +trait SymbolResolver { + fn resolve_symbol( + &self, + process: c::HANDLE, + symbol_address: u64, + inline_context: c::ULONG, + info: *mut c::SYMBOL_INFO, + ) -> c::BOOL; +} + +impl SymbolResolver for SymFromAddrFn { + fn resolve_symbol( + &self, + process: c::HANDLE, + symbol_address: u64, + _inline_context: c::ULONG, + info: *mut c::SYMBOL_INFO, + ) -> c::BOOL { + unsafe { + let mut displacement = 0u64; + self(process, symbol_address, &mut displacement, info) + } + } +} + +impl SymbolResolver for SymFromInlineContextFn { + fn resolve_symbol( + &self, + process: c::HANDLE, + symbol_address: u64, + inline_context: c::ULONG, + info: *mut c::SYMBOL_INFO, + ) -> c::BOOL { + unsafe { + let mut displacement = 0u64; + self( + process, + symbol_address, + inline_context, + &mut displacement, + info, + ) + } + } +} + pub fn foreach_symbol_fileline( frame: Frame, - f: F, + callback: F, context: &BacktraceContext, ) -> io::Result where F: FnMut(&[u8], u32) -> io::Result<()>, { match context.StackWalkVariant { - StackWalkVariant::StackWalkEx(_, ref fns) => - foreach_symbol_fileline_ex(fns.sym_get_line, frame, f, context), - StackWalkVariant::StackWalk64(_, ref fns) => - foreach_symbol_fileline_64(fns.sym_get_line, frame, f, context), + StackWalkVariant::StackWalkEx(_, ref fns) => { + foreach_symbol_fileline_iternal(fns.sym_get_line, frame, callback, context) + } + StackWalkVariant::StackWalk64(_, ref fns) => { + foreach_symbol_fileline_iternal(fns.sym_get_line, frame, callback, context) + } } } -fn foreach_symbol_fileline_ex( - SymGetLineFromInlineContext: SymGetLineFromInlineContextFn, +fn foreach_symbol_fileline_iternal( + line_getter: G, frame: Frame, - mut f: F, + mut callback: F, context: &BacktraceContext, ) -> io::Result where F: FnMut(&[u8], u32) -> io::Result<()>, + G: LineGetter, { unsafe { let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); line.SizeOfStruct = ::mem::size_of::() as u32; - let mut displacement = 0u32; - let ret = SymGetLineFromInlineContext( + let ret = line_getter.get_line( context.handle, frame.exact_position as u64, frame.inline_context, - 0, - &mut displacement, &mut line, ); if ret == c::TRUE { let name = CStr::from_ptr(line.Filename).to_bytes(); - f(name, line.LineNumber as u32)?; + callback(name, line.LineNumber as u32)?; } Ok(false) } } -fn foreach_symbol_fileline_64( - SymGetLineFromAddr64: SymGetLineFromAddr64Fn, - frame: Frame, - mut f: F, - context: &BacktraceContext, -) -> io::Result -where - F: FnMut(&[u8], u32) -> io::Result<()>, -{ - unsafe { - let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); - line.SizeOfStruct = ::mem::size_of::() as u32; +trait LineGetter { + fn get_line( + &self, + process: c::HANDLE, + frame_address: u64, + inline_context: c::ULONG, + line: *mut c::IMAGEHLP_LINE64, + ) -> c::BOOL; +} - let mut displacement = 0u32; - let ret = SymGetLineFromAddr64( - context.handle, - frame.exact_position as u64, - &mut displacement, - &mut line, - ); - if ret == c::TRUE { - let name = CStr::from_ptr(line.Filename).to_bytes(); - f(name, line.LineNumber as u32)?; +impl LineGetter for SymGetLineFromAddr64Fn { + fn get_line( + &self, + process: c::HANDLE, + frame_address: u64, + _inline_context: c::ULONG, + line: *mut c::IMAGEHLP_LINE64, + ) -> c::BOOL { + unsafe { + let mut displacement = 0u32; + self(process, frame_address, &mut displacement, line) + } + } +} + +impl LineGetter for SymGetLineFromInlineContextFn { + fn get_line( + &self, + process: c::HANDLE, + frame_address: u64, + inline_context: c::ULONG, + line: *mut c::IMAGEHLP_LINE64, + ) -> c::BOOL { + unsafe { + let mut displacement = 0u32; + self( + process, + frame_address, + inline_context, + 0, + &mut displacement, + line, + ) } - Ok(false) } } -- cgit 1.4.1-3-g733a5 From be7f619870085121bdd7911aa882c35e70aedb8a Mon Sep 17 00:00:00 2001 From: moxian Date: Mon, 4 Jun 2018 11:00:12 +0000 Subject: Change traits to bare FnMut where possible. --- src/libstd/sys/windows/backtrace/printing/msvc.rs | 178 ++++++++-------------- 1 file changed, 67 insertions(+), 111 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs index d8f0a4d8208..c8b946bf13a 100644 --- a/src/libstd/sys/windows/backtrace/printing/msvc.rs +++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs @@ -69,24 +69,48 @@ where F: FnOnce(Option<&str>) -> io::Result<()>, { match context.StackWalkVariant { - StackWalkVariant::StackWalkEx(_, ref fns) => { - resolve_symname_internal(fns.resolve_symname, frame, callback, context) - } - StackWalkVariant::StackWalk64(_, ref fns) => { - resolve_symname_internal(fns.resolve_symname, frame, callback, context) - } + StackWalkVariant::StackWalkEx(_, ref fns) => resolve_symname_internal( + |process: c::HANDLE, + symbol_address: u64, + inline_context: c::ULONG, + info: *mut c::SYMBOL_INFO| unsafe { + let mut displacement = 0u64; + (fns.resolve_symname)( + process, + symbol_address, + inline_context, + &mut displacement, + info, + ) + }, + frame, + callback, + context, + ), + StackWalkVariant::StackWalk64(_, ref fns) => resolve_symname_internal( + |process: c::HANDLE, + symbol_address: u64, + _inline_context: c::ULONG, + info: *mut c::SYMBOL_INFO| unsafe { + let mut displacement = 0u64; + (fns.resolve_symname)(process, symbol_address, &mut displacement, info) + }, + frame, + callback, + context, + ), } } fn resolve_symname_internal( - symbol_resolver: R, + mut symbol_resolver: R, frame: Frame, callback: F, context: &BacktraceContext, ) -> io::Result<()> where F: FnOnce(Option<&str>) -> io::Result<()>, - R: SymbolResolver, + R: FnMut(c::HANDLE, u64, c::ULONG, *mut c::SYMBOL_INFO) -> c::BOOL, { unsafe { let mut info: c::SYMBOL_INFO = mem::zeroed(); @@ -96,7 +120,7 @@ where // due to struct alignment. info.SizeOfStruct = 88; - let ret = symbol_resolver.resolve_symbol( + let ret = symbol_resolver( context.handle, frame.symbol_addr as u64, frame.inline_context, @@ -121,52 +145,6 @@ where } } -trait SymbolResolver { - fn resolve_symbol( - &self, - process: c::HANDLE, - symbol_address: u64, - inline_context: c::ULONG, - info: *mut c::SYMBOL_INFO, - ) -> c::BOOL; -} - -impl SymbolResolver for SymFromAddrFn { - fn resolve_symbol( - &self, - process: c::HANDLE, - symbol_address: u64, - _inline_context: c::ULONG, - info: *mut c::SYMBOL_INFO, - ) -> c::BOOL { - unsafe { - let mut displacement = 0u64; - self(process, symbol_address, &mut displacement, info) - } - } -} - -impl SymbolResolver for SymFromInlineContextFn { - fn resolve_symbol( - &self, - process: c::HANDLE, - symbol_address: u64, - inline_context: c::ULONG, - info: *mut c::SYMBOL_INFO, - ) -> c::BOOL { - unsafe { - let mut displacement = 0u64; - self( - process, - symbol_address, - inline_context, - &mut displacement, - info, - ) - } - } -} - pub fn foreach_symbol_fileline( frame: Frame, callback: F, @@ -176,30 +154,55 @@ where F: FnMut(&[u8], u32) -> io::Result<()>, { match context.StackWalkVariant { - StackWalkVariant::StackWalkEx(_, ref fns) => { - foreach_symbol_fileline_iternal(fns.sym_get_line, frame, callback, context) - } - StackWalkVariant::StackWalk64(_, ref fns) => { - foreach_symbol_fileline_iternal(fns.sym_get_line, frame, callback, context) - } + StackWalkVariant::StackWalkEx(_, ref fns) => foreach_symbol_fileline_iternal( + |process: c::HANDLE, + frame_address: u64, + inline_context: c::ULONG, + line: *mut c::IMAGEHLP_LINE64| unsafe { + let mut displacement = 0u32; + (fns.sym_get_line)( + process, + frame_address, + inline_context, + 0, + &mut displacement, + line, + ) + }, + frame, + callback, + context, + ), + StackWalkVariant::StackWalk64(_, ref fns) => foreach_symbol_fileline_iternal( + |process: c::HANDLE, + frame_address: u64, + _inline_context: c::ULONG, + line: *mut c::IMAGEHLP_LINE64| unsafe { + let mut displacement = 0u32; + (fns.sym_get_line)(process, frame_address, &mut displacement, line) + }, + frame, + callback, + context, + ), } } fn foreach_symbol_fileline_iternal( - line_getter: G, + mut line_getter: G, frame: Frame, mut callback: F, context: &BacktraceContext, ) -> io::Result where F: FnMut(&[u8], u32) -> io::Result<()>, - G: LineGetter, + G: FnMut(c::HANDLE, u64, c::ULONG, *mut c::IMAGEHLP_LINE64) -> c::BOOL, { unsafe { let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); line.SizeOfStruct = ::mem::size_of::() as u32; - let ret = line_getter.get_line( + let ret = line_getter( context.handle, frame.exact_position as u64, frame.inline_context, @@ -212,50 +215,3 @@ where Ok(false) } } - -trait LineGetter { - fn get_line( - &self, - process: c::HANDLE, - frame_address: u64, - inline_context: c::ULONG, - line: *mut c::IMAGEHLP_LINE64, - ) -> c::BOOL; -} - -impl LineGetter for SymGetLineFromAddr64Fn { - fn get_line( - &self, - process: c::HANDLE, - frame_address: u64, - _inline_context: c::ULONG, - line: *mut c::IMAGEHLP_LINE64, - ) -> c::BOOL { - unsafe { - let mut displacement = 0u32; - self(process, frame_address, &mut displacement, line) - } - } -} - -impl LineGetter for SymGetLineFromInlineContextFn { - fn get_line( - &self, - process: c::HANDLE, - frame_address: u64, - inline_context: c::ULONG, - line: *mut c::IMAGEHLP_LINE64, - ) -> c::BOOL { - unsafe { - let mut displacement = 0u32; - self( - process, - frame_address, - inline_context, - 0, - &mut displacement, - line, - ) - } - } -} -- cgit 1.4.1-3-g733a5 From 73166f751b7509dd95ce903ecdeab2dd5d89aa90 Mon Sep 17 00:00:00 2001 From: Dror Levin Date: Mon, 2 Jul 2018 17:38:15 +0300 Subject: Fill in tracking issue number for read_exact_at/write_all_at --- src/libstd/sys/unix/ext/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 4c2cea0d32c..507e9d88171 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -109,7 +109,7 @@ pub trait FileExt { /// Ok(()) /// } /// ``` - #[unstable(feature = "rw_exact_all_at", issue = "0")] + #[unstable(feature = "rw_exact_all_at", issue = "51984")] fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> { while !buf.is_empty() { match self.read_at(buf, offset) { @@ -204,7 +204,7 @@ pub trait FileExt { /// Ok(()) /// } /// ``` - #[unstable(feature = "rw_exact_all_at", issue = "0")] + #[unstable(feature = "rw_exact_all_at", issue = "51984")] fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> { while !buf.is_empty() { match self.write_at(buf, offset) { -- cgit 1.4.1-3-g733a5 From ea6f9f9c5529bb3f222ccf95c75bc54609cd99b7 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Tue, 3 Jul 2018 11:13:16 +0200 Subject: Remove stability attributes on private types and leftover docs --- src/libstd/sys/redox/ext/unixsocket.rs | 2 -- src/libstd/sys/unix/ext/unixsocket.rs | 16 ---------------- 2 files changed, 18 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/unixsocket.rs b/src/libstd/sys/redox/ext/unixsocket.rs index be37575145a..5f7b2df8992 100644 --- a/src/libstd/sys/redox/ext/unixsocket.rs +++ b/src/libstd/sys/redox/ext/unixsocket.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![stable(feature = "unix_socket", since = "1.10.0")] - use fmt; use io::{self, Error, ErrorKind, Initializer}; use net::Shutdown; diff --git a/src/libstd/sys/unix/ext/unixsocket.rs b/src/libstd/sys/unix/ext/unixsocket.rs index 124555141a3..ad2d7019cb8 100644 --- a/src/libstd/sys/unix/ext/unixsocket.rs +++ b/src/libstd/sys/unix/ext/unixsocket.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![stable(feature = "unix_socket", since = "1.10.0")] - //! Unix-specific networking functionality #[cfg(unix)] @@ -144,20 +142,6 @@ impl<'a> fmt::Display for AsciiEscaped<'a> { } } -/// A Unix stream socket. -/// -/// # Examples -/// -/// ```no_run -/// use std::os::unix::net::UnixStream; -/// use std::io::prelude::*; -/// -/// let mut stream = UnixStream::connect("/path/to/my/socket").unwrap(); -/// stream.write_all(b"hello world").unwrap(); -/// let mut response = String::new(); -/// stream.read_to_string(&mut response).unwrap(); -/// println!("{}", response); -/// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub struct UnixStream(Socket); -- cgit 1.4.1-3-g733a5 From abac5e722f3786fe2692bde9ab626afb25dd02de Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Sat, 7 Jul 2018 06:50:55 +0200 Subject: Revert unification of interfaces --- src/libstd/sys/redox/ext/mod.rs | 1 - src/libstd/sys/redox/ext/net.rs | 695 +++++++++++++++++++++++++++++++- src/libstd/sys/unix/ext/mod.rs | 1 - src/libstd/sys/unix/ext/net.rs | 871 ++++++++++++++++++++++++++++++++++++++-- src/libstd/sys_common/mod.rs | 3 - 5 files changed, 1539 insertions(+), 32 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/mod.rs b/src/libstd/sys/redox/ext/mod.rs index c86b5d78524..cb2c75ae0bf 100644 --- a/src/libstd/sys/redox/ext/mod.rs +++ b/src/libstd/sys/redox/ext/mod.rs @@ -36,7 +36,6 @@ pub mod io; pub mod net; pub mod process; pub mod thread; -pub(crate) mod unixsocket; /// A prelude for conveniently writing platform-specific code. /// diff --git a/src/libstd/sys/redox/ext/net.rs b/src/libstd/sys/redox/ext/net.rs index 16eec67fb87..d29d28c8427 100644 --- a/src/libstd/sys/redox/ext/net.rs +++ b/src/libstd/sys/redox/ext/net.rs @@ -8,6 +8,695 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![stable(feature = "unix_socket", since = "1.10.0")] -#[stable(feature = "unix_socket", since = "1.10.0")] -pub use sys_common::unixsocket::*; +#![unstable(feature = "unix_socket_redox", reason = "new feature", issue="51553")] + +//! Unix-specific networking functionality + +use fmt; +use io::{self, Error, ErrorKind, Initializer}; +use net::Shutdown; +use os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd}; +use path::Path; +use time::Duration; +use sys::{cvt, fd::FileDesc, syscall}; + +/// An address associated with a Unix socket. +/// +/// # Examples +/// +/// ``` +/// use std::os::unix::net::UnixListener; +/// +/// let socket = match UnixListener::bind("/tmp/sock") { +/// Ok(sock) => sock, +/// Err(e) => { +/// println!("Couldn't bind: {:?}", e); +/// return +/// } +/// }; +/// let addr = socket.local_addr().expect("Couldn't get local address"); +/// ``` +#[derive(Clone)] +pub struct SocketAddr(()); + +impl SocketAddr { + /// Returns the contents of this address if it is a `pathname` address. + /// + /// # Examples + /// + /// With a pathname: + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// use std::path::Path; + /// + /// let socket = UnixListener::bind("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock"))); + /// ``` + /// + /// Without a pathname: + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// + /// let socket = UnixDatagram::unbound().unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.as_pathname(), None); + /// ``` + pub fn as_pathname(&self) -> Option<&Path> { + None + } +} +impl fmt::Debug for SocketAddr { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "SocketAddr") + } +} + +/// A Unix stream socket. +/// +/// # Examples +/// +/// ```no_run +/// use std::os::unix::net::UnixStream; +/// use std::io::prelude::*; +/// +/// let mut stream = UnixStream::connect("/path/to/my/socket").unwrap(); +/// stream.write_all(b"hello world").unwrap(); +/// let mut response = String::new(); +/// stream.read_to_string(&mut response).unwrap(); +/// println!("{}", response); +/// ``` +pub struct UnixStream(FileDesc); + +impl fmt::Debug for UnixStream { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut builder = fmt.debug_struct("UnixStream"); + builder.field("fd", &self.0.raw()); + if let Ok(addr) = self.local_addr() { + builder.field("local", &addr); + } + if let Ok(addr) = self.peer_addr() { + builder.field("peer", &addr); + } + builder.finish() + } +} + +impl UnixStream { + /// Connects to the socket named by `path`. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = match UnixStream::connect("/tmp/sock") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return + /// } + /// }; + /// ``` + pub fn connect>(path: P) -> io::Result { + if let Some(s) = path.as_ref().to_str() { + cvt(syscall::open(format!("chan:{}", s), syscall::O_CLOEXEC)) + .map(FileDesc::new) + .map(UnixStream) + } else { + Err(Error::new( + ErrorKind::Other, + "UnixStream::connect: non-utf8 paths not supported on redox" + )) + } + } + + /// Creates an unnamed pair of connected sockets. + /// + /// Returns two `UnixStream`s which are connected to each other. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let (sock1, sock2) = match UnixStream::pair() { + /// Ok((sock1, sock2)) => (sock1, sock2), + /// Err(e) => { + /// println!("Couldn't create a pair of sockets: {:?}", e); + /// return + /// } + /// }; + /// ``` + pub fn pair() -> io::Result<(UnixStream, UnixStream)> { + let server = cvt(syscall::open("chan:", syscall::O_CREAT | syscall::O_CLOEXEC)) + .map(FileDesc::new)?; + let client = server.duplicate_path(b"connect")?; + let stream = server.duplicate_path(b"listen")?; + Ok((UnixStream(client), UnixStream(stream))) + } + + /// Creates a new independently owned handle to the underlying socket. + /// + /// The returned `UnixStream` is a reference to the same stream that this + /// object references. Both handles will read and write the same stream of + /// data, and options set on one stream will be propagated to the other + /// stream. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); + /// ``` + pub fn try_clone(&self) -> io::Result { + self.0.duplicate().map(UnixStream) + } + + /// Returns the socket address of the local half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// ``` + pub fn local_addr(&self) -> io::Result { + Err(Error::new(ErrorKind::Other, "UnixStream::local_addr unimplemented on redox")) + } + + /// Returns the socket address of the remote half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let addr = socket.peer_addr().expect("Couldn't get peer address"); + /// ``` + pub fn peer_addr(&self) -> io::Result { + Err(Error::new(ErrorKind::Other, "UnixStream::peer_addr unimplemented on redox")) + } + + /// Sets the read timeout for the socket. + /// + /// If the provided value is [`None`], then [`read`] calls will block + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err + /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read + /// [`Duration`]: ../../../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` + pub fn set_read_timeout(&self, _timeout: Option) -> io::Result<()> { + Err(Error::new(ErrorKind::Other, "UnixStream::set_read_timeout unimplemented on redox")) + } + + /// Sets the write timeout for the socket. + /// + /// If the provided value is [`None`], then [`write`] calls will block + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is + /// passed to this method. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err + /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write + /// [`Duration`]: ../../../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); + /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::net::UdpSocket; + /// use std::time::Duration; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); + /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` + pub fn set_write_timeout(&self, _timeout: Option) -> io::Result<()> { + Err(Error::new(ErrorKind::Other, "UnixStream::set_write_timeout unimplemented on redox")) + } + + /// Returns the read timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` + pub fn read_timeout(&self) -> io::Result> { + Err(Error::new(ErrorKind::Other, "UnixStream::read_timeout unimplemented on redox")) + } + + /// Returns the write timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); + /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` + pub fn write_timeout(&self) -> io::Result> { + Err(Error::new(ErrorKind::Other, "UnixStream::write_timeout unimplemented on redox")) + } + + /// Moves the socket into or out of nonblocking mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); + /// ``` + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.0.set_nonblocking(nonblocking) + } + + /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// if let Ok(Some(err)) = socket.take_error() { + /// println!("Got error: {:?}", err); + /// } + /// ``` + /// + /// # Platform specific + /// On Redox this always returns None. + pub fn take_error(&self) -> io::Result> { + Ok(None) + } + + /// Shuts down the read, write, or both halves of this connection. + /// + /// This function will cause all pending and future I/O calls on the + /// specified portions to immediately return with an appropriate value + /// (see the documentation of [`Shutdown`]). + /// + /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::net::Shutdown; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); + /// ``` + pub fn shutdown(&self, _how: Shutdown) -> io::Result<()> { + Err(Error::new(ErrorKind::Other, "UnixStream::shutdown unimplemented on redox")) + } +} + +impl io::Read for UnixStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + io::Read::read(&mut &*self, buf) + } + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() + } +} + +impl<'a> io::Read for &'a UnixStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.0.read(buf) + } + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() + } +} + +impl io::Write for UnixStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + io::Write::write(&mut &*self, buf) + } + + fn flush(&mut self) -> io::Result<()> { + io::Write::flush(&mut &*self) + } +} + +impl<'a> io::Write for &'a UnixStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +impl AsRawFd for UnixStream { + fn as_raw_fd(&self) -> RawFd { + self.0.raw() + } +} + +impl FromRawFd for UnixStream { + unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { + UnixStream(FileDesc::new(fd)) + } +} + +impl IntoRawFd for UnixStream { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw() + } +} + +/// A structure representing a Unix domain socket server. +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// use std::os::unix::net::{UnixStream, UnixListener}; +/// +/// fn handle_client(stream: UnixStream) { +/// // ... +/// } +/// +/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); +/// +/// // accept connections and process them, spawning a new thread for each one +/// for stream in listener.incoming() { +/// match stream { +/// Ok(stream) => { +/// /* connection succeeded */ +/// thread::spawn(|| handle_client(stream)); +/// } +/// Err(err) => { +/// /* connection failed */ +/// break; +/// } +/// } +/// } +/// ``` +pub struct UnixListener(FileDesc); + +impl fmt::Debug for UnixListener { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut builder = fmt.debug_struct("UnixListener"); + builder.field("fd", &self.0.raw()); + if let Ok(addr) = self.local_addr() { + builder.field("local", &addr); + } + builder.finish() + } +} + +impl UnixListener { + /// Creates a new `UnixListener` bound to the specified socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = match UnixListener::bind("/path/to/the/socket") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return + /// } + /// }; + /// ``` + pub fn bind>(path: P) -> io::Result { + if let Some(s) = path.as_ref().to_str() { + cvt(syscall::open(format!("chan:{}", s), syscall::O_CREAT | syscall::O_CLOEXEC)) + .map(FileDesc::new) + .map(UnixListener) + } else { + Err(Error::new( + ErrorKind::Other, + "UnixListener::bind: non-utf8 paths not supported on redox" + )) + } + } + + /// Accepts a new incoming connection to this listener. + /// + /// This function will block the calling thread until a new Unix connection + /// is established. When established, the corresponding [`UnixStream`] and + /// the remote peer's address will be returned. + /// + /// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// match listener.accept() { + /// Ok((socket, addr)) => println!("Got a client: {:?}", addr), + /// Err(e) => println!("accept function failed: {:?}", e), + /// } + /// ``` + pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { + self.0.duplicate_path(b"listen").map(|fd| (UnixStream(fd), SocketAddr(()))) + } + + /// Creates a new independently owned handle to the underlying socket. + /// + /// The returned `UnixListener` is a reference to the same socket that this + /// object references. Both handles can be used to accept incoming + /// connections and options set on one listener will affect the other. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// let listener_copy = listener.try_clone().expect("try_clone failed"); + /// ``` + pub fn try_clone(&self) -> io::Result { + self.0.duplicate().map(UnixListener) + } + + /// Returns the local socket address of this listener. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// let addr = listener.local_addr().expect("Couldn't get local address"); + /// ``` + pub fn local_addr(&self) -> io::Result { + Err(Error::new(ErrorKind::Other, "UnixListener::local_addr unimplemented on redox")) + } + + /// Moves the socket into or out of nonblocking mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); + /// ``` + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.0.set_nonblocking(nonblocking) + } + + /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/tmp/sock").unwrap(); + /// + /// if let Ok(Some(err)) = listener.take_error() { + /// println!("Got error: {:?}", err); + /// } + /// ``` + /// + /// # Platform specific + /// On Redox this always returns None. + pub fn take_error(&self) -> io::Result> { + Ok(None) + } + + /// Returns an iterator over incoming connections. + /// + /// The iterator will never return [`None`] and will also not yield the + /// peer's [`SocketAddr`] structure. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`SocketAddr`]: struct.SocketAddr.html + /// + /// # Examples + /// + /// ```no_run + /// use std::thread; + /// use std::os::unix::net::{UnixStream, UnixListener}; + /// + /// fn handle_client(stream: UnixStream) { + /// // ... + /// } + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// for stream in listener.incoming() { + /// match stream { + /// Ok(stream) => { + /// thread::spawn(|| handle_client(stream)); + /// } + /// Err(err) => { + /// break; + /// } + /// } + /// } + /// ``` + pub fn incoming<'a>(&'a self) -> Incoming<'a> { + Incoming { listener: self } + } +} + +impl AsRawFd for UnixListener { + fn as_raw_fd(&self) -> RawFd { + self.0.raw() + } +} + +impl FromRawFd for UnixListener { + unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { + UnixListener(FileDesc::new(fd)) + } +} + +impl IntoRawFd for UnixListener { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw() + } +} + +impl<'a> IntoIterator for &'a UnixListener { + type Item = io::Result; + type IntoIter = Incoming<'a>; + + fn into_iter(self) -> Incoming<'a> { + self.incoming() + } +} + +/// An iterator over incoming connections to a [`UnixListener`]. +/// +/// It will never return [`None`]. +/// +/// [`None`]: ../../../../std/option/enum.Option.html#variant.None +/// [`UnixListener`]: struct.UnixListener.html +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// use std::os::unix::net::{UnixStream, UnixListener}; +/// +/// fn handle_client(stream: UnixStream) { +/// // ... +/// } +/// +/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); +/// +/// for stream in listener.incoming() { +/// match stream { +/// Ok(stream) => { +/// thread::spawn(|| handle_client(stream)); +/// } +/// Err(err) => { +/// break; +/// } +/// } +/// } +/// ``` +#[derive(Debug)] +pub struct Incoming<'a> { + listener: &'a UnixListener, +} + +impl<'a> Iterator for Incoming<'a> { + type Item = io::Result; + + fn next(&mut self) -> Option> { + Some(self.listener.accept().map(|s| s.0)) + } + + fn size_hint(&self) -> (usize, Option) { + (usize::max_value(), None) + } +} diff --git a/src/libstd/sys/unix/ext/mod.rs b/src/libstd/sys/unix/ext/mod.rs index b7a1b45e9b7..88e4237f8e2 100644 --- a/src/libstd/sys/unix/ext/mod.rs +++ b/src/libstd/sys/unix/ext/mod.rs @@ -44,7 +44,6 @@ pub mod process; pub mod raw; pub mod thread; pub mod net; -pub(crate) mod unixsocket; /// A prelude for conveniently writing platform-specific code. /// diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 9251871baf6..55f43ccd7db 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -25,34 +25,32 @@ mod libc { pub struct sockaddr_un; } +use ascii; +use ffi::OsStr; use fmt; -use io; +use io::{self, Initializer}; use mem; use net::{self, Shutdown}; use os::unix::ffi::OsStrExt; use os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd}; use path::Path; use time::Duration; -use sys::ext::unixsocket as inner; -use sys::net::Socket; use sys::{self, cvt}; +use sys::net::Socket; use sys_common::{self, AsInner, FromInner, IntoInner}; -#[stable(feature = "unix_socket", since = "1.10.0")] -pub use sys_common::unixsocket::*; - #[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"))] -pub(crate) use libc::MSG_NOSIGNAL; +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")))] -pub(crate) const MSG_NOSIGNAL: libc::c_int = 0x0; +const MSG_NOSIGNAL: libc::c_int = 0x0; -pub(crate) fn sun_path_offset() -> usize { +fn sun_path_offset() -> usize { // Work with an actual instance of the type since using a null pointer is UB let addr: libc::sockaddr_un = unsafe { mem::uninitialized() }; let base = &addr as *const _ as usize; @@ -60,7 +58,7 @@ pub(crate) fn sun_path_offset() -> usize { path - base } -pub(crate) unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> { +unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> { let mut addr: libc::sockaddr_un = mem::zeroed(); addr.sun_family = libc::AF_UNIX as libc::sa_family_t; @@ -89,22 +87,557 @@ pub(crate) unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, Ok((addr, len as libc::socklen_t)) } -#[stable(feature = "into_raw_os", since = "1.4.0")] +enum AddressKind<'a> { + Unnamed, + Pathname(&'a Path), + Abstract(&'a [u8]), +} + +/// An address associated with a Unix socket. +/// +/// # Examples +/// +/// ``` +/// use std::os::unix::net::UnixListener; +/// +/// let socket = match UnixListener::bind("/tmp/sock") { +/// Ok(sock) => sock, +/// Err(e) => { +/// println!("Couldn't bind: {:?}", e); +/// return +/// } +/// }; +/// let addr = socket.local_addr().expect("Couldn't get local address"); +/// ``` +#[derive(Clone)] +#[stable(feature = "unix_socket", since = "1.10.0")] +pub struct SocketAddr { + addr: libc::sockaddr_un, + len: libc::socklen_t, +} + +impl SocketAddr { + fn new(f: F) -> io::Result + where F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int + { + unsafe { + let mut addr: libc::sockaddr_un = mem::zeroed(); + let mut len = mem::size_of::() as libc::socklen_t; + cvt(f(&mut addr as *mut _ as *mut _, &mut len))?; + SocketAddr::from_parts(addr, len) + } + } + + fn from_parts(addr: libc::sockaddr_un, mut len: libc::socklen_t) -> io::Result { + if len == 0 { + // When there is a datagram from unnamed unix socket + // linux returns zero bytes of address + len = sun_path_offset() as libc::socklen_t; // i.e. zero-length address + } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t { + return Err(io::Error::new(io::ErrorKind::InvalidInput, + "file descriptor did not correspond to a Unix socket")); + } + + Ok(SocketAddr { + addr, + len, + }) + } + + /// Returns true if and only if the address is unnamed. + /// + /// # Examples + /// + /// A named address: + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let socket = UnixListener::bind("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.is_unnamed(), false); + /// ``` + /// + /// An unnamed address: + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// + /// let socket = UnixDatagram::unbound().unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.is_unnamed(), true); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn is_unnamed(&self) -> bool { + if let AddressKind::Unnamed = self.address() { + true + } else { + false + } + } + + /// Returns the contents of this address if it is a `pathname` address. + /// + /// # Examples + /// + /// With a pathname: + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// use std::path::Path; + /// + /// let socket = UnixListener::bind("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock"))); + /// ``` + /// + /// Without a pathname: + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// + /// let socket = UnixDatagram::unbound().unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.as_pathname(), None); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn as_pathname(&self) -> Option<&Path> { + if let AddressKind::Pathname(path) = self.address() { + Some(path) + } else { + None + } + } + + fn address<'a>(&'a self) -> AddressKind<'a> { + let len = self.len as usize - sun_path_offset(); + let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; + + // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses + if len == 0 + || (cfg!(not(any(target_os = "linux", target_os = "android"))) + && self.addr.sun_path[0] == 0) + { + AddressKind::Unnamed + } else if self.addr.sun_path[0] == 0 { + AddressKind::Abstract(&path[1..len]) + } else { + AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref()) + } + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl fmt::Debug for SocketAddr { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match self.address() { + AddressKind::Unnamed => write!(fmt, "(unnamed)"), + AddressKind::Abstract(name) => write!(fmt, "{} (abstract)", AsciiEscaped(name)), + AddressKind::Pathname(path) => write!(fmt, "{:?} (pathname)", path), + } + } +} + +struct AsciiEscaped<'a>(&'a [u8]); + +impl<'a> fmt::Display for AsciiEscaped<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "\"")?; + for byte in self.0.iter().cloned().flat_map(ascii::escape_default) { + write!(fmt, "{}", byte as char)?; + } + write!(fmt, "\"") + } +} + +/// A Unix stream socket. +/// +/// # Examples +/// +/// ```no_run +/// use std::os::unix::net::UnixStream; +/// use std::io::prelude::*; +/// +/// let mut stream = UnixStream::connect("/path/to/my/socket").unwrap(); +/// stream.write_all(b"hello world").unwrap(); +/// let mut response = String::new(); +/// stream.read_to_string(&mut response).unwrap(); +/// println!("{}", response); +/// ``` +#[stable(feature = "unix_socket", since = "1.10.0")] +pub struct UnixStream(Socket); + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl fmt::Debug for UnixStream { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut builder = fmt.debug_struct("UnixStream"); + builder.field("fd", self.0.as_inner()); + if let Ok(addr) = self.local_addr() { + builder.field("local", &addr); + } + if let Ok(addr) = self.peer_addr() { + builder.field("peer", &addr); + } + builder.finish() + } +} + +impl UnixStream { + /// Connects to the socket named by `path`. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = match UnixStream::connect("/tmp/sock") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return + /// } + /// }; + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn connect>(path: P) -> io::Result { + fn inner(path: &Path) -> io::Result { + unsafe { + let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; + let (addr, len) = sockaddr_un(path)?; + + cvt(libc::connect(*inner.as_inner(), &addr as *const _ as *const _, len))?; + Ok(UnixStream(inner)) + } + } + inner(path.as_ref()) + } + + /// Creates an unnamed pair of connected sockets. + /// + /// Returns two `UnixStream`s which are connected to each other. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let (sock1, sock2) = match UnixStream::pair() { + /// Ok((sock1, sock2)) => (sock1, sock2), + /// Err(e) => { + /// println!("Couldn't create a pair of sockets: {:?}", e); + /// return + /// } + /// }; + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn pair() -> io::Result<(UnixStream, UnixStream)> { + let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?; + Ok((UnixStream(i1), UnixStream(i2))) + } + + /// Creates a new independently owned handle to the underlying socket. + /// + /// The returned `UnixStream` is a reference to the same stream that this + /// object references. Both handles will read and write the same stream of + /// data, and options set on one stream will be propagated to the other + /// stream. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn try_clone(&self) -> io::Result { + self.0.duplicate().map(UnixStream) + } + + /// Returns the socket address of the local half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn local_addr(&self) -> io::Result { + SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) + } + + /// Returns the socket address of the remote half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let addr = socket.peer_addr().expect("Couldn't get peer address"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn peer_addr(&self) -> io::Result { + SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) + } + + /// Sets the read timeout for the socket. + /// + /// If the provided value is [`None`], then [`read`] calls will block + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err + /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read + /// [`Duration`]: ../../../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { + self.0.set_timeout(timeout, libc::SO_RCVTIMEO) + } + + /// Sets the write timeout for the socket. + /// + /// If the provided value is [`None`], then [`write`] calls will block + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is + /// passed to this method. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err + /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write + /// [`Duration`]: ../../../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); + /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// use std::io; + /// use std::net::UdpSocket; + /// use std::time::Duration; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); + /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { + self.0.set_timeout(timeout, libc::SO_SNDTIMEO) + } + + /// Returns the read timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn read_timeout(&self) -> io::Result> { + self.0.timeout(libc::SO_RCVTIMEO) + } + + /// Returns the write timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); + /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn write_timeout(&self) -> io::Result> { + self.0.timeout(libc::SO_SNDTIMEO) + } + + /// Moves the socket into or out of nonblocking mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.0.set_nonblocking(nonblocking) + } + + /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// if let Ok(Some(err)) = socket.take_error() { + /// println!("Got error: {:?}", err); + /// } + /// ``` + /// + /// # Platform specific + /// On Redox this always returns None. + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn take_error(&self) -> io::Result> { + self.0.take_error() + } + + /// Shuts down the read, write, or both halves of this connection. + /// + /// This function will cause all pending and future I/O calls on the + /// specified portions to immediately return with an appropriate value + /// (see the documentation of [`Shutdown`]). + /// + /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::net::Shutdown; + /// + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { + self.0.shutdown(how) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl io::Read for UnixStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + io::Read::read(&mut &*self, buf) + } + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl<'a> io::Read for &'a UnixStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.0.read(buf) + } + + #[inline] + unsafe fn initializer(&self) -> Initializer { + Initializer::nop() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl io::Write for UnixStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + io::Write::write(&mut &*self, buf) + } + + fn flush(&mut self) -> io::Result<()> { + io::Write::flush(&mut &*self) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl<'a> io::Write for &'a UnixStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl AsRawFd for UnixStream { + fn as_raw_fd(&self) -> RawFd { + *self.0.as_inner() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl FromRawFd for UnixStream { + unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { + UnixStream(Socket::from_inner(fd)) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl IntoRawFd for UnixStream { + fn into_raw_fd(self) -> RawFd { + self.0.into_inner() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for net::TcpStream { fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } } -#[stable(feature = "into_raw_os", since = "1.4.0")] +#[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for net::TcpListener { fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } } -#[stable(feature = "into_raw_os", since = "1.4.0")] +#[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for net::UdpSocket { fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } } -#[stable(feature = "into_raw_os", since = "1.4.0")] +#[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawFd for net::TcpStream { unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream { let socket = sys::net::Socket::from_inner(fd); @@ -112,7 +645,7 @@ impl FromRawFd for net::TcpStream { } } -#[stable(feature = "into_raw_os", since = "1.4.0")] +#[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawFd for net::TcpListener { unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener { let socket = sys::net::Socket::from_inner(fd); @@ -120,7 +653,7 @@ impl FromRawFd for net::TcpListener { } } -#[stable(feature = "into_raw_os", since = "1.4.0")] +#[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawFd for net::UdpSocket { unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket { let socket = sys::net::Socket::from_inner(fd); @@ -147,6 +680,300 @@ impl IntoRawFd for net::UdpSocket { } } +/// A structure representing a Unix domain socket server. +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// use std::os::unix::net::{UnixStream, UnixListener}; +/// +/// fn handle_client(stream: UnixStream) { +/// // ... +/// } +/// +/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); +/// +/// // accept connections and process them, spawning a new thread for each one +/// for stream in listener.incoming() { +/// match stream { +/// Ok(stream) => { +/// /* connection succeeded */ +/// thread::spawn(|| handle_client(stream)); +/// } +/// Err(err) => { +/// /* connection failed */ +/// break; +/// } +/// } +/// } +/// ``` +#[stable(feature = "unix_socket", since = "1.10.0")] +pub struct UnixListener(Socket); + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl fmt::Debug for UnixListener { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut builder = fmt.debug_struct("UnixListener"); + builder.field("fd", self.0.as_inner()); + if let Ok(addr) = self.local_addr() { + builder.field("local", &addr); + } + builder.finish() + } +} + +impl UnixListener { + /// Creates a new `UnixListener` bound to the specified socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = match UnixListener::bind("/path/to/the/socket") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return + /// } + /// }; + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn bind>(path: P) -> io::Result { + fn inner(path: &Path) -> io::Result { + unsafe { + let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; + let (addr, len) = sockaddr_un(path)?; + + cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len as _))?; + cvt(libc::listen(*inner.as_inner(), 128))?; + + Ok(UnixListener(inner)) + } + } + inner(path.as_ref()) + } + + /// Accepts a new incoming connection to this listener. + /// + /// This function will block the calling thread until a new Unix connection + /// is established. When established, the corresponding [`UnixStream`] and + /// the remote peer's address will be returned. + /// + /// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// match listener.accept() { + /// Ok((socket, addr)) => println!("Got a client: {:?}", addr), + /// Err(e) => println!("accept function failed: {:?}", e), + /// } + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { + let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() }; + let mut len = mem::size_of_val(&storage) as libc::socklen_t; + let sock = self.0.accept(&mut storage as *mut _ as *mut _, &mut len)?; + let addr = SocketAddr::from_parts(storage, len)?; + Ok((UnixStream(sock), addr)) + } + + /// Creates a new independently owned handle to the underlying socket. + /// + /// The returned `UnixListener` is a reference to the same socket that this + /// object references. Both handles can be used to accept incoming + /// connections and options set on one listener will affect the other. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// let listener_copy = listener.try_clone().expect("try_clone failed"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn try_clone(&self) -> io::Result { + self.0.duplicate().map(UnixListener) + } + + /// Returns the local socket address of this listener. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// let addr = listener.local_addr().expect("Couldn't get local address"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn local_addr(&self) -> io::Result { + SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) + } + + /// Moves the socket into or out of nonblocking mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.0.set_nonblocking(nonblocking) + } + + /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/tmp/sock").unwrap(); + /// + /// if let Ok(Some(err)) = listener.take_error() { + /// println!("Got error: {:?}", err); + /// } + /// ``` + /// + /// # Platform specific + /// On Redox this always returns None. + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn take_error(&self) -> io::Result> { + self.0.take_error() + } + + /// Returns an iterator over incoming connections. + /// + /// The iterator will never return [`None`] and will also not yield the + /// peer's [`SocketAddr`] structure. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`SocketAddr`]: struct.SocketAddr.html + /// + /// # Examples + /// + /// ```no_run + /// use std::thread; + /// use std::os::unix::net::{UnixStream, UnixListener}; + /// + /// fn handle_client(stream: UnixStream) { + /// // ... + /// } + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// for stream in listener.incoming() { + /// match stream { + /// Ok(stream) => { + /// thread::spawn(|| handle_client(stream)); + /// } + /// Err(err) => { + /// break; + /// } + /// } + /// } + /// ``` + #[stable(feature = "unix_socket", since = "1.10.0")] + pub fn incoming<'a>(&'a self) -> Incoming<'a> { + Incoming { listener: self } + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl AsRawFd for UnixListener { + fn as_raw_fd(&self) -> RawFd { + *self.0.as_inner() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl FromRawFd for UnixListener { + unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { + UnixListener(Socket::from_inner(fd)) + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl IntoRawFd for UnixListener { + fn into_raw_fd(self) -> RawFd { + self.0.into_inner() + } +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl<'a> IntoIterator for &'a UnixListener { + type Item = io::Result; + type IntoIter = Incoming<'a>; + + fn into_iter(self) -> Incoming<'a> { + self.incoming() + } +} + +/// An iterator over incoming connections to a [`UnixListener`]. +/// +/// It will never return [`None`]. +/// +/// [`None`]: ../../../../std/option/enum.Option.html#variant.None +/// [`UnixListener`]: struct.UnixListener.html +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// use std::os::unix::net::{UnixStream, UnixListener}; +/// +/// fn handle_client(stream: UnixStream) { +/// // ... +/// } +/// +/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); +/// +/// for stream in listener.incoming() { +/// match stream { +/// Ok(stream) => { +/// thread::spawn(|| handle_client(stream)); +/// } +/// Err(err) => { +/// break; +/// } +/// } +/// } +/// ``` +#[derive(Debug)] +#[stable(feature = "unix_socket", since = "1.10.0")] +pub struct Incoming<'a> { + listener: &'a UnixListener, +} + +#[stable(feature = "unix_socket", since = "1.10.0")] +impl<'a> Iterator for Incoming<'a> { + type Item = io::Result; + + fn next(&mut self) -> Option> { + Some(self.listener.accept().map(|s| s.0)) + } + + fn size_hint(&self) -> (usize, Option) { + (usize::max_value(), None) + } +} + /// A Unix datagram socket. /// /// # Examples @@ -323,9 +1150,7 @@ impl UnixDatagram { /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn local_addr(&self) -> io::Result { - inner::SocketAddr::new(|addr, len| unsafe { - libc::getsockname(*self.0.as_inner(), addr, len) - }).map(SocketAddr) + SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) } /// Returns the address of this socket's peer. @@ -346,9 +1171,7 @@ impl UnixDatagram { /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn peer_addr(&self) -> io::Result { - inner::SocketAddr::new(|addr, len| unsafe { - libc::getsockname(*self.0.as_inner(), addr, len) - }).map(SocketAddr) + SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) } /// Receives data from the socket. @@ -371,7 +1194,7 @@ impl UnixDatagram { #[stable(feature = "unix_socket", since = "1.10.0")] pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { let mut count = 0; - let addr = SocketAddr(inner::SocketAddr::new(|addr, len| { + let addr = SocketAddr::new(|addr, len| { unsafe { count = libc::recvfrom(*self.0.as_inner(), buf.as_mut_ptr() as *mut _, @@ -387,7 +1210,7 @@ impl UnixDatagram { -1 } } - })?); + })?; Ok((count as usize, addr)) } diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index 89f5fd79f40..d0c4d6a7737 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -55,9 +55,6 @@ pub mod wtf8; pub mod bytestring; pub mod process; -#[cfg(any(all(unix, not(target_os = "emscripten")), target_os = "redox"))] -pub(crate) mod unixsocket; - cfg_if! { if #[cfg(any(target_os = "cloudabi", target_os = "l4re", target_os = "redox"))] { pub use sys::net; -- cgit 1.4.1-3-g733a5 From c007a78d23b684b8edaf624a93ec2d0579a37a86 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Sat, 7 Jul 2018 06:52:03 +0200 Subject: Add is_unnamed --- src/libstd/sys/redox/ext/net.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/net.rs b/src/libstd/sys/redox/ext/net.rs index d29d28c8427..4c5f8574621 100644 --- a/src/libstd/sys/redox/ext/net.rs +++ b/src/libstd/sys/redox/ext/net.rs @@ -67,6 +67,33 @@ impl SocketAddr { pub fn as_pathname(&self) -> Option<&Path> { None } + + /// Returns true if and only if the address is unnamed. + /// + /// # Examples + /// + /// A named address: + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let socket = UnixListener::bind("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.is_unnamed(), false); + /// ``` + /// + /// An unnamed address: + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// + /// let socket = UnixDatagram::unbound().unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.is_unnamed(), true); + /// ``` + pub fn is_unnamed(&self) -> bool { + false + } } impl fmt::Debug for SocketAddr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { -- cgit 1.4.1-3-g733a5 From 0b56e7f1a911f1157cd46cedbb1a0544e3ee3c3c Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Sun, 8 Jul 2018 20:48:11 +0200 Subject: Delete leftover files --- src/libstd/sys/redox/ext/unixsocket.rs | 252 ------------ src/libstd/sys/unix/ext/unixsocket.rs | 354 ---------------- src/libstd/sys_common/unixsocket.rs | 731 --------------------------------- 3 files changed, 1337 deletions(-) delete mode 100644 src/libstd/sys/redox/ext/unixsocket.rs delete mode 100644 src/libstd/sys/unix/ext/unixsocket.rs delete mode 100644 src/libstd/sys_common/unixsocket.rs (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/unixsocket.rs b/src/libstd/sys/redox/ext/unixsocket.rs deleted file mode 100644 index 5f7b2df8992..00000000000 --- a/src/libstd/sys/redox/ext/unixsocket.rs +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright 2016 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use fmt; -use io::{self, Error, ErrorKind, Initializer}; -use net::Shutdown; -use os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd}; -use path::Path; -use time::Duration; -use sys::{cvt, fd::FileDesc, syscall}; - -#[stable(feature = "unix_socket", since = "1.10.0")] -#[derive(Clone)] -pub struct SocketAddr(()); - -impl SocketAddr { - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn is_unnamed(&self) -> bool { - false - } - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn as_pathname(&self) -> Option<&Path> { - None - } -} -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for SocketAddr { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "SocketAddr") - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct UnixStream(FileDesc); - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for UnixStream { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut builder = fmt.debug_struct("UnixStream"); - builder.field("fd", &self.0.raw()); - if let Ok(addr) = self.local_addr() { - builder.field("local", &addr); - } - if let Ok(addr) = self.peer_addr() { - builder.field("peer", &addr); - } - builder.finish() - } -} - -impl UnixStream { - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn connect(path: &Path) -> io::Result { - if let Some(s) = path.to_str() { - cvt(syscall::open(format!("chan:{}", s), syscall::O_CLOEXEC)) - .map(FileDesc::new) - .map(UnixStream) - } else { - Err(Error::new( - ErrorKind::Other, - "UnixStream::connect: non-utf8 paths not supported on redox" - )) - } - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn pair() -> io::Result<(UnixStream, UnixStream)> { - let server = cvt(syscall::open("chan:", syscall::O_CREAT | syscall::O_CLOEXEC)) - .map(FileDesc::new)?; - let client = server.duplicate_path(b"connect")?; - let stream = server.duplicate_path(b"listen")?; - Ok((UnixStream(client), UnixStream(stream))) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn try_clone(&self) -> io::Result { - self.0.duplicate().map(UnixStream) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn local_addr(&self) -> io::Result { - Err(Error::new(ErrorKind::Other, "UnixStream::local_addr unimplemented on redox")) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn peer_addr(&self) -> io::Result { - Err(Error::new(ErrorKind::Other, "UnixStream::peer_addr unimplemented on redox")) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_read_timeout(&self, _timeout: Option) -> io::Result<()> { - Err(Error::new(ErrorKind::Other, "UnixStream::set_read_timeout unimplemented on redox")) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_write_timeout(&self, _timeout: Option) -> io::Result<()> { - Err(Error::new(ErrorKind::Other, "UnixStream::set_write_timeout unimplemented on redox")) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn read_timeout(&self) -> io::Result> { - Err(Error::new(ErrorKind::Other, "UnixStream::read_timeout unimplemented on redox")) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn write_timeout(&self) -> io::Result> { - Err(Error::new(ErrorKind::Other, "UnixStream::write_timeout unimplemented on redox")) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - self.0.set_nonblocking(nonblocking) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn take_error(&self) -> io::Result> { - Ok(None) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn shutdown(&self, _how: Shutdown) -> io::Result<()> { - Err(Error::new(ErrorKind::Other, "UnixStream::shutdown unimplemented on redox")) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> io::Read for &'a UnixStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) - } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> io::Write for &'a UnixStream { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.0.write(buf) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl AsRawFd for UnixStream { - fn as_raw_fd(&self) -> RawFd { - self.0.raw() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl FromRawFd for UnixStream { - unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { - UnixStream(FileDesc::new(fd)) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl IntoRawFd for UnixStream { - fn into_raw_fd(self) -> RawFd { - self.0.into_raw() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct UnixListener(FileDesc); - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for UnixListener { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut builder = fmt.debug_struct("UnixListener"); - builder.field("fd", &self.0.raw()); - if let Ok(addr) = self.local_addr() { - builder.field("local", &addr); - } - builder.finish() - } -} - -impl UnixListener { - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn bind(path: &Path) -> io::Result { - if let Some(s) = path.to_str() { - cvt(syscall::open(format!("chan:{}", s), syscall::O_CREAT | syscall::O_CLOEXEC)) - .map(FileDesc::new) - .map(UnixListener) - } else { - Err(Error::new( - ErrorKind::Other, - "UnixListener::bind: non-utf8 paths not supported on redox" - )) - } - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { - self.0.duplicate_path(b"listen").map(|fd| (UnixStream(fd), SocketAddr(()))) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn try_clone(&self) -> io::Result { - self.0.duplicate().map(UnixListener) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn local_addr(&self) -> io::Result { - Err(Error::new(ErrorKind::Other, "UnixListener::local_addr unimplemented on redox")) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - self.0.set_nonblocking(nonblocking) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn take_error(&self) -> io::Result> { - Ok(None) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl AsRawFd for UnixListener { - fn as_raw_fd(&self) -> RawFd { - self.0.raw() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl FromRawFd for UnixListener { - unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { - UnixListener(FileDesc::new(fd)) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl IntoRawFd for UnixListener { - fn into_raw_fd(self) -> RawFd { - self.0.into_raw() - } -} diff --git a/src/libstd/sys/unix/ext/unixsocket.rs b/src/libstd/sys/unix/ext/unixsocket.rs deleted file mode 100644 index ad2d7019cb8..00000000000 --- a/src/libstd/sys/unix/ext/unixsocket.rs +++ /dev/null @@ -1,354 +0,0 @@ -// Copyright 2016 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Unix-specific networking functionality - -#[cfg(unix)] -use libc; - -// FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here? -#[cfg(not(unix))] -mod libc { - pub use libc::c_int; - pub type socklen_t = u32; - pub struct sockaddr; - #[derive(Clone)] - pub struct sockaddr_un; -} - -use ascii; -use ffi::OsStr; -use fmt; -use io::{self, Initializer}; -use mem; -use net::Shutdown; -use os::unix::ffi::OsStrExt; -use os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd}; -use path::Path; -use time::Duration; -use sys::cvt; -use sys::net::Socket; -use sys::ext::net::*; -use sys_common::{AsInner, FromInner, IntoInner}; - -enum AddressKind<'a> { - Unnamed, - Pathname(&'a Path), - Abstract(&'a [u8]), -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -#[derive(Clone)] -pub struct SocketAddr { - addr: libc::sockaddr_un, - len: libc::socklen_t, -} - -impl SocketAddr { - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn new(f: F) -> io::Result - where F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int - { - unsafe { - let mut addr: libc::sockaddr_un = mem::zeroed(); - let mut len = mem::size_of::() as libc::socklen_t; - cvt(f(&mut addr as *mut _ as *mut _, &mut len))?; - SocketAddr::from_parts(addr, len) - } - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn from_parts(addr: libc::sockaddr_un, mut len: libc::socklen_t) - -> io::Result - { - if len == 0 { - // When there is a datagram from unnamed unix socket - // linux returns zero bytes of address - len = sun_path_offset() as libc::socklen_t; // i.e. zero-length address - } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t { - return Err(io::Error::new(io::ErrorKind::InvalidInput, - "file descriptor did not correspond to a Unix socket")); - } - - Ok(SocketAddr { - addr, - len, - }) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn is_unnamed(&self) -> bool { - if let AddressKind::Unnamed = self.address() { - true - } else { - false - } - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn as_pathname(&self) -> Option<&Path> { - if let AddressKind::Pathname(path) = self.address() { - Some(path) - } else { - None - } - } - - fn address<'a>(&'a self) -> AddressKind<'a> { - let len = self.len as usize - sun_path_offset(); - let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; - - // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses - if len == 0 - || (cfg!(not(any(target_os = "linux", target_os = "android"))) - && self.addr.sun_path[0] == 0) - { - AddressKind::Unnamed - } else if self.addr.sun_path[0] == 0 { - AddressKind::Abstract(&path[1..len]) - } else { - AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref()) - } - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for SocketAddr { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match self.address() { - AddressKind::Unnamed => write!(fmt, "(unnamed)"), - AddressKind::Abstract(name) => write!(fmt, "{} (abstract)", AsciiEscaped(name)), - AddressKind::Pathname(path) => write!(fmt, "{:?} (pathname)", path), - } - } -} - -struct AsciiEscaped<'a>(&'a [u8]); - -impl<'a> fmt::Display for AsciiEscaped<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "\"")?; - for byte in self.0.iter().cloned().flat_map(ascii::escape_default) { - write!(fmt, "{}", byte as char)?; - } - write!(fmt, "\"") - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct UnixStream(Socket); - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for UnixStream { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut builder = fmt.debug_struct("UnixStream"); - builder.field("fd", self.0.as_inner()); - if let Ok(addr) = self.local_addr() { - builder.field("local", &addr); - } - if let Ok(addr) = self.peer_addr() { - builder.field("peer", &addr); - } - builder.finish() - } -} - -impl UnixStream { - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn connect(path: &Path) -> io::Result { - unsafe { - let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; - let (addr, len) = sockaddr_un(path)?; - - cvt(libc::connect(*inner.as_inner(), &addr as *const _ as *const _, len))?; - Ok(UnixStream(inner)) - } - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn pair() -> io::Result<(UnixStream, UnixStream)> { - let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?; - Ok((UnixStream(i1), UnixStream(i2))) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn try_clone(&self) -> io::Result { - self.0.duplicate().map(UnixStream) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn local_addr(&self) -> io::Result { - SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn peer_addr(&self) -> io::Result { - SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { - self.0.set_timeout(timeout, libc::SO_RCVTIMEO) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { - self.0.set_timeout(timeout, libc::SO_SNDTIMEO) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn read_timeout(&self) -> io::Result> { - self.0.timeout(libc::SO_RCVTIMEO) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn write_timeout(&self) -> io::Result> { - self.0.timeout(libc::SO_SNDTIMEO) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - self.0.set_nonblocking(nonblocking) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn take_error(&self) -> io::Result> { - self.0.take_error() - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { - self.0.shutdown(how) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> io::Read for &'a UnixStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) - } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> io::Write for &'a UnixStream { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.0.write(buf) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl AsRawFd for UnixStream { - fn as_raw_fd(&self) -> RawFd { - *self.0.as_inner() - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl FromRawFd for UnixStream { - unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { - UnixStream(Socket::from_inner(fd)) - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawFd for UnixStream { - fn into_raw_fd(self) -> RawFd { - self.0.into_inner() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct UnixListener(Socket); - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for UnixListener { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut builder = fmt.debug_struct("UnixListener"); - builder.field("fd", self.0.as_inner()); - if let Ok(addr) = self.local_addr() { - builder.field("local", &addr); - } - builder.finish() - } -} - -impl UnixListener { - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn bind(path: &Path) -> io::Result { - unsafe { - let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; - let (addr, len) = sockaddr_un(path)?; - - cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len as _))?; - cvt(libc::listen(*inner.as_inner(), 128))?; - - Ok(UnixListener(inner)) - } - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { - let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() }; - let mut len = mem::size_of_val(&storage) as libc::socklen_t; - let sock = self.0.accept(&mut storage as *mut _ as *mut _, &mut len)?; - let addr = SocketAddr::from_parts(storage, len)?; - Ok((UnixStream(sock), addr)) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn try_clone(&self) -> io::Result { - self.0.duplicate().map(UnixListener) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn local_addr(&self) -> io::Result { - SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - self.0.set_nonblocking(nonblocking) - } - - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn take_error(&self) -> io::Result> { - self.0.take_error() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl AsRawFd for UnixListener { - fn as_raw_fd(&self) -> RawFd { - *self.0.as_inner() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl FromRawFd for UnixListener { - unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { - UnixListener(Socket::from_inner(fd)) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl IntoRawFd for UnixListener { - fn into_raw_fd(self) -> RawFd { - self.0.into_inner() - } -} diff --git a/src/libstd/sys_common/unixsocket.rs b/src/libstd/sys_common/unixsocket.rs deleted file mode 100644 index c7d71ae6790..00000000000 --- a/src/libstd/sys_common/unixsocket.rs +++ /dev/null @@ -1,731 +0,0 @@ -// Copyright 2016 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![stable(feature = "unix_socket", since = "1.10.0")] - -//! Unix-specific networking functionality - -use fmt; -use io::{self, Initializer}; -use net::Shutdown; -use os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd}; -use path::Path; -use time::Duration; - -use sys::ext::unixsocket as inner; - -/// An address associated with a Unix socket. -/// -/// # Examples -/// -/// ``` -/// use std::os::unix::net::UnixListener; -/// -/// let socket = match UnixListener::bind("/tmp/sock") { -/// Ok(sock) => sock, -/// Err(e) => { -/// println!("Couldn't bind: {:?}", e); -/// return -/// } -/// }; -/// let addr = socket.local_addr().expect("Couldn't get local address"); -/// ``` -#[stable(feature = "unix_socket", since = "1.10.0")] -#[derive(Clone)] -pub struct SocketAddr(pub(crate) inner::SocketAddr); - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for SocketAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self.0) - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawFd for UnixStream { - fn into_raw_fd(self) -> RawFd { - self.0.into_raw_fd() - } -} -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl AsRawFd for UnixStream { - fn as_raw_fd(&self) -> RawFd { - self.0.as_raw_fd() - } -} -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl FromRawFd for UnixStream { - unsafe fn from_raw_fd(fd: RawFd) -> Self { - UnixStream(inner::UnixStream::from_raw_fd(fd)) - } -} -#[stable(feature = "unix_socket", since = "1.10.0")] -impl io::Read for UnixStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - io::Read::read(&mut &self.0, buf) - } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - io::Read::initializer(&&self.0) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> io::Read for &'a UnixStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - io::Read::read(&mut &self.0, buf) - } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - io::Read::initializer(&&self.0) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl io::Write for UnixStream { - fn write(&mut self, buf: &[u8]) -> io::Result { - io::Write::write(&mut &self.0, buf) - } - - fn flush(&mut self) -> io::Result<()> { - io::Write::flush(&mut &self.0) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> io::Write for &'a UnixStream { - fn write(&mut self, buf: &[u8]) -> io::Result { - io::Write::write(&mut &self.0, buf) - } - - fn flush(&mut self) -> io::Result<()> { - io::Write::flush(&mut &self.0) - } -} - -impl SocketAddr { - /// Returns true if and only if the address is unnamed. - /// - /// # Examples - /// - /// A named address: - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let socket = UnixListener::bind("/tmp/sock").unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.is_unnamed(), false); - /// ``` - /// - /// An unnamed address: - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// - /// let socket = UnixDatagram::unbound().unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.is_unnamed(), true); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn is_unnamed(&self) -> bool { - self.0.is_unnamed() - } - - /// Returns the contents of this address if it is a `pathname` address. - /// - /// # Examples - /// - /// With a pathname: - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// use std::path::Path; - /// - /// let socket = UnixListener::bind("/tmp/sock").unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock"))); - /// ``` - /// - /// Without a pathname: - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// - /// let socket = UnixDatagram::unbound().unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.as_pathname(), None); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn as_pathname(&self) -> Option<&Path> { - self.0.as_pathname() - } -} - -/// A Unix stream socket. -/// -/// # Examples -/// -/// ```no_run -/// use std::os::unix::net::UnixStream; -/// use std::io::prelude::*; -/// -/// let mut stream = UnixStream::connect("/path/to/my/socket").unwrap(); -/// stream.write_all(b"hello world").unwrap(); -/// let mut response = String::new(); -/// stream.read_to_string(&mut response).unwrap(); -/// println!("{}", response); -/// ``` -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct UnixStream(inner::UnixStream); - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for UnixStream { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self.0) - } -} - -impl UnixStream { - /// Connects to the socket named by `path`. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = match UnixStream::connect("/tmp/sock") { - /// Ok(sock) => sock, - /// Err(e) => { - /// println!("Couldn't connect: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn connect>(path: P) -> io::Result { - inner::UnixStream::connect(path.as_ref()).map(UnixStream) - } - - /// Creates an unnamed pair of connected sockets. - /// - /// Returns two `UnixStream`s which are connected to each other. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let (sock1, sock2) = match UnixStream::pair() { - /// Ok((sock1, sock2)) => (sock1, sock2), - /// Err(e) => { - /// println!("Couldn't create a pair of sockets: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn pair() -> io::Result<(UnixStream, UnixStream)> { - inner::UnixStream::pair().map(|(s1, s2)| (UnixStream(s1), UnixStream(s2))) - } - - /// Creates a new independently owned handle to the underlying socket. - /// - /// The returned `UnixStream` is a reference to the same stream that this - /// object references. Both handles will read and write the same stream of - /// data, and options set on one stream will be propagated to the other - /// stream. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn try_clone(&self) -> io::Result { - self.0.try_clone().map(UnixStream) - } - - /// Returns the socket address of the local half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn local_addr(&self) -> io::Result { - self.0.local_addr().map(SocketAddr) - } - - /// Returns the socket address of the remote half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let addr = socket.peer_addr().expect("Couldn't get peer address"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn peer_addr(&self) -> io::Result { - self.0.peer_addr().map(SocketAddr) - } - - /// Sets the read timeout for the socket. - /// - /// If the provided value is [`None`], then [`read`] calls will block - /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method. - /// - /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err - /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read - /// [`Duration`]: ../../../../std/time/struct.Duration.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); - /// ``` - /// - /// An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method: - /// - /// ```no_run - /// use std::io; - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); - /// let err = result.unwrap_err(); - /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { - self.0.set_read_timeout(timeout) - } - - /// Sets the write timeout for the socket. - /// - /// If the provided value is [`None`], then [`write`] calls will block - /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is - /// passed to this method. - /// - /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err - /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write - /// [`Duration`]: ../../../../std/time/struct.Duration.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); - /// ``` - /// - /// An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method: - /// - /// ```no_run - /// use std::io; - /// use std::net::UdpSocket; - /// use std::time::Duration; - /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); - /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); - /// let err = result.unwrap_err(); - /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { - self.0.set_write_timeout(timeout) - } - - /// Returns the read timeout of this socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); - /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0))); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn read_timeout(&self) -> io::Result> { - self.0.read_timeout() - } - - /// Returns the write timeout of this socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); - /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0))); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn write_timeout(&self) -> io::Result> { - self.0.write_timeout() - } - - /// Moves the socket into or out of nonblocking mode. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - self.0.set_nonblocking(nonblocking) - } - - /// Returns the value of the `SO_ERROR` option. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// if let Ok(Some(err)) = socket.take_error() { - /// println!("Got error: {:?}", err); - /// } - /// ``` - /// - /// # Platform specific - /// On Redox this always returns None. - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn take_error(&self) -> io::Result> { - self.0.take_error() - } - - /// Shuts down the read, write, or both halves of this connection. - /// - /// This function will cause all pending and future I/O calls on the - /// specified portions to immediately return with an appropriate value - /// (see the documentation of [`Shutdown`]). - /// - /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::net::Shutdown; - /// - /// let socket = UnixStream::connect("/tmp/sock").unwrap(); - /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { - self.0.shutdown(how) - } -} - -/// A structure representing a Unix domain socket server. -/// -/// # Examples -/// -/// ```no_run -/// use std::thread; -/// use std::os::unix::net::{UnixStream, UnixListener}; -/// -/// pub fn handle_client(stream: UnixStream) { -/// // ... -/// } -/// -/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); -/// -/// // accept connections and process them, spawning a new thread for each one -/// for stream in listener.incoming() { -/// match stream { -/// Ok(stream) => { -/// /* connection succeeded */ -/// thread::spawn(|| handle_client(stream)); -/// } -/// Err(err) => { -/// /* connection failed */ -/// break; -/// } -/// } -/// } -/// ``` -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct UnixListener(inner::UnixListener); - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for UnixListener { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self.0) - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawFd for UnixListener { - fn into_raw_fd(self) -> RawFd { - self.0.into_raw_fd() - } -} -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl AsRawFd for UnixListener { - fn as_raw_fd(&self) -> RawFd { - self.0.as_raw_fd() - } -} -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl FromRawFd for UnixListener { - unsafe fn from_raw_fd(fd: RawFd) -> Self { - UnixListener(inner::UnixListener::from_raw_fd(fd)) - } -} - -impl UnixListener { - /// Creates a new `UnixListener` bound to the specified socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = match UnixListener::bind("/path/to/the/socket") { - /// Ok(sock) => sock, - /// Err(e) => { - /// println!("Couldn't connect: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn bind>(path: P) -> io::Result { - inner::UnixListener::bind(path.as_ref()).map(UnixListener) - } - - /// Accepts a new incoming connection to this listener. - /// - /// This function will block the calling thread until a new Unix connection - /// is established. When established, the corresponding [`UnixStream`] and - /// the remote peer's address will be returned. - /// - /// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// match listener.accept() { - /// Ok((socket, addr)) => println!("Got a client: {:?}", addr), - /// Err(e) => println!("accept function failed: {:?}", e), - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { - self.0.accept().map(|(s, a)| (UnixStream(s), SocketAddr(a))) - } - - /// Creates a new independently owned handle to the underlying socket. - /// - /// The returned `UnixListener` is a reference to the same socket that this - /// object references. Both handles can be used to accept incoming - /// connections and options set on one listener will affect the other. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// let listener_copy = listener.try_clone().expect("try_clone failed"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn try_clone(&self) -> io::Result { - self.0.try_clone().map(UnixListener) - } - - /// Returns the local socket address of this listener. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// let addr = listener.local_addr().expect("Couldn't get local address"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn local_addr(&self) -> io::Result { - self.0.local_addr().map(SocketAddr) - } - - /// Moves the socket into or out of nonblocking mode. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - self.0.set_nonblocking(nonblocking) - } - - /// Returns the value of the `SO_ERROR` option. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = UnixListener::bind("/tmp/sock").unwrap(); - /// - /// if let Ok(Some(err)) = listener.take_error() { - /// println!("Got error: {:?}", err); - /// } - /// ``` - /// - /// # Platform specific - /// On Redox this always returns None. - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn take_error(&self) -> io::Result> { - self.0.take_error() - } - - /// Returns an iterator over incoming connections. - /// - /// The iterator will never return [`None`] and will also not yield the - /// peer's [`SocketAddr`] structure. - /// - /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`SocketAddr`]: struct.SocketAddr.html - /// - /// # Examples - /// - /// ```no_run - /// use std::thread; - /// use std::os::unix::net::{UnixStream, UnixListener}; - /// - /// pub fn handle_client(stream: UnixStream) { - /// // ... - /// } - /// - /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); - /// - /// for stream in listener.incoming() { - /// match stream { - /// Ok(stream) => { - /// thread::spawn(|| handle_client(stream)); - /// } - /// Err(err) => { - /// break; - /// } - /// } - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn incoming<'a>(&'a self) -> Incoming<'a> { - Incoming { listener: self } - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> IntoIterator for &'a UnixListener { - type Item = io::Result; - type IntoIter = Incoming<'a>; - - fn into_iter(self) -> Incoming<'a> { - self.incoming() - } -} - -/// An iterator over incoming connections to a [`UnixListener`]. -/// -/// It will never return [`None`]. -/// -/// [`None`]: ../../../../std/option/enum.Option.html#variant.None -/// [`UnixListener`]: struct.UnixListener.html -/// -/// # Examples -/// -/// ```no_run -/// use std::thread; -/// use std::os::unix::net::{UnixStream, UnixListener}; -/// -/// pub fn handle_client(stream: UnixStream) { -/// // ... -/// } -/// -/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); -/// -/// for stream in listener.incoming() { -/// match stream { -/// Ok(stream) => { -/// thread::spawn(|| handle_client(stream)); -/// } -/// Err(err) => { -/// break; -/// } -/// } -/// } -/// ``` -#[stable(feature = "unix_socket", since = "1.10.0")] -#[derive(Debug)] -pub struct Incoming<'a> { - listener: &'a UnixListener, -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> Iterator for Incoming<'a> { - type Item = io::Result; - - fn next(&mut self) -> Option> { - Some(self.listener.accept().map(|s| s.0)) - } - - fn size_hint(&self) -> (usize, Option) { - (usize::max_value(), None) - } -} -- cgit 1.4.1-3-g733a5 From 560d8079ec26f2a45ecb80e95d24917025e02104 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Tue, 10 Jul 2018 20:35:36 +0200 Subject: Deny bare trait objects in `src/libstd`. --- src/libstd/error.rs | 86 ++++++++++++++++++------------------ src/libstd/ffi/c_str.rs | 2 +- src/libstd/io/error.rs | 14 +++--- src/libstd/io/mod.rs | 4 +- src/libstd/io/stdio.rs | 8 ++-- src/libstd/lib.rs | 1 + src/libstd/net/parser.rs | 2 +- src/libstd/panic.rs | 2 +- src/libstd/panicking.rs | 36 +++++++-------- src/libstd/process.rs | 4 +- src/libstd/rt.rs | 2 +- src/libstd/sync/mpsc/mod.rs | 10 ++--- src/libstd/sync/mpsc/select.rs | 2 +- src/libstd/sync/once.rs | 2 +- src/libstd/sys/windows/thread.rs | 2 +- src/libstd/sys_common/at_exit_imp.rs | 4 +- src/libstd/sys_common/backtrace.rs | 10 ++--- src/libstd/sys_common/poison.rs | 2 +- src/libstd/sys_common/thread.rs | 2 +- src/libstd/thread/mod.rs | 2 +- 20 files changed, 99 insertions(+), 98 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 1958915602f..8d715ac0ec3 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -138,7 +138,7 @@ pub trait Error: Debug + Display { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn cause(&self) -> Option<&Error> { None } + fn cause(&self) -> Option<&dyn Error> { None } /// Get the `TypeId` of `self` #[doc(hidden)] @@ -151,22 +151,22 @@ pub trait Error: Debug + Display { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + 'a> From for Box { - fn from(err: E) -> Box { +impl<'a, E: Error + 'a> From for Box { + fn from(err: E) -> Box { Box::new(err) } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + Send + Sync + 'a> From for Box { - fn from(err: E) -> Box { +impl<'a, E: Error + Send + Sync + 'a> From for Box { + fn from(err: E) -> Box { Box::new(err) } } #[stable(feature = "rust1", since = "1.0.0")] -impl From for Box { - fn from(err: String) -> Box { +impl From for Box { + fn from(err: String) -> Box { #[derive(Debug)] struct StringError(String); @@ -185,38 +185,38 @@ impl From for Box { } #[stable(feature = "string_box_error", since = "1.6.0")] -impl From for Box { - fn from(str_err: String) -> Box { - let err1: Box = From::from(str_err); - let err2: Box = err1; +impl From for Box { + fn from(str_err: String) -> Box { + let err1: Box = From::from(str_err); + let err2: Box = err1; err2 } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b> From<&'b str> for Box { - fn from(err: &'b str) -> Box { +impl<'a, 'b> From<&'b str> for Box { + fn from(err: &'b str) -> Box { From::from(String::from(err)) } } #[stable(feature = "string_box_error", since = "1.6.0")] -impl<'a> From<&'a str> for Box { - fn from(err: &'a str) -> Box { +impl<'a> From<&'a str> for Box { + fn from(err: &'a str) -> Box { From::from(String::from(err)) } } #[stable(feature = "cow_box_error", since = "1.22.0")] -impl<'a, 'b> From> for Box { - fn from(err: Cow<'b, str>) -> Box { +impl<'a, 'b> From> for Box { + fn from(err: Cow<'b, str>) -> Box { From::from(String::from(err)) } } #[stable(feature = "cow_box_error", since = "1.22.0")] -impl<'a> From> for Box { - fn from(err: Cow<'a, str>) -> Box { +impl<'a> From> for Box { + fn from(err: Cow<'a, str>) -> Box { From::from(String::from(err)) } } @@ -327,7 +327,7 @@ impl Error for Box { Error::description(&**self) } - fn cause(&self) -> Option<&Error> { + fn cause(&self) -> Option<&dyn Error> { Error::cause(&**self) } } @@ -368,7 +368,7 @@ impl Error for char::ParseCharError { } // copied from any.rs -impl Error + 'static { +impl dyn Error + 'static { /// Returns true if the boxed type is the same as `T` #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] @@ -390,7 +390,7 @@ impl Error + 'static { pub fn downcast_ref(&self) -> Option<&T> { if self.is::() { unsafe { - Some(&*(self as *const Error as *const T)) + Some(&*(self as *const dyn Error as *const T)) } } else { None @@ -404,7 +404,7 @@ impl Error + 'static { pub fn downcast_mut(&mut self) -> Option<&mut T> { if self.is::() { unsafe { - Some(&mut *(self as *mut Error as *mut T)) + Some(&mut *(self as *mut dyn Error as *mut T)) } } else { None @@ -412,60 +412,60 @@ impl Error + 'static { } } -impl Error + 'static + Send { +impl dyn Error + 'static + Send { /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn is(&self) -> bool { - ::is::(self) + ::is::(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_ref(&self) -> Option<&T> { - ::downcast_ref::(self) + ::downcast_ref::(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_mut(&mut self) -> Option<&mut T> { - ::downcast_mut::(self) + ::downcast_mut::(self) } } -impl Error + 'static + Send + Sync { +impl dyn Error + 'static + Send + Sync { /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn is(&self) -> bool { - ::is::(self) + ::is::(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_ref(&self) -> Option<&T> { - ::downcast_ref::(self) + ::downcast_ref::(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_mut(&mut self) -> Option<&mut T> { - ::downcast_mut::(self) + ::downcast_mut::(self) } } -impl Error { +impl dyn Error { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] /// Attempt to downcast the box to a concrete type. - pub fn downcast(self: Box) -> Result, Box> { + pub fn downcast(self: Box) -> Result, Box> { if self.is::() { unsafe { - let raw: *mut Error = Box::into_raw(self); + let raw: *mut dyn Error = Box::into_raw(self); Ok(Box::from_raw(raw as *mut T)) } } else { @@ -474,30 +474,30 @@ impl Error { } } -impl Error + Send { +impl dyn Error + Send { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] /// Attempt to downcast the box to a concrete type. pub fn downcast(self: Box) - -> Result, Box> { - let err: Box = self; - ::downcast(err).map_err(|s| unsafe { + -> Result, Box> { + let err: Box = self; + ::downcast(err).map_err(|s| unsafe { // reapply the Send marker - transmute::, Box>(s) + transmute::, Box>(s) }) } } -impl Error + Send + Sync { +impl dyn Error + Send + Sync { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] /// Attempt to downcast the box to a concrete type. pub fn downcast(self: Box) -> Result, Box> { - let err: Box = self; - ::downcast(err).map_err(|s| unsafe { + let err: Box = self; + ::downcast(err).map_err(|s| unsafe { // reapply the Send+Sync marker - transmute::, Box>(s) + transmute::, Box>(s) }) } } diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 6513d11dd51..03e0d0aa6dd 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -883,7 +883,7 @@ impl Error for IntoStringError { "C string contained non-utf8 bytes" } - fn cause(&self) -> Option<&Error> { + fn cause(&self) -> Option<&dyn Error> { Some(&self.error) } } diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index bdd675e6e2b..02a3ce8b9c4 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -83,7 +83,7 @@ enum Repr { #[derive(Debug)] struct Custom { kind: ErrorKind, - error: Box, + error: Box, } /// A list specifying general categories of I/O error. @@ -250,12 +250,12 @@ impl Error { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(kind: ErrorKind, error: E) -> Error - where E: Into> + where E: Into> { Self::_new(kind, error.into()) } - fn _new(kind: ErrorKind, error: Box) -> Error { + fn _new(kind: ErrorKind, error: Box) -> Error { Error { repr: Repr::Custom(Box::new(Custom { kind, @@ -373,7 +373,7 @@ impl Error { /// } /// ``` #[stable(feature = "io_error_inner", since = "1.3.0")] - pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> { + pub fn get_ref(&self) -> Option<&(dyn error::Error+Send+Sync+'static)> { match self.repr { Repr::Os(..) => None, Repr::Simple(..) => None, @@ -444,7 +444,7 @@ impl Error { /// } /// ``` #[stable(feature = "io_error_inner", since = "1.3.0")] - pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> { + pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error+Send+Sync+'static)> { match self.repr { Repr::Os(..) => None, Repr::Simple(..) => None, @@ -478,7 +478,7 @@ impl Error { /// } /// ``` #[stable(feature = "io_error_inner", since = "1.3.0")] - pub fn into_inner(self) -> Option> { + pub fn into_inner(self) -> Option> { match self.repr { Repr::Os(..) => None, Repr::Simple(..) => None, @@ -551,7 +551,7 @@ impl error::Error for Error { } } - fn cause(&self) -> Option<&error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { match self.repr { Repr::Os(..) => None, Repr::Simple(..) => None, diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 2b4644bd013..85304874848 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1972,7 +1972,7 @@ impl BufRead for Take { } } -fn read_one_byte(reader: &mut Read) -> Option> { +fn read_one_byte(reader: &mut dyn Read) -> Option> { let mut buf = [0]; loop { return match reader.read(&mut buf) { @@ -2081,7 +2081,7 @@ impl std_error::Error for CharsError { CharsError::Other(ref e) => std_error::Error::description(e), } } - fn cause(&self) -> Option<&std_error::Error> { + fn cause(&self) -> Option<&dyn std_error::Error> { match *self { CharsError::NotUtf8 => None, CharsError::Other(ref e) => e.cause(), diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index fce85a200ba..fffe8fc559b 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -21,7 +21,7 @@ use thread::LocalKey; /// Stdout used by print! and println! macros thread_local! { - static LOCAL_STDOUT: RefCell>> = { + static LOCAL_STDOUT: RefCell>> = { RefCell::new(None) } } @@ -624,7 +624,7 @@ impl<'a> fmt::Debug for StderrLock<'a> { with a more general mechanism", issue = "0")] #[doc(hidden)] -pub fn set_panic(sink: Option>) -> Option> { +pub fn set_panic(sink: Option>) -> Option> { use panicking::LOCAL_STDERR; use mem; LOCAL_STDERR.with(move |slot| { @@ -648,7 +648,7 @@ pub fn set_panic(sink: Option>) -> Option> { with a more general mechanism", issue = "0")] #[doc(hidden)] -pub fn set_print(sink: Option>) -> Option> { +pub fn set_print(sink: Option>) -> Option> { use mem; LOCAL_STDOUT.with(move |slot| { mem::replace(&mut *slot.borrow_mut(), sink) @@ -670,7 +670,7 @@ pub fn set_print(sink: Option>) -> Option> { /// However, if the actual I/O causes an error, this function does panic. fn print_to( args: fmt::Arguments, - local_s: &'static LocalKey>>>, + local_s: &'static LocalKey>>>, global_s: fn() -> T, label: &str, ) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index d73cb1f8349..006922383cf 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -221,6 +221,7 @@ // Don't link to std. We are std. #![no_std] +#![deny(bare_trait_objects)] #![deny(missing_docs)] #![deny(missing_debug_implementations)] diff --git a/src/libstd/net/parser.rs b/src/libstd/net/parser.rs index ae5037cc44e..234c5618a06 100644 --- a/src/libstd/net/parser.rs +++ b/src/libstd/net/parser.rs @@ -61,7 +61,7 @@ impl<'a> Parser<'a> { } // Return result of first successful parser - fn read_or(&mut self, parsers: &mut [Box Option + 'static>]) + fn read_or(&mut self, parsers: &mut [Box Option + 'static>]) -> Option { for pf in parsers { if let Some(r) = self.read_atomically(|p: &mut Parser| pf(p)) { diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index 451420ae88a..b8c1c4f9e68 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -421,6 +421,6 @@ pub fn catch_unwind R + UnwindSafe, R>(f: F) -> Result { /// } /// ``` #[stable(feature = "resume_unwind", since = "1.9.0")] -pub fn resume_unwind(payload: Box) -> ! { +pub fn resume_unwind(payload: Box) -> ! { panicking::update_count_then_panic(payload) } diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 46b6cf60705..283fd36af41 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -36,7 +36,7 @@ use sys_common::util; use thread; thread_local! { - pub static LOCAL_STDERR: RefCell>> = { + pub static LOCAL_STDERR: RefCell>> = { RefCell::new(None) } } @@ -64,7 +64,7 @@ extern { #[derive(Copy, Clone)] enum Hook { Default, - Custom(*mut (Fn(&PanicInfo) + 'static + Sync + Send)), + Custom(*mut (dyn Fn(&PanicInfo) + 'static + Sync + Send)), } static HOOK_LOCK: RWLock = RWLock::new(); @@ -104,7 +104,7 @@ static mut HOOK: Hook = Hook::Default; /// panic!("Normal panic"); /// ``` #[stable(feature = "panic_hooks", since = "1.10.0")] -pub fn set_hook(hook: Box) { +pub fn set_hook(hook: Box) { if thread::panicking() { panic!("cannot modify the panic hook from a panicking thread"); } @@ -149,7 +149,7 @@ pub fn set_hook(hook: Box) { /// panic!("Normal panic"); /// ``` #[stable(feature = "panic_hooks", since = "1.10.0")] -pub fn take_hook() -> Box { +pub fn take_hook() -> Box { if thread::panicking() { panic!("cannot modify the panic hook from a panicking thread"); } @@ -197,7 +197,7 @@ fn default_hook(info: &PanicInfo) { let thread = thread_info::current_thread(); let name = thread.as_ref().and_then(|t| t.name()).unwrap_or(""); - let write = |err: &mut ::io::Write| { + let write = |err: &mut dyn (::io::Write)| { let _ = writeln!(err, "thread '{}' panicked at '{}', {}", name, msg, location); @@ -248,7 +248,7 @@ pub fn update_panic_count(amt: isize) -> usize { pub use realstd::rt::update_panic_count; /// Invoke a closure, capturing the cause of an unwinding panic if one occurs. -pub unsafe fn try R>(f: F) -> Result> { +pub unsafe fn try R>(f: F) -> Result> { #[allow(unions_with_drop_fields)] union Data { f: F, @@ -369,12 +369,12 @@ fn continue_panic_fmt(info: &PanicInfo) -> ! { } unsafe impl<'a> BoxMeUp for PanicPayload<'a> { - fn box_me_up(&mut self) -> *mut (Any + Send) { + fn box_me_up(&mut self) -> *mut (dyn Any + Send) { let contents = mem::replace(self.fill(), String::new()); Box::into_raw(Box::new(contents)) } - fn get(&mut self) -> &(Any + Send) { + fn get(&mut self) -> &(dyn Any + Send) { self.fill() } } @@ -419,15 +419,15 @@ pub fn begin_panic(msg: M, file_line_col: &(&'static str, u32, u3 } unsafe impl BoxMeUp for PanicPayload { - fn box_me_up(&mut self) -> *mut (Any + Send) { + fn box_me_up(&mut self) -> *mut (dyn Any + Send) { let data = match self.inner.take() { - Some(a) => Box::new(a) as Box, + Some(a) => Box::new(a) as Box, None => Box::new(()), }; Box::into_raw(data) } - fn get(&mut self) -> &(Any + Send) { + fn get(&mut self) -> &(dyn Any + Send) { match self.inner { Some(ref a) => a, None => &(), @@ -441,7 +441,7 @@ pub fn begin_panic(msg: M, file_line_col: &(&'static str, u32, u3 /// Executes the primary logic for a panic, including checking for recursive /// panics, panic hooks, and finally dispatching to the panic runtime to either /// abort or unwind. -fn rust_panic_with_hook(payload: &mut BoxMeUp, +fn rust_panic_with_hook(payload: &mut dyn BoxMeUp, message: Option<&fmt::Arguments>, file_line_col: &(&str, u32, u32)) -> ! { let (file, line, col) = *file_line_col; @@ -496,17 +496,17 @@ fn rust_panic_with_hook(payload: &mut BoxMeUp, } /// Shim around rust_panic. Called by resume_unwind. -pub fn update_count_then_panic(msg: Box) -> ! { +pub fn update_count_then_panic(msg: Box) -> ! { update_panic_count(1); - struct RewrapBox(Box); + struct RewrapBox(Box); unsafe impl BoxMeUp for RewrapBox { - fn box_me_up(&mut self) -> *mut (Any + Send) { + fn box_me_up(&mut self) -> *mut (dyn Any + Send) { Box::into_raw(mem::replace(&mut self.0, Box::new(()))) } - fn get(&mut self) -> &(Any + Send) { + fn get(&mut self) -> &(dyn Any + Send) { &*self.0 } } @@ -517,9 +517,9 @@ pub fn update_count_then_panic(msg: Box) -> ! { /// A private no-mangle function on which to slap yer breakpoints. #[no_mangle] #[allow(private_no_mangle_fns)] // yes we get it, but we like breakpoints -pub fn rust_panic(mut msg: &mut BoxMeUp) -> ! { +pub fn rust_panic(mut msg: &mut dyn BoxMeUp) -> ! { let code = unsafe { - let obj = &mut msg as *mut &mut BoxMeUp; + let obj = &mut msg as *mut &mut dyn BoxMeUp; __rust_start_panic(obj as usize) }; rtabort!("failed to initiate panic, error {}", code) diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 00051d4487a..39692836866 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -813,13 +813,13 @@ impl fmt::Debug for Output { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let stdout_utf8 = str::from_utf8(&self.stdout); - let stdout_debug: &fmt::Debug = match stdout_utf8 { + let stdout_debug: &dyn fmt::Debug = match stdout_utf8 { Ok(ref str) => str, Err(_) => &self.stdout }; let stderr_utf8 = str::from_utf8(&self.stderr); - let stderr_debug: &fmt::Debug = match stderr_utf8 { + let stderr_debug: &dyn fmt::Debug = match stderr_utf8 { Ok(ref str) => str, Err(_) => &self.stderr }; diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index 8f945470b7e..9e957bd87d7 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -29,7 +29,7 @@ pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count}; // To reduce the generated code of the new `lang_start`, this function is doing // the real work. #[cfg(not(test))] -fn lang_start_internal(main: &(Fn() -> i32 + Sync + ::panic::RefUnwindSafe), +fn lang_start_internal(main: &(dyn Fn() -> i32 + Sync + ::panic::RefUnwindSafe), argc: isize, argv: *const *const u8) -> isize { use panic; use sys; diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 2dd3aebe610..1dc0b1c0042 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -1638,7 +1638,7 @@ impl error::Error for SendError { "sending on a closed channel" } - fn cause(&self) -> Option<&error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { None } } @@ -1681,7 +1681,7 @@ impl error::Error for TrySendError { } } - fn cause(&self) -> Option<&error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { None } } @@ -1709,7 +1709,7 @@ impl error::Error for RecvError { "receiving on a closed channel" } - fn cause(&self) -> Option<&error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { None } } @@ -1742,7 +1742,7 @@ impl error::Error for TryRecvError { } } - fn cause(&self) -> Option<&error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { None } } @@ -1783,7 +1783,7 @@ impl error::Error for RecvTimeoutError { } } - fn cause(&self) -> Option<&error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { None } } diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs index 9310dad9172..a7a284cfb79 100644 --- a/src/libstd/sync/mpsc/select.rs +++ b/src/libstd/sync/mpsc/select.rs @@ -93,7 +93,7 @@ pub struct Handle<'rx, T:Send+'rx> { next: *mut Handle<'static, ()>, prev: *mut Handle<'static, ()>, added: bool, - packet: &'rx (Packet+'rx), + packet: &'rx (dyn Packet+'rx), // due to our fun transmutes, we be sure to place this at the end. (nothing // previous relies on T) diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 7eb7be23128..1c63f99753a 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -301,7 +301,7 @@ impl Once { #[cold] fn call_inner(&'static self, ignore_poisoning: bool, - init: &mut FnMut(bool)) { + init: &mut dyn FnMut(bool)) { let mut state = self.state.load(Ordering::SeqCst); 'outer: loop { diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index b6f63303dc2..44ec872b244 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -28,7 +28,7 @@ pub struct Thread { } impl Thread { - pub unsafe fn new<'a>(stack: usize, p: Box) + pub unsafe fn new<'a>(stack: usize, p: Box) -> io::Result { let p = box p; diff --git a/src/libstd/sys_common/at_exit_imp.rs b/src/libstd/sys_common/at_exit_imp.rs index d268d9ad6f9..b28a4d2f8be 100644 --- a/src/libstd/sys_common/at_exit_imp.rs +++ b/src/libstd/sys_common/at_exit_imp.rs @@ -17,7 +17,7 @@ use ptr; use mem; use sys_common::mutex::Mutex; -type Queue = Vec>; +type Queue = Vec>; // 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 @@ -68,7 +68,7 @@ pub fn cleanup() { } } -pub fn push(f: Box) -> bool { +pub fn push(f: Box) -> 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 61d7ed463dd..6184ba4ded6 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -49,7 +49,7 @@ pub struct Frame { const MAX_NB_FRAMES: usize = 100; /// Prints the current backtrace. -pub fn print(w: &mut Write, format: PrintFormat) -> io::Result<()> { +pub fn print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> { static LOCK: Mutex = Mutex::new(); // Use a lock to prevent mixed output in multithreading context. @@ -62,7 +62,7 @@ pub fn print(w: &mut Write, format: PrintFormat) -> io::Result<()> { } } -fn _print(w: &mut 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(), @@ -177,7 +177,7 @@ pub fn log_enabled() -> Option { /// /// These output functions should now be used everywhere to ensure consistency. /// You may want to also use `output_fileline`. -fn output(w: &mut Write, idx: usize, frame: Frame, +fn output(w: &mut dyn Write, idx: usize, frame: Frame, s: Option<&str>, format: PrintFormat) -> io::Result<()> { // Remove the `17: 0x0 - ` line. if format == PrintFormat::Short && frame.exact_position == ptr::null() { @@ -202,7 +202,7 @@ fn output(w: &mut Write, idx: usize, frame: Frame, /// /// See also `output`. #[allow(dead_code)] -fn output_fileline(w: &mut Write, +fn output_fileline(w: &mut dyn Write, file: &[u8], line: u32, format: PrintFormat) -> io::Result<()> { @@ -254,7 +254,7 @@ fn output_fileline(w: &mut Write, // Note that this demangler isn't quite as fancy as it could be. We have lots // of other information in our symbols like hashes, version, type information, // etc. Additionally, this doesn't handle glue symbols at all. -pub fn demangle(writer: &mut Write, mut s: &str, format: PrintFormat) -> io::Result<()> { +pub fn demangle(writer: &mut dyn Write, mut s: &str, format: PrintFormat) -> io::Result<()> { // During ThinLTO LLVM may import and rename internal symbols, so strip out // those endings first as they're one of the last manglings applied to // symbol names. diff --git a/src/libstd/sys_common/poison.rs b/src/libstd/sys_common/poison.rs index e74c40ae04b..1625efe4a2a 100644 --- a/src/libstd/sys_common/poison.rs +++ b/src/libstd/sys_common/poison.rs @@ -251,7 +251,7 @@ impl Error for TryLockError { } } - fn cause(&self) -> Option<&Error> { + fn cause(&self) -> Option<&dyn Error> { match *self { TryLockError::Poisoned(ref p) => Some(p), _ => None diff --git a/src/libstd/sys_common/thread.rs b/src/libstd/sys_common/thread.rs index da6f58ef6bb..86a5e2b8694 100644 --- a/src/libstd/sys_common/thread.rs +++ b/src/libstd/sys_common/thread.rs @@ -21,7 +21,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)() + Box::from_raw(main as *mut Box)() } pub fn min_stack() -> usize { diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 90f054186d1..cc0ec8a5b4d 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -1175,7 +1175,7 @@ impl fmt::Debug for Thread { /// /// [`Result`]: ../../std/result/enum.Result.html #[stable(feature = "rust1", since = "1.0.0")] -pub type Result = ::result::Result>; +pub type Result = ::result::Result>; // This packet is used to communicate the return value between the child thread // and the parent thread. Memory is shared through the `Arc` within and there's -- cgit 1.4.1-3-g733a5 From b29a6fbabcb425f6e238a00946fb1c9869f657e9 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Tue, 10 Jul 2018 20:52:29 +0200 Subject: Add missing `dyn` for cloudabi, redox, unix and wasm --- src/libstd/sys/cloudabi/thread.rs | 2 +- src/libstd/sys/redox/thread.rs | 2 +- src/libstd/sys/unix/process/process_common.rs | 6 +++--- src/libstd/sys/unix/thread.rs | 2 +- src/libstd/sys/wasm/thread.rs | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs index 5d66936b2a4..8cca47efd22 100644 --- a/src/libstd/sys/cloudabi/thread.rs +++ b/src/libstd/sys/cloudabi/thread.rs @@ -32,7 +32,7 @@ unsafe impl Send for Thread {} unsafe impl Sync for Thread {} impl Thread { - pub unsafe fn new<'a>(stack: usize, p: Box) -> io::Result { + pub unsafe fn new<'a>(stack: usize, p: Box) -> io::Result { let p = box p; let mut native: libc::pthread_t = mem::zeroed(); let mut attr: libc::pthread_attr_t = mem::zeroed(); diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs index 110d46ca3ab..f4177087d77 100644 --- a/src/libstd/sys/redox/thread.rs +++ b/src/libstd/sys/redox/thread.rs @@ -28,7 +28,7 @@ unsafe impl Send for Thread {} unsafe impl Sync for Thread {} impl Thread { - pub unsafe fn new<'a>(_stack: usize, p: Box) -> io::Result { + pub unsafe fn new<'a>(_stack: usize, p: Box) -> io::Result { let p = box p; let id = cvt(syscall::clone(syscall::CLONE_VM | syscall::CLONE_FS | syscall::CLONE_FILES))?; diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index 6396bb3a49e..77f125f3c5b 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -52,7 +52,7 @@ pub struct Command { uid: Option, gid: Option, saw_nul: bool, - closures: Vec io::Result<()> + Send + Sync>>, + closures: Vec io::Result<()> + Send + Sync>>, stdin: Option, stdout: Option, stderr: Option, @@ -155,12 +155,12 @@ impl Command { self.gid } - pub fn get_closures(&mut self) -> &mut Vec io::Result<()> + Send + Sync>> { + pub fn get_closures(&mut self) -> &mut Vec io::Result<()> + Send + Sync>> { &mut self.closures } pub fn before_exec(&mut self, - f: Box io::Result<()> + Send + Sync>) { + f: Box io::Result<()> + Send + Sync>) { self.closures.push(f); } diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 7fdecc9c0c0..e26306c045d 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -49,7 +49,7 @@ unsafe fn pthread_attr_setstacksize(_attr: *mut libc::pthread_attr_t, } impl Thread { - pub unsafe fn new<'a>(stack: usize, p: Box) + pub unsafe fn new<'a>(stack: usize, p: Box) -> io::Result { let p = box p; let mut native: libc::pthread_t = mem::zeroed(); diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs index 728e678a2e8..8173a624211 100644 --- a/src/libstd/sys/wasm/thread.rs +++ b/src/libstd/sys/wasm/thread.rs @@ -19,7 +19,7 @@ pub struct Thread(Void); pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; impl Thread { - pub unsafe fn new<'a>(_stack: usize, _p: Box) + pub unsafe fn new<'a>(_stack: usize, _p: Box) -> io::Result { unsupported() -- cgit 1.4.1-3-g733a5 From a6fa656555583524d3c4e6cde702e1b63578cc44 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Wed, 11 Jul 2018 18:11:53 -0700 Subject: Use fast TLS on Fuchsia --- src/libstd/sys/unix/fast_thread_local.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs index 6cdbe5df75d..d59d800a579 100644 --- a/src/libstd/sys/unix/fast_thread_local.rs +++ b/src/libstd/sys/unix/fast_thread_local.rs @@ -20,7 +20,7 @@ // fallback implementation to use as well. // // Due to rust-lang/rust#18804, make sure this is not generic! -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "fuchsia"))] pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { use libc; use mem; @@ -55,11 +55,6 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { _tlv_atexit(dtor, t); } -// Just use the thread_local fallback implementation, at least until there's -// a more direct implementation. -#[cfg(target_os = "fuchsia")] -pub use sys_common::thread_local::register_dtor_fallback as register_dtor; - pub fn requires_move_before_drop() -> bool { // The macOS implementation of TLS apparently had an odd aspect to it // where the pointer we have may be overwritten while this destructor -- cgit 1.4.1-3-g733a5 From 72e2c00af48ac0c59f5dcae819a6842e8e2029cf Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Fri, 13 Jul 2018 14:25:22 +0900 Subject: Fix redox libstd leftover --- src/libstd/sys/redox/process.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index d0b94e14f54..02bc467541e 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -51,7 +51,7 @@ pub struct Command { uid: Option, gid: Option, saw_nul: bool, - closures: Vec io::Result<()> + Send + Sync>>, + closures: Vec io::Result<()> + Send + Sync>>, stdin: Option, stdout: Option, stderr: Option, @@ -122,7 +122,7 @@ impl Command { } pub fn before_exec(&mut self, - f: Box io::Result<()> + Send + Sync>) { + f: Box io::Result<()> + Send + Sync>) { self.closures.push(f); } -- cgit 1.4.1-3-g733a5 From 49c8ba91c73c97404d3308133594702a2bf48fd1 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Mon, 23 Jul 2018 15:32:57 +0200 Subject: Change single char str patterns to chars --- src/librustc/dep_graph/debug.rs | 2 +- src/librustc/middle/stability.rs | 2 +- src/librustc_mir/util/pretty.rs | 6 +++--- src/librustc_target/abi/mod.rs | 4 ++-- src/libstd/sys/redox/net/mod.rs | 4 ++-- src/libstd/sys/unix/os.rs | 2 +- src/tools/tidy/src/deps.rs | 2 +- src/tools/tidy/src/features.rs | 2 +- src/tools/tidy/src/style.rs | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/librustc/dep_graph/debug.rs b/src/librustc/dep_graph/debug.rs index e56333aba9b..f0e43e78a50 100644 --- a/src/librustc/dep_graph/debug.rs +++ b/src/librustc/dep_graph/debug.rs @@ -40,7 +40,7 @@ impl DepNodeFilter { /// Tests whether `node` meets the filter, returning true if so. pub fn test(&self, node: &DepNode) -> bool { let debug_str = format!("{:?}", node); - self.text.split("&") + self.text.split('&') .map(|s| s.trim()) .all(|f| debug_str.contains(f)) } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index fdcae38fc6a..262a617cb69 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -165,7 +165,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { &attr::Stable {since: stab_since}) = (&stab.rustc_depr, &stab.level) { // Explicit version of iter::order::lt to handle parse errors properly for (dep_v, stab_v) in - dep_since.as_str().split(".").zip(stab_since.as_str().split(".")) { + dep_since.as_str().split('.').zip(stab_since.as_str().split('.')) { if let (Ok(dep_v), Ok(stab_v)) = (dep_v.parse::(), stab_v.parse()) { match dep_v.cmp(&stab_v) { Ordering::Less => { diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 6472e588bc6..0c4edb44272 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -117,8 +117,8 @@ pub fn dump_enabled<'a, 'gcx, 'tcx>( // see notes on #41697 below tcx.item_path_str(source.def_id) }); - filters.split("|").any(|or_filter| { - or_filter.split("&").all(|and_filter| { + filters.split('|').any(|or_filter| { + or_filter.split('&').all(|and_filter| { and_filter == "all" || pass_name.contains(and_filter) || node_path.contains(and_filter) }) }) @@ -388,7 +388,7 @@ struct ExtraComments<'cx, 'gcx: 'tcx, 'tcx: 'cx> { impl<'cx, 'gcx, 'tcx> ExtraComments<'cx, 'gcx, 'tcx> { fn push(&mut self, lines: &str) { - for line in lines.split("\n") { + for line in lines.split('\n') { self.comments.push(line.to_string()); } } diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 57622692426..df09be00c34 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -92,8 +92,8 @@ impl TargetDataLayout { let mut dl = TargetDataLayout::default(); let mut i128_align_src = 64; - for spec in target.data_layout.split("-") { - match &spec.split(":").collect::>()[..] { + for spec in target.data_layout.split('-') { + match &spec.split(':').collect::>()[..] { &["e"] => dl.endian = Endian::Little, &["E"] => dl.endian = Endian::Big, &["a", ref a..] => dl.aggregate_align = align(a, "a")?, diff --git a/src/libstd/sys/redox/net/mod.rs b/src/libstd/sys/redox/net/mod.rs index 0291d7f0e92..67f22231d5f 100644 --- a/src/libstd/sys/redox/net/mod.rs +++ b/src/libstd/sys/redox/net/mod.rs @@ -41,12 +41,12 @@ impl Iterator for LookupHost { pub fn lookup_host(host: &str) -> Result { let mut ip_string = String::new(); File::open("/etc/net/ip")?.read_to_string(&mut ip_string)?; - let ip: Vec = ip_string.trim().split(".").map(|part| part.parse::() + let ip: Vec = ip_string.trim().split('.').map(|part| part.parse::() .unwrap_or(0)).collect(); let mut dns_string = String::new(); File::open("/etc/net/dns")?.read_to_string(&mut dns_string)?; - let dns: Vec = dns_string.trim().split(".").map(|part| part.parse::() + let dns: Vec = dns_string.trim().split('.').map(|part| part.parse::() .unwrap_or(0)).collect(); if ip.len() == 4 && dns.len() == 4 { diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 82d05f78850..addf555eb10 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -564,7 +564,7 @@ fn glibc_version_cstr() -> Option<&'static CStr> { // ignoring any extra dot-separated parts. Otherwise return None. #[cfg(target_env = "gnu")] fn parse_glibc_version(version: &str) -> Option<(usize, usize)> { - let mut parsed_ints = version.split(".").map(str::parse::).fuse(); + let mut parsed_ints = version.split('.').map(str::parse::).fuse(); match (parsed_ints.next(), parsed_ints.next()) { (Some(Ok(major)), Some(Ok(minor))) => Some((major, minor)), _ => None diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 942d27202ec..5105fc4ca4c 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -165,7 +165,7 @@ impl<'a> Crate<'a> { impl<'a> CrateVersion<'a> { /// Returns the struct and whether or not the dep is in-tree pub fn from_str(s: &'a str) -> (Self, bool) { - let mut parts = s.split(" "); + let mut parts = s.split(' '); let name = parts.next().unwrap(); let version = parts.next().unwrap(); let path = parts.next().unwrap(); diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 4c0db993809..c9bc1b9d849 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -257,7 +257,7 @@ pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features { None } else { next_feature_is_rustc_internal = false; - let s = issue_str.split("(").nth(1).unwrap().split(")").nth(0).unwrap(); + let s = issue_str.split('(').nth(1).unwrap().split(')').nth(0).unwrap(); Some(s.parse().unwrap()) }; Some((name.to_owned(), diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index b784a0e4c5f..f2f35f0f586 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -131,7 +131,7 @@ pub fn check(path: &Path, bad: &mut bool) { let skip_length = contents.contains("ignore-tidy-linelength"); let skip_end_whitespace = contents.contains("ignore-tidy-end-whitespace"); let mut trailing_new_lines = 0; - for (i, line) in contents.split("\n").enumerate() { + for (i, line) in contents.split('\n').enumerate() { let mut err = |msg: &str| { tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg); }; -- cgit 1.4.1-3-g733a5 From 1581971635b725764f23be86a618decffb0d754e Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Tue, 24 Jul 2018 05:27:45 +0200 Subject: Stablize Redox Unix Sockets --- src/libstd/sys/redox/ext/net.rs | 42 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/net.rs b/src/libstd/sys/redox/ext/net.rs index 4c5f8574621..2ab77703242 100644 --- a/src/libstd/sys/redox/ext/net.rs +++ b/src/libstd/sys/redox/ext/net.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![unstable(feature = "unix_socket_redox", reason = "new feature", issue="51553")] +#![stable(feature = "unix_socket_redox", since = "1.29")] //! Unix-specific networking functionality @@ -37,6 +37,7 @@ use sys::{cvt, fd::FileDesc, syscall}; /// let addr = socket.local_addr().expect("Couldn't get local address"); /// ``` #[derive(Clone)] +#[stable(feature = "unix_socket_redox", since = "1.29")] pub struct SocketAddr(()); impl SocketAddr { @@ -64,6 +65,7 @@ impl SocketAddr { /// let addr = socket.local_addr().expect("Couldn't get local address"); /// assert_eq!(addr.as_pathname(), None); /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn as_pathname(&self) -> Option<&Path> { None } @@ -91,10 +93,12 @@ impl SocketAddr { /// let addr = socket.local_addr().expect("Couldn't get local address"); /// assert_eq!(addr.is_unnamed(), true); /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn is_unnamed(&self) -> bool { false } } +#[stable(feature = "unix_socket_redox", since = "1.29")] impl fmt::Debug for SocketAddr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "SocketAddr") @@ -115,8 +119,10 @@ impl fmt::Debug for SocketAddr { /// stream.read_to_string(&mut response).unwrap(); /// println!("{}", response); /// ``` +#[stable(feature = "unix_socket_redox", since = "1.29")] pub struct UnixStream(FileDesc); +#[stable(feature = "unix_socket_redox", since = "1.29")] impl fmt::Debug for UnixStream { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut builder = fmt.debug_struct("UnixStream"); @@ -147,6 +153,7 @@ impl UnixStream { /// } /// }; /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn connect>(path: P) -> io::Result { if let Some(s) = path.as_ref().to_str() { cvt(syscall::open(format!("chan:{}", s), syscall::O_CLOEXEC)) @@ -177,6 +184,7 @@ impl UnixStream { /// } /// }; /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn pair() -> io::Result<(UnixStream, UnixStream)> { let server = cvt(syscall::open("chan:", syscall::O_CREAT | syscall::O_CLOEXEC)) .map(FileDesc::new)?; @@ -200,6 +208,7 @@ impl UnixStream { /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UnixStream) } @@ -214,6 +223,7 @@ impl UnixStream { /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// let addr = socket.local_addr().expect("Couldn't get local address"); /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn local_addr(&self) -> io::Result { Err(Error::new(ErrorKind::Other, "UnixStream::local_addr unimplemented on redox")) } @@ -228,6 +238,7 @@ impl UnixStream { /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// let addr = socket.peer_addr().expect("Couldn't get peer address"); /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn peer_addr(&self) -> io::Result { Err(Error::new(ErrorKind::Other, "UnixStream::peer_addr unimplemented on redox")) } @@ -266,6 +277,7 @@ impl UnixStream { /// let err = result.unwrap_err(); /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn set_read_timeout(&self, _timeout: Option) -> io::Result<()> { Err(Error::new(ErrorKind::Other, "UnixStream::set_read_timeout unimplemented on redox")) } @@ -304,6 +316,7 @@ impl UnixStream { /// let err = result.unwrap_err(); /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput) /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn set_write_timeout(&self, _timeout: Option) -> io::Result<()> { Err(Error::new(ErrorKind::Other, "UnixStream::set_write_timeout unimplemented on redox")) } @@ -320,6 +333,7 @@ impl UnixStream { /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0))); /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn read_timeout(&self) -> io::Result> { Err(Error::new(ErrorKind::Other, "UnixStream::read_timeout unimplemented on redox")) } @@ -336,6 +350,7 @@ impl UnixStream { /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0))); /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn write_timeout(&self) -> io::Result> { Err(Error::new(ErrorKind::Other, "UnixStream::write_timeout unimplemented on redox")) } @@ -350,6 +365,7 @@ impl UnixStream { /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } @@ -369,6 +385,7 @@ impl UnixStream { /// /// # Platform specific /// On Redox this always returns None. + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn take_error(&self) -> io::Result> { Ok(None) } @@ -390,11 +407,13 @@ impl UnixStream { /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn shutdown(&self, _how: Shutdown) -> io::Result<()> { Err(Error::new(ErrorKind::Other, "UnixStream::shutdown unimplemented on redox")) } } +#[stable(feature = "unix_socket_redox", since = "1.29")] impl io::Read for UnixStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { io::Read::read(&mut &*self, buf) @@ -406,6 +425,7 @@ impl io::Read for UnixStream { } } +#[stable(feature = "unix_socket_redox", since = "1.29")] impl<'a> io::Read for &'a UnixStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) @@ -417,6 +437,7 @@ impl<'a> io::Read for &'a UnixStream { } } +#[stable(feature = "unix_socket_redox", since = "1.29")] impl io::Write for UnixStream { fn write(&mut self, buf: &[u8]) -> io::Result { io::Write::write(&mut &*self, buf) @@ -427,6 +448,7 @@ impl io::Write for UnixStream { } } +#[stable(feature = "unix_socket_redox", since = "1.29")] impl<'a> io::Write for &'a UnixStream { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) @@ -437,18 +459,21 @@ impl<'a> io::Write for &'a UnixStream { } } +#[stable(feature = "unix_socket_redox", since = "1.29")] impl AsRawFd for UnixStream { fn as_raw_fd(&self) -> RawFd { self.0.raw() } } +#[stable(feature = "unix_socket_redox", since = "1.29")] impl FromRawFd for UnixStream { unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { UnixStream(FileDesc::new(fd)) } } +#[stable(feature = "unix_socket_redox", since = "1.29")] impl IntoRawFd for UnixStream { fn into_raw_fd(self) -> RawFd { self.0.into_raw() @@ -483,8 +508,10 @@ impl IntoRawFd for UnixStream { /// } /// } /// ``` +#[stable(feature = "unix_socket_redox", since = "1.29")] pub struct UnixListener(FileDesc); +#[stable(feature = "unix_socket_redox", since = "1.29")] impl fmt::Debug for UnixListener { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut builder = fmt.debug_struct("UnixListener"); @@ -512,6 +539,7 @@ impl UnixListener { /// } /// }; /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn bind>(path: P) -> io::Result { if let Some(s) = path.as_ref().to_str() { cvt(syscall::open(format!("chan:{}", s), syscall::O_CREAT | syscall::O_CLOEXEC)) @@ -545,6 +573,7 @@ impl UnixListener { /// Err(e) => println!("accept function failed: {:?}", e), /// } /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { self.0.duplicate_path(b"listen").map(|fd| (UnixStream(fd), SocketAddr(()))) } @@ -564,6 +593,7 @@ impl UnixListener { /// /// let listener_copy = listener.try_clone().expect("try_clone failed"); /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UnixListener) } @@ -579,6 +609,7 @@ impl UnixListener { /// /// let addr = listener.local_addr().expect("Couldn't get local address"); /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn local_addr(&self) -> io::Result { Err(Error::new(ErrorKind::Other, "UnixListener::local_addr unimplemented on redox")) } @@ -594,6 +625,7 @@ impl UnixListener { /// /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } @@ -614,6 +646,7 @@ impl UnixListener { /// /// # Platform specific /// On Redox this always returns None. + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn take_error(&self) -> io::Result> { Ok(None) } @@ -649,29 +682,34 @@ impl UnixListener { /// } /// } /// ``` + #[stable(feature = "unix_socket_redox", since = "1.29")] pub fn incoming<'a>(&'a self) -> Incoming<'a> { Incoming { listener: self } } } +#[stable(feature = "unix_socket_redox", since = "1.29")] impl AsRawFd for UnixListener { fn as_raw_fd(&self) -> RawFd { self.0.raw() } } +#[stable(feature = "unix_socket_redox", since = "1.29")] impl FromRawFd for UnixListener { unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { UnixListener(FileDesc::new(fd)) } } +#[stable(feature = "unix_socket_redox", since = "1.29")] impl IntoRawFd for UnixListener { fn into_raw_fd(self) -> RawFd { self.0.into_raw() } } +#[stable(feature = "unix_socket_redox", since = "1.29")] impl<'a> IntoIterator for &'a UnixListener { type Item = io::Result; type IntoIter = Incoming<'a>; @@ -712,10 +750,12 @@ impl<'a> IntoIterator for &'a UnixListener { /// } /// ``` #[derive(Debug)] +#[stable(feature = "unix_socket_redox", since = "1.29")] pub struct Incoming<'a> { listener: &'a UnixListener, } +#[stable(feature = "unix_socket_redox", since = "1.29")] impl<'a> Iterator for Incoming<'a> { type Item = io::Result; -- cgit 1.4.1-3-g733a5 From 66c4dc9769b7ae456fe2960dc5a1e037b2432184 Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Fri, 13 Jul 2018 14:25:22 +0900 Subject: Add missing dyn --- src/liballoc/tests/arc.rs | 6 +++--- src/liballoc/tests/btree/set.rs | 2 +- src/liballoc/tests/lib.rs | 2 +- src/liballoc/tests/rc.rs | 6 +++--- src/libcore/tests/any.rs | 16 +++++++++------ src/libcore/tests/hash/mod.rs | 2 +- src/libcore/tests/intrinsics.rs | 2 +- src/libcore/tests/mem.rs | 4 ++-- src/libcore/tests/option.rs | 2 +- src/libcore/tests/ptr.rs | 20 +++++++++--------- src/libcore/tests/result.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/core.rs | 2 +- src/librustdoc/html/highlight.rs | 4 ++-- src/librustdoc/html/layout.rs | 4 ++-- src/librustdoc/html/render.rs | 2 +- src/librustdoc/test.rs | 2 +- src/libstd/sys/redox/process.rs | 4 ++-- src/tools/compiletest/src/header.rs | 2 +- src/tools/compiletest/src/read2.rs | 6 +++--- src/tools/error_index_generator/main.rs | 36 ++++++++++++++++----------------- src/tools/tidy/src/features.rs | 2 +- src/tools/tidy/src/lib.rs | 4 ++-- 23 files changed, 69 insertions(+), 65 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/liballoc/tests/arc.rs b/src/liballoc/tests/arc.rs index 753873dd294..d90c22a3b18 100644 --- a/src/liballoc/tests/arc.rs +++ b/src/liballoc/tests/arc.rs @@ -18,7 +18,7 @@ fn uninhabited() { a = a.clone(); assert!(a.upgrade().is_none()); - let mut a: Weak = a; // Unsizing + let mut a: Weak = a; // Unsizing a = a.clone(); assert!(a.upgrade().is_none()); } @@ -39,7 +39,7 @@ fn slice() { #[test] fn trait_object() { let a: Arc = Arc::new(4); - let a: Arc = a; // Unsizing + let a: Arc = a; // Unsizing // Exercise is_dangling() with a DST let mut a = Arc::downgrade(&a); @@ -49,7 +49,7 @@ fn trait_object() { let mut b = Weak::::new(); b = b.clone(); assert!(b.upgrade().is_none()); - let mut b: Weak = b; // Unsizing + let mut b: Weak = b; // Unsizing b = b.clone(); assert!(b.upgrade().is_none()); } diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs index 6171b8ba624..0330bda5e32 100644 --- a/src/liballoc/tests/btree/set.rs +++ b/src/liballoc/tests/btree/set.rs @@ -40,7 +40,7 @@ fn test_hash() { } fn check(a: &[i32], b: &[i32], expected: &[i32], f: F) - where F: FnOnce(&BTreeSet, &BTreeSet, &mut FnMut(&i32) -> bool) -> bool + where F: FnOnce(&BTreeSet, &BTreeSet, &mut dyn FnMut(&i32) -> bool) -> bool { let mut set_a = BTreeSet::new(); let mut set_b = BTreeSet::new(); diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 2c361598e89..91bc778ad4c 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -63,7 +63,7 @@ fn test_boxed_hasher() { 5u32.hash(&mut hasher_1); assert_eq!(ordinary_hash, hasher_1.finish()); - let mut hasher_2 = Box::new(DefaultHasher::new()) as Box; + let mut hasher_2 = Box::new(DefaultHasher::new()) as Box; 5u32.hash(&mut hasher_2); assert_eq!(ordinary_hash, hasher_2.finish()); } diff --git a/src/liballoc/tests/rc.rs b/src/liballoc/tests/rc.rs index baa0406acfc..9ec7c831444 100644 --- a/src/liballoc/tests/rc.rs +++ b/src/liballoc/tests/rc.rs @@ -18,7 +18,7 @@ fn uninhabited() { a = a.clone(); assert!(a.upgrade().is_none()); - let mut a: Weak = a; // Unsizing + let mut a: Weak = a; // Unsizing a = a.clone(); assert!(a.upgrade().is_none()); } @@ -39,7 +39,7 @@ fn slice() { #[test] fn trait_object() { let a: Rc = Rc::new(4); - let a: Rc = a; // Unsizing + let a: Rc = a; // Unsizing // Exercise is_dangling() with a DST let mut a = Rc::downgrade(&a); @@ -49,7 +49,7 @@ fn trait_object() { let mut b = Weak::::new(); b = b.clone(); assert!(b.upgrade().is_none()); - let mut b: Weak = b; // Unsizing + let mut b: Weak = b; // Unsizing b = b.clone(); assert!(b.upgrade().is_none()); } diff --git a/src/libcore/tests/any.rs b/src/libcore/tests/any.rs index 2d3e81aa131..a80bf939530 100644 --- a/src/libcore/tests/any.rs +++ b/src/libcore/tests/any.rs @@ -17,7 +17,7 @@ static TEST: &'static str = "Test"; #[test] fn any_referenced() { - let (a, b, c) = (&5 as &Any, &TEST as &Any, &Test as &Any); + let (a, b, c) = (&5 as &dyn Any, &TEST as &dyn Any, &Test as &dyn Any); assert!(a.is::()); assert!(!b.is::()); @@ -34,7 +34,11 @@ fn any_referenced() { #[test] fn any_owning() { - let (a, b, c) = (box 5_usize as Box, box TEST as Box, box Test as Box); + let (a, b, c) = ( + box 5_usize as Box, + box TEST as Box, + box Test as Box, + ); assert!(a.is::()); assert!(!b.is::()); @@ -51,7 +55,7 @@ fn any_owning() { #[test] fn any_downcast_ref() { - let a = &5_usize as &Any; + let a = &5_usize as &dyn Any; match a.downcast_ref::() { Some(&5) => {} @@ -69,9 +73,9 @@ fn any_downcast_mut() { let mut a = 5_usize; let mut b: Box<_> = box 7_usize; - let a_r = &mut a as &mut Any; + let a_r = &mut a as &mut dyn Any; let tmp: &mut usize = &mut *b; - let b_r = tmp as &mut Any; + let b_r = tmp as &mut dyn Any; match a_r.downcast_mut::() { Some(x) => { @@ -113,7 +117,7 @@ fn any_downcast_mut() { #[test] fn any_fixed_vec() { let test = [0_usize; 8]; - let test = &test as &Any; + let test = &test as &dyn Any; assert!(test.is::<[usize; 8]>()); assert!(!test.is::<[usize; 10]>()); } diff --git a/src/libcore/tests/hash/mod.rs b/src/libcore/tests/hash/mod.rs index 8716421b424..85c9d41b65b 100644 --- a/src/libcore/tests/hash/mod.rs +++ b/src/libcore/tests/hash/mod.rs @@ -128,7 +128,7 @@ fn test_custom_state() { fn test_indirect_hasher() { let mut hasher = MyHasher { hash: 0 }; { - let mut indirect_hasher: &mut Hasher = &mut hasher; + let mut indirect_hasher: &mut dyn Hasher = &mut hasher; 5u32.hash(&mut indirect_hasher); } assert_eq!(hasher.hash, 5); diff --git a/src/libcore/tests/intrinsics.rs b/src/libcore/tests/intrinsics.rs index 2b380abf63c..9f3cba26a62 100644 --- a/src/libcore/tests/intrinsics.rs +++ b/src/libcore/tests/intrinsics.rs @@ -22,7 +22,7 @@ fn test_typeid_sized_types() { #[test] fn test_typeid_unsized_types() { trait Z {} - struct X(str); struct Y(Z + 'static); + struct X(str); struct Y(dyn Z + 'static); assert_eq!(TypeId::of::(), TypeId::of::()); assert_eq!(TypeId::of::(), TypeId::of::()); diff --git a/src/libcore/tests/mem.rs b/src/libcore/tests/mem.rs index f55a1c81463..714f2babbdf 100644 --- a/src/libcore/tests/mem.rs +++ b/src/libcore/tests/mem.rs @@ -109,11 +109,11 @@ fn test_transmute() { trait Foo { fn dummy(&self) { } } impl Foo for isize {} - let a = box 100isize as Box; + let a = box 100isize as Box; unsafe { let x: ::core::raw::TraitObject = transmute(a); assert!(*(x.data as *const isize) == 100); - let _x: Box = transmute(x); + let _x: Box = transmute(x); } unsafe { diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs index bc3e61a4f54..324ebf43565 100644 --- a/src/libcore/tests/option.rs +++ b/src/libcore/tests/option.rs @@ -240,7 +240,7 @@ fn test_collect() { assert!(v == None); // test that it does not take more elements than it needs - let mut functions: [Box Option<()>>; 3] = + let mut functions: [Box Option<()>>; 3] = [box || Some(()), box || None, box || panic!()]; let v: Option> = functions.iter_mut().map(|f| (*f)()).collect(); diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs index 31bc1d67768..92160910d8f 100644 --- a/src/libcore/tests/ptr.rs +++ b/src/libcore/tests/ptr.rs @@ -84,16 +84,16 @@ fn test_is_null() { assert!(nms.is_null()); // Pointers to unsized types -- trait objects - let ci: *const ToString = &3; + let ci: *const dyn ToString = &3; assert!(!ci.is_null()); - let mi: *mut ToString = &mut 3; + let mi: *mut dyn ToString = &mut 3; assert!(!mi.is_null()); - let nci: *const ToString = null::(); + let nci: *const dyn ToString = null::(); assert!(nci.is_null()); - let nmi: *mut ToString = null_mut::(); + let nmi: *mut dyn ToString = null_mut::(); assert!(nmi.is_null()); } @@ -140,16 +140,16 @@ fn test_as_ref() { assert_eq!(nms.as_ref(), None); // Pointers to unsized types -- trait objects - let ci: *const ToString = &3; + let ci: *const dyn ToString = &3; assert!(ci.as_ref().is_some()); - let mi: *mut ToString = &mut 3; + let mi: *mut dyn ToString = &mut 3; assert!(mi.as_ref().is_some()); - let nci: *const ToString = null::(); + let nci: *const dyn ToString = null::(); assert!(nci.as_ref().is_none()); - let nmi: *mut ToString = null_mut::(); + let nmi: *mut dyn ToString = null_mut::(); assert!(nmi.as_ref().is_none()); } } @@ -182,10 +182,10 @@ fn test_as_mut() { assert_eq!(nms.as_mut(), None); // Pointers to unsized types -- trait objects - let mi: *mut ToString = &mut 3; + let mi: *mut dyn ToString = &mut 3; assert!(mi.as_mut().is_some()); - let nmi: *mut ToString = null_mut::(); + let nmi: *mut dyn ToString = null_mut::(); assert!(nmi.as_mut().is_none()); } } diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs index d9927ce4487..0616252c82c 100644 --- a/src/libcore/tests/result.rs +++ b/src/libcore/tests/result.rs @@ -81,7 +81,7 @@ fn test_collect() { assert!(v == Err(2)); // test that it does not take more elements than it needs - let mut functions: [Box Result<(), isize>>; 3] = + let mut functions: [Box Result<(), isize>>; 3] = [box || Ok(()), box || Err(1), box || panic!()]; let v: Result, isize> = functions.iter_mut().map(|f| (*f)()).collect(); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 98684b27973..c601f138d0a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -375,7 +375,7 @@ impl fmt::Debug for Item { let fake = MAX_DEF_ID.with(|m| m.borrow().get(&self.def_id.krate) .map(|id| self.def_id >= *id).unwrap_or(false)); - let def_id: &fmt::Debug = if fake { &"**FAKE**" } else { &self.def_id }; + let def_id: &dyn fmt::Debug = if fake { &"**FAKE**" } else { &self.def_id }; fmt.debug_struct("Item") .field("source", &self.source) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 6e1b4589547..4b8dbaf4211 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -55,7 +55,7 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> { /// The stack of module NodeIds up till this point pub mod_ids: RefCell>, pub crate_name: Option, - pub cstore: Rc, + pub cstore: Rc, pub populated_all_crate_impls: Cell, // Note that external items for which `doc(hidden)` applies to are shown as // non-reachable while local items aren't. This is because we're reusing diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 5939d5341e3..6cf9b143373 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -395,7 +395,7 @@ impl Class { fn write_header(class: Option<&str>, id: Option<&str>, - out: &mut Write) + out: &mut dyn Write) -> io::Result<()> { write!(out, "

    ,
         write!(out, "class=\"rust {}\">\n", class.unwrap_or(""))
     }
     
    -fn write_footer(out: &mut Write) -> io::Result<()> {
    +fn write_footer(out: &mut dyn Write) -> io::Result<()> {
         write!(out, "
    \n") } diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 5e93b20ea17..af7c0a04215 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -32,7 +32,7 @@ pub struct Page<'a> { } pub fn render( - dst: &mut io::Write, layout: &Layout, page: &Page, sidebar: &S, t: &T, + dst: &mut dyn io::Write, layout: &Layout, page: &Page, sidebar: &S, t: &T, css_file_extension: bool, themes: &[PathBuf]) -> io::Result<()> { @@ -194,7 +194,7 @@ pub fn render( ) } -pub fn redirect(dst: &mut io::Write, url: &str) -> io::Result<()> { +pub fn redirect(dst: &mut dyn io::Write, url: &str) -> io::Result<()> { //