FenrirWolf
6 years ago
committed by
GitHub
101 changed files with 3171 additions and 1383 deletions
@ -0,0 +1,116 @@
@@ -0,0 +1,116 @@
|
||||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Asynchronous values.
|
||||
|
||||
use core::cell::Cell; |
||||
use core::marker::Unpin; |
||||
use core::mem::PinMut; |
||||
use core::option::Option; |
||||
use core::ptr::NonNull; |
||||
use core::task::{self, Poll}; |
||||
use core::ops::{Drop, Generator, GeneratorState}; |
||||
|
||||
#[doc(inline)] |
||||
pub use core::future::*; |
||||
|
||||
/// Wrap a future in a generator.
|
||||
///
|
||||
/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
|
||||
/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
|
||||
#[unstable(feature = "gen_future", issue = "50547")] |
||||
pub fn from_generator<T: Generator<Yield = ()>>(x: T) -> impl Future<Output = T::Return> { |
||||
GenFuture(x) |
||||
} |
||||
|
||||
/// A wrapper around generators used to implement `Future` for `async`/`await` code.
|
||||
#[unstable(feature = "gen_future", issue = "50547")] |
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] |
||||
struct GenFuture<T: Generator<Yield = ()>>(T); |
||||
|
||||
// We rely on the fact that async/await futures are immovable in order to create
|
||||
// self-referential borrows in the underlying generator.
|
||||
impl<T: Generator<Yield = ()>> !Unpin for GenFuture<T> {} |
||||
|
||||
#[unstable(feature = "gen_future", issue = "50547")] |
||||
impl<T: Generator<Yield = ()>> Future for GenFuture<T> { |
||||
type Output = T::Return; |
||||
fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> { |
||||
set_task_cx(cx, || match unsafe { PinMut::get_mut_unchecked(self).0.resume() } { |
||||
GeneratorState::Yielded(()) => Poll::Pending, |
||||
GeneratorState::Complete(x) => Poll::Ready(x), |
||||
}) |
||||
} |
||||
} |
||||
|
||||
thread_local! { |
||||
static TLS_CX: Cell<Option<NonNull<task::Context<'static>>>> = Cell::new(None); |
||||
} |
||||
|
||||
struct SetOnDrop(Option<NonNull<task::Context<'static>>>); |
||||
|
||||
impl Drop for SetOnDrop { |
||||
fn drop(&mut self) { |
||||
TLS_CX.with(|tls_cx| { |
||||
tls_cx.set(self.0.take()); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
#[unstable(feature = "gen_future", issue = "50547")] |
||||
/// Sets the thread-local task context used by async/await futures.
|
||||
pub fn set_task_cx<F, R>(cx: &mut task::Context, f: F) -> R |
||||
where |
||||
F: FnOnce() -> R |
||||
{ |
||||
let old_cx = TLS_CX.with(|tls_cx| { |
||||
tls_cx.replace(NonNull::new( |
||||
cx |
||||
as *mut task::Context |
||||
as *mut () |
||||
as *mut task::Context<'static> |
||||
)) |
||||
}); |
||||
let _reset_cx = SetOnDrop(old_cx); |
||||
f() |
||||
} |
||||
|
||||
#[unstable(feature = "gen_future", issue = "50547")] |
||||
/// Retrieves the thread-local task context used by async/await futures.
|
||||
///
|
||||
/// This function acquires exclusive access to the task context.
|
||||
///
|
||||
/// Panics if no task has been set or if the task context has already been
|
||||
/// retrived by a surrounding call to get_task_cx.
|
||||
pub fn get_task_cx<F, R>(f: F) -> R |
||||
where |
||||
F: FnOnce(&mut task::Context) -> R |
||||
{ |
||||
let cx_ptr = TLS_CX.with(|tls_cx| { |
||||
// Clear the entry so that nested `with_get_cx` calls
|
||||
// will fail or set their own value.
|
||||
tls_cx.replace(None) |
||||
}); |
||||
let _reset_cx = SetOnDrop(cx_ptr); |
||||
|
||||
let mut cx_ptr = cx_ptr.expect( |
||||
"TLS task::Context not set. This is a rustc bug. \ |
||||
Please file an issue on https://github.com/rust-lang/rust.");
|
||||
unsafe { f(cx_ptr.as_mut()) } |
||||
} |
||||
|
||||
#[unstable(feature = "gen_future", issue = "50547")] |
||||
/// Polls a future in the current thread-local task context.
|
||||
pub fn poll_in_task_cx<F>(f: PinMut<F>) -> Poll<F::Output> |
||||
where |
||||
F: Future |
||||
{ |
||||
get_task_cx(|cx| f.poll(cx)) |
||||
} |
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[doc(keyword = "fn")] |
||||
//
|
||||
/// The `fn` keyword.
|
||||
///
|
||||
/// The `fn` keyword is used to declare a function.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```rust
|
||||
/// fn some_function() {
|
||||
/// // code goes in here
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// For more information about functions, take a look at the [Rust Book][book].
|
||||
///
|
||||
/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-03-how-functions-work.html
|
||||
mod fn_keyword { } |
||||
|
||||
#[doc(keyword = "let")] |
||||
//
|
||||
/// The `let` keyword.
|
||||
///
|
||||
/// The `let` keyword is used to declare a variable.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```rust
|
||||
/// # #![allow(unused_assignments)]
|
||||
/// let x = 3; // We create a variable named `x` with the value `3`.
|
||||
/// ```
|
||||
///
|
||||
/// By default, all variables are **not** mutable. If you want a mutable variable,
|
||||
/// you'll have to use the `mut` keyword.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```rust
|
||||
/// # #![allow(unused_assignments)]
|
||||
/// let mut x = 3; // We create a mutable variable named `x` with the value `3`.
|
||||
///
|
||||
/// x += 4; // `x` is now equal to `7`.
|
||||
/// ```
|
||||
///
|
||||
/// For more information about the `let` keyword, take a look at the [Rust Book][book].
|
||||
///
|
||||
/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-01-variables-and-mutability.html
|
||||
mod let_keyword { } |
@ -0,0 +1,389 @@
@@ -0,0 +1,389 @@
|
||||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![stable(feature = "metadata_ext", since = "1.1.0")] |
||||
|
||||
use libc; |
||||
|
||||
use fs::Metadata; |
||||
use sys_common::AsInner; |
||||
|
||||
#[allow(deprecated)] |
||||
use os::hermit::raw; |
||||
|
||||
/// 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
|
||||
/// the raw information returned by the OS.
|
||||
///
|
||||
/// The contents of the returned [`stat`] are **not** consistent across
|
||||
/// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the
|
||||
/// cross-Unix abstractions contained within the raw stat.
|
||||
///
|
||||
/// [`stat`]: ../../../../std/os/linux/raw/struct.stat.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// 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",
|
||||
reason = "deprecated in favor of the accessor \ |
||||
methods of this trait")] |
||||
#[allow(deprecated)] |
||||
fn as_raw_stat(&self) -> &raw::stat; |
||||
|
||||
/// Returns the device ID on which this file resides.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// 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; |
||||
/// Returns the inode number.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// 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; |
||||
/// Returns the file type and mode.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// 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; |
||||
/// Returns the number of hard links to file.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// 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; |
||||
/// Returns the user ID of the file owner.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// 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; |
||||
/// Returns the group ID of the file owner.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// 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; |
||||
/// Returns the device ID that this file represents. Only relevant for special file.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// 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; |
||||
/// Returns the size of the file (if it is a regular file or a symbolic link) in bytes.
|
||||
///
|
||||
/// The size of a symbolic link is the length of the pathname it contains,
|
||||
/// without a terminating null byte.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// 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; |
||||
/// Returns the last access time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// 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; |
||||
/// Returns the last access time, nano seconds part.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// 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; |
||||
/// Returns the last modification time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// 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; |
||||
/// Returns the last modification time, nano seconds part.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// 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; |
||||
/// Returns the last status change time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// 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; |
||||
/// Returns the last status change time, nano seconds part.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// 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; |
||||
/// Returns the "preferred" blocksize for efficient filesystem I/O.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// 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; |
||||
/// Returns the number of blocks allocated to the file, 512-byte units.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// 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; |
||||
} |
||||
|
||||
#[stable(feature = "metadata_ext", since = "1.1.0")] |
||||
impl MetadataExt for Metadata { |
||||
#[allow(deprecated)] |
||||
fn as_raw_stat(&self) -> &raw::stat { |
||||
unsafe { |
||||
&*(self.as_inner().as_inner() as *const libc::stat64 |
||||
as *const raw::stat) |
||||
} |
||||
} |
||||
fn st_dev(&self) -> u64 { |
||||
self.as_inner().as_inner().st_dev as u64 |
||||
} |
||||
fn st_ino(&self) -> u64 { |
||||
self.as_inner().as_inner().st_ino as u64 |
||||
} |
||||
fn st_mode(&self) -> u32 { |
||||
self.as_inner().as_inner().st_mode as u32 |
||||
} |
||||
fn st_nlink(&self) -> u64 { |
||||
self.as_inner().as_inner().st_nlink as u64 |
||||
} |
||||
fn st_uid(&self) -> u32 { |
||||
self.as_inner().as_inner().st_uid as u32 |
||||
} |
||||
fn st_gid(&self) -> u32 { |
||||
self.as_inner().as_inner().st_gid as u32 |
||||
} |
||||
fn st_rdev(&self) -> u64 { |
||||
self.as_inner().as_inner().st_rdev as u64 |
||||
} |
||||
fn st_size(&self) -> u64 { |
||||
self.as_inner().as_inner().st_size as u64 |
||||
} |
||||
fn st_atime(&self) -> i64 { |
||||
self.as_inner().as_inner().st_atime as i64 |
||||
} |
||||
fn st_atime_nsec(&self) -> i64 { |
||||
self.as_inner().as_inner().st_atime_nsec as i64 |
||||
} |
||||
fn st_mtime(&self) -> i64 { |
||||
self.as_inner().as_inner().st_mtime as i64 |
||||
} |
||||
fn st_mtime_nsec(&self) -> i64 { |
||||
self.as_inner().as_inner().st_mtime_nsec as i64 |
||||
} |
||||
fn st_ctime(&self) -> i64 { |
||||
self.as_inner().as_inner().st_ctime as i64 |
||||
} |
||||
fn st_ctime_nsec(&self) -> i64 { |
||||
self.as_inner().as_inner().st_ctime_nsec as i64 |
||||
} |
||||
fn st_blksize(&self) -> u64 { |
||||
self.as_inner().as_inner().st_blksize as u64 |
||||
} |
||||
fn st_blocks(&self) -> u64 { |
||||
self.as_inner().as_inner().st_blocks as u64 |
||||
} |
||||
} |
@ -0,0 +1,16 @@
@@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! HermitCore-specific definitions
|
||||
|
||||
#![stable(feature = "raw_ext", since = "1.1.0")] |
||||
|
||||
pub mod raw; |
||||
pub mod fs; |
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! HermitCore-specific raw type definitions
|
||||
|
||||
#![stable(feature = "raw_ext", since = "1.1.0")] |
||||
#![rustc_deprecated(since = "1.8.0",
|
||||
reason = "these type aliases are no longer supported by \ |
||||
the standard library, the `libc` crate on \ |
||||
crates.io should be used instead for the correct \ |
||||
definitions")] |
||||
#![allow(deprecated)] |
||||
#![allow(missing_debug_implementations)] |
||||
|
||||
#[stable(feature = "pthread_t", since = "1.8.0")] |
||||
pub use libc::pthread_t; |
||||
|
||||
#[doc(inline)] |
||||
#[stable(feature = "raw_ext", since = "1.1.0")] |
||||
pub use libc::{dev_t, mode_t, off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t}; |
@ -0,0 +1,769 @@
@@ -0,0 +1,769 @@
|
||||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![stable(feature = "unix_socket_redox", since = "1.29")] |
||||
|
||||
//! 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)] |
||||
#[stable(feature = "unix_socket_redox", since = "1.29")] |
||||
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_redox", since = "1.29")] |
||||
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);
|
||||
/// ```
|
||||
#[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") |
||||
} |
||||
} |
||||
|
||||
/// 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_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"); |
||||
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_redox", since = "1.29")] |
||||
pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> { |
||||
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_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)?; |
||||
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_redox", since = "1.29")] |
||||
pub fn try_clone(&self) -> io::Result<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");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")] |
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> { |
||||
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_redox", since = "1.29")] |
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> { |
||||
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_redox", since = "1.29")] |
||||
pub fn set_read_timeout(&self, _timeout: Option<Duration>) -> 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_redox", since = "1.29")] |
||||
pub fn set_write_timeout(&self, _timeout: Option<Duration>) -> 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_redox", since = "1.29")] |
||||
pub fn read_timeout(&self) -> io::Result<Option<Duration>> { |
||||
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_redox", since = "1.29")] |
||||
pub fn write_timeout(&self) -> io::Result<Option<Duration>> { |
||||
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_redox", since = "1.29")] |
||||
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_redox", since = "1.29")] |
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> { |
||||
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");
|
||||
/// ```
|
||||
#[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<usize> { |
||||
io::Read::read(&mut &*self, buf) |
||||
} |
||||
|
||||
#[inline] |
||||
unsafe fn initializer(&self) -> Initializer { |
||||
Initializer::nop() |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")] |
||||
impl<'a> io::Read for &'a UnixStream { |
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { |
||||
self.0.read(buf) |
||||
} |
||||
|
||||
#[inline] |
||||
unsafe fn initializer(&self) -> Initializer { |
||||
Initializer::nop() |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")] |
||||
impl io::Write for UnixStream { |
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
||||
io::Write::write(&mut &*self, buf) |
||||
} |
||||
|
||||
fn flush(&mut self) -> io::Result<()> { |
||||
io::Write::flush(&mut &*self) |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")] |
||||
impl<'a> io::Write for &'a UnixStream { |
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
||||
self.0.write(buf) |
||||
} |
||||
|
||||
fn flush(&mut self) -> io::Result<()> { |
||||
Ok(()) |
||||
} |
||||
} |
||||
|
||||
#[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() |
||||
} |
||||
} |
||||
|
||||
/// 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_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"); |
||||
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_redox", since = "1.29")] |
||||
pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> { |
||||
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_redox", since = "1.29")] |
||||
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_redox", since = "1.29")] |
||||
pub fn try_clone(&self) -> io::Result<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");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")] |
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> { |
||||
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_redox", since = "1.29")] |
||||
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_redox", since = "1.29")] |
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> { |
||||
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;
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[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<UnixStream>; |
||||
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_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<UnixStream>; |
||||
|
||||
fn next(&mut self) -> Option<io::Result<UnixStream>> { |
||||
Some(self.listener.accept().map(|s| s.0)) |
||||
} |
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { |
||||
(usize::max_value(), None) |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue