When working with an arbitrary reader or writer, code that uses vectored
operations may end up being slower than code that copies into a single
buffer when the underlying reader or writer doesn't actually support
vectored operations. These new methods allow you to ask the reader or
witer up front if vectored operations are efficiently supported.
Currently, you have to use some heuristics to guess by e.g. checking if
the read or write only accessed the first buffer. Hyper is one concrete
example of a library that has to do this dynamically:
0eaf304644/src/proto/h1/io.rs (L582-L594)
Standard library support for riscv64gc-unknown-linux-gnu
Add std support for RISC-V 64-bit GNU/Linux and update libc for RISC-V support.
r? @alexcrichton
Redesign the interface to the unikernel HermitCore
We are developing the unikernel HermitCore, where the kernel is written in Rust and is already part of the Rust Standard Library. The interface between the standard library and the kernel based on a small C library. With this pull request, we remove completely the dependency to C and use lld as linker. Currently, the kernel will be linked to the application as static library, which is published at https://github.com/hermitcore/libhermit-rs.
We don’t longer support the C interface to the kernel. Consequently, we remove this part from the Rust Standard Library.
- the old interface between HermitCore and the Rust Standard Library
based on a small C library (newlib)
- remove this interface and call directly the unikernel
- remove the dependency to the HermitCore linker
- use rust-lld as linker
This renames `std::io::IoVec` to `std::io::IoSlice` and
`std::io::IoVecMut` to `std::io::IoSliceMut`, and stabilizes
`std::io::IoSlice`, `std::io::IoSliceMut`,
`std::io::Read::read_vectored`, and `std::io::Write::write_vectored`.
Closes#58452
This commit implements the `{read,write}_vectored` methods on more types
in the standard library, namely:
* `std::fs::File`
* `std::process::ChildStd{in,out,err}`
* `std::io::Std{in,out,err}`
* `std::io::Std{in,out,err}Lock`
* `std::io::Std{in,out,err}Raw`
Where supported the OS implementations hook up to native support,
otherwise it falls back to the already-defaulted implementation.
This commit fills out the `std::fs` module and implementation for WASI.
Not all APIs are implemented, such as permissions-related ones and
`canonicalize`, but all others APIs have been implemented and very
lightly tested so far. We'll eventually want to run a more exhaustive
test suite!
For now the highlights of this commit are:
* The `std::fs::File` type is now backed by `WasiFd`, a raw WASI file
descriptor.
* All APIs in `std::fs` (except permissions/canonicalize) have
implementations for the WASI target.
* A suite of unstable extension traits were added to
`std::os::wasi::fs`. These traits expose the raw filesystem
functionality of WASI, namely `*at` syscalls (opening a file relative
to an already opened one, for example). Additionally metadata only
available on wasi is exposed through these traits.
Perhaps one of the most notable parts is the implementation of
path-taking APIs. WASI actually has no fundamental API that just takes a
path, but rather everything is relative to a previously opened file
descriptor. To allow existing APIs to work (that only take a path) WASI
has a few syscalls to learn about "pre opened" file descriptors by the
runtime. We use these to build a map of existing directory names to file
descriptors, and then when using a path we try to anchor it at an
already-opened file.
This support is very rudimentary though and is intended to be shared
with C since it's likely to be so tricky. For now though the C library
doesn't expose quite an API for us to use, so we implement it for now
and will swap it out as soon as one is available.
A convenience method like fs::copy() should try to prevent pitfalls a
normal user doesn't think about.
In case of an empty umask, setting the file mode early prevents
temporarily world readable or even writeable files,
because the default mode is 0o666.
In case the target is a named pipe or special device node, setting the
file mode can lead to unwanted side effects, like setting permissons on
`/dev/stdout` or for root setting permissions on `/dev/null`.
copy_file_range() returns EINVAL, if the destination is a FIFO/pipe or
a device like "/dev/null", so fallback to io::copy, too.
Use `fcopyfile` on MacOS instead of `copyfile`.
Fixes: https://github.com/rust-lang/rust/issues/26933
Fixed: https://github.com/rust-lang/rust/issues/37885
As a start, the port uses the simplest possible configuration (no jemalloc, abort on panic)
and makes use of existing Unix-specific code wherever possible.
It adds targets for x86_64 (current main HermitCore platform) and aarch64 (HermitCore platform
under development).
Together with the patches to "liblibc" and "llvm", this enables HermitCore applications to be
written in Rust.
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.
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
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.
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
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.
fs: copy: use copy_file_range on Linux
Linux 4.5 introduced a new system call [copy_file_range](http://man7.org/linux/man-pages/man2/copy_file_range.2.html) to copy data from one file to another.
This PR uses the new system call (if available). This has several advantages:
1. No need to constantly copy data from userspace to kernel space, if the buffer is small or the file is large
2. On some filesystems, like BTRFS, the kernel can leverage internal fs mechanisms for huge performance gains
3. Filesystems on the network dont need to copy data between the host and the client machine (they have to in the current read/write implementation)
I have created a small library that also implements the new system call for some huge performance gains here: https://github.com/nicokoch/fastcopy
Benchmark results are in the README