floss: upgrade to rustyline 10
This drops the last transitive dependency on nix-0.20, which frees our
codebase of RUSTSEC-2021-0119.
BUG=b:239449434
TEST=CQ
Change-Id: I81afe69a4297f9d05805da7ea2f2a89c2ddedea6
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/rust_crates/+/4210191
Tested-by: George Burgess <gbiv@chromium.org>
Reviewed-by: Abhishek Pandit-Subedi <abhishekpandit@google.com>
Commit-Queue: George Burgess <gbiv@chromium.org>
diff --git a/cargo-vet/config.toml b/cargo-vet/config.toml
index ca275e0..d870ed2 100644
--- a/cargo-vet/config.toml
+++ b/cargo-vet/config.toml
@@ -711,10 +711,6 @@
criteria = ["safe-to-run", "crypto-safe"]
[[exemptions.fd-lock]]
-version = "2.0.0"
-criteria = "crypto-safe"
-
-[[exemptions.fd-lock]]
version = "3.0.6"
criteria = ["safe-to-run", "crypto-safe"]
@@ -1155,10 +1151,6 @@
criteria = "crypto-safe"
[[exemptions.nix]]
-version = "0.20.0"
-criteria = "crypto-safe"
-
-[[exemptions.nix]]
version = "0.23.1"
criteria = ["safe-to-run", "crypto-safe"]
@@ -1599,10 +1591,6 @@
criteria = ["safe-to-run", "crypto-safe"]
[[exemptions.rustyline]]
-version = "8.2.0"
-criteria = ["safe-to-run", "crypto-safe"]
-
-[[exemptions.rustyline]]
version = "9.1.2"
criteria = ["safe-to-run", "crypto-safe"]
diff --git a/projects/Cargo.lock b/projects/Cargo.lock
index 31787f7..c285ab5 100644
--- a/projects/Cargo.lock
+++ b/projects/Cargo.lock
@@ -1672,16 +1672,6 @@
[[package]]
name = "fd-lock"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0010f02effd88c702318c5dde0463206be67495d0b4d906ba7c0a8f166cc7f06"
-dependencies = [
- "libc",
- "winapi",
-]
-
-[[package]]
-name = "fd-lock"
version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e11dcc7e4d79a8c89b9ab4c6f5c30b1fc4a83c420792da3542fd31179ed5f517"
@@ -1790,7 +1780,7 @@
"quote 1.0.23",
"rand 0.8.5",
"regex",
- "rustyline 8.2.0",
+ "rustyline 10.0.0",
"rustyline-derive 0.4.0",
"serde_json",
"shell-words",
@@ -3191,18 +3181,6 @@
[[package]]
name = "nix"
-version = "0.20.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a"
-dependencies = [
- "bitflags",
- "cc",
- "cfg-if",
- "libc",
-]
-
-[[package]]
-name = "nix"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6"
@@ -4628,30 +4606,6 @@
[[package]]
name = "rustyline"
-version = "8.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbd4eaf7a7738f76c98e4f0395253ae853be3eb018f7b0bb57fe1b6c17e31874"
-dependencies = [
- "bitflags",
- "cfg-if",
- "clipboard-win",
- "dirs-next",
- "fd-lock 2.0.0",
- "libc",
- "log",
- "memchr",
- "nix 0.20.0",
- "radix_trie",
- "scopeguard",
- "smallvec",
- "unicode-segmentation",
- "unicode-width",
- "utf8parse",
- "winapi",
-]
-
-[[package]]
-name = "rustyline"
version = "9.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db7826789c0e25614b03e5a54a0717a86f9ff6e6e5247f92b369472869320039"
@@ -4660,7 +4614,7 @@
"cfg-if",
"clipboard-win",
"dirs-next",
- "fd-lock 3.0.6",
+ "fd-lock",
"libc",
"log",
"memchr",
@@ -4684,7 +4638,7 @@
"cfg-if",
"clipboard-win",
"dirs-next",
- "fd-lock 3.0.6",
+ "fd-lock",
"libc",
"log",
"memchr",
diff --git a/projects/aosp/floss/Cargo.toml b/projects/aosp/floss/Cargo.toml
index 15ba4d5..c0b8d59 100644
--- a/projects/aosp/floss/Cargo.toml
+++ b/projects/aosp/floss/Cargo.toml
@@ -38,7 +38,7 @@
quote = "1.0.8"
rand = "0.8.3"
regex = "1.5"
-rustyline = "8.0"
+rustyline = "10"
rustyline-derive = "0.4.0"
thiserror = "1.0.23"
serde_json = "1.0"
diff --git a/vendor/fd-lock-2.0.0/.cargo-checksum.json b/vendor/fd-lock-2.0.0/.cargo-checksum.json
deleted file mode 100644
index bc108ac..0000000
--- a/vendor/fd-lock-2.0.0/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"b9f736439cc7f70abe65db7971186c052bebec8630db899e4208a12940bd626f","LICENSE-APACHE":"ff49652989754a5d6fd251a1c11e9d0c4a29c1a66715f1b8bfaa3751c56c0cfb","LICENSE-MIT":"759f9e09f3f4c987268743402eda0f0896902188882d379720fcc0d868ed9c76","README.md":"9326b1cc2d309d007fe2615471e3850f67788a1bbb6831732f542bc3f87a291a","src/lib.rs":"8aebe3cc5ab4b3accb9fe77b47813c4519af447c67c9692514f49246b8b210ce","src/unix.rs":"96091c0dfb63da53373cd23292c1da520e73bde6bb8df2ca3905a20c961e1db1","src/windows.rs":"c7baa6f3d455c10fb5361e9570494ccba6abeb7b5e5ff34bb706139d45943e90","tests/test.rs":"b62a6f8041d3f88a01c9351e81af2725e471ba178cec5ed6f4e6801cdb484bc5"},"package":"0010f02effd88c702318c5dde0463206be67495d0b4d906ba7c0a8f166cc7f06"}
\ No newline at end of file
diff --git a/vendor/fd-lock-2.0.0/Cargo.toml b/vendor/fd-lock-2.0.0/Cargo.toml
deleted file mode 100644
index 228e510..0000000
--- a/vendor/fd-lock-2.0.0/Cargo.toml
+++ /dev/null
@@ -1,30 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
-#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
-
-[package]
-edition = "2018"
-name = "fd-lock"
-version = "2.0.0"
-authors = ["Yoshua Wuyts <yoshuawuyts@gmail.com>"]
-description = "Advisory cross-platform lock on a file using a file descriptor to it."
-documentation = "https://docs.rs/fd-lock"
-readme = "README.md"
-keywords = ["file", "fd", "lock", "windows", "unix"]
-categories = ["filesystem", "os", "os::macos-apis", "os::unix-apis", "os::windows-apis"]
-license = "MIT OR Apache-2.0"
-repository = "https://github.com/yoshuawuyts/fd-lock"
-[dependencies.libc]
-version = "0.2.58"
-[dev-dependencies.tempfile]
-version = "3.0.8"
-[target."cfg(windows)".dependencies.winapi]
-version = "0.3.7"
diff --git a/vendor/fd-lock-2.0.0/LICENSE-APACHE b/vendor/fd-lock-2.0.0/LICENSE-APACHE
deleted file mode 100644
index 388f79a..0000000
--- a/vendor/fd-lock-2.0.0/LICENSE-APACHE
+++ /dev/null
@@ -1,190 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- Copyright 2019 Yoshua Wuyts
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/vendor/fd-lock-2.0.0/LICENSE-MIT b/vendor/fd-lock-2.0.0/LICENSE-MIT
deleted file mode 100644
index f26563c..0000000
--- a/vendor/fd-lock-2.0.0/LICENSE-MIT
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2019 Yoshua Wuyts
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/vendor/fd-lock-2.0.0/README.md b/vendor/fd-lock-2.0.0/README.md
deleted file mode 100644
index 2f1d333..0000000
--- a/vendor/fd-lock-2.0.0/README.md
+++ /dev/null
@@ -1,76 +0,0 @@
-# fd-lock
-[![crates.io version][1]][2]
-[![downloads][5]][6] [![docs.rs docs][7]][8]
-
-Advisory cross-platform file locks using file descriptors. Adapted from
-[mafintosh/fd-lock].
-
-Note that advisory lock compliance is opt-in, and can freely be ignored by other
-parties. This means this crate __should never be used for security purposes__,
-but solely to coordinate file access.
-
-[mafintosh/fd-lock]: https://github.com/mafintosh/fd-lock
-
-- [Documentation][8]
-- [Crates.io][2]
-- [Releases][releases]
-
-## Examples
-__Basic usage__
-```rust
-use fd_lock::FdLock;
-use tempfile::tempfile;
-use std::io::prelude::*;
-use std::fs::File;
-
-fn main() -> Result<(), failure::Error> {
- // Lock a file and write to it.
- let mut f = FdLock::new(tempfile()?);
- f.try_lock()?.write_all(b"chashu cat")?;
-
- // Locks can also be held for extended durations.
- let mut f = f.try_lock()?;
- f.write_all(b"nori cat")?;
- f.write_all(b"bird!")?;
- Ok(())
-}
-```
-
-## Installation
-```sh
-$ cargo add fd-lock
-```
-
-## Safety
-This crate uses `unsafe` to interface with `libc` and `winapi`. All invariants
-have been carefully checked, and are manually enforced.
-
-## Contributing
-Want to join us? Check out our ["Contributing" guide][contributing] and take a
-look at some of these issues:
-
-- [Issues labeled "good first issue"][good-first-issue]
-- [Issues labeled "help wanted"][help-wanted]
-
-## References
-- [LockFile function - WDC](https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-lockfile)
-- [flock(2) - Linux Man Page](https://linux.die.net/man/2/flock)
-- [`libc::flock`](https://docs.rs/libc/0.2.58/libc/fn.flock.html)
-- [`winapi::um::fileapi::LockFile`](https://docs.rs/winapi/0.3.7/x86_64-pc-windows-msvc/winapi/um/fileapi/fn.LockFile.html)
-
-## License
-[MIT](./LICENSE-MIT) OR [Apache-2.0](./LICENSE-APACHE)
-
-[1]: https://img.shields.io/crates/v/fd-lock.svg?style=flat-square
-[2]: https://crates.io/crates/fd-lock
-[3]: https://img.shields.io/travis/yoshuawuyts/fd-lock/master.svg?style=flat-square
-[4]: https://travis-ci.org/yoshuawuyts/fd-lock
-[5]: https://img.shields.io/crates/d/fd-lock.svg?style=flat-square
-[6]: https://crates.io/crates/fd-lock
-[7]: https://img.shields.io/badge/docs-latest-blue.svg?style=flat-square
-[8]: https://docs.rs/fd-lock
-
-[releases]: https://github.com/yoshuawuyts/fd-lock/releases
-[contributing]: https://github.com/yoshuawuyts/fd-lock/blob/master.github/CONTRIBUTING.md
-[good-first-issue]: https://github.com/yoshuawuyts/fd-lock/labels/good%20first%20issue
-[help-wanted]: https://github.com/yoshuawuyts/fd-lock/labels/help%20wanted
diff --git a/vendor/fd-lock-2.0.0/src/lib.rs b/vendor/fd-lock-2.0.0/src/lib.rs
deleted file mode 100644
index 1314266..0000000
--- a/vendor/fd-lock-2.0.0/src/lib.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-//! Advisory cross-platform file locks using file descriptors.
-//!
-//! Note that advisory lock compliance is opt-in, and can freely be ignored by other parties. This
-//! means this crate __should not be relied on for security__, but solely used to coordinate file
-//! access.
-//!
-//! ## Example
-//! ```rust
-//! use fd_lock::FdLock;
-//! # use tempfile::tempfile;
-//! # use std::io::{self, prelude::*};
-//! # use std::fs::File;
-//!
-//! # fn main() -> io::Result<()> {
-//! // Lock a file and write to it.
-//! let mut f = FdLock::new(tempfile()?);
-//! f.try_lock()?.write_all(b"chashu cat")?;
-//!
-//! // Locks can also be held for extended durations.
-//! let mut f = f.try_lock()?;
-//! f.write_all(b"nori cat")?;
-//! f.write_all(b"bird!")?;
-//! # Ok(())}
-//! ```
-
-#![forbid(future_incompatible)]
-#![deny(missing_debug_implementations, nonstandard_style)]
-#![warn(
- missing_docs,
- missing_doc_code_examples,
- unreachable_pub,
- rust_2018_idioms
-)]
-
-#[cfg(unix)]
-mod unix;
-
-#[cfg(windows)]
-mod windows;
-
-#[cfg(unix)]
-pub use unix::*;
-#[cfg(windows)]
-pub use windows::*;
diff --git a/vendor/fd-lock-2.0.0/src/unix.rs b/vendor/fd-lock-2.0.0/src/unix.rs
deleted file mode 100644
index a13519b..0000000
--- a/vendor/fd-lock-2.0.0/src/unix.rs
+++ /dev/null
@@ -1,96 +0,0 @@
-use libc::{flock, LOCK_EX, LOCK_NB, LOCK_UN};
-use std::io::{self, Error, ErrorKind};
-use std::ops;
-use std::os::unix::io::AsRawFd;
-
-/// A guard that unlocks the file descriptor when it goes out of scope.
-///
-/// # Panics
-///
-/// Dropping this type may panic if the lock fails to unlock.
-#[derive(Debug)]
-pub struct FdLockGuard<'fdlock, T: AsRawFd> {
- lock: &'fdlock mut FdLock<T>,
-}
-
-impl<T: AsRawFd> ops::Deref for FdLockGuard<'_, T> {
- type Target = T;
-
- #[inline]
- fn deref(&self) -> &Self::Target {
- &self.lock.t
- }
-}
-
-impl<T: AsRawFd> ops::DerefMut for FdLockGuard<'_, T> {
- #[inline]
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.lock.t
- }
-}
-
-impl<T: AsRawFd> Drop for FdLockGuard<'_, T> {
- #[inline]
- fn drop(&mut self) {
- let fd = self.lock.t.as_raw_fd();
- if unsafe { flock(fd, LOCK_UN | LOCK_NB) } != 0 {
- panic!("Could not unlock the file descriptor");
- }
- }
-}
-
-/// A file descriptor lock.
-#[derive(Debug)]
-pub struct FdLock<T: AsRawFd> {
- t: T,
-}
-
-impl<T: AsRawFd> FdLock<T> {
- /// Create a new instance.
- #[inline]
- pub fn new(t: T) -> Self {
- FdLock { t }
- }
-
- /// Acquires a new lock, blocking the current thread until it's able to do so.
- ///
- /// This function will block the local thread until it is available to acquire the lock. Upon
- /// returning, the thread is the only thread with the lock held. An RAII guard is returned to allow
- /// scoped unlock of the lock. When the guard goes out of scope, the lock will be unlocked.
- ///
- /// # Errors
- ///
- /// On Unix this may return an error if the operation was interrupted by a signal handler.
- #[inline]
- pub fn lock(&mut self) -> io::Result<FdLockGuard<'_, T>> {
- let fd = self.t.as_raw_fd();
- match unsafe { flock(fd, LOCK_EX) } {
- 0 => Ok(FdLockGuard { lock: self }),
- _ => Err(Error::last_os_error()),
- }
- }
-
- /// Attempts to acquire an advisory lock.
- ///
- /// Unlike `FdLock::lock` this function will never block, but instead will
- /// return an error if the lock cannot be acquired.
- ///
- /// # Errors
- ///
- /// If the lock is already held and `ErrorKind::WouldBlock` error is
- /// returned. This may also return an error if the operation was interrupted
- /// by a signal handler.
- #[inline]
- pub fn try_lock(&mut self) -> Result<FdLockGuard<'_, T>, Error> {
- let fd = self.t.as_raw_fd();
- match unsafe { flock(fd, LOCK_EX | LOCK_NB) } {
- 0 => Ok(FdLockGuard { lock: self }),
- _ => match Error::last_os_error().kind() {
- ErrorKind::AlreadyExists | ErrorKind::WouldBlock => {
- Err(ErrorKind::WouldBlock.into())
- }
- kind => Err(kind.into()),
- },
- }
- }
-}
diff --git a/vendor/fd-lock-2.0.0/src/windows.rs b/vendor/fd-lock-2.0.0/src/windows.rs
deleted file mode 100644
index 5ee4fbd..0000000
--- a/vendor/fd-lock-2.0.0/src/windows.rs
+++ /dev/null
@@ -1,117 +0,0 @@
-use std::io::{self, Error, ErrorKind};
-use std::mem;
-use std::ops;
-use std::os::windows::io::AsRawHandle;
-
-use winapi::um::fileapi::{LockFile, LockFileEx, UnlockFile};
-use winapi::um::minwinbase::{LOCKFILE_EXCLUSIVE_LOCK, OVERLAPPED};
-
-/// A guard that unlocks the file descriptor when it goes out of scope.
-///
-/// # Panics
-///
-/// Dropping this type may panic if the lock fails to unlock.
-#[derive(Debug)]
-pub struct FdLockGuard<'fdlock, T: AsRawHandle> {
- lock: &'fdlock mut FdLock<T>,
-}
-
-impl<T: AsRawHandle> ops::Deref for FdLockGuard<'_, T> {
- type Target = T;
-
- #[inline]
- fn deref(&self) -> &Self::Target {
- &self.lock.t
- }
-}
-
-impl<T: AsRawHandle> ops::DerefMut for FdLockGuard<'_, T> {
- #[inline]
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.lock.t
- }
-}
-
-impl<T: AsRawHandle> Drop for FdLockGuard<'_, T> {
- #[inline]
- fn drop(&mut self) {
- let handle = self.lock.t.as_raw_handle();
- if unsafe { !UnlockFile(handle, 0, 0, 1, 0) } == 0 {
- panic!("Could not unlock the file descriptor");
- }
- }
-}
-
-/// A file descriptor lock.
-#[derive(Debug)]
-pub struct FdLock<T: AsRawHandle> {
- t: T,
-}
-
-impl<T: AsRawHandle> FdLock<T> {
- /// Create a new instance.
- #[inline]
- pub fn new(t: T) -> Self {
- FdLock { t }
- }
-
- /// Acquires a new lock, blocking the current thread until it's able to do so.
- ///
- /// This function will block the local thread until it is available to acquire the lock. Upon
- /// returning, the thread is the only thread with the lock held. An RAII guard is returned to allow
- /// scoped unlock of the lock. When the guard goes out of scope, the lock will be unlocked.
- ///
- /// # Errors
- ///
- /// On Unix this may return an error if the operation was interrupted by a signal handler.
- #[inline]
- pub fn lock(&mut self) -> Result<FdLockGuard<'_, T>, Error> {
- // See: https://stackoverflow.com/a/9186532, https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-lockfileex
- let handle = self.t.as_raw_handle();
- let overlapped = Overlapped::zero();
- let flags = LOCKFILE_EXCLUSIVE_LOCK;
- match unsafe { LockFileEx(handle, flags, 0, 1, 0, overlapped.raw()) } {
- 0 => Err(ErrorKind::Other.into()),
- _ => Ok(FdLockGuard { lock: self }),
- }
- }
-
- /// Attempts to acquire this lock.
- ///
- /// Unlike `FdLock::lock` this function will never block, but instead will
- /// return an error if the lock cannot be acquired.
- ///
- /// # Errors
- ///
- /// If the lock is already held and `ErrorKind::WouldBlock` error is returned.
- #[inline]
- pub fn try_lock(&mut self) -> io::Result<FdLockGuard<'_, T>> {
- let handle = self.t.as_raw_handle();
- match unsafe { LockFile(handle, 0, 0, 1, 0) } {
- 1 => Ok(FdLockGuard { lock: self }),
- _ => {
- let err = Error::last_os_error();
- Err(Error::new(ErrorKind::WouldBlock, format!("{}", err)))
- }
- }
- }
-}
-
-/// A wrapper around `OVERLAPPED` to provide "rustic" accessors and
-/// initializers.
-struct Overlapped(OVERLAPPED);
-
-impl Overlapped {
- /// Creates a new zeroed out instance of an overlapped I/O tracking state.
- ///
- /// This is suitable for passing to methods which will then later get
- /// notified via an I/O Completion Port.
- fn zero() -> Overlapped {
- Overlapped(unsafe { mem::zeroed() })
- }
-
- /// Gain access to the raw underlying data
- fn raw(&self) -> *mut OVERLAPPED {
- &self.0 as *const _ as *mut _
- }
-}
diff --git a/vendor/fd-lock-2.0.0/tests/test.rs b/vendor/fd-lock-2.0.0/tests/test.rs
deleted file mode 100644
index 8fd7e30..0000000
--- a/vendor/fd-lock-2.0.0/tests/test.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-use fd_lock::FdLock;
-use std::fs::File;
-use std::io::ErrorKind;
-
-use tempfile::tempdir;
-
-#[test]
-fn double_lock() {
- let dir = tempdir().unwrap();
- let path = dir.path().join("lockfile");
-
- let mut l0 = FdLock::new(File::create(&path).unwrap());
- let mut l1 = FdLock::new(File::open(path).unwrap());
-
- let g0 = l0.try_lock().unwrap();
-
- let err = l1.try_lock().unwrap_err();
- assert!(matches!(err.kind(), ErrorKind::WouldBlock));
-
- drop(g0);
-}
diff --git a/vendor/nix-0.20.0/.cargo-checksum.json b/vendor/nix-0.20.0/.cargo-checksum.json
deleted file mode 100644
index 72eb4d1..0000000
--- a/vendor/nix-0.20.0/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"CHANGELOG.md":"3e0a33a313c3d40823d692ce5c08956b4fd3fafa8c3c76427e85619a56e105e2","CONTRIBUTING.md":"7da4f8c2ff8e06850bdd9ebc0a3552419fd21d2c6bb0c6f0719566e263b0a1b9","CONVENTIONS.md":"df0d4fe9fe65af0bfa4723dc7b641d5130087259799e6b404ad63884f79031cb","Cargo.toml":"b675bc0871541506d722a54a6b8ef21de901a142b2221f4da84cbdac84f81a16","LICENSE":"66e3ee1fa7f909ad3c612d556f2a0cdabcd809ad6e66f3b0605015ac64841b70","README.md":"0332325aa2edf9e1cf79e21cbe27d3fdad0996eddccbebf22419bcc5344e94bd","src/dir.rs":"52170e8bfc8c4bc1996db2f5cd5a2aace71beac59e4a0e7c1817fdecbf8bd6a7","src/env.rs":"bc52e80d3fa6c5388e3e23767d214a72f88d2927c5604246016c4cf978bbbeb7","src/errno.rs":"1aab33e5dcab9c6f83e48e452f361840645ce6a434bc13bd8ab9abb0e0ef25c3","src/fcntl.rs":"7f3f95baad70ceb1231b8a647988a8e54292d84176820eb6a9f89d40f309c3a6","src/features.rs":"2cb080da3f26eca2d2e18282a41afec921426423a6354a50b840cf20f3f153f6","src/ifaddrs.rs":"4f19ed3b15f5059c2859958c6aa313d6fa75703e68f8608359ef8e0089508ed3","src/kmod.rs":"873bec7f32e30a552a4fd86d5f884c2b3a0cd73012121dfe1587b508475beb0a","src/lib.rs":"ae1a16e142c47afc3f52a07a2afb2fc013cfd427df955aa42e4bd372c77c49d5","src/macros.rs":"a80227a253bd876fd4069f70ae6e995e6b1a7f9ebe284b68233f86bf289216e1","src/mount.rs":"cde7c59b79a8e535c4d8c57c53d7825384b110be244803b1f895d5a3b97bc72f","src/mqueue.rs":"3520495f6a881a7239fba19e90234f7fc9df6729b6bc150bd2e6664b7c98d6a1","src/net/if_.rs":"928066a6ec473ce565e2323858ff64e179e4b81b80768d830dd29008f2fafb7f","src/net/mod.rs":"577f70170e53d4a6de1abb70bf8f1031ec3e65c0e63ef5fcf05c907125e7ac17","src/poll.rs":"ba635fbed688a165279a9851269310220befd211c8fcf5761d1a62dab39ba52b","src/pty.rs":"7a73ba21b2ec8910f7932e456d2fb097a0553c5fe07717238c58455e3de7b275","src/sched.rs":"2bdb5ce449bc093a8eecdd8964e5d05feee3e7b804e4271e40d674178295df79","src/sys/aio.rs":"bbcc1d8639a9c89c66c00357353dde94d0f48b516b4354ab3d3dcfc16a2e0b56","src/sys/epoll.rs":"a3ace2282e77989e9b927dcdca8ad2070d4fb7710398af0763ea6eb26d431968","src/sys/event.rs":"075e84e5a5d1fd922fbcac8c01c8e7cd7f1a1c1f8f60ede8f7ebc5fe6d5e76ac","src/sys/eventfd.rs":"b5301029e95f77f280cc169bb8aa247352efbb600c749f26e2fffa0474c872bb","src/sys/inotify.rs":"114be3860c9daaee1c781df90b63abb87cd82d677c4470b359bbf0787a25d302","src/sys/ioctl/bsd.rs":"853b50c3539dc4a1284c847f2689fde3dbed5dca7a8599db36193048e030296a","src/sys/ioctl/linux.rs":"642b25d3997518815dea454fa976e9067ad5fe4ed75622e7540e3f0d0c7d320a","src/sys/ioctl/mod.rs":"dd3435e44c42f55a600e40599038bebc7417934dade00113ef0f3b6318bf54de","src/sys/memfd.rs":"35dba6c3eeb4f74edbf86530ba1696d9251495b82b814a36b76e6d2b26490e3c","src/sys/mman.rs":"bdca4a151dc31d27c7435e30a5030ad2edef9dd3ac69a33363454cada8466ca3","src/sys/mod.rs":"b8d7d9e3cb331f1d972699cfbaa54fff34a9f26eaba38b8ee49e84bfeee22bd3","src/sys/personality.rs":"2019e58aa69c5ad68ae060e1b9a399138a2e4742f37a868e2681588963ca8acf","src/sys/pthread.rs":"cfa9ccd6f3b86c0c3fe012773c9c82a7813b298c2f20f8ab629781db627ce56b","src/sys/ptrace/bsd.rs":"feced79575c5dbeaf0a0877ba888761675310b277f477acee820c785e132dbe9","src/sys/ptrace/linux.rs":"34524ad4911d2ef7ec0e21a49e479d6fd91d4ef5c660e0b7e2afa4878b27367a","src/sys/ptrace/mod.rs":"671a6ccac955e75d5998f7e53ffc45ed4c7b6522a0f24a0937d60141f692dd39","src/sys/quota.rs":"4ceb895896bbd0bb67ce98e91dec3bd40c9a7d5936abbe13b74691c6afa07f9f","src/sys/reboot.rs":"1fd26955bc095bd4f8804c850183f527560803cbceaf345c3760c8f32fe1224f","src/sys/select.rs":"02226a733d160701f07d27384f87bf21032f3cc4d5a6214dc61e398dd1606b60","src/sys/sendfile.rs":"110955788e3f5f36a7e563c334c6fe400edfb93d6cb2fdce6b8a79d2e892f8ce","src/sys/signal.rs":"53232ef1165272d109173fbba769cde77f3446050dbdaf36e56c4c0fde084348","src/sys/signalfd.rs":"37704804eb75571d03bbc1c99bd90846ae50ce361cc9998777744f8265d51074","src/sys/socket/addr.rs":"1b5c04140abacf08b56e78fe1fa9a3db784ff49be2a6b5709b38c4497e9e1378","src/sys/socket/mod.rs":"738b7a4d5ac22dbec08fd336f796894f03827ba997aaf94a266fa1fb24d716f6","src/sys/socket/sockopt.rs":"42b335e7a2e2b8cf160506524490bb685bd2488ebff65921aa10f60363ffda7b","src/sys/stat.rs":"a969ae88221a50c89d54f97987d108d3c017339d7eedd66ac7218463d2bb07db","src/sys/statfs.rs":"6bd23f941107dc79ec34dc50516ff5eb18d9fad108ad976796669505692c1582","src/sys/statvfs.rs":"09a7268f3f6f321961e4f25943236fe103fe8c7661ea841f4e71014fda0d8952","src/sys/sysinfo.rs":"1aa6f402bc10689c5dd7ad454ecb60834e2b065dddbd3d87d1daecf88cb2b3ee","src/sys/termios.rs":"1d4ae103e4edf7af1a43cbbea1c48a6ba423ac8ed27bd869071c751063e8f483","src/sys/time.rs":"cc955b6b6647ca1db33ac076780ca6c984200e3cc47df5d836b1528489cdef70","src/sys/timerfd.rs":"51443f37b1dd4b03f16e1b569945f0ae715db4028f69e3ddd6c311db00e67ab3","src/sys/uio.rs":"a25dd7a84135ea50a671a7a06a8989dc9d53d3e755d36cef9f37cdc79a123d9d","src/sys/utsname.rs":"9509a092c837d1700f9f4ac30e4568e5b9b63ad8925a56cd8ad7add05d0ac452","src/sys/wait.rs":"ab18e66acaf161750394d802409ee8c95707dbd68d2fb59c88f7d4ed8936a1be","src/time.rs":"957845f8c689aec3c5dcf1af8bbc274a28ed5a214e4ee31ec8a89ed5eea0d3f1","src/ucontext.rs":"10fdfebcecafa8d1c6cf573a5768adc07b87e9ff52a0bdc2527e77f73608f264","src/unistd.rs":"4d8fecd258448fbfb1f99cc064e9522d299ac92853cbdc4dc4b8b7745771c1b6","test/common/mod.rs":"a26ecf30fc06008bab21d96eabf711bb0c41e8b50fe4c1f35cb2797ef405296c","test/sys/mod.rs":"c6f6a376fca73025bd76043a1739f54d24e856d4d0af9c58cc2b9d730ab87144","test/sys/test_aio.rs":"f21c157a07a29d60b0d68baa78ce24b352a19a35eaced0a792f62fa16d38617f","test/sys/test_aio_drop.rs":"eb086fcebd53ec82359ed7323f039b16ef7abced66b111f4876486fb058476e5","test/sys/test_epoll.rs":"35093d0cb1096a934dfc4f6efc737eadc4bdc2e2134d2a879061374a51b10c97","test/sys/test_inotify.rs":"a4f804bcf414b6635d9863c8534769a609009c451c3476cc839cdc30c439b3b1","test/sys/test_ioctl.rs":"39ddd52b27d942ab1b4018d213a378fb221598febc8fc7759ae5e6f746364396","test/sys/test_lio_listio_resubmit.rs":"29718e5fd04ef041125db4963f518f6f518b50436ea2df91e44c9c6b9418b704","test/sys/test_mman.rs":"b129b1d40d7a6e23cfc10956f9aa689d578a745f82fa267d24c40475063b592c","test/sys/test_pthread.rs":"891726053083bf488655eca1518630b08fa7c5937433fb5e446a9eed181ff7c5","test/sys/test_ptrace.rs":"46e51267cc93e45894a1e5a194563af5fb65a170dca95ad7cf9110520d764703","test/sys/test_select.rs":"7ece285a78cb66852ba8e89cac82c2d4fcff7d17a5f35e282cc52a09f5820daf","test/sys/test_signal.rs":"753f2ccbfcf2c5353a75b1e48d746a07c1949defba515c0ceee589ad1ed0aff6","test/sys/test_signalfd.rs":"2068a028c88395ff51c09e43b18c03d16e2d851f1d26ca1d121cdb5cb050f5c5","test/sys/test_socket.rs":"d70f1d8d5712b9f03110dc24f31607d8d7d95d69a9fa0847d1dc7ab5a2564511","test/sys/test_sockopt.rs":"3334e12322e8b4e7c095ddc4a40a2d0e73a0d3a6e1820a6e0970eb8e1136c6de","test/sys/test_sysinfo.rs":"1e1bea9130fe38ccb07cd0ad7334c7be1e45efc33f7656a5973f8cad7126f225","test/sys/test_termios.rs":"93cd5cc181f1d8cef5c69aa23ddfabbf0480369cffab523e677c81e208998328","test/sys/test_timerfd.rs":"fcada956abd981e4d846da58e5640c5705b16026d47bccd1d603fae765ad10db","test/sys/test_uio.rs":"ae915c03e4f64ce370ae46f5dbe37834dae2849bb9fa7961872cec50f45de1f4","test/sys/test_wait.rs":"1fefed60ea3f9c5d8d4518e1d7a122d50aad44c2bd87873ac9ddc31ecdcc5a39","test/test.rs":"be9c29b8a8c9669b6674746ac8065c828a5d1d40ba41226846fe964310a18188","test/test_clearenv.rs":"45ca548035b3c20ec87314715feaba2be973709a635d85b8cde46fd1d9f1ecd4","test/test_dir.rs":"e0dc7c317871eda3873a5d9df801c2ebb34cd958210c42a15f8dff623f05cae0","test/test_fcntl.rs":"e60c1dde6d0a6fde7a52cf98332e5b96fef5749868f0313cb7082bda7a66adb9","test/test_kmod/hello_mod/Makefile":"0219f7bce0603f97d997fb377ca071966c90333ecc665e78a54dfeb97a9c811b","test/test_kmod/hello_mod/hello.c":"bcac6b19c5bd807e1f3878c15e426acc85785a8ade9840c3bb4d068635c9188c","test/test_kmod/mod.rs":"07f5445812593c994d1c25d5c8669aa3c4b1750f3b8ed2c1ddb1c661809983dc","test/test_mount.rs":"55503e8b28f77b45d755d549375cab34fa3a3cc9b94cbb23cfbd4426c5d9cb9c","test/test_mq.rs":"1020a4eb2f88cc29c59c44ad965d0573fba2beeb4c8986060aac56de99eea63c","test/test_net.rs":"ec6d580b87292519d514b0236bdd5abdd576fcf4835cfe49ed1ddb47c5f1aea3","test/test_nix_path.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","test/test_poll.rs":"6942da37678835c0cc89da3da566ac7ef414983d05d1b05b8ff558249c7113c1","test/test_pty.rs":"56198cb9537ec3409717acecb133a49eb48bfc180c135ff0296974ec466d1171","test/test_ptymaster_drop.rs":"d162510cc96b8b7389d8bc34e097db1c80b84b5070c1d16f15b053ffd20cfa17","test/test_sched.rs":"f8ad92eb554164b0f92428f716db99040186d741cc6e1976f7930f099652f70c","test/test_sendfile.rs":"e0cbabbd34052ccaa03d6555d5631686aa076728f6378ee90f7ecec68f891144","test/test_stat.rs":"9668fc1f894b7f8a60dfddbdaef4bc833463e4e0cf04c1cff7f8c0569a226ad2","test/test_time.rs":"199b1c89d373e9398cca97f83ecd6459c6bd5ba7adca28013d9109d5cbad03f3","test/test_unistd.rs":"9bf047d877fd7c0826a2241737574923c3fd102a6b143b6d9710f52af5655588"},"package":"fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a"}
\ No newline at end of file
diff --git a/vendor/nix-0.20.0/CHANGELOG.md b/vendor/nix-0.20.0/CHANGELOG.md
deleted file mode 100644
index 1297ba7..0000000
--- a/vendor/nix-0.20.0/CHANGELOG.md
+++ /dev/null
@@ -1,1024 +0,0 @@
-# Change Log
-
-All notable changes to this project will be documented in this file.
-This project adheres to [Semantic Versioning](http://semver.org/).
-
-## [0.20.0] - 20 February 2021
-### Added
-
-- Added a `passwd` field to `Group` (#[1338](https://github.com/nix-rust/nix/pull/1338))
-- Added `mremap` (#[1306](https://github.com/nix-rust/nix/pull/1306))
-- Added `personality` (#[1331](https://github.com/nix-rust/nix/pull/1331))
-- Added limited Fuchsia support (#[1285](https://github.com/nix-rust/nix/pull/1285))
-- Added `getpeereid` (#[1342](https://github.com/nix-rust/nix/pull/1342))
-- Implemented `IntoIterator` for `Dir`
- (#[1333](https://github.com/nix-rust/nix/pull/1333)).
-
-### Changed
-
-- Minimum supported Rust version is now 1.40.0.
- ([#1356](https://github.com/nix-rust/nix/pull/1356))
-- i686-apple-darwin has been demoted to Tier 2 support, because it's deprecated
- by Xcode.
- (#[1350](https://github.com/nix-rust/nix/pull/1350))
-- Fixed calling `recvfrom` on an `AddrFamily::Packet` socket
- (#[1344](https://github.com/nix-rust/nix/pull/1344))
-
-### Fixed
-- `TimerFd` now closes the underlying fd on drop.
- ([#1381](https://github.com/nix-rust/nix/pull/1381))
-- Define `*_MAGIC` filesystem constants on Linux s390x
- (#[1372](https://github.com/nix-rust/nix/pull/1372))
-- mqueue, sysinfo, timespec, statfs, test_ptrace_syscall() on x32
- (#[1366](https://github.com/nix-rust/nix/pull/1366))
-
-### Removed
-
-- `Dir`, `SignalFd`, and `PtyMaster` are no longer `Clone`.
- (#[1382](https://github.com/nix-rust/nix/pull/1382))
-- Removed `SockLevel`, which hasn't been used for a few years
- (#[1362](https://github.com/nix-rust/nix/pull/1362))
-- Removed both `Copy` and `Clone` from `TimerFd`.
- ([#1381](https://github.com/nix-rust/nix/pull/1381))
-
-## [0.19.1] - 28 November 2020
-### Fixed
-- Fixed bugs in `recvmmsg`.
- (#[1341](https://github.com/nix-rust/nix/pull/1341))
-
-## [0.19.0] - 6 October 2020
-### Added
-- Added Netlink protocol families to the `SockProtocol` enum
- (#[1289](https://github.com/nix-rust/nix/pull/1289))
-- Added `clock_gettime`, `clock_settime`, `clock_getres`,
- `clock_getcpuclockid` functions and `ClockId` struct.
- (#[1281](https://github.com/nix-rust/nix/pull/1281))
-- Added wrapper functions for `PTRACE_SYSEMU` and `PTRACE_SYSEMU_SINGLESTEP`.
- (#[1300](https://github.com/nix-rust/nix/pull/1300))
-- Add support for Vsock on Android rather than just Linux.
- (#[1301](https://github.com/nix-rust/nix/pull/1301))
-- Added `TCP_KEEPCNT` and `TCP_KEEPINTVL` TCP keepalive options.
- (#[1283](https://github.com/nix-rust/nix/pull/1283))
-### Changed
-- Expose `SeekData` and `SeekHole` on all Linux targets
- (#[1284](https://github.com/nix-rust/nix/pull/1284))
-- Changed unistd::{execv,execve,execvp,execvpe,fexecve,execveat} to take both `&[&CStr]` and `&[CString]` as its list argument(s).
- (#[1278](https://github.com/nix-rust/nix/pull/1278))
-- Made `unistd::fork` an unsafe funtion, bringing it in line with [libstd's decision](https://github.com/rust-lang/rust/pull/58059).
- (#[1293](https://github.com/nix-rust/nix/pull/1293))
-### Fixed
-### Removed
-
-## [0.18.0] - 26 July 2020
-### Added
-- Added `fchown(2)` wrapper.
- (#[1257](https://github.com/nix-rust/nix/pull/1257))
-- Added support on linux systems for `MAP_HUGE_`_`SIZE`_ family of flags.
- (#[1211](https://github.com/nix-rust/nix/pull/1211))
-- Added support for `F_OFD_*` `fcntl` commands on Linux and Android.
- (#[1195](https://github.com/nix-rust/nix/pull/1195))
-- Added `env::clearenv()`: calls `libc::clearenv` on platforms
- where it's available, and clears the environment of all variables
- via `std::env::vars` and `std::env::remove_var` on others.
- (#[1185](https://github.com/nix-rust/nix/pull/1185))
-- `FsType` inner value made public.
- (#[1187](https://github.com/nix-rust/nix/pull/1187))
-- Added `unistd::setfsuid` and `unistd::setfsgid` to set the user or group
- identity for filesystem checks per-thread.
- (#[1163](https://github.com/nix-rust/nix/pull/1163))
-- Derived `Ord`, `PartialOrd` for `unistd::Pid` (#[1189](https://github.com/nix-rust/nix/pull/1189))
-- Added `select::FdSet::fds` method to iterate over file descriptors in a set.
- ([#1207](https://github.com/nix-rust/nix/pull/1207))
-- Added support for UDP generic segmentation offload (GSO) and generic
- receive offload (GRO) ([#1209](https://github.com/nix-rust/nix/pull/1209))
-- Added support for `sendmmsg` and `recvmmsg` calls
- (#[1208](https://github.com/nix-rust/nix/pull/1208))
-- Added support for `SCM_CREDS` messages (`UnixCredentials`) on FreeBSD/DragonFly
- (#[1216](https://github.com/nix-rust/nix/pull/1216))
-- Added `BindToDevice` socket option (sockopt) on Linux
- (#[1233](https://github.com/nix-rust/nix/pull/1233))
-- Added `EventFilter` bitflags for `EV_DISPATCH` and `EV_RECEIPT` on OpenBSD.
- (#[1252](https://github.com/nix-rust/nix/pull/1252))
-- Added support for `Ipv4PacketInfo` and `Ipv6PacketInfo` to `ControlMessage`.
- (#[1222](https://github.com/nix-rust/nix/pull/1222))
-- `CpuSet` and `UnixCredentials` now implement `Default`.
- (#[1244](https://github.com/nix-rust/nix/pull/1244))
-- Added `unistd::ttyname`
- (#[1259](https://github.com/nix-rust/nix/pull/1259))
-- Added support for `Ipv4PacketInfo` and `Ipv6PacketInfo` to `ControlMessage` for iOS and Android.
- (#[1265](https://github.com/nix-rust/nix/pull/1265))
-- Added support for `TimerFd`.
- (#[1261](https://github.com/nix-rust/nix/pull/1261))
-
-### Changed
-- Changed `fallocate` return type from `c_int` to `()` (#[1201](https://github.com/nix-rust/nix/pull/1201))
-- Enabled `sys::ptrace::setregs` and `sys::ptrace::getregs` on x86_64-unknown-linux-musl target
- (#[1198](https://github.com/nix-rust/nix/pull/1198))
-- On Linux, `ptrace::write` is now an `unsafe` function. Caveat programmer.
- (#[1245](https://github.com/nix-rust/nix/pull/1245))
-- `execv`, `execve`, `execvp` and `execveat` in `::nix::unistd` and `reboot` in
- `::nix::sys::reboot` now return `Result<Infallible>` instead of `Result<Void>` (#[1239](https://github.com/nix-rust/nix/pull/1239))
-- `sys::socket::sockaddr_storage_to_addr` is no longer `unsafe`. So is
- `offset_of!`.
-- `sys::socket::sockaddr_storage_to_addr`, `offset_of!`, and `Errno::clear` are
- no longer `unsafe`.
-- `SockAddr::as_ffi_pair`,`sys::socket::sockaddr_storage_to_addr`, `offset_of!`,
- and `Errno::clear` are no longer `unsafe`.
- (#[1244](https://github.com/nix-rust/nix/pull/1244))
-- Several `Inotify` methods now take `self` by value instead of by reference
- (#[1244](https://github.com/nix-rust/nix/pull/1244))
-- `nix::poll::ppoll`: `timeout` parameter is now optional, None is equivalent for infinite timeout.
-
-### Fixed
-
-- Fixed `getsockopt`. The old code produced UB which triggers a panic with
- Rust 1.44.0.
- (#[1214](https://github.com/nix-rust/nix/pull/1214))
-
-- Fixed a bug in nix::unistd that would result in an infinite loop
- when a group or user lookup required a buffer larger than
- 16KB. (#[1198](https://github.com/nix-rust/nix/pull/1198))
-- Fixed unaligned casting of `cmsg_data` to `af_alg_iv` (#[1206](https://github.com/nix-rust/nix/pull/1206))
-- Fixed `readlink`/`readlinkat` when reading symlinks longer than `PATH_MAX` (#[1231](https://github.com/nix-rust/nix/pull/1231))
-- `PollFd`, `EpollEvent`, `IpMembershipRequest`, `Ipv6MembershipRequest`,
- `TimeVal`, and `IoVec` are now `repr(transparent)`. This is required for
- correctness's sake across all architectures and compilers, though now bugs
- have been reported so far.
- (#[1243](https://github.com/nix-rust/nix/pull/1243))
-- Fixed unaligned pointer read in `Inotify::read_events`.
- (#[1244](https://github.com/nix-rust/nix/pull/1244))
-
-### Removed
-
-- Removed `sys::socket::addr::from_libc_sockaddr` from the public API.
- (#[1215](https://github.com/nix-rust/nix/pull/1215))
-- Removed `sys::termios::{get_libc_termios, get_libc_termios_mut, update_wrapper`
- from the public API. These were previously hidden in the docs but still usable
- by downstream.
- (#[1235](https://github.com/nix-rust/nix/pull/1235))
-
-- Nix no longer implements `NixPath` for `Option<P> where P: NixPath`. Most
- Nix functions that accept `NixPath` arguments can't do anything useful with
- `None`. The exceptions (`mount` and `quotactl_sync`) already take explicitly
- optional arguments.
- (#[1242](https://github.com/nix-rust/nix/pull/1242))
-
-- Removed `unistd::daemon` and `unistd::pipe2` on OSX and ios
- (#[1255](https://github.com/nix-rust/nix/pull/1255))
-
-- Removed `sys::event::FilterFlag::NOTE_EXIT_REPARENTED` and
- `sys::event::FilterFlag::NOTE_REAP` on OSX and ios.
- (#[1255](https://github.com/nix-rust/nix/pull/1255))
-
-- Removed `sys::ptrace::ptrace` on Android and Linux.
- (#[1255](https://github.com/nix-rust/nix/pull/1255))
-
-- Dropped support for powerpc64-unknown-linux-gnu
- (#[1266](https://github.com/nix-rust/nix/pull/1268))
-
-## [0.17.0] - 3 February 2020
-### Added
-- Add `CLK_TCK` to `SysconfVar`
- (#[1177](https://github.com/nix-rust/nix/pull/1177))
-### Changed
-### Fixed
-### Removed
-- Removed deprecated Error::description from error types
- (#[1175](https://github.com/nix-rust/nix/pull/1175))
-
-## [0.16.1] - 23 December 2019
-### Added
-### Changed
-### Fixed
-
-- Fixed the build for OpenBSD
- (#[1168](https://github.com/nix-rust/nix/pull/1168))
-
-### Removed
-
-## [0.16.0] - 1 December 2019
-### Added
-- Added `ptrace::seize()`: similar to `attach()` on Linux
- but with better-defined semantics.
- (#[1154](https://github.com/nix-rust/nix/pull/1154))
-
-- Added `Signal::as_str()`: returns signal name as `&'static str`
- (#[1138](https://github.com/nix-rust/nix/pull/1138))
-
-- Added `posix_fallocate`.
- ([#1105](https://github.com/nix-rust/nix/pull/1105))
-
-- Implemented `Default` for `FdSet`
- ([#1107](https://github.com/nix-rust/nix/pull/1107))
-
-- Added `NixPath::is_empty`.
- ([#1107](https://github.com/nix-rust/nix/pull/1107))
-
-- Added `mkfifoat`
- ([#1133](https://github.com/nix-rust/nix/pull/1133))
-
-- Added `User::from_uid`, `User::from_name`, `User::from_gid` and
- `Group::from_name`,
- ([#1139](https://github.com/nix-rust/nix/pull/1139))
-
-- Added `linkat`
- ([#1101](https://github.com/nix-rust/nix/pull/1101))
-
-- Added `sched_getaffinity`.
- ([#1148](https://github.com/nix-rust/nix/pull/1148))
-
-- Added optional `Signal` argument to `ptrace::{detach, syscall}` for signal
- injection. ([#1083](https://github.com/nix-rust/nix/pull/1083))
-
-### Changed
-- `sys::termios::BaudRate` now implements `TryFrom<speed_t>` instead of
- `From<speed_t>`. The old `From` implementation would panic on failure.
- ([#1159](https://github.com/nix-rust/nix/pull/1159))
-
-- `sys::socket::ControlMessage::ScmCredentials` and
- `sys::socket::ControlMessageOwned::ScmCredentials` now wrap `UnixCredentials`
- rather than `libc::ucred`.
- ([#1160](https://github.com/nix-rust/nix/pull/1160))
-
-- `sys::socket::recvmsg` now takes a plain `Vec` instead of a `CmsgBuffer`
- implementor. If you were already using `cmsg_space!`, then you needn't worry.
- ([#1156](https://github.com/nix-rust/nix/pull/1156))
-
-- `sys::socket::recvfrom` now returns
- `Result<(usize, Option<SockAddr>)>` instead of `Result<(usize, SockAddr)>`.
- ([#1145](https://github.com/nix-rust/nix/pull/1145))
-
-- `Signal::from_c_int` has been replaced by `Signal::try_from`
- ([#1113](https://github.com/nix-rust/nix/pull/1113))
-
-- Changed `readlink` and `readlinkat` to return `OsString`
- ([#1109](https://github.com/nix-rust/nix/pull/1109))
-
- ```rust
- # use nix::fcntl::{readlink, readlinkat};
- // the buffer argument of `readlink` and `readlinkat` has been removed,
- // and the return value is now an owned type (`OsString`).
- // Existing code can be updated by removing the buffer argument
- // and removing any clone or similar operation on the output
-
- // old code `readlink(&path, &mut buf)` can be replaced with the following
- let _: OsString = readlink(&path);
-
- // old code `readlinkat(dirfd, &path, &mut buf)` can be replaced with the following
- let _: OsString = readlinkat(dirfd, &path);
- ```
-
-- Minimum supported Rust version is now 1.36.0.
- ([#1108](https://github.com/nix-rust/nix/pull/1108))
-
-- `Ipv4Addr::octets`, `Ipv4Addr::to_std`, `Error::as_errno`,
- `ForkResult::is_child`, `ForkResult::is_parent`, `Gid::as_raw`,
- `Uid::is_root`, `Uid::as_raw`, `Pid::as_raw`, and `PollFd::revents` now take
- `self` by value.
- ([#1107](https://github.com/nix-rust/nix/pull/1107))
-
-- Type `&CString` for parameters of `exec(v|ve|vp|vpe|veat)` are changed to `&CStr`.
- ([#1121](https://github.com/nix-rust/nix/pull/1121))
-
-### Fixed
-- Fix length of abstract socket addresses
- ([#1120](https://github.com/nix-rust/nix/pull/1120))
-
-- Fix initialization of msghdr in recvmsg/sendmsg when built with musl
- ([#1136](https://github.com/nix-rust/nix/pull/1136))
-
-### Removed
-- Remove the deprecated `CmsgSpace`.
- ([#1156](https://github.com/nix-rust/nix/pull/1156))
-
-## [0.15.0] - 10 August 2019
-### Added
-- Added `MSG_WAITALL` to `MsgFlags` in `sys::socket`.
- ([#1079](https://github.com/nix-rust/nix/pull/1079))
-- Implemented `Clone`, `Copy`, `Debug`, `Eq`, `Hash`, and `PartialEq` for most
- types that support them. ([#1035](https://github.com/nix-rust/nix/pull/1035))
-- Added `copy_file_range` wrapper
- ([#1069](https://github.com/nix-rust/nix/pull/1069))
-- Add `mkdirat`.
- ([#1084](https://github.com/nix-rust/nix/pull/1084))
-- Add `posix_fadvise`.
- ([#1089](https://github.com/nix-rust/nix/pull/1089))
-- Added `AF_VSOCK` to `AddressFamily`.
- ([#1091](https://github.com/nix-rust/nix/pull/1091))
-- Add `unlinkat`
- ([#1058](https://github.com/nix-rust/nix/pull/1058))
-- Add `renameat`.
- ([#1097](https://github.com/nix-rust/nix/pull/1097))
-
-### Changed
-- Support for `ifaddrs` now present when building for Android.
- ([#1077](https://github.com/nix-rust/nix/pull/1077))
-- Minimum supported Rust version is now 1.31.0
- ([#1035](https://github.com/nix-rust/nix/pull/1035))
- ([#1095](https://github.com/nix-rust/nix/pull/1095))
-- Now functions `statfs()` and `fstatfs()` return result with `Statfs` wrapper
- ([#928](https://github.com/nix-rust/nix/pull/928))
-
-### Fixed
-- Enabled `sched_yield` for all nix hosts.
- ([#1090](https://github.com/nix-rust/nix/pull/1090))
-
-### Removed
-
-## [0.14.1] - 2019-06-06
-### Added
-- Macros exported by `nix` may now be imported via `use` on the Rust 2018
- edition without importing helper macros on Linux targets.
- ([#1066](https://github.com/nix-rust/nix/pull/1066))
-
- For example, in Rust 2018, the `ioctl_read_bad!` macro can now be imported
- without importing the `convert_ioctl_res!` macro.
-
- ```rust
- use nix::ioctl_read_bad;
-
- ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios);
- ```
-
-### Changed
-- Changed some public types from reexports of libc types like `uint32_t` to the
- native equivalents like `u32.`
- ([#1072](https://github.com/nix-rust/nix/pull/1072/commits))
-
-### Fixed
-- Fix the build on Android and Linux/mips with recent versions of libc.
- ([#1072](https://github.com/nix-rust/nix/pull/1072/commits))
-
-### Removed
-
-## [0.14.0] - 2019-05-21
-### Added
-- Add IP_RECVIF & IP_RECVDSTADDR. Enable IP_PKTINFO and IP6_PKTINFO on netbsd/openbsd.
- ([#1002](https://github.com/nix-rust/nix/pull/1002))
-- Added `inotify_init1`, `inotify_add_watch` and `inotify_rm_watch` wrappers for
- Android and Linux. ([#1016](https://github.com/nix-rust/nix/pull/1016))
-- Add `ALG_SET_IV`, `ALG_SET_OP` and `ALG_SET_AEAD_ASSOCLEN` control messages and `AF_ALG`
- socket types on Linux and Android ([#1031](https://github.com/nix-rust/nix/pull/1031))
-- Add killpg
- ([#1034](https://github.com/nix-rust/nix/pull/1034))
-- Added ENOTSUP errno support for Linux and Android.
- ([#969](https://github.com/nix-rust/nix/pull/969))
-- Add several errno constants from OpenBSD 6.2
- ([#1036](https://github.com/nix-rust/nix/pull/1036))
-- Added `from_std` and `to_std` methods for `sys::socket::IpAddr`
- ([#1043](https://github.com/nix-rust/nix/pull/1043))
-- Added `nix::unistd:seteuid` and `nix::unistd::setegid` for those platforms that do
- not support `setresuid` nor `setresgid` respectively.
- ([#1044](https://github.com/nix-rust/nix/pull/1044))
-- Added a `access` wrapper
- ([#1045](https://github.com/nix-rust/nix/pull/1045))
-- Add `forkpty`
- ([#1042](https://github.com/nix-rust/nix/pull/1042))
-- Add `sched_yield`
- ([#1050](https://github.com/nix-rust/nix/pull/1050))
-
-### Changed
-- `PollFd` event flags renamed to `PollFlags` ([#1024](https://github.com/nix-rust/nix/pull/1024/))
-- `recvmsg` now returns an Iterator over `ControlMessageOwned` objects rather
- than `ControlMessage` objects. This is sadly not backwards-compatible. Fix
- code like this:
- ```rust
- if let ControlMessage::ScmRights(&fds) = cmsg {
- ```
-
- By replacing it with code like this:
- ```rust
- if let ControlMessageOwned::ScmRights(fds) = cmsg {
- ```
- ([#1020](https://github.com/nix-rust/nix/pull/1020))
-- Replaced `CmsgSpace` with the `cmsg_space` macro.
- ([#1020](https://github.com/nix-rust/nix/pull/1020))
-
-### Fixed
-- Fixed multiple bugs when using `sendmsg` and `recvmsg` with ancillary control messages
- ([#1020](https://github.com/nix-rust/nix/pull/1020))
-- Macros exported by `nix` may now be imported via `use` on the Rust 2018
- edition without importing helper macros for BSD targets.
- ([#1041](https://github.com/nix-rust/nix/pull/1041))
-
- For example, in Rust 2018, the `ioctl_read_bad!` macro can now be imported
- without importing the `convert_ioctl_res!` macro.
-
- ```rust
- use nix::ioctl_read_bad;
-
- ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios);
- ```
-
-### Removed
-- `Daemon`, `NOTE_REAP`, and `NOTE_EXIT_REPARENTED` are now deprecated on OSX
- and iOS.
- ([#1033](https://github.com/nix-rust/nix/pull/1033))
-- `PTRACE_GETREGS`, `PTRACE_SETREGS`, `PTRACE_GETFPREGS`, and
- `PTRACE_SETFPREGS` have been removed from some platforms where they never
- should've been defined in the first place.
- ([#1055](https://github.com/nix-rust/nix/pull/1055))
-
-## [0.13.0] - 2019-01-15
-### Added
-- Added PKTINFO(V4) & V6PKTINFO cmsg support - Android/FreeBSD/iOS/Linux/MacOS.
- ([#990](https://github.com/nix-rust/nix/pull/990))
-- Added support of CString type in `setsockopt`.
- ([#972](https://github.com/nix-rust/nix/pull/972))
-- Added option `TCP_CONGESTION` in `setsockopt`.
- ([#972](https://github.com/nix-rust/nix/pull/972))
-- Added `symlinkat` wrapper.
- ([#997](https://github.com/nix-rust/nix/pull/997))
-- Added `ptrace::{getregs, setregs}`.
- ([#1010](https://github.com/nix-rust/nix/pull/1010))
-- Added `nix::sys::signal::signal`.
- ([#817](https://github.com/nix-rust/nix/pull/817))
-- Added an `mprotect` wrapper.
- ([#991](https://github.com/nix-rust/nix/pull/991))
-
-### Changed
-### Fixed
-- `lutimes` never worked on OpenBSD as it is not implemented on OpenBSD. It has
- been removed. ([#1000](https://github.com/nix-rust/nix/pull/1000))
-- `fexecve` never worked on NetBSD or on OpenBSD as it is not implemented on
- either OS. It has been removed. ([#1000](https://github.com/nix-rust/nix/pull/1000))
-
-### Removed
-
-## [0.12.0] 2018-11-28
-
-### Added
-- Added `FromStr` and `Display` impls for `nix::sys::Signal`
- ([#884](https://github.com/nix-rust/nix/pull/884))
-- Added a `sync` wrapper.
- ([#961](https://github.com/nix-rust/nix/pull/961))
-- Added a `sysinfo` wrapper.
- ([#922](https://github.com/nix-rust/nix/pull/922))
-- Support the `SO_PEERCRED` socket option and the `UnixCredentials` type on all Linux and Android targets.
- ([#921](https://github.com/nix-rust/nix/pull/921))
-- Added support for `SCM_CREDENTIALS`, allowing to send process credentials over Unix sockets.
- ([#923](https://github.com/nix-rust/nix/pull/923))
-- Added a `dir` module for reading directories (wraps `fdopendir`, `readdir`, and `rewinddir`).
- ([#916](https://github.com/nix-rust/nix/pull/916))
-- Added `kmod` module that allows loading and unloading kernel modules on Linux.
- ([#930](https://github.com/nix-rust/nix/pull/930))
-- Added `futimens` and `utimesat` wrappers ([#944](https://github.com/nix-rust/nix/pull/944)),
- an `lutimes` wrapper ([#967](https://github.com/nix-rust/nix/pull/967)),
- and a `utimes` wrapper ([#946](https://github.com/nix-rust/nix/pull/946)).
-- Added `AF_UNSPEC` wrapper to `AddressFamily` ([#948](https://github.com/nix-rust/nix/pull/948))
-- Added the `mode_t` public alias within `sys::stat`.
- ([#954](https://github.com/nix-rust/nix/pull/954))
-- Added a `truncate` wrapper.
- ([#956](https://github.com/nix-rust/nix/pull/956))
-- Added a `fchownat` wrapper.
- ([#955](https://github.com/nix-rust/nix/pull/955))
-- Added support for `ptrace` on BSD operating systems ([#949](https://github.com/nix-rust/nix/pull/949))
-- Added `ptrace` functions for reads and writes to tracee memory and ptrace kill
- ([#949](https://github.com/nix-rust/nix/pull/949)) ([#958](https://github.com/nix-rust/nix/pull/958))
-- Added a `acct` wrapper module for enabling and disabling process accounting
- ([#952](https://github.com/nix-rust/nix/pull/952))
-- Added the `time_t` and `suseconds_t` public aliases within `sys::time`.
- ([#968](https://github.com/nix-rust/nix/pull/968))
-- Added `unistd::execvpe` for Haiku, Linux and OpenBSD
- ([#975](https://github.com/nix-rust/nix/pull/975))
-- Added `Error::as_errno`.
- ([#977](https://github.com/nix-rust/nix/pull/977))
-
-### Changed
-- Increased required Rust version to 1.24.1
- ([#900](https://github.com/nix-rust/nix/pull/900))
- ([#966](https://github.com/nix-rust/nix/pull/966))
-
-### Fixed
-- Made `preadv` take immutable slice of IoVec.
- ([#914](https://github.com/nix-rust/nix/pull/914))
-- Fixed passing multiple file descriptors over Unix Sockets.
- ([#918](https://github.com/nix-rust/nix/pull/918))
-
-### Removed
-
-## [0.11.0] 2018-06-01
-
-### Added
-- Added `sendfile` on FreeBSD and Darwin.
- ([#901](https://github.com/nix-rust/nix/pull/901))
-- Added `pselect`
- ([#894](https://github.com/nix-rust/nix/pull/894))
-- Exposed `preadv` and `pwritev` on the BSDs.
- ([#883](https://github.com/nix-rust/nix/pull/883))
-- Added `mlockall` and `munlockall`
- ([#876](https://github.com/nix-rust/nix/pull/876))
-- Added `SO_MARK` on Linux.
- ([#873](https://github.com/nix-rust/nix/pull/873))
-- Added safe support for nearly any buffer type in the `sys::aio` module.
- ([#872](https://github.com/nix-rust/nix/pull/872))
-- Added `sys::aio::LioCb` as a wrapper for `libc::lio_listio`.
- ([#872](https://github.com/nix-rust/nix/pull/872))
-- Added `unistd::getsid`
- ([#850](https://github.com/nix-rust/nix/pull/850))
-- Added `alarm`. ([#830](https://github.com/nix-rust/nix/pull/830))
-- Added interface flags `IFF_NO_PI, IFF_TUN, IFF_TAP` on linux-like systems.
- ([#853](https://github.com/nix-rust/nix/pull/853))
-- Added `statvfs` module to all MacOS and Linux architectures.
- ([#832](https://github.com/nix-rust/nix/pull/832))
-- Added `EVFILT_EMPTY`, `EVFILT_PROCDESC`, and `EVFILT_SENDFILE` on FreeBSD.
- ([#825](https://github.com/nix-rust/nix/pull/825))
-- Exposed `termios::cfmakesane` on FreeBSD.
- ([#825](https://github.com/nix-rust/nix/pull/825))
-- Exposed `MSG_CMSG_CLOEXEC` on *BSD.
- ([#825](https://github.com/nix-rust/nix/pull/825))
-- Added `fchmod`, `fchmodat`.
- ([#857](https://github.com/nix-rust/nix/pull/857))
-- Added `request_code_write_int!` on FreeBSD/DragonFlyBSD
- ([#833](https://github.com/nix-rust/nix/pull/833))
-
-### Changed
-- `Display` and `Debug` for `SysControlAddr` now includes all fields.
- ([#837](https://github.com/nix-rust/nix/pull/837))
-- `ioctl!` has been replaced with a family of `ioctl_*!` macros.
- ([#833](https://github.com/nix-rust/nix/pull/833))
-- `io!`, `ior!`, `iow!`, and `iorw!` has been renamed to `request_code_none!`, `request_code_read!`,
- `request_code_write!`, and `request_code_readwrite!` respectively. These have also now been exposed
- in the documentation.
- ([#833](https://github.com/nix-rust/nix/pull/833))
-- Enabled more `ptrace::Request` definitions for uncommon Linux platforms
- ([#892](https://github.com/nix-rust/nix/pull/892))
-- Emulation of `FD_CLOEXEC` and `O_NONBLOCK` was removed from `socket()`, `accept4()`, and
- `socketpair()`.
- ([#907](https://github.com/nix-rust/nix/pull/907))
-
-### Fixed
-- Fixed possible panics when using `SigAction::flags` on Linux
- ([#869](https://github.com/nix-rust/nix/pull/869))
-- Properly exposed 460800 and 921600 baud rates on NetBSD
- ([#837](https://github.com/nix-rust/nix/pull/837))
-- Fixed `ioctl_write_int!` on FreeBSD/DragonFlyBSD
- ([#833](https://github.com/nix-rust/nix/pull/833))
-- `ioctl_write_int!` now properly supports passing a `c_ulong` as the parameter on Linux non-musl targets
- ([#833](https://github.com/nix-rust/nix/pull/833))
-
-### Removed
-- Removed explicit support for the `bytes` crate from the `sys::aio` module.
- See `sys::aio::AioCb::from_boxed_slice` examples for alternatives.
- ([#872](https://github.com/nix-rust/nix/pull/872))
-- Removed `sys::aio::lio_listio`. Use `sys::aio::LioCb::listio` instead.
- ([#872](https://github.com/nix-rust/nix/pull/872))
-- Removed emulated `accept4()` from macos, ios, and netbsd targets
- ([#907](https://github.com/nix-rust/nix/pull/907))
-- Removed `IFF_NOTRAILERS` on OpenBSD, as it has been removed in OpenBSD 6.3
- ([#893](https://github.com/nix-rust/nix/pull/893))
-
-## [0.10.0] 2018-01-26
-
-### Added
-- Added specialized wrapper: `sys::ptrace::step`
- ([#852](https://github.com/nix-rust/nix/pull/852))
-- Added `AioCb::from_ptr` and `AioCb::from_mut_ptr`
- ([#820](https://github.com/nix-rust/nix/pull/820))
-- Added specialized wrappers: `sys::ptrace::{traceme, syscall, cont, attach}`. Using the matching routines
- with `sys::ptrace::ptrace` is now deprecated.
-- Added `nix::poll` module for all platforms
- ([#672](https://github.com/nix-rust/nix/pull/672))
-- Added `nix::ppoll` function for FreeBSD and DragonFly
- ([#672](https://github.com/nix-rust/nix/pull/672))
-- Added protocol families in `AddressFamily` enum.
- ([#647](https://github.com/nix-rust/nix/pull/647))
-- Added the `pid()` method to `WaitStatus` for extracting the PID.
- ([#722](https://github.com/nix-rust/nix/pull/722))
-- Added `nix::unistd:fexecve`.
- ([#727](https://github.com/nix-rust/nix/pull/727))
-- Expose `uname()` on all platforms.
- ([#739](https://github.com/nix-rust/nix/pull/739))
-- Expose `signalfd` module on Android as well.
- ([#739](https://github.com/nix-rust/nix/pull/739))
-- Added `nix::sys::ptrace::detach`.
- ([#749](https://github.com/nix-rust/nix/pull/749))
-- Added timestamp socket control message variant:
- `nix::sys::socket::ControlMessage::ScmTimestamp`
- ([#663](https://github.com/nix-rust/nix/pull/663))
-- Added socket option variant that enables the timestamp socket
- control message: `nix::sys::socket::sockopt::ReceiveTimestamp`
- ([#663](https://github.com/nix-rust/nix/pull/663))
-- Added more accessor methods for `AioCb`
- ([#773](https://github.com/nix-rust/nix/pull/773))
-- Add `nix::sys::fallocate`
- ([#768](https:://github.com/nix-rust/nix/pull/768))
-- Added `nix::unistd::mkfifo`.
- ([#602](https://github.com/nix-rust/nix/pull/774))
-- Added `ptrace::Options::PTRACE_O_EXITKILL` on Linux and Android.
- ([#771](https://github.com/nix-rust/nix/pull/771))
-- Added `nix::sys::uio::{process_vm_readv, process_vm_writev}` on Linux
- ([#568](https://github.com/nix-rust/nix/pull/568))
-- Added `nix::unistd::{getgroups, setgroups, getgrouplist, initgroups}`. ([#733](https://github.com/nix-rust/nix/pull/733))
-- Added `nix::sys::socket::UnixAddr::as_abstract` on Linux and Android.
- ([#785](https://github.com/nix-rust/nix/pull/785))
-- Added `nix::unistd::execveat` on Linux and Android.
- ([#800](https://github.com/nix-rust/nix/pull/800))
-- Added the `from_raw()` method to `WaitStatus` for converting raw status values
- to `WaitStatus` independent of syscalls.
- ([#741](https://github.com/nix-rust/nix/pull/741))
-- Added more standard trait implementations for various types.
- ([#814](https://github.com/nix-rust/nix/pull/814))
-- Added `sigprocmask` to the signal module.
- ([#826](https://github.com/nix-rust/nix/pull/826))
-- Added `nix::sys::socket::LinkAddr` on Linux and all bsdlike system.
- ([#813](https://github.com/nix-rust/nix/pull/813))
-- Add socket options for `IP_TRANSPARENT` / `BIND_ANY`.
- ([#835](https://github.com/nix-rust/nix/pull/835))
-
-### Changed
-- Exposed the `mqueue` module for all supported operating systems.
- ([#834](https://github.com/nix-rust/nix/pull/834))
-- Use native `pipe2` on all BSD targets. Users should notice no difference.
- ([#777](https://github.com/nix-rust/nix/pull/777))
-- Renamed existing `ptrace` wrappers to encourage namespacing ([#692](https://github.com/nix-rust/nix/pull/692))
-- Marked `sys::ptrace::ptrace` as `unsafe`.
-- Changed function signature of `socket()` and `socketpair()`. The `protocol` argument
- has changed type from `c_int` to `SockProtocol`.
- It accepts a `None` value for default protocol that was specified with zero using `c_int`.
- ([#647](https://github.com/nix-rust/nix/pull/647))
-- Made `select` easier to use, adding the ability to automatically calculate the `nfds` parameter using the new
- `FdSet::highest` ([#701](https://github.com/nix-rust/nix/pull/701))
-- Exposed `unistd::setresuid` and `unistd::setresgid` on FreeBSD and OpenBSD
- ([#721](https://github.com/nix-rust/nix/pull/721))
-- Refactored the `statvfs` module removing extraneous API functions and the
- `statvfs::vfs` module. Additionally `(f)statvfs()` now return the struct
- directly. And the returned `Statvfs` struct now exposes its data through
- accessor methods. ([#729](https://github.com/nix-rust/nix/pull/729))
-- The `addr` argument to `madvise` and `msync` is now `*mut` to better match the
- libc API. ([#731](https://github.com/nix-rust/nix/pull/731))
-- `shm_open` and `shm_unlink` are no longer exposed on Android targets, where
- they are not officially supported. ([#731](https://github.com/nix-rust/nix/pull/731))
-- `MapFlags`, `MmapAdvise`, and `MsFlags` expose some more variants and only
- officially-supported variants are provided for each target.
- ([#731](https://github.com/nix-rust/nix/pull/731))
-- Marked `pty::ptsname` function as `unsafe`
- ([#744](https://github.com/nix-rust/nix/pull/744))
-- Moved constants ptrace request, event and options to enums and updated ptrace functions and argument types accordingly.
- ([#749](https://github.com/nix-rust/nix/pull/749))
-- `AioCb::Drop` will now panic if the `AioCb` is still in-progress ([#715](https://github.com/nix-rust/nix/pull/715))
-- Restricted `nix::sys::socket::UnixAddr::new_abstract` to Linux and Android only.
- ([#785](https://github.com/nix-rust/nix/pull/785))
-- The `ucred` struct has been removed in favor of a `UserCredentials` struct that
- contains only getters for its fields.
- ([#814](https://github.com/nix-rust/nix/pull/814))
-- Both `ip_mreq` and `ipv6_mreq` have been replaced with `IpMembershipRequest` and
- `Ipv6MembershipRequest`.
- ([#814](https://github.com/nix-rust/nix/pull/814))
-- Removed return type from `pause`.
- ([#829](https://github.com/nix-rust/nix/pull/829))
-- Changed the termios APIs to allow for using a `u32` instead of the `BaudRate`
- enum on BSD platforms to support arbitrary baud rates. See the module docs for
- `nix::sys::termios` for more details.
- ([#843](https://github.com/nix-rust/nix/pull/843))
-
-### Fixed
-- Fix compilation and tests for OpenBSD targets
- ([#688](https://github.com/nix-rust/nix/pull/688))
-- Fixed error handling in `AioCb::fsync`, `AioCb::read`, and `AioCb::write`.
- It is no longer an error to drop an `AioCb` that failed to enqueue in the OS.
- ([#715](https://github.com/nix-rust/nix/pull/715))
-- Fix potential memory corruption on non-Linux platforms when using
- `sendmsg`/`recvmsg`, caused by mismatched `msghdr` definition.
- ([#648](https://github.com/nix-rust/nix/pull/648))
-
-### Removed
-- `AioCb::from_boxed_slice` has been removed. It was never actually safe. Use
- `from_bytes` or `from_bytes_mut` instead.
- ([#820](https://github.com/nix-rust/nix/pull/820))
-- The syscall module has been removed. This only exposed enough functionality for
- `memfd_create()` and `pivot_root()`, which are still exposed as separate functions.
- ([#747](https://github.com/nix-rust/nix/pull/747))
-- The `Errno` variants are no longer reexported from the `errno` module. `Errno` itself is no longer reexported from the
- crate root and instead must be accessed using the `errno` module. ([#696](https://github.com/nix-rust/nix/pull/696))
-- Removed `MS_VERBOSE`, `MS_NOSEC`, and `MS_BORN` from `MsFlags`. These
- are internal kernel flags and should never have been exposed.
- ([#814](https://github.com/nix-rust/nix/pull/814))
-
-
-## [0.9.0] 2017-07-23
-
-### Added
-- Added `sysconf`, `pathconf`, and `fpathconf`
- ([#630](https://github.com/nix-rust/nix/pull/630)
-- Added `sys::signal::SigAction::{ flags, mask, handler}`
- ([#611](https://github.com/nix-rust/nix/pull/609)
-- Added `nix::sys::pthread::pthread_self`
- ([#591](https://github.com/nix-rust/nix/pull/591)
-- Added `AioCb::from_boxed_slice`
- ([#582](https://github.com/nix-rust/nix/pull/582)
-- Added `nix::unistd::{openat, fstatat, readlink, readlinkat}`
- ([#551](https://github.com/nix-rust/nix/pull/551))
-- Added `nix::pty::{grantpt, posix_openpt, ptsname/ptsname_r, unlockpt}`
- ([#556](https://github.com/nix-rust/nix/pull/556)
-- Added `nix::ptr::openpty`
- ([#456](https://github.com/nix-rust/nix/pull/456))
-- Added `nix::ptrace::{ptrace_get_data, ptrace_getsiginfo, ptrace_setsiginfo
- and nix::Error::UnsupportedOperation}`
- ([#614](https://github.com/nix-rust/nix/pull/614))
-- Added `cfmakeraw`, `cfsetspeed`, and `tcgetsid`. ([#527](https://github.com/nix-rust/nix/pull/527))
-- Added "bad none", "bad write_ptr", "bad write_int", and "bad readwrite" variants to the `ioctl!`
- macro. ([#670](https://github.com/nix-rust/nix/pull/670))
-- On Linux and Android, added support for receiving `PTRACE_O_TRACESYSGOOD`
- events from `wait` and `waitpid` using `WaitStatus::PtraceSyscall`
- ([#566](https://github.com/nix-rust/nix/pull/566)).
-
-### Changed
-- The `ioctl!` macro and its variants now allow the generated functions to have
- doccomments. ([#661](https://github.com/nix-rust/nix/pull/661))
-- Changed `ioctl!(write ...)` into `ioctl!(write_ptr ...)` and `ioctl!(write_int ..)` variants
- to more clearly separate those use cases. ([#670](https://github.com/nix-rust/nix/pull/670))
-- Marked `sys::mman::{ mmap, munmap, madvise, munlock, msync }` as unsafe.
- ([#559](https://github.com/nix-rust/nix/pull/559))
-- Minimum supported Rust version is now 1.13.
-- Removed `revents` argument from `PollFd::new()` as it's an output argument and
- will be overwritten regardless of value.
- ([#542](https://github.com/nix-rust/nix/pull/542))
-- Changed type signature of `sys::select::FdSet::contains` to make `self`
- immutable ([#564](https://github.com/nix-rust/nix/pull/564))
-- Introduced wrapper types for `gid_t`, `pid_t`, and `uid_t` as `Gid`, `Pid`, and `Uid`
- respectively. Various functions have been changed to use these new types as
- arguments. ([#629](https://github.com/nix-rust/nix/pull/629))
-- Fixed compilation on all Android and iOS targets ([#527](https://github.com/nix-rust/nix/pull/527))
- and promoted them to Tier 2 support.
-- `nix::sys::statfs::{statfs,fstatfs}` uses statfs definition from `libc::statfs` instead of own linux specific type `nix::sys::Statfs`.
- Also file system type constants like `nix::sys::statfs::ADFS_SUPER_MAGIC` were removed in favor of the libc equivalent.
- ([#561](https://github.com/nix-rust/nix/pull/561))
-- Revised the termios API including additional tests and documentation and exposed it on iOS. ([#527](https://github.com/nix-rust/nix/pull/527))
-- `eventfd`, `signalfd`, and `pwritev`/`preadv` functionality is now included by default for all
- supported platforms. ([#681](https://github.com/nix-rust/nix/pull/561))
-- The `ioctl!` macro's plain variants has been replaced with "bad read" to be consistent with
- other variants. The generated functions also have more strict types for their arguments. The
- "*_buf" variants also now calculate total array size and take slice references for improved type
- safety. The documentation has also been dramatically improved.
- ([#670](https://github.com/nix-rust/nix/pull/670))
-
-### Removed
-- Removed `io::Error` from `nix::Error` and the conversion from `nix::Error` to `Errno`
- ([#614](https://github.com/nix-rust/nix/pull/614))
-- All feature flags have been removed in favor of conditional compilation on supported platforms.
- `execvpe` is no longer supported, but this was already broken and will be added back in the next
- release. ([#681](https://github.com/nix-rust/nix/pull/561))
-- Removed `ioc_*` functions and many helper constants and macros within the `ioctl` module. These
- should always have been private and only the `ioctl!` should be used in public code.
- ([#670](https://github.com/nix-rust/nix/pull/670))
-
-### Fixed
-- Fixed multiple issues compiling under different archetectures and OSes.
- Now compiles on Linux/MIPS ([#538](https://github.com/nix-rust/nix/pull/538)),
- `Linux/PPC` ([#553](https://github.com/nix-rust/nix/pull/553)),
- `MacOS/x86_64,i686` ([#553](https://github.com/nix-rust/nix/pull/553)),
- `NetBSD/x64_64` ([#538](https://github.com/nix-rust/nix/pull/538)),
- `FreeBSD/x86_64,i686` ([#536](https://github.com/nix-rust/nix/pull/536)), and
- `Android` ([#631](https://github.com/nix-rust/nix/pull/631)).
-- `bind` and `errno_location` now work correctly on `Android`
- ([#631](https://github.com/nix-rust/nix/pull/631))
-- Added `nix::ptrace` on all Linux-kernel-based platforms
- [#624](https://github.com/nix-rust/nix/pull/624). Previously it was
- only available on x86, x86-64, and ARM, and also not on Android.
-- Fixed `sys::socket::sendmsg` with zero entry `cmsgs` parameter.
- ([#623](https://github.com/nix-rust/nix/pull/623))
-- Multiple constants related to the termios API have now been properly defined for
- all supported platforms. ([#527](https://github.com/nix-rust/nix/pull/527))
-- `ioctl!` macro now supports working with non-int datatypes and properly supports all platforms.
- ([#670](https://github.com/nix-rust/nix/pull/670))
-
-## [0.8.1] 2017-04-16
-
-### Fixed
-- Fixed build on FreeBSD. (Cherry-picked
- [a859ee3c](https://github.com/nix-rust/nix/commit/a859ee3c9396dfdb118fcc2c8ecc697e2d303467))
-
-## [0.8.0] 2017-03-02
-
-### Added
-- Added `::nix::sys::termios::BaudRate` enum to provide portable baudrate
- values. ([#518](https://github.com/nix-rust/nix/pull/518))
-- Added a new `WaitStatus::PtraceEvent` to support ptrace events on Linux
- and Android ([#438](https://github.com/nix-rust/nix/pull/438))
-- Added support for POSIX AIO
- ([#483](https://github.com/nix-rust/nix/pull/483))
- ([#506](https://github.com/nix-rust/nix/pull/506))
-- Added support for XNU system control sockets
- ([#478](https://github.com/nix-rust/nix/pull/478))
-- Added support for `ioctl` calls on BSD platforms
- ([#478](https://github.com/nix-rust/nix/pull/478))
-- Added struct `TimeSpec`
- ([#475](https://github.com/nix-rust/nix/pull/475))
- ([#483](https://github.com/nix-rust/nix/pull/483))
-- Added complete definitions for all kqueue-related constants on all supported
- OSes
- ([#415](https://github.com/nix-rust/nix/pull/415))
-- Added function `epoll_create1` and bitflags `EpollCreateFlags` in
- `::nix::sys::epoll` in order to support `::libc::epoll_create1`.
- ([#410](https://github.com/nix-rust/nix/pull/410))
-- Added `setresuid` and `setresgid` for Linux in `::nix::unistd`
- ([#448](https://github.com/nix-rust/nix/pull/448))
-- Added `getpgid` in `::nix::unistd`
- ([#433](https://github.com/nix-rust/nix/pull/433))
-- Added `tcgetpgrp` and `tcsetpgrp` in `::nix::unistd`
- ([#451](https://github.com/nix-rust/nix/pull/451))
-- Added `CLONE_NEWCGROUP` in `::nix::sched`
- ([#457](https://github.com/nix-rust/nix/pull/457))
-- Added `getpgrp` in `::nix::unistd`
- ([#491](https://github.com/nix-rust/nix/pull/491))
-- Added `fchdir` in `::nix::unistd`
- ([#497](https://github.com/nix-rust/nix/pull/497))
-- Added `major` and `minor` in `::nix::sys::stat` for decomposing `dev_t`
- ([#508](https://github.com/nix-rust/nix/pull/508))
-- Fixed the style of many bitflags and use `libc` in more places.
- ([#503](https://github.com/nix-rust/nix/pull/503))
-- Added `ppoll` in `::nix::poll`
- ([#520](https://github.com/nix-rust/nix/pull/520))
-- Added support for getting and setting pipe size with fcntl(2) on Linux
- ([#540](https://github.com/nix-rust/nix/pull/540))
-
-### Changed
-- `::nix::sys::termios::{cfgetispeed, cfsetispeed, cfgetospeed, cfsetospeed}`
- switched to use `BaudRate` enum from `speed_t`.
- ([#518](https://github.com/nix-rust/nix/pull/518))
-- `epoll_ctl` now could accept None as argument `event`
- when op is `EpollOp::EpollCtlDel`.
- ([#480](https://github.com/nix-rust/nix/pull/480))
-- Removed the `bad` keyword from the `ioctl!` macro
- ([#478](https://github.com/nix-rust/nix/pull/478))
-- Changed `TimeVal` into an opaque Newtype
- ([#475](https://github.com/nix-rust/nix/pull/475))
-- `kill`'s signature, defined in `::nix::sys::signal`, changed, so that the
- signal parameter has type `T: Into<Option<Signal>>`. `None` as an argument
- for that parameter will result in a 0 passed to libc's `kill`, while a
- `Some`-argument will result in the previous behavior for the contained
- `Signal`.
- ([#445](https://github.com/nix-rust/nix/pull/445))
-- The minimum supported version of rustc is now 1.7.0.
- ([#444](https://github.com/nix-rust/nix/pull/444))
-- Changed `KEvent` to an opaque structure that may only be modified by its
- constructor and the `ev_set` method.
- ([#415](https://github.com/nix-rust/nix/pull/415))
- ([#442](https://github.com/nix-rust/nix/pull/442))
- ([#463](https://github.com/nix-rust/nix/pull/463))
-- `pipe2` now calls `libc::pipe2` where available. Previously it was emulated
- using `pipe`, which meant that setting `O_CLOEXEC` was not atomic.
- ([#427](https://github.com/nix-rust/nix/pull/427))
-- Renamed `EpollEventKind` to `EpollFlags` in `::nix::sys::epoll` in order for
- it to conform with our conventions.
- ([#410](https://github.com/nix-rust/nix/pull/410))
-- `EpollEvent` in `::nix::sys::epoll` is now an opaque proxy for
- `::libc::epoll_event`. The formerly public field `events` is now be read-only
- accessible with the new method `events()` of `EpollEvent`. Instances of
- `EpollEvent` can be constructed using the new method `new()` of EpollEvent.
- ([#410](https://github.com/nix-rust/nix/pull/410))
-- `SigFlags` in `::nix::sys::signal` has be renamed to `SigmaskHow` and its type
- has changed from `bitflags` to `enum` in order to conform to our conventions.
- ([#460](https://github.com/nix-rust/nix/pull/460))
-- `sethostname` now takes a `&str` instead of a `&[u8]` as this provides an API
- that makes more sense in normal, correct usage of the API.
-- `gethostname` previously did not expose the actual length of the hostname
- written from the underlying system call at all. This has been updated to
- return a `&CStr` within the provided buffer that is always properly
- NUL-terminated (this is not guaranteed by the call with all platforms/libc
- implementations).
-- Exposed all fcntl(2) operations at the module level, so they can be
- imported direclty instead of via `FcntlArg` enum.
- ([#541](https://github.com/nix-rust/nix/pull/541))
-
-### Fixed
-- Fixed multiple issues with Unix domain sockets on non-Linux OSes
- ([#474](https://github.com/nix-rust/nix/pull/415))
-- Fixed using kqueue with `EVFILT_USER` on FreeBSD
- ([#415](https://github.com/nix-rust/nix/pull/415))
-- Fixed the build on FreeBSD, and fixed the getsockopt, sendmsg, and recvmsg
- functions on that same OS.
- ([#397](https://github.com/nix-rust/nix/pull/397))
-- Fixed an off-by-one bug in `UnixAddr::new_abstract` in `::nix::sys::socket`.
- ([#429](https://github.com/nix-rust/nix/pull/429))
-- Fixed clone passing a potentially unaligned stack.
- ([#490](https://github.com/nix-rust/nix/pull/490))
-- Fixed mkdev not creating a `dev_t` the same way as libc.
- ([#508](https://github.com/nix-rust/nix/pull/508))
-
-## [0.7.0] 2016-09-09
-
-### Added
-- Added `lseek` and `lseek64` in `::nix::unistd`
- ([#377](https://github.com/nix-rust/nix/pull/377))
-- Added `mkdir` and `getcwd` in `::nix::unistd`
- ([#416](https://github.com/nix-rust/nix/pull/416))
-- Added accessors `sigmask_mut` and `sigmask` to `UContext` in
- `::nix::ucontext`.
- ([#370](https://github.com/nix-rust/nix/pull/370))
-- Added `WUNTRACED` to `WaitPidFlag` in `::nix::sys::wait` for non-_linux_
- targets.
- ([#379](https://github.com/nix-rust/nix/pull/379))
-- Added new module `::nix::sys::reboot` with enumeration `RebootMode` and
- functions `reboot` and `set_cad_enabled`. Currently for _linux_ only.
- ([#386](https://github.com/nix-rust/nix/pull/386))
-- `FdSet` in `::nix::sys::select` now also implements `Clone`.
- ([#405](https://github.com/nix-rust/nix/pull/405))
-- Added `F_FULLFSYNC` to `FcntlArg` in `::nix::fcntl` for _apple_ targets.
- ([#407](https://github.com/nix-rust/nix/pull/407))
-- Added `CpuSet::unset` in `::nix::sched`.
- ([#402](https://github.com/nix-rust/nix/pull/402))
-- Added constructor method `new()` to `PollFd` in `::nix::poll`, in order to
- allow creation of objects, after removing public access to members.
- ([#399](https://github.com/nix-rust/nix/pull/399))
-- Added method `revents()` to `PollFd` in `::nix::poll`, in order to provide
- read access to formerly public member `revents`.
- ([#399](https://github.com/nix-rust/nix/pull/399))
-- Added `MSG_CMSG_CLOEXEC` to `MsgFlags` in `::nix::sys::socket` for _linux_ only.
- ([#422](https://github.com/nix-rust/nix/pull/422))
-
-### Changed
-- Replaced the reexported integer constants for signals by the enumeration
- `Signal` in `::nix::sys::signal`.
- ([#362](https://github.com/nix-rust/nix/pull/362))
-- Renamed `EventFdFlag` to `EfdFlags` in `::nix::sys::eventfd`.
- ([#383](https://github.com/nix-rust/nix/pull/383))
-- Changed the result types of `CpuSet::is_set` and `CpuSet::set` in
- `::nix::sched` to `Result<bool>` and `Result<()>`, respectively. They now
- return `EINVAL`, if an invalid argument for the `field` parameter is passed.
- ([#402](https://github.com/nix-rust/nix/pull/402))
-- `MqAttr` in `::nix::mqueue` is now an opaque proxy for `::libc::mq_attr`,
- which has the same structure as the old `MqAttr`. The field `mq_flags` of
- `::libc::mq_attr` is readable using the new method `flags()` of `MqAttr`.
- `MqAttr` also no longer implements `Debug`.
- ([#392](https://github.com/nix-rust/nix/pull/392))
-- The parameter `msq_prio` of `mq_receive` with type `u32` in `::nix::mqueue`
- was replaced by a parameter named `msg_prio` with type `&mut u32`, so that
- the message priority can be obtained by the caller.
- ([#392](https://github.com/nix-rust/nix/pull/392))
-- The type alias `MQd` in `::nix::queue` was replaced by the type alias
- `libc::mqd_t`, both of which are aliases for the same type.
- ([#392](https://github.com/nix-rust/nix/pull/392))
-
-### Removed
-- Type alias `SigNum` from `::nix::sys::signal`.
- ([#362](https://github.com/nix-rust/nix/pull/362))
-- Type alias `CpuMask` from `::nix::shed`.
- ([#402](https://github.com/nix-rust/nix/pull/402))
-- Removed public fields from `PollFd` in `::nix::poll`. (See also added method
- `revents()`.
- ([#399](https://github.com/nix-rust/nix/pull/399))
-
-### Fixed
-- Fixed the build problem for NetBSD (Note, that we currently do not support
- it, so it might already be broken again).
- ([#389](https://github.com/nix-rust/nix/pull/389))
-- Fixed the build on FreeBSD, and fixed the getsockopt, sendmsg, and recvmsg
- functions on that same OS.
- ([#397](https://github.com/nix-rust/nix/pull/397))
-
-## [0.6.0] 2016-06-10
-
-### Added
-- Added `gettid` in `::nix::unistd` for _linux_ and _android_.
- ([#293](https://github.com/nix-rust/nix/pull/293))
-- Some _mips_ support in `::nix::sched` and `::nix::sys::syscall`.
- ([#301](https://github.com/nix-rust/nix/pull/301))
-- Added `SIGNALFD_SIGINFO_SIZE` in `::nix::sys::signalfd`.
- ([#309](https://github.com/nix-rust/nix/pull/309))
-- Added new module `::nix::ucontext` with struct `UContext`. Currently for
- _linux_ only.
- ([#311](https://github.com/nix-rust/nix/pull/311))
-- Added `EPOLLEXCLUSIVE` to `EpollEventKind` in `::nix::sys::epoll`.
- ([#330](https://github.com/nix-rust/nix/pull/330))
-- Added `pause` to `::nix::unistd`.
- ([#336](https://github.com/nix-rust/nix/pull/336))
-- Added `sleep` to `::nix::unistd`.
- ([#351](https://github.com/nix-rust/nix/pull/351))
-- Added `S_IFDIR`, `S_IFLNK`, `S_IFMT` to `SFlag` in `::nix::sys::stat`.
- ([#359](https://github.com/nix-rust/nix/pull/359))
-- Added `clear` and `extend` functions to `SigSet`'s implementation in
- `::nix::sys::signal`.
- ([#347](https://github.com/nix-rust/nix/pull/347))
-- `sockaddr_storage_to_addr` in `::nix::sys::socket` now supports `sockaddr_nl`
- on _linux_ and _android_.
- ([#366](https://github.com/nix-rust/nix/pull/366))
-- Added support for `SO_ORIGINAL_DST` in `::nix::sys::socket` on _linux_.
- ([#367](https://github.com/nix-rust/nix/pull/367))
-- Added `SIGINFO` in `::nix::sys::signal` for the _macos_ target as well as
- `SIGPWR` and `SIGSTKFLT` in `::nix::sys::signal` for non-_macos_ targets.
- ([#361](https://github.com/nix-rust/nix/pull/361))
-
-### Changed
-- Changed the structure `IoVec` in `::nix::sys::uio`.
- ([#304](https://github.com/nix-rust/nix/pull/304))
-- Replaced `CREATE_NEW_FD` by `SIGNALFD_NEW` in `::nix::sys::signalfd`.
- ([#309](https://github.com/nix-rust/nix/pull/309))
-- Renamed `SaFlag` to `SaFlags` and `SigFlag` to `SigFlags` in
- `::nix::sys::signal`.
- ([#314](https://github.com/nix-rust/nix/pull/314))
-- Renamed `Fork` to `ForkResult` and changed its fields in `::nix::unistd`.
- ([#332](https://github.com/nix-rust/nix/pull/332))
-- Added the `signal` parameter to `clone`'s signature in `::nix::sched`.
- ([#344](https://github.com/nix-rust/nix/pull/344))
-- `execv`, `execve`, and `execvp` now return `Result<Void>` instead of
- `Result<()>` in `::nix::unistd`.
- ([#357](https://github.com/nix-rust/nix/pull/357))
-
-### Fixed
-- Improved the conversion from `std::net::SocketAddr` to `InetAddr` in
- `::nix::sys::socket::addr`.
- ([#335](https://github.com/nix-rust/nix/pull/335))
-
-## [0.5.0] 2016-03-01
diff --git a/vendor/nix-0.20.0/CONTRIBUTING.md b/vendor/nix-0.20.0/CONTRIBUTING.md
deleted file mode 100644
index 55990c4..0000000
--- a/vendor/nix-0.20.0/CONTRIBUTING.md
+++ /dev/null
@@ -1,114 +0,0 @@
-# Contributing to nix
-
-We're really glad you're interested in contributing to nix! This
-document has a few pointers and guidelines to help get you started.
-
-To have a welcoming and inclusive project, nix uses the Rust project's
-[Code of Conduct][conduct]. All contributors are expected to follow it.
-
-[conduct]: https://www.rust-lang.org/conduct.html
-
-
-# Issues
-
-We use GitHub's [issue tracker][issues].
-
-[issues]: https://github.com/nix-rust/nix/issues
-
-
-## Bug reports
-
-Before submitting a new bug report, please [search existing
-issues][issue-search] to see if there's something related. If not, just
-[open a new issue][new-issue]!
-
-As a reminder, the more information you can give in your issue, the
-easier it is to figure out how to fix it. For nix, this will likely
-include the OS and version, and the architecture.
-
-[issue-search]: https://github.com/nix-rust/nix/search?utf8=%E2%9C%93&q=is%3Aissue&type=Issues
-[new-issue]: https://github.com/nix-rust/nix/issues/new
-
-
-## Feature / API requests
-
-If you'd like a new API or feature added, please [open a new
-issue][new-issue] requesting it. As with reporting a bug, the more
-information you can provide, the better.
-
-
-## Labels
-
-We use labels to help manage issues. The structure is modeled after
-[Rust's issue labeling scheme][rust-labels]:
-- **A-**prefixed labels state which area of the project the issue
- relates to
-- **E-**prefixed labels explain the level of experience necessary to fix the
- issue
-- **O-**prefixed labels specify the OS for issues that are OS-specific
-- **R-**prefixed labels specify the architecture for issues that are
- architecture-specific
-
-[rust-labels]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#issue-triage
-
-
-# Pull requests
-
-GitHub pull requests are the primary mechanism we use to change nix. GitHub itself has
-some [great documentation][pr-docs] on using the Pull Request feature. We use the 'fork and
-pull' model described there.
-
-Please make pull requests against the `master` branch.
-
-If you change the API by way of adding, removing or changing something or if
-you fix a bug, please add an appropriate note to the [change log][cl]. We
-follow the conventions of [Keep A CHANGELOG][kacl].
-
-[cl]: https://github.com/nix-rust/nix/blob/master/CHANGELOG.md
-[kacl]: https://github.com/olivierlacan/keep-a-changelog/tree/18adb5f5be7a898d046f6a4acb93e39dcf40c4ad
-[pr-docs]: https://help.github.com/articles/using-pull-requests/
-
-## Testing
-
-nix has a test suite that you can run with `cargo test`. Ideally, we'd like pull
-requests to include tests where they make sense. For example, when fixing a bug,
-add a test that would have failed without the fix.
-
-After you've made your change, make sure the tests pass in your development
-environment. We also have [continuous integration set up on
-Cirrus-CI][cirrus-ci], which might find some issues on other platforms. The CI
-will run once you open a pull request.
-
-There is also infrastructure for running tests for other targets
-locally. More information is available in the [CI Readme][ci-readme].
-
-[cirrus-ci]: https://cirrus-ci.com/github/nix-rust/nix
-[ci-readme]: ci/README.md
-
-### Disabling a test in the CI environment
-
-Sometimes there are features that cannot be tested in the CI environment.
-To stop a test from running under CI, add `skip_if_cirrus!()` to it. Please
-describe the reason it shouldn't run under CI, and a link to an issue if
-possible!
-
-## bors, the bot who merges all the PRs
-
-All pull requests are merged via [bors], an integration bot. After the
-pull request has been reviewed, the reviewer will leave a comment like
-
-> bors r+
-
-to let bors know that it was approved. Then bors will check that it passes
-tests when merged with the latest changes in the `master` branch, and
-merge if the tests succeed.
-
-[bors]: https://bors-ng.github.io/
-
-
-## API conventions
-
-If you're adding a new API, we have a [document with
-conventions][conventions] to use throughout the nix project.
-
-[conventions]: https://github.com/nix-rust/nix/blob/master/CONVENTIONS.md
diff --git a/vendor/nix-0.20.0/CONVENTIONS.md b/vendor/nix-0.20.0/CONVENTIONS.md
deleted file mode 100644
index 2461085..0000000
--- a/vendor/nix-0.20.0/CONVENTIONS.md
+++ /dev/null
@@ -1,86 +0,0 @@
-# Conventions
-
-In order to achieve our goal of wrapping [libc][libc] code in idiomatic rust
-constructs with minimal performance overhead, we follow the following
-conventions.
-
-Note that, thus far, not all the code follows these conventions and not all
-conventions we try to follow have been documented here. If you find an instance
-of either, feel free to remedy the flaw by opening a pull request with
-appropriate changes or additions.
-
-## Change Log
-
-We follow the conventions laid out in [Keep A CHANGELOG][kacl].
-
-[kacl]: https://github.com/olivierlacan/keep-a-changelog/tree/18adb5f5be7a898d046f6a4acb93e39dcf40c4ad
-
-## libc constants, functions and structs
-
-We do not define integer constants ourselves, but use or reexport them from the
-[libc crate][libc].
-
-We use the functions exported from [libc][libc] instead of writing our own
-`extern` declarations.
-
-We use the `struct` definitions from [libc][libc] internally instead of writing
-our own. If we want to add methods to a libc type, we use the newtype pattern.
-For example,
-
-```rust
-pub struct SigSet(libc::sigset_t);
-
-impl SigSet {
- ...
-}
-```
-
-When creating newtypes, we use Rust's `CamelCase` type naming convention.
-
-## Bitflags
-
-Many C functions have flags parameters that are combined from constants using
-bitwise operations. We represent the types of these parameters by types defined
-using our `libc_bitflags!` macro, which is a convenience wrapper around the
-`bitflags!` macro from the [bitflags crate][bitflags] that brings in the
-constant value from `libc`.
-
-We name the type for a set of constants whose element's names start with `FOO_`
-`FooFlags`.
-
-For example,
-
-```rust
-libc_bitflags!{
- pub struct ProtFlags: libc::c_int {
- PROT_NONE;
- PROT_READ;
- PROT_WRITE;
- PROT_EXEC;
- #[cfg(any(target_os = "linux", target_os = "android"))]
- PROT_GROWSDOWN;
- #[cfg(any(target_os = "linux", target_os = "android"))]
- PROT_GROWSUP;
- }
-}
-```
-
-
-## Enumerations
-
-We represent sets of constants that are intended as mutually exclusive arguments
-to parameters of functions by [enumerations][enum].
-
-
-## Structures Initialized by libc Functions
-
-Whenever we need to use a [libc][libc] function to properly initialize a
-variable and said function allows us to use uninitialized memory, we use
-[`std::mem::MaybeUninit`][std_MaybeUninit] when defining the variable. This
-allows us to avoid the overhead incurred by zeroing or otherwise initializing
-the variable.
-
-[bitflags]: https://crates.io/crates/bitflags/
-[enum]: https://doc.rust-lang.org/reference.html#enumerations
-[libc]: https://crates.io/crates/libc/
-[std_MaybeUninit]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html
diff --git a/vendor/nix-0.20.0/Cargo.toml b/vendor/nix-0.20.0/Cargo.toml
deleted file mode 100644
index 0562246..0000000
--- a/vendor/nix-0.20.0/Cargo.toml
+++ /dev/null
@@ -1,78 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
-#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
-
-[package]
-edition = "2018"
-name = "nix"
-version = "0.20.0"
-authors = ["The nix-rust Project Developers"]
-exclude = ["/.gitignore", "/.cirrus.yml", "/ci/*", "/Cross.toml", "/RELEASE_PROCEDURE.md", "/bors.toml"]
-description = "Rust friendly bindings to *nix APIs"
-categories = ["os::unix-apis"]
-license = "MIT"
-repository = "https://github.com/nix-rust/nix"
-[package.metadata.docs.rs]
-targets = ["x86_64-unknown-linux-gnu", "aarch64-linux-android", "x86_64-apple-darwin", "aarch64-apple-ios", "x86_64-unknown-freebsd", "x86_64-unknown-openbsd", "x86_64-unknown-netbsd", "x86_64-unknown-dragonfly", "x86_64-fuchsia", "x86_64-unknown-redox"]
-
-[[test]]
-name = "test"
-path = "test/test.rs"
-
-[[test]]
-name = "test-aio-drop"
-path = "test/sys/test_aio_drop.rs"
-
-[[test]]
-name = "test-clearenv"
-path = "test/test_clearenv.rs"
-
-[[test]]
-name = "test-lio-listio-resubmit"
-path = "test/sys/test_lio_listio_resubmit.rs"
-
-[[test]]
-name = "test-mount"
-path = "test/test_mount.rs"
-harness = false
-
-[[test]]
-name = "test-ptymaster-drop"
-path = "test/test_ptymaster_drop.rs"
-[dependencies.bitflags]
-version = "1.1"
-
-[dependencies.cfg-if]
-version = "1.0"
-
-[dependencies.libc]
-version = "0.2.82"
-features = ["extra_traits"]
-[dev-dependencies.bytes]
-version = "0.4.8"
-
-[dev-dependencies.lazy_static]
-version = "1.2"
-
-[dev-dependencies.rand]
-version = "0.6"
-
-[dev-dependencies.semver]
-version = "0.9.0"
-
-[dev-dependencies.tempfile]
-version = "3.0.5"
-[target."cfg(any(target_os = \"android\", target_os = \"linux\"))".dev-dependencies.caps]
-version = "0.5.1"
-[target."cfg(target_os = \"dragonfly\")".build-dependencies.cc]
-version = "1"
-[target."cfg(target_os = \"freebsd\")".dev-dependencies.sysctl]
-version = "0.1"
diff --git a/vendor/nix-0.20.0/LICENSE b/vendor/nix-0.20.0/LICENSE
deleted file mode 100644
index aff9096..0000000
--- a/vendor/nix-0.20.0/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2015 Carl Lerche + nix-rust Authors
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/vendor/nix-0.20.0/README.md b/vendor/nix-0.20.0/README.md
deleted file mode 100644
index 167d192..0000000
--- a/vendor/nix-0.20.0/README.md
+++ /dev/null
@@ -1,109 +0,0 @@
-# Rust bindings to *nix APIs
-
-[](https://cirrus-ci.com/github/nix-rust/nix)
-[](https://crates.io/crates/nix)
-
-[Documentation (Releases)](https://docs.rs/nix/)
-
-Nix seeks to provide friendly bindings to various *nix platform APIs (Linux, Darwin,
-...). The goal is to not provide a 100% unified interface, but to unify
-what can be while still providing platform specific APIs.
-
-For many system APIs, Nix provides a safe alternative to the unsafe APIs
-exposed by the [libc crate](https://github.com/rust-lang/libc). This is done by
-wrapping the libc functionality with types/abstractions that enforce legal/safe
-usage.
-
-
-As an example of what Nix provides, examine the differences between what is
-exposed by libc and nix for the
-[gethostname](http://man7.org/linux/man-pages/man2/gethostname.2.html) system
-call:
-
-```rust,ignore
-// libc api (unsafe, requires handling return code/errno)
-pub unsafe extern fn gethostname(name: *mut c_char, len: size_t) -> c_int;
-
-// nix api (returns a nix::Result<CStr>)
-pub fn gethostname<'a>(buffer: &'a mut [u8]) -> Result<&'a CStr>;
-```
-
-## Supported Platforms
-
-nix target support consists of two tiers. While nix attempts to support all
-platforms supported by [libc](https://github.com/rust-lang/libc), only some
-platforms are actively supported due to either technical or manpower
-limitations. Support for platforms is split into three tiers:
-
- * Tier 1 - Builds and tests for this target are run in CI. Failures of either
- block the inclusion of new code.
- * Tier 2 - Builds for this target are run in CI. Failures during the build
- blocks the inclusion of new code. Tests may be run, but failures
- in tests don't block the inclusion of new code.
- * Tier 3 - Builds for this target are run in CI. Failures during the build
- *do not* block the inclusion of new code. Testing may be run, but
- failures in tests don't block the inclusion of new code.
-
-The following targets are supported by `nix`:
-
-Tier 1:
- * aarch64-unknown-linux-gnu
- * arm-unknown-linux-gnueabi
- * armv7-unknown-linux-gnueabihf
- * i686-unknown-freebsd
- * i686-unknown-linux-gnu
- * i686-unknown-linux-musl
- * mips-unknown-linux-gnu
- * mips64-unknown-linux-gnuabi64
- * mips64el-unknown-linux-gnuabi64
- * mipsel-unknown-linux-gnu
- * powerpc64le-unknown-linux-gnu
- * x86_64-apple-darwin
- * x86_64-unknown-freebsd
- * x86_64-unknown-linux-gnu
- * x86_64-unknown-linux-musl
-
-Tier 2:
- * aarch64-apple-ios
- * aarch64-linux-android
- * arm-linux-androideabi
- * arm-unknown-linux-musleabi
- * armv7-apple-ios
- * armv7-linux-androideabi
- * armv7s-apple-ios
- * i386-apple-ios
- * i686-apple-darwin
- * i686-linux-android
- * powerpc-unknown-linux-gnu
- * s390x-unknown-linux-gnu
- * x86_64-apple-ios
- * x86_64-linux-android
- * x86_64-unknown-netbsd
-
-Tier 3:
- * x86_64-fuchsia
- * x86_64-unknown-redox
- * x86_64-unknown-linux-gnux32
-
-## Usage
-
-`nix` requires Rust 1.40.0 or newer.
-
-To use `nix`, add this to your `Cargo.toml`:
-
-```toml
-[dependencies]
-nix = "0.20.0"
-```
-
-## Contributing
-
-Contributions are very welcome. Please See [CONTRIBUTING](CONTRIBUTING.md) for
-additional details.
-
-Feel free to join us in [the nix-rust/nix](https://gitter.im/nix-rust/nix) channel on Gitter to
-discuss `nix` development.
-
-## License
-
-Nix is licensed under the MIT license. See [LICENSE](LICENSE) for more details.
diff --git a/vendor/nix-0.20.0/src/dir.rs b/vendor/nix-0.20.0/src/dir.rs
deleted file mode 100644
index 7d4ab82..0000000
--- a/vendor/nix-0.20.0/src/dir.rs
+++ /dev/null
@@ -1,240 +0,0 @@
-use crate::{Error, NixPath, Result};
-use crate::errno::Errno;
-use crate::fcntl::{self, OFlag};
-use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
-use std::ptr;
-use std::ffi;
-use crate::sys;
-
-#[cfg(target_os = "linux")]
-use libc::{dirent64 as dirent, readdir64_r as readdir_r};
-
-#[cfg(not(target_os = "linux"))]
-use libc::{dirent, readdir_r};
-
-/// An open directory.
-///
-/// This is a lower-level interface than `std::fs::ReadDir`. Notable differences:
-/// * can be opened from a file descriptor (as returned by `openat`, perhaps before knowing
-/// if the path represents a file or directory).
-/// * implements `AsRawFd`, so it can be passed to `fstat`, `openat`, etc.
-/// The file descriptor continues to be owned by the `Dir`, so callers must not keep a `RawFd`
-/// after the `Dir` is dropped.
-/// * can be iterated through multiple times without closing and reopening the file
-/// descriptor. Each iteration rewinds when finished.
-/// * returns entries for `.` (current directory) and `..` (parent directory).
-/// * returns entries' names as a `CStr` (no allocation or conversion beyond whatever libc
-/// does).
-#[derive(Debug, Eq, Hash, PartialEq)]
-pub struct Dir(
- ptr::NonNull<libc::DIR>
-);
-
-impl Dir {
- /// Opens the given path as with `fcntl::open`.
- pub fn open<P: ?Sized + NixPath>(path: &P, oflag: OFlag,
- mode: sys::stat::Mode) -> Result<Self> {
- let fd = fcntl::open(path, oflag, mode)?;
- Dir::from_fd(fd)
- }
-
- /// Opens the given path as with `fcntl::openat`.
- pub fn openat<P: ?Sized + NixPath>(dirfd: RawFd, path: &P, oflag: OFlag,
- mode: sys::stat::Mode) -> Result<Self> {
- let fd = fcntl::openat(dirfd, path, oflag, mode)?;
- Dir::from_fd(fd)
- }
-
- /// Converts from a descriptor-based object, closing the descriptor on success or failure.
- #[inline]
- pub fn from<F: IntoRawFd>(fd: F) -> Result<Self> {
- Dir::from_fd(fd.into_raw_fd())
- }
-
- /// Converts from a file descriptor, closing it on success or failure.
- pub fn from_fd(fd: RawFd) -> Result<Self> {
- let d = unsafe { libc::fdopendir(fd) };
- if d.is_null() {
- let e = Error::last();
- unsafe { libc::close(fd) };
- return Err(e);
- };
- // Always guaranteed to be non-null by the previous check
- Ok(Dir(ptr::NonNull::new(d).unwrap()))
- }
-
- /// Returns an iterator of `Result<Entry>` which rewinds when finished.
- pub fn iter(&mut self) -> Iter {
- Iter(self)
- }
-}
-
-// `Dir` is not `Sync`. With the current implementation, it could be, but according to
-// https://www.gnu.org/software/libc/manual/html_node/Reading_002fClosing-Directory.html,
-// future versions of POSIX are likely to obsolete `readdir_r` and specify that it's unsafe to
-// call `readdir` simultaneously from multiple threads.
-//
-// `Dir` is safe to pass from one thread to another, as it's not reference-counted.
-unsafe impl Send for Dir {}
-
-impl AsRawFd for Dir {
- fn as_raw_fd(&self) -> RawFd {
- unsafe { libc::dirfd(self.0.as_ptr()) }
- }
-}
-
-impl Drop for Dir {
- fn drop(&mut self) {
- let e = Errno::result(unsafe { libc::closedir(self.0.as_ptr()) });
- if !std::thread::panicking() && e == Err(Error::Sys(Errno::EBADF)) {
- panic!("Closing an invalid file descriptor!");
- };
- }
-}
-
-fn next(dir: &mut Dir) -> Option<Result<Entry>> {
- unsafe {
- // Note: POSIX specifies that portable applications should dynamically allocate a
- // buffer with room for a `d_name` field of size `pathconf(..., _PC_NAME_MAX)` plus 1
- // for the NUL byte. It doesn't look like the std library does this; it just uses
- // fixed-sized buffers (and libc's dirent seems to be sized so this is appropriate).
- // Probably fine here too then.
- let mut ent = std::mem::MaybeUninit::<dirent>::uninit();
- let mut result = ptr::null_mut();
- if let Err(e) = Errno::result(
- readdir_r(dir.0.as_ptr(), ent.as_mut_ptr(), &mut result))
- {
- return Some(Err(e));
- }
- if result.is_null() {
- return None;
- }
- assert_eq!(result, ent.as_mut_ptr());
- Some(Ok(Entry(ent.assume_init())))
- }
-}
-
-#[derive(Debug, Eq, Hash, PartialEq)]
-pub struct Iter<'d>(&'d mut Dir);
-
-impl<'d> Iterator for Iter<'d> {
- type Item = Result<Entry>;
-
- fn next(&mut self) -> Option<Self::Item> {
- next(self.0)
- }
-}
-
-impl<'d> Drop for Iter<'d> {
- fn drop(&mut self) {
- unsafe { libc::rewinddir((self.0).0.as_ptr()) }
- }
-}
-
-/// The return type of [Dir::into_iter]
-#[derive(Debug, Eq, Hash, PartialEq)]
-pub struct OwningIter(Dir);
-
-impl Iterator for OwningIter {
- type Item = Result<Entry>;
-
- fn next(&mut self) -> Option<Self::Item> {
- next(&mut self.0)
- }
-}
-
-impl IntoIterator for Dir {
- type Item = Result<Entry>;
- type IntoIter = OwningIter;
-
- /// Creates a owning iterator, that is, one that takes ownership of the
- /// `Dir`. The `Dir` cannot be used after calling this. This can be useful
- /// when you have a function that both creates a `Dir` instance and returns
- /// an `Iterator`.
- ///
- /// Example:
- ///
- /// ```
- /// use nix::{dir::Dir, fcntl::OFlag, sys::stat::Mode};
- /// use std::{iter::Iterator, string::String};
- ///
- /// fn ls_upper(dirname: &str) -> impl Iterator<Item=String> {
- /// let d = Dir::open(dirname, OFlag::O_DIRECTORY, Mode::S_IXUSR).unwrap();
- /// d.into_iter().map(|x| x.unwrap().file_name().as_ref().to_string_lossy().to_ascii_uppercase())
- /// }
- /// ```
- fn into_iter(self) -> Self::IntoIter {
- OwningIter(self)
- }
-}
-
-/// A directory entry, similar to `std::fs::DirEntry`.
-///
-/// Note that unlike the std version, this may represent the `.` or `..` entries.
-#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
-#[repr(transparent)]
-pub struct Entry(dirent);
-
-#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
-pub enum Type {
- Fifo,
- CharacterDevice,
- Directory,
- BlockDevice,
- File,
- Symlink,
- Socket,
-}
-
-impl Entry {
- /// Returns the inode number (`d_ino`) of the underlying `dirent`.
- #[cfg(any(target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "haiku",
- target_os = "ios",
- target_os = "l4re",
- target_os = "linux",
- target_os = "macos",
- target_os = "solaris"))]
- pub fn ino(&self) -> u64 {
- self.0.d_ino as u64
- }
-
- /// Returns the inode number (`d_fileno`) of the underlying `dirent`.
- #[cfg(not(any(target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "haiku",
- target_os = "ios",
- target_os = "l4re",
- target_os = "linux",
- target_os = "macos",
- target_os = "solaris")))]
- pub fn ino(&self) -> u64 {
- u64::from(self.0.d_fileno)
- }
-
- /// Returns the bare file name of this directory entry without any other leading path component.
- pub fn file_name(&self) -> &ffi::CStr {
- unsafe { ::std::ffi::CStr::from_ptr(self.0.d_name.as_ptr()) }
- }
-
- /// Returns the type of this directory entry, if known.
- ///
- /// See platform `readdir(3)` or `dirent(5)` manpage for when the file type is known;
- /// notably, some Linux filesystems don't implement this. The caller should use `stat` or
- /// `fstat` if this returns `None`.
- pub fn file_type(&self) -> Option<Type> {
- match self.0.d_type {
- libc::DT_FIFO => Some(Type::Fifo),
- libc::DT_CHR => Some(Type::CharacterDevice),
- libc::DT_DIR => Some(Type::Directory),
- libc::DT_BLK => Some(Type::BlockDevice),
- libc::DT_REG => Some(Type::File),
- libc::DT_LNK => Some(Type::Symlink),
- libc::DT_SOCK => Some(Type::Socket),
- /* libc::DT_UNKNOWN | */ _ => None,
- }
- }
-}
diff --git a/vendor/nix-0.20.0/src/env.rs b/vendor/nix-0.20.0/src/env.rs
deleted file mode 100644
index f144dfe..0000000
--- a/vendor/nix-0.20.0/src/env.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-use cfg_if::cfg_if;
-use crate::{Error, Result};
-
-/// Clear the environment of all name-value pairs.
-///
-/// On platforms where libc provides `clearenv()`, it will be used. libc's
-/// `clearenv()` is documented to return an error code but not set errno; if the
-/// return value indicates a failure, this function will return
-/// `Error::UnsupportedOperation`.
-///
-/// On platforms where libc does not provide `clearenv()`, a fallback
-/// implementation will be used that iterates over all environment variables and
-/// removes them one-by-one.
-///
-/// # Safety
-///
-/// This function is not threadsafe and can cause undefined behavior in
-/// combination with `std::env` or other program components that access the
-/// environment. See, for example, the discussion on `std::env::remove_var`; this
-/// function is a case of an "inherently unsafe non-threadsafe API" dealing with
-/// the environment.
-///
-/// The caller must ensure no other threads access the process environment while
-/// this function executes and that no raw pointers to an element of libc's
-/// `environ` is currently held. The latter is not an issue if the only other
-/// environment access in the program is via `std::env`, but the requirement on
-/// thread safety must still be upheld.
-pub unsafe fn clearenv() -> Result<()> {
- let ret;
- cfg_if! {
- if #[cfg(any(target_os = "fuchsia",
- target_os = "wasi",
- target_env = "wasi",
- target_env = "uclibc",
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten"))] {
- ret = libc::clearenv();
- } else {
- use std::env;
- for (name, _) in env::vars_os() {
- env::remove_var(name);
- }
- ret = 0;
- }
- }
-
- if ret == 0 {
- Ok(())
- } else {
- Err(Error::UnsupportedOperation)
- }
-}
diff --git a/vendor/nix-0.20.0/src/errno.rs b/vendor/nix-0.20.0/src/errno.rs
deleted file mode 100644
index e5c7092..0000000
--- a/vendor/nix-0.20.0/src/errno.rs
+++ /dev/null
@@ -1,2201 +0,0 @@
-use cfg_if::cfg_if;
-use libc::{c_int, c_void};
-use std::{fmt, io, error};
-use crate::{Error, Result};
-
-pub use self::consts::*;
-
-cfg_if! {
- if #[cfg(any(target_os = "freebsd",
- target_os = "ios",
- target_os = "macos"))] {
- unsafe fn errno_location() -> *mut c_int {
- libc::__error()
- }
- } else if #[cfg(any(target_os = "android",
- target_os = "netbsd",
- target_os = "openbsd"))] {
- unsafe fn errno_location() -> *mut c_int {
- libc::__errno()
- }
- } else if #[cfg(any(target_os = "linux",
- target_os = "redox",
- target_os = "dragonfly",
- target_os = "fuchsia"))] {
- unsafe fn errno_location() -> *mut c_int {
- libc::__errno_location()
- }
- }
-}
-
-/// Sets the platform-specific errno to no-error
-fn clear() {
- // Safe because errno is a thread-local variable
- unsafe {
- *errno_location() = 0;
- }
-}
-
-/// Returns the platform-specific value of errno
-pub fn errno() -> i32 {
- unsafe {
- (*errno_location()) as i32
- }
-}
-
-impl Errno {
- pub fn last() -> Self {
- last()
- }
-
- pub fn desc(self) -> &'static str {
- desc(self)
- }
-
- pub fn from_i32(err: i32) -> Errno {
- from_i32(err)
- }
-
- pub fn clear() {
- clear()
- }
-
- /// Returns `Ok(value)` if it does not contain the sentinel value. This
- /// should not be used when `-1` is not the errno sentinel value.
- pub fn result<S: ErrnoSentinel + PartialEq<S>>(value: S) -> Result<S> {
- if value == S::sentinel() {
- Err(Error::Sys(Self::last()))
- } else {
- Ok(value)
- }
- }
-}
-
-/// The sentinel value indicates that a function failed and more detailed
-/// information about the error can be found in `errno`
-pub trait ErrnoSentinel: Sized {
- fn sentinel() -> Self;
-}
-
-impl ErrnoSentinel for isize {
- fn sentinel() -> Self { -1 }
-}
-
-impl ErrnoSentinel for i32 {
- fn sentinel() -> Self { -1 }
-}
-
-impl ErrnoSentinel for i64 {
- fn sentinel() -> Self { -1 }
-}
-
-impl ErrnoSentinel for *mut c_void {
- fn sentinel() -> Self { (-1 as isize) as *mut c_void }
-}
-
-impl ErrnoSentinel for libc::sighandler_t {
- fn sentinel() -> Self { libc::SIG_ERR }
-}
-
-impl error::Error for Errno {}
-
-impl fmt::Display for Errno {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{:?}: {}", self, self.desc())
- }
-}
-
-impl From<Errno> for io::Error {
- fn from(err: Errno) -> Self {
- io::Error::from_raw_os_error(err as i32)
- }
-}
-
-fn last() -> Errno {
- Errno::from_i32(errno())
-}
-
-fn desc(errno: Errno) -> &'static str {
- use self::Errno::*;
- match errno {
- UnknownErrno => "Unknown errno",
- EPERM => "Operation not permitted",
- ENOENT => "No such file or directory",
- ESRCH => "No such process",
- EINTR => "Interrupted system call",
- EIO => "I/O error",
- ENXIO => "No such device or address",
- E2BIG => "Argument list too long",
- ENOEXEC => "Exec format error",
- EBADF => "Bad file number",
- ECHILD => "No child processes",
- EAGAIN => "Try again",
- ENOMEM => "Out of memory",
- EACCES => "Permission denied",
- EFAULT => "Bad address",
- ENOTBLK => "Block device required",
- EBUSY => "Device or resource busy",
- EEXIST => "File exists",
- EXDEV => "Cross-device link",
- ENODEV => "No such device",
- ENOTDIR => "Not a directory",
- EISDIR => "Is a directory",
- EINVAL => "Invalid argument",
- ENFILE => "File table overflow",
- EMFILE => "Too many open files",
- ENOTTY => "Not a typewriter",
- ETXTBSY => "Text file busy",
- EFBIG => "File too large",
- ENOSPC => "No space left on device",
- ESPIPE => "Illegal seek",
- EROFS => "Read-only file system",
- EMLINK => "Too many links",
- EPIPE => "Broken pipe",
- EDOM => "Math argument out of domain of func",
- ERANGE => "Math result not representable",
- EDEADLK => "Resource deadlock would occur",
- ENAMETOOLONG => "File name too long",
- ENOLCK => "No record locks available",
- ENOSYS => "Function not implemented",
- ENOTEMPTY => "Directory not empty",
- ELOOP => "Too many symbolic links encountered",
- ENOMSG => "No message of desired type",
- EIDRM => "Identifier removed",
- EINPROGRESS => "Operation now in progress",
- EALREADY => "Operation already in progress",
- ENOTSOCK => "Socket operation on non-socket",
- EDESTADDRREQ => "Destination address required",
- EMSGSIZE => "Message too long",
- EPROTOTYPE => "Protocol wrong type for socket",
- ENOPROTOOPT => "Protocol not available",
- EPROTONOSUPPORT => "Protocol not supported",
- ESOCKTNOSUPPORT => "Socket type not supported",
- EPFNOSUPPORT => "Protocol family not supported",
- EAFNOSUPPORT => "Address family not supported by protocol",
- EADDRINUSE => "Address already in use",
- EADDRNOTAVAIL => "Cannot assign requested address",
- ENETDOWN => "Network is down",
- ENETUNREACH => "Network is unreachable",
- ENETRESET => "Network dropped connection because of reset",
- ECONNABORTED => "Software caused connection abort",
- ECONNRESET => "Connection reset by peer",
- ENOBUFS => "No buffer space available",
- EISCONN => "Transport endpoint is already connected",
- ENOTCONN => "Transport endpoint is not connected",
- ESHUTDOWN => "Cannot send after transport endpoint shutdown",
- ETOOMANYREFS => "Too many references: cannot splice",
- ETIMEDOUT => "Connection timed out",
- ECONNREFUSED => "Connection refused",
- EHOSTDOWN => "Host is down",
- EHOSTUNREACH => "No route to host",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ECHRNG => "Channel number out of range",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EL2NSYNC => "Level 2 not synchronized",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EL3HLT => "Level 3 halted",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EL3RST => "Level 3 reset",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ELNRNG => "Link number out of range",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EUNATCH => "Protocol driver not attached",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ENOCSI => "No CSI structure available",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EL2HLT => "Level 2 halted",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EBADE => "Invalid exchange",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EBADR => "Invalid request descriptor",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EXFULL => "Exchange full",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ENOANO => "No anode",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EBADRQC => "Invalid request code",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EBADSLT => "Invalid slot",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EBFONT => "Bad font file format",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ENOSTR => "Device not a stream",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ENODATA => "No data available",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ETIME => "Timer expired",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ENOSR => "Out of streams resources",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ENONET => "Machine is not on the network",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ENOPKG => "Package not installed",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EREMOTE => "Object is remote",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ENOLINK => "Link has been severed",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EADV => "Advertise error",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ESRMNT => "Srmount error",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ECOMM => "Communication error on send",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EPROTO => "Protocol error",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EMULTIHOP => "Multihop attempted",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EDOTDOT => "RFS specific error",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EBADMSG => "Not a data message",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EOVERFLOW => "Value too large for defined data type",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ENOTUNIQ => "Name not unique on network",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EBADFD => "File descriptor in bad state",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EREMCHG => "Remote address changed",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ELIBACC => "Can not access a needed shared library",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ELIBBAD => "Accessing a corrupted shared library",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ELIBSCN => ".lib section in a.out corrupted",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ELIBMAX => "Attempting to link in too many shared libraries",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ELIBEXEC => "Cannot exec a shared library directly",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia", target_os = "openbsd"))]
- EILSEQ => "Illegal byte sequence",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ERESTART => "Interrupted system call should be restarted",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ESTRPIPE => "Streams pipe error",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EUSERS => "Too many users",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia", target_os = "netbsd",
- target_os = "redox"))]
- EOPNOTSUPP => "Operation not supported on transport endpoint",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ESTALE => "Stale file handle",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EUCLEAN => "Structure needs cleaning",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ENOTNAM => "Not a XENIX named type file",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ENAVAIL => "No XENIX semaphores available",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EISNAM => "Is a named type file",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EREMOTEIO => "Remote I/O error",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EDQUOT => "Quota exceeded",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia", target_os = "openbsd",
- target_os = "dragonfly"))]
- ENOMEDIUM => "No medium found",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia", target_os = "openbsd"))]
- EMEDIUMTYPE => "Wrong medium type",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ECANCELED => "Operation canceled",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ENOKEY => "Required key not available",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EKEYEXPIRED => "Key has expired",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EKEYREVOKED => "Key has been revoked",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EKEYREJECTED => "Key was rejected by service",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- EOWNERDEAD => "Owner died",
-
- #[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
- ENOTRECOVERABLE => "State not recoverable",
-
- #[cfg(any(all(target_os = "linux", not(target_arch="mips")),
- target_os = "fuchsia"))]
- ERFKILL => "Operation not possible due to RF-kill",
-
- #[cfg(any(all(target_os = "linux", not(target_arch="mips")),
- target_os = "fuchsia"))]
- EHWPOISON => "Memory page has hardware error",
-
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- EDOOFUS => "Programming error",
-
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "redox"))]
- EMULTIHOP => "Multihop attempted",
-
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "redox"))]
- ENOLINK => "Link has been severed",
-
- #[cfg(target_os = "freebsd")]
- ENOTCAPABLE => "Capabilities insufficient",
-
- #[cfg(target_os = "freebsd")]
- ECAPMODE => "Not permitted in capability mode",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd"))]
- ENEEDAUTH => "Need authenticator",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd",
- target_os = "redox"))]
- EOVERFLOW => "Value too large to be stored in data type",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "netbsd", target_os = "redox"))]
- EILSEQ => "Illegal byte sequence",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd"))]
- ENOATTR => "Attribute not found",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd",
- target_os = "redox"))]
- EBADMSG => "Bad message",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd",
- target_os = "redox"))]
- EPROTO => "Protocol error",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "ios", target_os = "openbsd", ))]
- ENOTRECOVERABLE => "State not recoverable",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "ios", target_os = "openbsd"))]
- EOWNERDEAD => "Previous owner died",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd"))]
- ENOTSUP => "Operation not supported",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd"))]
- EPROCLIM => "Too many processes",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd",
- target_os = "redox"))]
- EUSERS => "Too many users",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd",
- target_os = "redox"))]
- EDQUOT => "Disc quota exceeded",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd",
- target_os = "redox"))]
- ESTALE => "Stale NFS file handle",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd",
- target_os = "redox"))]
- EREMOTE => "Too many levels of remote in path",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd"))]
- EBADRPC => "RPC struct is bad",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd"))]
- ERPCMISMATCH => "RPC version wrong",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd"))]
- EPROGUNAVAIL => "RPC prog. not avail",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd"))]
- EPROGMISMATCH => "Program version wrong",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd"))]
- EPROCUNAVAIL => "Bad procedure for program",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd"))]
- EFTYPE => "Inappropriate file type or format",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd"))]
- EAUTH => "Authentication error",
-
- #[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd",
- target_os = "redox"))]
- ECANCELED => "Operation canceled",
-
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- EPWROFF => "Device power is off",
-
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- EDEVERR => "Device error, e.g. paper out",
-
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- EBADEXEC => "Bad executable",
-
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- EBADARCH => "Bad CPU type in executable",
-
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- ESHLIBVERS => "Shared library version mismatch",
-
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- EBADMACHO => "Malformed Macho file",
-
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
- EMULTIHOP => "Reserved",
-
- #[cfg(any(target_os = "macos", target_os = "ios",
- target_os = "netbsd", target_os = "redox"))]
- ENODATA => "No message available on STREAM",
-
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
- ENOLINK => "Reserved",
-
- #[cfg(any(target_os = "macos", target_os = "ios",
- target_os = "netbsd", target_os = "redox"))]
- ENOSR => "No STREAM resources",
-
- #[cfg(any(target_os = "macos", target_os = "ios",
- target_os = "netbsd", target_os = "redox"))]
- ENOSTR => "Not a STREAM",
-
- #[cfg(any(target_os = "macos", target_os = "ios",
- target_os = "netbsd", target_os = "redox"))]
- ETIME => "STREAM ioctl timeout",
-
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- EOPNOTSUPP => "Operation not supported on socket",
-
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- ENOPOLICY => "No such policy registered",
-
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- EQFULL => "Interface output queue is full",
-
- #[cfg(target_os = "openbsd")]
- EOPNOTSUPP => "Operation not supported",
-
- #[cfg(target_os = "openbsd")]
- EIPSEC => "IPsec processing failure",
-
- #[cfg(target_os = "dragonfly")]
- EASYNC => "Async",
- }
-}
-
-#[cfg(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia"))]
-mod consts {
- #[derive(Clone, Copy, Debug, Eq, PartialEq)]
- #[repr(i32)]
- pub enum Errno {
- UnknownErrno = 0,
- EPERM = libc::EPERM,
- ENOENT = libc::ENOENT,
- ESRCH = libc::ESRCH,
- EINTR = libc::EINTR,
- EIO = libc::EIO,
- ENXIO = libc::ENXIO,
- E2BIG = libc::E2BIG,
- ENOEXEC = libc::ENOEXEC,
- EBADF = libc::EBADF,
- ECHILD = libc::ECHILD,
- EAGAIN = libc::EAGAIN,
- ENOMEM = libc::ENOMEM,
- EACCES = libc::EACCES,
- EFAULT = libc::EFAULT,
- ENOTBLK = libc::ENOTBLK,
- EBUSY = libc::EBUSY,
- EEXIST = libc::EEXIST,
- EXDEV = libc::EXDEV,
- ENODEV = libc::ENODEV,
- ENOTDIR = libc::ENOTDIR,
- EISDIR = libc::EISDIR,
- EINVAL = libc::EINVAL,
- ENFILE = libc::ENFILE,
- EMFILE = libc::EMFILE,
- ENOTTY = libc::ENOTTY,
- ETXTBSY = libc::ETXTBSY,
- EFBIG = libc::EFBIG,
- ENOSPC = libc::ENOSPC,
- ESPIPE = libc::ESPIPE,
- EROFS = libc::EROFS,
- EMLINK = libc::EMLINK,
- EPIPE = libc::EPIPE,
- EDOM = libc::EDOM,
- ERANGE = libc::ERANGE,
- EDEADLK = libc::EDEADLK,
- ENAMETOOLONG = libc::ENAMETOOLONG,
- ENOLCK = libc::ENOLCK,
- ENOSYS = libc::ENOSYS,
- ENOTEMPTY = libc::ENOTEMPTY,
- ELOOP = libc::ELOOP,
- ENOMSG = libc::ENOMSG,
- EIDRM = libc::EIDRM,
- ECHRNG = libc::ECHRNG,
- EL2NSYNC = libc::EL2NSYNC,
- EL3HLT = libc::EL3HLT,
- EL3RST = libc::EL3RST,
- ELNRNG = libc::ELNRNG,
- EUNATCH = libc::EUNATCH,
- ENOCSI = libc::ENOCSI,
- EL2HLT = libc::EL2HLT,
- EBADE = libc::EBADE,
- EBADR = libc::EBADR,
- EXFULL = libc::EXFULL,
- ENOANO = libc::ENOANO,
- EBADRQC = libc::EBADRQC,
- EBADSLT = libc::EBADSLT,
- EBFONT = libc::EBFONT,
- ENOSTR = libc::ENOSTR,
- ENODATA = libc::ENODATA,
- ETIME = libc::ETIME,
- ENOSR = libc::ENOSR,
- ENONET = libc::ENONET,
- ENOPKG = libc::ENOPKG,
- EREMOTE = libc::EREMOTE,
- ENOLINK = libc::ENOLINK,
- EADV = libc::EADV,
- ESRMNT = libc::ESRMNT,
- ECOMM = libc::ECOMM,
- EPROTO = libc::EPROTO,
- EMULTIHOP = libc::EMULTIHOP,
- EDOTDOT = libc::EDOTDOT,
- EBADMSG = libc::EBADMSG,
- EOVERFLOW = libc::EOVERFLOW,
- ENOTUNIQ = libc::ENOTUNIQ,
- EBADFD = libc::EBADFD,
- EREMCHG = libc::EREMCHG,
- ELIBACC = libc::ELIBACC,
- ELIBBAD = libc::ELIBBAD,
- ELIBSCN = libc::ELIBSCN,
- ELIBMAX = libc::ELIBMAX,
- ELIBEXEC = libc::ELIBEXEC,
- EILSEQ = libc::EILSEQ,
- ERESTART = libc::ERESTART,
- ESTRPIPE = libc::ESTRPIPE,
- EUSERS = libc::EUSERS,
- ENOTSOCK = libc::ENOTSOCK,
- EDESTADDRREQ = libc::EDESTADDRREQ,
- EMSGSIZE = libc::EMSGSIZE,
- EPROTOTYPE = libc::EPROTOTYPE,
- ENOPROTOOPT = libc::ENOPROTOOPT,
- EPROTONOSUPPORT = libc::EPROTONOSUPPORT,
- ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT,
- EOPNOTSUPP = libc::EOPNOTSUPP,
- EPFNOSUPPORT = libc::EPFNOSUPPORT,
- EAFNOSUPPORT = libc::EAFNOSUPPORT,
- EADDRINUSE = libc::EADDRINUSE,
- EADDRNOTAVAIL = libc::EADDRNOTAVAIL,
- ENETDOWN = libc::ENETDOWN,
- ENETUNREACH = libc::ENETUNREACH,
- ENETRESET = libc::ENETRESET,
- ECONNABORTED = libc::ECONNABORTED,
- ECONNRESET = libc::ECONNRESET,
- ENOBUFS = libc::ENOBUFS,
- EISCONN = libc::EISCONN,
- ENOTCONN = libc::ENOTCONN,
- ESHUTDOWN = libc::ESHUTDOWN,
- ETOOMANYREFS = libc::ETOOMANYREFS,
- ETIMEDOUT = libc::ETIMEDOUT,
- ECONNREFUSED = libc::ECONNREFUSED,
- EHOSTDOWN = libc::EHOSTDOWN,
- EHOSTUNREACH = libc::EHOSTUNREACH,
- EALREADY = libc::EALREADY,
- EINPROGRESS = libc::EINPROGRESS,
- ESTALE = libc::ESTALE,
- EUCLEAN = libc::EUCLEAN,
- ENOTNAM = libc::ENOTNAM,
- ENAVAIL = libc::ENAVAIL,
- EISNAM = libc::EISNAM,
- EREMOTEIO = libc::EREMOTEIO,
- EDQUOT = libc::EDQUOT,
- ENOMEDIUM = libc::ENOMEDIUM,
- EMEDIUMTYPE = libc::EMEDIUMTYPE,
- ECANCELED = libc::ECANCELED,
- ENOKEY = libc::ENOKEY,
- EKEYEXPIRED = libc::EKEYEXPIRED,
- EKEYREVOKED = libc::EKEYREVOKED,
- EKEYREJECTED = libc::EKEYREJECTED,
- EOWNERDEAD = libc::EOWNERDEAD,
- ENOTRECOVERABLE = libc::ENOTRECOVERABLE,
- #[cfg(not(any(target_os = "android", target_arch="mips")))]
- ERFKILL = libc::ERFKILL,
- #[cfg(not(any(target_os = "android", target_arch="mips")))]
- EHWPOISON = libc::EHWPOISON,
- }
-
- pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
- pub const EDEADLOCK: Errno = Errno::EDEADLK;
- pub const ENOTSUP: Errno = Errno::EOPNOTSUPP;
-
- pub fn from_i32(e: i32) -> Errno {
- use self::Errno::*;
-
- match e {
- libc::EPERM => EPERM,
- libc::ENOENT => ENOENT,
- libc::ESRCH => ESRCH,
- libc::EINTR => EINTR,
- libc::EIO => EIO,
- libc::ENXIO => ENXIO,
- libc::E2BIG => E2BIG,
- libc::ENOEXEC => ENOEXEC,
- libc::EBADF => EBADF,
- libc::ECHILD => ECHILD,
- libc::EAGAIN => EAGAIN,
- libc::ENOMEM => ENOMEM,
- libc::EACCES => EACCES,
- libc::EFAULT => EFAULT,
- libc::ENOTBLK => ENOTBLK,
- libc::EBUSY => EBUSY,
- libc::EEXIST => EEXIST,
- libc::EXDEV => EXDEV,
- libc::ENODEV => ENODEV,
- libc::ENOTDIR => ENOTDIR,
- libc::EISDIR => EISDIR,
- libc::EINVAL => EINVAL,
- libc::ENFILE => ENFILE,
- libc::EMFILE => EMFILE,
- libc::ENOTTY => ENOTTY,
- libc::ETXTBSY => ETXTBSY,
- libc::EFBIG => EFBIG,
- libc::ENOSPC => ENOSPC,
- libc::ESPIPE => ESPIPE,
- libc::EROFS => EROFS,
- libc::EMLINK => EMLINK,
- libc::EPIPE => EPIPE,
- libc::EDOM => EDOM,
- libc::ERANGE => ERANGE,
- libc::EDEADLK => EDEADLK,
- libc::ENAMETOOLONG => ENAMETOOLONG,
- libc::ENOLCK => ENOLCK,
- libc::ENOSYS => ENOSYS,
- libc::ENOTEMPTY => ENOTEMPTY,
- libc::ELOOP => ELOOP,
- libc::ENOMSG => ENOMSG,
- libc::EIDRM => EIDRM,
- libc::ECHRNG => ECHRNG,
- libc::EL2NSYNC => EL2NSYNC,
- libc::EL3HLT => EL3HLT,
- libc::EL3RST => EL3RST,
- libc::ELNRNG => ELNRNG,
- libc::EUNATCH => EUNATCH,
- libc::ENOCSI => ENOCSI,
- libc::EL2HLT => EL2HLT,
- libc::EBADE => EBADE,
- libc::EBADR => EBADR,
- libc::EXFULL => EXFULL,
- libc::ENOANO => ENOANO,
- libc::EBADRQC => EBADRQC,
- libc::EBADSLT => EBADSLT,
- libc::EBFONT => EBFONT,
- libc::ENOSTR => ENOSTR,
- libc::ENODATA => ENODATA,
- libc::ETIME => ETIME,
- libc::ENOSR => ENOSR,
- libc::ENONET => ENONET,
- libc::ENOPKG => ENOPKG,
- libc::EREMOTE => EREMOTE,
- libc::ENOLINK => ENOLINK,
- libc::EADV => EADV,
- libc::ESRMNT => ESRMNT,
- libc::ECOMM => ECOMM,
- libc::EPROTO => EPROTO,
- libc::EMULTIHOP => EMULTIHOP,
- libc::EDOTDOT => EDOTDOT,
- libc::EBADMSG => EBADMSG,
- libc::EOVERFLOW => EOVERFLOW,
- libc::ENOTUNIQ => ENOTUNIQ,
- libc::EBADFD => EBADFD,
- libc::EREMCHG => EREMCHG,
- libc::ELIBACC => ELIBACC,
- libc::ELIBBAD => ELIBBAD,
- libc::ELIBSCN => ELIBSCN,
- libc::ELIBMAX => ELIBMAX,
- libc::ELIBEXEC => ELIBEXEC,
- libc::EILSEQ => EILSEQ,
- libc::ERESTART => ERESTART,
- libc::ESTRPIPE => ESTRPIPE,
- libc::EUSERS => EUSERS,
- libc::ENOTSOCK => ENOTSOCK,
- libc::EDESTADDRREQ => EDESTADDRREQ,
- libc::EMSGSIZE => EMSGSIZE,
- libc::EPROTOTYPE => EPROTOTYPE,
- libc::ENOPROTOOPT => ENOPROTOOPT,
- libc::EPROTONOSUPPORT => EPROTONOSUPPORT,
- libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT,
- libc::EOPNOTSUPP => EOPNOTSUPP,
- libc::EPFNOSUPPORT => EPFNOSUPPORT,
- libc::EAFNOSUPPORT => EAFNOSUPPORT,
- libc::EADDRINUSE => EADDRINUSE,
- libc::EADDRNOTAVAIL => EADDRNOTAVAIL,
- libc::ENETDOWN => ENETDOWN,
- libc::ENETUNREACH => ENETUNREACH,
- libc::ENETRESET => ENETRESET,
- libc::ECONNABORTED => ECONNABORTED,
- libc::ECONNRESET => ECONNRESET,
- libc::ENOBUFS => ENOBUFS,
- libc::EISCONN => EISCONN,
- libc::ENOTCONN => ENOTCONN,
- libc::ESHUTDOWN => ESHUTDOWN,
- libc::ETOOMANYREFS => ETOOMANYREFS,
- libc::ETIMEDOUT => ETIMEDOUT,
- libc::ECONNREFUSED => ECONNREFUSED,
- libc::EHOSTDOWN => EHOSTDOWN,
- libc::EHOSTUNREACH => EHOSTUNREACH,
- libc::EALREADY => EALREADY,
- libc::EINPROGRESS => EINPROGRESS,
- libc::ESTALE => ESTALE,
- libc::EUCLEAN => EUCLEAN,
- libc::ENOTNAM => ENOTNAM,
- libc::ENAVAIL => ENAVAIL,
- libc::EISNAM => EISNAM,
- libc::EREMOTEIO => EREMOTEIO,
- libc::EDQUOT => EDQUOT,
- libc::ENOMEDIUM => ENOMEDIUM,
- libc::EMEDIUMTYPE => EMEDIUMTYPE,
- libc::ECANCELED => ECANCELED,
- libc::ENOKEY => ENOKEY,
- libc::EKEYEXPIRED => EKEYEXPIRED,
- libc::EKEYREVOKED => EKEYREVOKED,
- libc::EKEYREJECTED => EKEYREJECTED,
- libc::EOWNERDEAD => EOWNERDEAD,
- libc::ENOTRECOVERABLE => ENOTRECOVERABLE,
- #[cfg(not(any(target_os = "android", target_arch="mips")))]
- libc::ERFKILL => ERFKILL,
- #[cfg(not(any(target_os = "android", target_arch="mips")))]
- libc::EHWPOISON => EHWPOISON,
- _ => UnknownErrno,
- }
- }
-}
-
-#[cfg(any(target_os = "macos", target_os = "ios"))]
-mod consts {
- #[derive(Clone, Copy, Debug, Eq, PartialEq)]
- #[repr(i32)]
- pub enum Errno {
- UnknownErrno = 0,
- EPERM = libc::EPERM,
- ENOENT = libc::ENOENT,
- ESRCH = libc::ESRCH,
- EINTR = libc::EINTR,
- EIO = libc::EIO,
- ENXIO = libc::ENXIO,
- E2BIG = libc::E2BIG,
- ENOEXEC = libc::ENOEXEC,
- EBADF = libc::EBADF,
- ECHILD = libc::ECHILD,
- EDEADLK = libc::EDEADLK,
- ENOMEM = libc::ENOMEM,
- EACCES = libc::EACCES,
- EFAULT = libc::EFAULT,
- ENOTBLK = libc::ENOTBLK,
- EBUSY = libc::EBUSY,
- EEXIST = libc::EEXIST,
- EXDEV = libc::EXDEV,
- ENODEV = libc::ENODEV,
- ENOTDIR = libc::ENOTDIR,
- EISDIR = libc::EISDIR,
- EINVAL = libc::EINVAL,
- ENFILE = libc::ENFILE,
- EMFILE = libc::EMFILE,
- ENOTTY = libc::ENOTTY,
- ETXTBSY = libc::ETXTBSY,
- EFBIG = libc::EFBIG,
- ENOSPC = libc::ENOSPC,
- ESPIPE = libc::ESPIPE,
- EROFS = libc::EROFS,
- EMLINK = libc::EMLINK,
- EPIPE = libc::EPIPE,
- EDOM = libc::EDOM,
- ERANGE = libc::ERANGE,
- EAGAIN = libc::EAGAIN,
- EINPROGRESS = libc::EINPROGRESS,
- EALREADY = libc::EALREADY,
- ENOTSOCK = libc::ENOTSOCK,
- EDESTADDRREQ = libc::EDESTADDRREQ,
- EMSGSIZE = libc::EMSGSIZE,
- EPROTOTYPE = libc::EPROTOTYPE,
- ENOPROTOOPT = libc::ENOPROTOOPT,
- EPROTONOSUPPORT = libc::EPROTONOSUPPORT,
- ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT,
- ENOTSUP = libc::ENOTSUP,
- EPFNOSUPPORT = libc::EPFNOSUPPORT,
- EAFNOSUPPORT = libc::EAFNOSUPPORT,
- EADDRINUSE = libc::EADDRINUSE,
- EADDRNOTAVAIL = libc::EADDRNOTAVAIL,
- ENETDOWN = libc::ENETDOWN,
- ENETUNREACH = libc::ENETUNREACH,
- ENETRESET = libc::ENETRESET,
- ECONNABORTED = libc::ECONNABORTED,
- ECONNRESET = libc::ECONNRESET,
- ENOBUFS = libc::ENOBUFS,
- EISCONN = libc::EISCONN,
- ENOTCONN = libc::ENOTCONN,
- ESHUTDOWN = libc::ESHUTDOWN,
- ETOOMANYREFS = libc::ETOOMANYREFS,
- ETIMEDOUT = libc::ETIMEDOUT,
- ECONNREFUSED = libc::ECONNREFUSED,
- ELOOP = libc::ELOOP,
- ENAMETOOLONG = libc::ENAMETOOLONG,
- EHOSTDOWN = libc::EHOSTDOWN,
- EHOSTUNREACH = libc::EHOSTUNREACH,
- ENOTEMPTY = libc::ENOTEMPTY,
- EPROCLIM = libc::EPROCLIM,
- EUSERS = libc::EUSERS,
- EDQUOT = libc::EDQUOT,
- ESTALE = libc::ESTALE,
- EREMOTE = libc::EREMOTE,
- EBADRPC = libc::EBADRPC,
- ERPCMISMATCH = libc::ERPCMISMATCH,
- EPROGUNAVAIL = libc::EPROGUNAVAIL,
- EPROGMISMATCH = libc::EPROGMISMATCH,
- EPROCUNAVAIL = libc::EPROCUNAVAIL,
- ENOLCK = libc::ENOLCK,
- ENOSYS = libc::ENOSYS,
- EFTYPE = libc::EFTYPE,
- EAUTH = libc::EAUTH,
- ENEEDAUTH = libc::ENEEDAUTH,
- EPWROFF = libc::EPWROFF,
- EDEVERR = libc::EDEVERR,
- EOVERFLOW = libc::EOVERFLOW,
- EBADEXEC = libc::EBADEXEC,
- EBADARCH = libc::EBADARCH,
- ESHLIBVERS = libc::ESHLIBVERS,
- EBADMACHO = libc::EBADMACHO,
- ECANCELED = libc::ECANCELED,
- EIDRM = libc::EIDRM,
- ENOMSG = libc::ENOMSG,
- EILSEQ = libc::EILSEQ,
- ENOATTR = libc::ENOATTR,
- EBADMSG = libc::EBADMSG,
- EMULTIHOP = libc::EMULTIHOP,
- ENODATA = libc::ENODATA,
- ENOLINK = libc::ENOLINK,
- ENOSR = libc::ENOSR,
- ENOSTR = libc::ENOSTR,
- EPROTO = libc::EPROTO,
- ETIME = libc::ETIME,
- EOPNOTSUPP = libc::EOPNOTSUPP,
- ENOPOLICY = libc::ENOPOLICY,
- ENOTRECOVERABLE = libc::ENOTRECOVERABLE,
- EOWNERDEAD = libc::EOWNERDEAD,
- EQFULL = libc::EQFULL,
- }
-
- pub const ELAST: Errno = Errno::EQFULL;
- pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
- pub const EDEADLOCK: Errno = Errno::EDEADLK;
-
- pub const EL2NSYNC: Errno = Errno::UnknownErrno;
-
- pub fn from_i32(e: i32) -> Errno {
- use self::Errno::*;
-
- match e {
- libc::EPERM => EPERM,
- libc::ENOENT => ENOENT,
- libc::ESRCH => ESRCH,
- libc::EINTR => EINTR,
- libc::EIO => EIO,
- libc::ENXIO => ENXIO,
- libc::E2BIG => E2BIG,
- libc::ENOEXEC => ENOEXEC,
- libc::EBADF => EBADF,
- libc::ECHILD => ECHILD,
- libc::EDEADLK => EDEADLK,
- libc::ENOMEM => ENOMEM,
- libc::EACCES => EACCES,
- libc::EFAULT => EFAULT,
- libc::ENOTBLK => ENOTBLK,
- libc::EBUSY => EBUSY,
- libc::EEXIST => EEXIST,
- libc::EXDEV => EXDEV,
- libc::ENODEV => ENODEV,
- libc::ENOTDIR => ENOTDIR,
- libc::EISDIR => EISDIR,
- libc::EINVAL => EINVAL,
- libc::ENFILE => ENFILE,
- libc::EMFILE => EMFILE,
- libc::ENOTTY => ENOTTY,
- libc::ETXTBSY => ETXTBSY,
- libc::EFBIG => EFBIG,
- libc::ENOSPC => ENOSPC,
- libc::ESPIPE => ESPIPE,
- libc::EROFS => EROFS,
- libc::EMLINK => EMLINK,
- libc::EPIPE => EPIPE,
- libc::EDOM => EDOM,
- libc::ERANGE => ERANGE,
- libc::EAGAIN => EAGAIN,
- libc::EINPROGRESS => EINPROGRESS,
- libc::EALREADY => EALREADY,
- libc::ENOTSOCK => ENOTSOCK,
- libc::EDESTADDRREQ => EDESTADDRREQ,
- libc::EMSGSIZE => EMSGSIZE,
- libc::EPROTOTYPE => EPROTOTYPE,
- libc::ENOPROTOOPT => ENOPROTOOPT,
- libc::EPROTONOSUPPORT => EPROTONOSUPPORT,
- libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT,
- libc::ENOTSUP => ENOTSUP,
- libc::EPFNOSUPPORT => EPFNOSUPPORT,
- libc::EAFNOSUPPORT => EAFNOSUPPORT,
- libc::EADDRINUSE => EADDRINUSE,
- libc::EADDRNOTAVAIL => EADDRNOTAVAIL,
- libc::ENETDOWN => ENETDOWN,
- libc::ENETUNREACH => ENETUNREACH,
- libc::ENETRESET => ENETRESET,
- libc::ECONNABORTED => ECONNABORTED,
- libc::ECONNRESET => ECONNRESET,
- libc::ENOBUFS => ENOBUFS,
- libc::EISCONN => EISCONN,
- libc::ENOTCONN => ENOTCONN,
- libc::ESHUTDOWN => ESHUTDOWN,
- libc::ETOOMANYREFS => ETOOMANYREFS,
- libc::ETIMEDOUT => ETIMEDOUT,
- libc::ECONNREFUSED => ECONNREFUSED,
- libc::ELOOP => ELOOP,
- libc::ENAMETOOLONG => ENAMETOOLONG,
- libc::EHOSTDOWN => EHOSTDOWN,
- libc::EHOSTUNREACH => EHOSTUNREACH,
- libc::ENOTEMPTY => ENOTEMPTY,
- libc::EPROCLIM => EPROCLIM,
- libc::EUSERS => EUSERS,
- libc::EDQUOT => EDQUOT,
- libc::ESTALE => ESTALE,
- libc::EREMOTE => EREMOTE,
- libc::EBADRPC => EBADRPC,
- libc::ERPCMISMATCH => ERPCMISMATCH,
- libc::EPROGUNAVAIL => EPROGUNAVAIL,
- libc::EPROGMISMATCH => EPROGMISMATCH,
- libc::EPROCUNAVAIL => EPROCUNAVAIL,
- libc::ENOLCK => ENOLCK,
- libc::ENOSYS => ENOSYS,
- libc::EFTYPE => EFTYPE,
- libc::EAUTH => EAUTH,
- libc::ENEEDAUTH => ENEEDAUTH,
- libc::EPWROFF => EPWROFF,
- libc::EDEVERR => EDEVERR,
- libc::EOVERFLOW => EOVERFLOW,
- libc::EBADEXEC => EBADEXEC,
- libc::EBADARCH => EBADARCH,
- libc::ESHLIBVERS => ESHLIBVERS,
- libc::EBADMACHO => EBADMACHO,
- libc::ECANCELED => ECANCELED,
- libc::EIDRM => EIDRM,
- libc::ENOMSG => ENOMSG,
- libc::EILSEQ => EILSEQ,
- libc::ENOATTR => ENOATTR,
- libc::EBADMSG => EBADMSG,
- libc::EMULTIHOP => EMULTIHOP,
- libc::ENODATA => ENODATA,
- libc::ENOLINK => ENOLINK,
- libc::ENOSR => ENOSR,
- libc::ENOSTR => ENOSTR,
- libc::EPROTO => EPROTO,
- libc::ETIME => ETIME,
- libc::EOPNOTSUPP => EOPNOTSUPP,
- libc::ENOPOLICY => ENOPOLICY,
- libc::ENOTRECOVERABLE => ENOTRECOVERABLE,
- libc::EOWNERDEAD => EOWNERDEAD,
- libc::EQFULL => EQFULL,
- _ => UnknownErrno,
- }
- }
-}
-
-#[cfg(target_os = "freebsd")]
-mod consts {
- #[derive(Clone, Copy, Debug, Eq, PartialEq)]
- #[repr(i32)]
- pub enum Errno {
- UnknownErrno = 0,
- EPERM = libc::EPERM,
- ENOENT = libc::ENOENT,
- ESRCH = libc::ESRCH,
- EINTR = libc::EINTR,
- EIO = libc::EIO,
- ENXIO = libc::ENXIO,
- E2BIG = libc::E2BIG,
- ENOEXEC = libc::ENOEXEC,
- EBADF = libc::EBADF,
- ECHILD = libc::ECHILD,
- EDEADLK = libc::EDEADLK,
- ENOMEM = libc::ENOMEM,
- EACCES = libc::EACCES,
- EFAULT = libc::EFAULT,
- ENOTBLK = libc::ENOTBLK,
- EBUSY = libc::EBUSY,
- EEXIST = libc::EEXIST,
- EXDEV = libc::EXDEV,
- ENODEV = libc::ENODEV,
- ENOTDIR = libc::ENOTDIR,
- EISDIR = libc::EISDIR,
- EINVAL = libc::EINVAL,
- ENFILE = libc::ENFILE,
- EMFILE = libc::EMFILE,
- ENOTTY = libc::ENOTTY,
- ETXTBSY = libc::ETXTBSY,
- EFBIG = libc::EFBIG,
- ENOSPC = libc::ENOSPC,
- ESPIPE = libc::ESPIPE,
- EROFS = libc::EROFS,
- EMLINK = libc::EMLINK,
- EPIPE = libc::EPIPE,
- EDOM = libc::EDOM,
- ERANGE = libc::ERANGE,
- EAGAIN = libc::EAGAIN,
- EINPROGRESS = libc::EINPROGRESS,
- EALREADY = libc::EALREADY,
- ENOTSOCK = libc::ENOTSOCK,
- EDESTADDRREQ = libc::EDESTADDRREQ,
- EMSGSIZE = libc::EMSGSIZE,
- EPROTOTYPE = libc::EPROTOTYPE,
- ENOPROTOOPT = libc::ENOPROTOOPT,
- EPROTONOSUPPORT = libc::EPROTONOSUPPORT,
- ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT,
- ENOTSUP = libc::ENOTSUP,
- EPFNOSUPPORT = libc::EPFNOSUPPORT,
- EAFNOSUPPORT = libc::EAFNOSUPPORT,
- EADDRINUSE = libc::EADDRINUSE,
- EADDRNOTAVAIL = libc::EADDRNOTAVAIL,
- ENETDOWN = libc::ENETDOWN,
- ENETUNREACH = libc::ENETUNREACH,
- ENETRESET = libc::ENETRESET,
- ECONNABORTED = libc::ECONNABORTED,
- ECONNRESET = libc::ECONNRESET,
- ENOBUFS = libc::ENOBUFS,
- EISCONN = libc::EISCONN,
- ENOTCONN = libc::ENOTCONN,
- ESHUTDOWN = libc::ESHUTDOWN,
- ETOOMANYREFS = libc::ETOOMANYREFS,
- ETIMEDOUT = libc::ETIMEDOUT,
- ECONNREFUSED = libc::ECONNREFUSED,
- ELOOP = libc::ELOOP,
- ENAMETOOLONG = libc::ENAMETOOLONG,
- EHOSTDOWN = libc::EHOSTDOWN,
- EHOSTUNREACH = libc::EHOSTUNREACH,
- ENOTEMPTY = libc::ENOTEMPTY,
- EPROCLIM = libc::EPROCLIM,
- EUSERS = libc::EUSERS,
- EDQUOT = libc::EDQUOT,
- ESTALE = libc::ESTALE,
- EREMOTE = libc::EREMOTE,
- EBADRPC = libc::EBADRPC,
- ERPCMISMATCH = libc::ERPCMISMATCH,
- EPROGUNAVAIL = libc::EPROGUNAVAIL,
- EPROGMISMATCH = libc::EPROGMISMATCH,
- EPROCUNAVAIL = libc::EPROCUNAVAIL,
- ENOLCK = libc::ENOLCK,
- ENOSYS = libc::ENOSYS,
- EFTYPE = libc::EFTYPE,
- EAUTH = libc::EAUTH,
- ENEEDAUTH = libc::ENEEDAUTH,
- EIDRM = libc::EIDRM,
- ENOMSG = libc::ENOMSG,
- EOVERFLOW = libc::EOVERFLOW,
- ECANCELED = libc::ECANCELED,
- EILSEQ = libc::EILSEQ,
- ENOATTR = libc::ENOATTR,
- EDOOFUS = libc::EDOOFUS,
- EBADMSG = libc::EBADMSG,
- EMULTIHOP = libc::EMULTIHOP,
- ENOLINK = libc::ENOLINK,
- EPROTO = libc::EPROTO,
- ENOTCAPABLE = libc::ENOTCAPABLE,
- ECAPMODE = libc::ECAPMODE,
- ENOTRECOVERABLE = libc::ENOTRECOVERABLE,
- EOWNERDEAD = libc::EOWNERDEAD,
- }
-
- pub const ELAST: Errno = Errno::EOWNERDEAD;
- pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
- pub const EDEADLOCK: Errno = Errno::EDEADLK;
-
- pub const EL2NSYNC: Errno = Errno::UnknownErrno;
-
- pub fn from_i32(e: i32) -> Errno {
- use self::Errno::*;
-
- match e {
- libc::EPERM => EPERM,
- libc::ENOENT => ENOENT,
- libc::ESRCH => ESRCH,
- libc::EINTR => EINTR,
- libc::EIO => EIO,
- libc::ENXIO => ENXIO,
- libc::E2BIG => E2BIG,
- libc::ENOEXEC => ENOEXEC,
- libc::EBADF => EBADF,
- libc::ECHILD => ECHILD,
- libc::EDEADLK => EDEADLK,
- libc::ENOMEM => ENOMEM,
- libc::EACCES => EACCES,
- libc::EFAULT => EFAULT,
- libc::ENOTBLK => ENOTBLK,
- libc::EBUSY => EBUSY,
- libc::EEXIST => EEXIST,
- libc::EXDEV => EXDEV,
- libc::ENODEV => ENODEV,
- libc::ENOTDIR => ENOTDIR,
- libc::EISDIR => EISDIR,
- libc::EINVAL => EINVAL,
- libc::ENFILE => ENFILE,
- libc::EMFILE => EMFILE,
- libc::ENOTTY => ENOTTY,
- libc::ETXTBSY => ETXTBSY,
- libc::EFBIG => EFBIG,
- libc::ENOSPC => ENOSPC,
- libc::ESPIPE => ESPIPE,
- libc::EROFS => EROFS,
- libc::EMLINK => EMLINK,
- libc::EPIPE => EPIPE,
- libc::EDOM => EDOM,
- libc::ERANGE => ERANGE,
- libc::EAGAIN => EAGAIN,
- libc::EINPROGRESS => EINPROGRESS,
- libc::EALREADY => EALREADY,
- libc::ENOTSOCK => ENOTSOCK,
- libc::EDESTADDRREQ => EDESTADDRREQ,
- libc::EMSGSIZE => EMSGSIZE,
- libc::EPROTOTYPE => EPROTOTYPE,
- libc::ENOPROTOOPT => ENOPROTOOPT,
- libc::EPROTONOSUPPORT => EPROTONOSUPPORT,
- libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT,
- libc::ENOTSUP => ENOTSUP,
- libc::EPFNOSUPPORT => EPFNOSUPPORT,
- libc::EAFNOSUPPORT => EAFNOSUPPORT,
- libc::EADDRINUSE => EADDRINUSE,
- libc::EADDRNOTAVAIL => EADDRNOTAVAIL,
- libc::ENETDOWN => ENETDOWN,
- libc::ENETUNREACH => ENETUNREACH,
- libc::ENETRESET => ENETRESET,
- libc::ECONNABORTED => ECONNABORTED,
- libc::ECONNRESET => ECONNRESET,
- libc::ENOBUFS => ENOBUFS,
- libc::EISCONN => EISCONN,
- libc::ENOTCONN => ENOTCONN,
- libc::ESHUTDOWN => ESHUTDOWN,
- libc::ETOOMANYREFS => ETOOMANYREFS,
- libc::ETIMEDOUT => ETIMEDOUT,
- libc::ECONNREFUSED => ECONNREFUSED,
- libc::ELOOP => ELOOP,
- libc::ENAMETOOLONG => ENAMETOOLONG,
- libc::EHOSTDOWN => EHOSTDOWN,
- libc::EHOSTUNREACH => EHOSTUNREACH,
- libc::ENOTEMPTY => ENOTEMPTY,
- libc::EPROCLIM => EPROCLIM,
- libc::EUSERS => EUSERS,
- libc::EDQUOT => EDQUOT,
- libc::ESTALE => ESTALE,
- libc::EREMOTE => EREMOTE,
- libc::EBADRPC => EBADRPC,
- libc::ERPCMISMATCH => ERPCMISMATCH,
- libc::EPROGUNAVAIL => EPROGUNAVAIL,
- libc::EPROGMISMATCH => EPROGMISMATCH,
- libc::EPROCUNAVAIL => EPROCUNAVAIL,
- libc::ENOLCK => ENOLCK,
- libc::ENOSYS => ENOSYS,
- libc::EFTYPE => EFTYPE,
- libc::EAUTH => EAUTH,
- libc::ENEEDAUTH => ENEEDAUTH,
- libc::EIDRM => EIDRM,
- libc::ENOMSG => ENOMSG,
- libc::EOVERFLOW => EOVERFLOW,
- libc::ECANCELED => ECANCELED,
- libc::EILSEQ => EILSEQ,
- libc::ENOATTR => ENOATTR,
- libc::EDOOFUS => EDOOFUS,
- libc::EBADMSG => EBADMSG,
- libc::EMULTIHOP => EMULTIHOP,
- libc::ENOLINK => ENOLINK,
- libc::EPROTO => EPROTO,
- libc::ENOTCAPABLE => ENOTCAPABLE,
- libc::ECAPMODE => ECAPMODE,
- libc::ENOTRECOVERABLE => ENOTRECOVERABLE,
- libc::EOWNERDEAD => EOWNERDEAD,
- _ => UnknownErrno,
- }
- }
-}
-
-
-#[cfg(target_os = "dragonfly")]
-mod consts {
- #[derive(Clone, Copy, Debug, Eq, PartialEq)]
- #[repr(i32)]
- pub enum Errno {
- UnknownErrno = 0,
- EPERM = libc::EPERM,
- ENOENT = libc::ENOENT,
- ESRCH = libc::ESRCH,
- EINTR = libc::EINTR,
- EIO = libc::EIO,
- ENXIO = libc::ENXIO,
- E2BIG = libc::E2BIG,
- ENOEXEC = libc::ENOEXEC,
- EBADF = libc::EBADF,
- ECHILD = libc::ECHILD,
- EDEADLK = libc::EDEADLK,
- ENOMEM = libc::ENOMEM,
- EACCES = libc::EACCES,
- EFAULT = libc::EFAULT,
- ENOTBLK = libc::ENOTBLK,
- EBUSY = libc::EBUSY,
- EEXIST = libc::EEXIST,
- EXDEV = libc::EXDEV,
- ENODEV = libc::ENODEV,
- ENOTDIR = libc::ENOTDIR,
- EISDIR = libc::EISDIR,
- EINVAL = libc::EINVAL,
- ENFILE = libc::ENFILE,
- EMFILE = libc::EMFILE,
- ENOTTY = libc::ENOTTY,
- ETXTBSY = libc::ETXTBSY,
- EFBIG = libc::EFBIG,
- ENOSPC = libc::ENOSPC,
- ESPIPE = libc::ESPIPE,
- EROFS = libc::EROFS,
- EMLINK = libc::EMLINK,
- EPIPE = libc::EPIPE,
- EDOM = libc::EDOM,
- ERANGE = libc::ERANGE,
- EAGAIN = libc::EAGAIN,
- EINPROGRESS = libc::EINPROGRESS,
- EALREADY = libc::EALREADY,
- ENOTSOCK = libc::ENOTSOCK,
- EDESTADDRREQ = libc::EDESTADDRREQ,
- EMSGSIZE = libc::EMSGSIZE,
- EPROTOTYPE = libc::EPROTOTYPE,
- ENOPROTOOPT = libc::ENOPROTOOPT,
- EPROTONOSUPPORT = libc::EPROTONOSUPPORT,
- ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT,
- ENOTSUP = libc::ENOTSUP,
- EPFNOSUPPORT = libc::EPFNOSUPPORT,
- EAFNOSUPPORT = libc::EAFNOSUPPORT,
- EADDRINUSE = libc::EADDRINUSE,
- EADDRNOTAVAIL = libc::EADDRNOTAVAIL,
- ENETDOWN = libc::ENETDOWN,
- ENETUNREACH = libc::ENETUNREACH,
- ENETRESET = libc::ENETRESET,
- ECONNABORTED = libc::ECONNABORTED,
- ECONNRESET = libc::ECONNRESET,
- ENOBUFS = libc::ENOBUFS,
- EISCONN = libc::EISCONN,
- ENOTCONN = libc::ENOTCONN,
- ESHUTDOWN = libc::ESHUTDOWN,
- ETOOMANYREFS = libc::ETOOMANYREFS,
- ETIMEDOUT = libc::ETIMEDOUT,
- ECONNREFUSED = libc::ECONNREFUSED,
- ELOOP = libc::ELOOP,
- ENAMETOOLONG = libc::ENAMETOOLONG,
- EHOSTDOWN = libc::EHOSTDOWN,
- EHOSTUNREACH = libc::EHOSTUNREACH,
- ENOTEMPTY = libc::ENOTEMPTY,
- EPROCLIM = libc::EPROCLIM,
- EUSERS = libc::EUSERS,
- EDQUOT = libc::EDQUOT,
- ESTALE = libc::ESTALE,
- EREMOTE = libc::EREMOTE,
- EBADRPC = libc::EBADRPC,
- ERPCMISMATCH = libc::ERPCMISMATCH,
- EPROGUNAVAIL = libc::EPROGUNAVAIL,
- EPROGMISMATCH = libc::EPROGMISMATCH,
- EPROCUNAVAIL = libc::EPROCUNAVAIL,
- ENOLCK = libc::ENOLCK,
- ENOSYS = libc::ENOSYS,
- EFTYPE = libc::EFTYPE,
- EAUTH = libc::EAUTH,
- ENEEDAUTH = libc::ENEEDAUTH,
- EIDRM = libc::EIDRM,
- ENOMSG = libc::ENOMSG,
- EOVERFLOW = libc::EOVERFLOW,
- ECANCELED = libc::ECANCELED,
- EILSEQ = libc::EILSEQ,
- ENOATTR = libc::ENOATTR,
- EDOOFUS = libc::EDOOFUS,
- EBADMSG = libc::EBADMSG,
- EMULTIHOP = libc::EMULTIHOP,
- ENOLINK = libc::ENOLINK,
- EPROTO = libc::EPROTO,
- ENOMEDIUM = libc::ENOMEDIUM,
- EASYNC = libc::EASYNC,
- }
-
- pub const ELAST: Errno = Errno::EASYNC;
- pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
- pub const EDEADLOCK: Errno = Errno::EDEADLK;
- pub const EOPNOTSUPP: Errno = Errno::ENOTSUP;
-
- pub const EL2NSYNC: Errno = Errno::UnknownErrno;
-
- pub fn from_i32(e: i32) -> Errno {
- use self::Errno::*;
-
- match e {
- libc::EPERM => EPERM,
- libc::ENOENT => ENOENT,
- libc::ESRCH => ESRCH,
- libc::EINTR => EINTR,
- libc::EIO => EIO,
- libc::ENXIO => ENXIO,
- libc::E2BIG => E2BIG,
- libc::ENOEXEC => ENOEXEC,
- libc::EBADF => EBADF,
- libc::ECHILD => ECHILD,
- libc::EDEADLK => EDEADLK,
- libc::ENOMEM => ENOMEM,
- libc::EACCES => EACCES,
- libc::EFAULT => EFAULT,
- libc::ENOTBLK => ENOTBLK,
- libc::EBUSY => EBUSY,
- libc::EEXIST => EEXIST,
- libc::EXDEV => EXDEV,
- libc::ENODEV => ENODEV,
- libc::ENOTDIR => ENOTDIR,
- libc::EISDIR=> EISDIR,
- libc::EINVAL => EINVAL,
- libc::ENFILE => ENFILE,
- libc::EMFILE => EMFILE,
- libc::ENOTTY => ENOTTY,
- libc::ETXTBSY => ETXTBSY,
- libc::EFBIG => EFBIG,
- libc::ENOSPC => ENOSPC,
- libc::ESPIPE => ESPIPE,
- libc::EROFS => EROFS,
- libc::EMLINK => EMLINK,
- libc::EPIPE => EPIPE,
- libc::EDOM => EDOM,
- libc::ERANGE => ERANGE,
- libc::EAGAIN => EAGAIN,
- libc::EINPROGRESS => EINPROGRESS,
- libc::EALREADY => EALREADY,
- libc::ENOTSOCK => ENOTSOCK,
- libc::EDESTADDRREQ => EDESTADDRREQ,
- libc::EMSGSIZE => EMSGSIZE,
- libc::EPROTOTYPE => EPROTOTYPE,
- libc::ENOPROTOOPT => ENOPROTOOPT,
- libc::EPROTONOSUPPORT => EPROTONOSUPPORT,
- libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT,
- libc::ENOTSUP => ENOTSUP,
- libc::EPFNOSUPPORT => EPFNOSUPPORT,
- libc::EAFNOSUPPORT => EAFNOSUPPORT,
- libc::EADDRINUSE => EADDRINUSE,
- libc::EADDRNOTAVAIL => EADDRNOTAVAIL,
- libc::ENETDOWN => ENETDOWN,
- libc::ENETUNREACH => ENETUNREACH,
- libc::ENETRESET => ENETRESET,
- libc::ECONNABORTED => ECONNABORTED,
- libc::ECONNRESET => ECONNRESET,
- libc::ENOBUFS => ENOBUFS,
- libc::EISCONN => EISCONN,
- libc::ENOTCONN => ENOTCONN,
- libc::ESHUTDOWN => ESHUTDOWN,
- libc::ETOOMANYREFS => ETOOMANYREFS,
- libc::ETIMEDOUT => ETIMEDOUT,
- libc::ECONNREFUSED => ECONNREFUSED,
- libc::ELOOP => ELOOP,
- libc::ENAMETOOLONG => ENAMETOOLONG,
- libc::EHOSTDOWN => EHOSTDOWN,
- libc::EHOSTUNREACH => EHOSTUNREACH,
- libc::ENOTEMPTY => ENOTEMPTY,
- libc::EPROCLIM => EPROCLIM,
- libc::EUSERS => EUSERS,
- libc::EDQUOT => EDQUOT,
- libc::ESTALE => ESTALE,
- libc::EREMOTE => EREMOTE,
- libc::EBADRPC => EBADRPC,
- libc::ERPCMISMATCH => ERPCMISMATCH,
- libc::EPROGUNAVAIL => EPROGUNAVAIL,
- libc::EPROGMISMATCH => EPROGMISMATCH,
- libc::EPROCUNAVAIL => EPROCUNAVAIL,
- libc::ENOLCK => ENOLCK,
- libc::ENOSYS => ENOSYS,
- libc::EFTYPE => EFTYPE,
- libc::EAUTH => EAUTH,
- libc::ENEEDAUTH => ENEEDAUTH,
- libc::EIDRM => EIDRM,
- libc::ENOMSG => ENOMSG,
- libc::EOVERFLOW => EOVERFLOW,
- libc::ECANCELED => ECANCELED,
- libc::EILSEQ => EILSEQ,
- libc::ENOATTR => ENOATTR,
- libc::EDOOFUS => EDOOFUS,
- libc::EBADMSG => EBADMSG,
- libc::EMULTIHOP => EMULTIHOP,
- libc::ENOLINK => ENOLINK,
- libc::EPROTO => EPROTO,
- libc::ENOMEDIUM => ENOMEDIUM,
- libc::EASYNC => EASYNC,
- _ => UnknownErrno,
- }
- }
-}
-
-
-#[cfg(target_os = "openbsd")]
-mod consts {
- #[derive(Clone, Copy, Debug, Eq, PartialEq)]
- #[repr(i32)]
- pub enum Errno {
- UnknownErrno = 0,
- EPERM = libc::EPERM,
- ENOENT = libc::ENOENT,
- ESRCH = libc::ESRCH,
- EINTR = libc::EINTR,
- EIO = libc::EIO,
- ENXIO = libc::ENXIO,
- E2BIG = libc::E2BIG,
- ENOEXEC = libc::ENOEXEC,
- EBADF = libc::EBADF,
- ECHILD = libc::ECHILD,
- EDEADLK = libc::EDEADLK,
- ENOMEM = libc::ENOMEM,
- EACCES = libc::EACCES,
- EFAULT = libc::EFAULT,
- ENOTBLK = libc::ENOTBLK,
- EBUSY = libc::EBUSY,
- EEXIST = libc::EEXIST,
- EXDEV = libc::EXDEV,
- ENODEV = libc::ENODEV,
- ENOTDIR = libc::ENOTDIR,
- EISDIR = libc::EISDIR,
- EINVAL = libc::EINVAL,
- ENFILE = libc::ENFILE,
- EMFILE = libc::EMFILE,
- ENOTTY = libc::ENOTTY,
- ETXTBSY = libc::ETXTBSY,
- EFBIG = libc::EFBIG,
- ENOSPC = libc::ENOSPC,
- ESPIPE = libc::ESPIPE,
- EROFS = libc::EROFS,
- EMLINK = libc::EMLINK,
- EPIPE = libc::EPIPE,
- EDOM = libc::EDOM,
- ERANGE = libc::ERANGE,
- EAGAIN = libc::EAGAIN,
- EINPROGRESS = libc::EINPROGRESS,
- EALREADY = libc::EALREADY,
- ENOTSOCK = libc::ENOTSOCK,
- EDESTADDRREQ = libc::EDESTADDRREQ,
- EMSGSIZE = libc::EMSGSIZE,
- EPROTOTYPE = libc::EPROTOTYPE,
- ENOPROTOOPT = libc::ENOPROTOOPT,
- EPROTONOSUPPORT = libc::EPROTONOSUPPORT,
- ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT,
- EOPNOTSUPP = libc::EOPNOTSUPP,
- EPFNOSUPPORT = libc::EPFNOSUPPORT,
- EAFNOSUPPORT = libc::EAFNOSUPPORT,
- EADDRINUSE = libc::EADDRINUSE,
- EADDRNOTAVAIL = libc::EADDRNOTAVAIL,
- ENETDOWN = libc::ENETDOWN,
- ENETUNREACH = libc::ENETUNREACH,
- ENETRESET = libc::ENETRESET,
- ECONNABORTED = libc::ECONNABORTED,
- ECONNRESET = libc::ECONNRESET,
- ENOBUFS = libc::ENOBUFS,
- EISCONN = libc::EISCONN,
- ENOTCONN = libc::ENOTCONN,
- ESHUTDOWN = libc::ESHUTDOWN,
- ETOOMANYREFS = libc::ETOOMANYREFS,
- ETIMEDOUT = libc::ETIMEDOUT,
- ECONNREFUSED = libc::ECONNREFUSED,
- ELOOP = libc::ELOOP,
- ENAMETOOLONG = libc::ENAMETOOLONG,
- EHOSTDOWN = libc::EHOSTDOWN,
- EHOSTUNREACH = libc::EHOSTUNREACH,
- ENOTEMPTY = libc::ENOTEMPTY,
- EPROCLIM = libc::EPROCLIM,
- EUSERS = libc::EUSERS,
- EDQUOT = libc::EDQUOT,
- ESTALE = libc::ESTALE,
- EREMOTE = libc::EREMOTE,
- EBADRPC = libc::EBADRPC,
- ERPCMISMATCH = libc::ERPCMISMATCH,
- EPROGUNAVAIL = libc::EPROGUNAVAIL,
- EPROGMISMATCH = libc::EPROGMISMATCH,
- EPROCUNAVAIL = libc::EPROCUNAVAIL,
- ENOLCK = libc::ENOLCK,
- ENOSYS = libc::ENOSYS,
- EFTYPE = libc::EFTYPE,
- EAUTH = libc::EAUTH,
- ENEEDAUTH = libc::ENEEDAUTH,
- EIPSEC = libc::EIPSEC,
- ENOATTR = libc::ENOATTR,
- EILSEQ = libc::EILSEQ,
- ENOMEDIUM = libc::ENOMEDIUM,
- EMEDIUMTYPE = libc::EMEDIUMTYPE,
- EOVERFLOW = libc::EOVERFLOW,
- ECANCELED = libc::ECANCELED,
- EIDRM = libc::EIDRM,
- ENOMSG = libc::ENOMSG,
- ENOTSUP = libc::ENOTSUP,
- EBADMSG = libc::EBADMSG,
- ENOTRECOVERABLE = libc::ENOTRECOVERABLE,
- EOWNERDEAD = libc::EOWNERDEAD,
- EPROTO = libc::EPROTO,
- }
-
- pub const ELAST: Errno = Errno::ENOTSUP;
- pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-
- pub const EL2NSYNC: Errno = Errno::UnknownErrno;
-
- pub fn from_i32(e: i32) -> Errno {
- use self::Errno::*;
-
- match e {
- libc::EPERM => EPERM,
- libc::ENOENT => ENOENT,
- libc::ESRCH => ESRCH,
- libc::EINTR => EINTR,
- libc::EIO => EIO,
- libc::ENXIO => ENXIO,
- libc::E2BIG => E2BIG,
- libc::ENOEXEC => ENOEXEC,
- libc::EBADF => EBADF,
- libc::ECHILD => ECHILD,
- libc::EDEADLK => EDEADLK,
- libc::ENOMEM => ENOMEM,
- libc::EACCES => EACCES,
- libc::EFAULT => EFAULT,
- libc::ENOTBLK => ENOTBLK,
- libc::EBUSY => EBUSY,
- libc::EEXIST => EEXIST,
- libc::EXDEV => EXDEV,
- libc::ENODEV => ENODEV,
- libc::ENOTDIR => ENOTDIR,
- libc::EISDIR => EISDIR,
- libc::EINVAL => EINVAL,
- libc::ENFILE => ENFILE,
- libc::EMFILE => EMFILE,
- libc::ENOTTY => ENOTTY,
- libc::ETXTBSY => ETXTBSY,
- libc::EFBIG => EFBIG,
- libc::ENOSPC => ENOSPC,
- libc::ESPIPE => ESPIPE,
- libc::EROFS => EROFS,
- libc::EMLINK => EMLINK,
- libc::EPIPE => EPIPE,
- libc::EDOM => EDOM,
- libc::ERANGE => ERANGE,
- libc::EAGAIN => EAGAIN,
- libc::EINPROGRESS => EINPROGRESS,
- libc::EALREADY => EALREADY,
- libc::ENOTSOCK => ENOTSOCK,
- libc::EDESTADDRREQ => EDESTADDRREQ,
- libc::EMSGSIZE => EMSGSIZE,
- libc::EPROTOTYPE => EPROTOTYPE,
- libc::ENOPROTOOPT => ENOPROTOOPT,
- libc::EPROTONOSUPPORT => EPROTONOSUPPORT,
- libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT,
- libc::EOPNOTSUPP => EOPNOTSUPP,
- libc::EPFNOSUPPORT => EPFNOSUPPORT,
- libc::EAFNOSUPPORT => EAFNOSUPPORT,
- libc::EADDRINUSE => EADDRINUSE,
- libc::EADDRNOTAVAIL => EADDRNOTAVAIL,
- libc::ENETDOWN => ENETDOWN,
- libc::ENETUNREACH => ENETUNREACH,
- libc::ENETRESET => ENETRESET,
- libc::ECONNABORTED => ECONNABORTED,
- libc::ECONNRESET => ECONNRESET,
- libc::ENOBUFS => ENOBUFS,
- libc::EISCONN => EISCONN,
- libc::ENOTCONN => ENOTCONN,
- libc::ESHUTDOWN => ESHUTDOWN,
- libc::ETOOMANYREFS => ETOOMANYREFS,
- libc::ETIMEDOUT => ETIMEDOUT,
- libc::ECONNREFUSED => ECONNREFUSED,
- libc::ELOOP => ELOOP,
- libc::ENAMETOOLONG => ENAMETOOLONG,
- libc::EHOSTDOWN => EHOSTDOWN,
- libc::EHOSTUNREACH => EHOSTUNREACH,
- libc::ENOTEMPTY => ENOTEMPTY,
- libc::EPROCLIM => EPROCLIM,
- libc::EUSERS => EUSERS,
- libc::EDQUOT => EDQUOT,
- libc::ESTALE => ESTALE,
- libc::EREMOTE => EREMOTE,
- libc::EBADRPC => EBADRPC,
- libc::ERPCMISMATCH => ERPCMISMATCH,
- libc::EPROGUNAVAIL => EPROGUNAVAIL,
- libc::EPROGMISMATCH => EPROGMISMATCH,
- libc::EPROCUNAVAIL => EPROCUNAVAIL,
- libc::ENOLCK => ENOLCK,
- libc::ENOSYS => ENOSYS,
- libc::EFTYPE => EFTYPE,
- libc::EAUTH => EAUTH,
- libc::ENEEDAUTH => ENEEDAUTH,
- libc::EIPSEC => EIPSEC,
- libc::ENOATTR => ENOATTR,
- libc::EILSEQ => EILSEQ,
- libc::ENOMEDIUM => ENOMEDIUM,
- libc::EMEDIUMTYPE => EMEDIUMTYPE,
- libc::EOVERFLOW => EOVERFLOW,
- libc::ECANCELED => ECANCELED,
- libc::EIDRM => EIDRM,
- libc::ENOMSG => ENOMSG,
- libc::ENOTSUP => ENOTSUP,
- libc::EBADMSG => EBADMSG,
- libc::ENOTRECOVERABLE => ENOTRECOVERABLE,
- libc::EOWNERDEAD => EOWNERDEAD,
- libc::EPROTO => EPROTO,
- _ => UnknownErrno,
- }
- }
-}
-
-#[cfg(target_os = "netbsd")]
-mod consts {
- #[derive(Clone, Copy, Debug, Eq, PartialEq)]
- #[repr(i32)]
- pub enum Errno {
- UnknownErrno = 0,
- EPERM = libc::EPERM,
- ENOENT = libc::ENOENT,
- ESRCH = libc::ESRCH,
- EINTR = libc::EINTR,
- EIO = libc::EIO,
- ENXIO = libc::ENXIO,
- E2BIG = libc::E2BIG,
- ENOEXEC = libc::ENOEXEC,
- EBADF = libc::EBADF,
- ECHILD = libc::ECHILD,
- EDEADLK = libc::EDEADLK,
- ENOMEM = libc::ENOMEM,
- EACCES = libc::EACCES,
- EFAULT = libc::EFAULT,
- ENOTBLK = libc::ENOTBLK,
- EBUSY = libc::EBUSY,
- EEXIST = libc::EEXIST,
- EXDEV = libc::EXDEV,
- ENODEV = libc::ENODEV,
- ENOTDIR = libc::ENOTDIR,
- EISDIR = libc::EISDIR,
- EINVAL = libc::EINVAL,
- ENFILE = libc::ENFILE,
- EMFILE = libc::EMFILE,
- ENOTTY = libc::ENOTTY,
- ETXTBSY = libc::ETXTBSY,
- EFBIG = libc::EFBIG,
- ENOSPC = libc::ENOSPC,
- ESPIPE = libc::ESPIPE,
- EROFS = libc::EROFS,
- EMLINK = libc::EMLINK,
- EPIPE = libc::EPIPE,
- EDOM = libc::EDOM,
- ERANGE = libc::ERANGE,
- EAGAIN = libc::EAGAIN,
- EINPROGRESS = libc::EINPROGRESS,
- EALREADY = libc::EALREADY,
- ENOTSOCK = libc::ENOTSOCK,
- EDESTADDRREQ = libc::EDESTADDRREQ,
- EMSGSIZE = libc::EMSGSIZE,
- EPROTOTYPE = libc::EPROTOTYPE,
- ENOPROTOOPT = libc::ENOPROTOOPT,
- EPROTONOSUPPORT = libc::EPROTONOSUPPORT,
- ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT,
- EOPNOTSUPP = libc::EOPNOTSUPP,
- EPFNOSUPPORT = libc::EPFNOSUPPORT,
- EAFNOSUPPORT = libc::EAFNOSUPPORT,
- EADDRINUSE = libc::EADDRINUSE,
- EADDRNOTAVAIL = libc::EADDRNOTAVAIL,
- ENETDOWN = libc::ENETDOWN,
- ENETUNREACH = libc::ENETUNREACH,
- ENETRESET = libc::ENETRESET,
- ECONNABORTED = libc::ECONNABORTED,
- ECONNRESET = libc::ECONNRESET,
- ENOBUFS = libc::ENOBUFS,
- EISCONN = libc::EISCONN,
- ENOTCONN = libc::ENOTCONN,
- ESHUTDOWN = libc::ESHUTDOWN,
- ETOOMANYREFS = libc::ETOOMANYREFS,
- ETIMEDOUT = libc::ETIMEDOUT,
- ECONNREFUSED = libc::ECONNREFUSED,
- ELOOP = libc::ELOOP,
- ENAMETOOLONG = libc::ENAMETOOLONG,
- EHOSTDOWN = libc::EHOSTDOWN,
- EHOSTUNREACH = libc::EHOSTUNREACH,
- ENOTEMPTY = libc::ENOTEMPTY,
- EPROCLIM = libc::EPROCLIM,
- EUSERS = libc::EUSERS,
- EDQUOT = libc::EDQUOT,
- ESTALE = libc::ESTALE,
- EREMOTE = libc::EREMOTE,
- EBADRPC = libc::EBADRPC,
- ERPCMISMATCH = libc::ERPCMISMATCH,
- EPROGUNAVAIL = libc::EPROGUNAVAIL,
- EPROGMISMATCH = libc::EPROGMISMATCH,
- EPROCUNAVAIL = libc::EPROCUNAVAIL,
- ENOLCK = libc::ENOLCK,
- ENOSYS = libc::ENOSYS,
- EFTYPE = libc::EFTYPE,
- EAUTH = libc::EAUTH,
- ENEEDAUTH = libc::ENEEDAUTH,
- EIDRM = libc::EIDRM,
- ENOMSG = libc::ENOMSG,
- EOVERFLOW = libc::EOVERFLOW,
- EILSEQ = libc::EILSEQ,
- ENOTSUP = libc::ENOTSUP,
- ECANCELED = libc::ECANCELED,
- EBADMSG = libc::EBADMSG,
- ENODATA = libc::ENODATA,
- ENOSR = libc::ENOSR,
- ENOSTR = libc::ENOSTR,
- ETIME = libc::ETIME,
- ENOATTR = libc::ENOATTR,
- EMULTIHOP = libc::EMULTIHOP,
- ENOLINK = libc::ENOLINK,
- EPROTO = libc::EPROTO,
- }
-
- pub const ELAST: Errno = Errno::ENOTSUP;
- pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-
- pub const EL2NSYNC: Errno = Errno::UnknownErrno;
-
- pub fn from_i32(e: i32) -> Errno {
- use self::Errno::*;
-
- match e {
- libc::EPERM => EPERM,
- libc::ENOENT => ENOENT,
- libc::ESRCH => ESRCH,
- libc::EINTR => EINTR,
- libc::EIO => EIO,
- libc::ENXIO => ENXIO,
- libc::E2BIG => E2BIG,
- libc::ENOEXEC => ENOEXEC,
- libc::EBADF => EBADF,
- libc::ECHILD => ECHILD,
- libc::EDEADLK => EDEADLK,
- libc::ENOMEM => ENOMEM,
- libc::EACCES => EACCES,
- libc::EFAULT => EFAULT,
- libc::ENOTBLK => ENOTBLK,
- libc::EBUSY => EBUSY,
- libc::EEXIST => EEXIST,
- libc::EXDEV => EXDEV,
- libc::ENODEV => ENODEV,
- libc::ENOTDIR => ENOTDIR,
- libc::EISDIR => EISDIR,
- libc::EINVAL => EINVAL,
- libc::ENFILE => ENFILE,
- libc::EMFILE => EMFILE,
- libc::ENOTTY => ENOTTY,
- libc::ETXTBSY => ETXTBSY,
- libc::EFBIG => EFBIG,
- libc::ENOSPC => ENOSPC,
- libc::ESPIPE => ESPIPE,
- libc::EROFS => EROFS,
- libc::EMLINK => EMLINK,
- libc::EPIPE => EPIPE,
- libc::EDOM => EDOM,
- libc::ERANGE => ERANGE,
- libc::EAGAIN => EAGAIN,
- libc::EINPROGRESS => EINPROGRESS,
- libc::EALREADY => EALREADY,
- libc::ENOTSOCK => ENOTSOCK,
- libc::EDESTADDRREQ => EDESTADDRREQ,
- libc::EMSGSIZE => EMSGSIZE,
- libc::EPROTOTYPE => EPROTOTYPE,
- libc::ENOPROTOOPT => ENOPROTOOPT,
- libc::EPROTONOSUPPORT => EPROTONOSUPPORT,
- libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT,
- libc::EOPNOTSUPP => EOPNOTSUPP,
- libc::EPFNOSUPPORT => EPFNOSUPPORT,
- libc::EAFNOSUPPORT => EAFNOSUPPORT,
- libc::EADDRINUSE => EADDRINUSE,
- libc::EADDRNOTAVAIL => EADDRNOTAVAIL,
- libc::ENETDOWN => ENETDOWN,
- libc::ENETUNREACH => ENETUNREACH,
- libc::ENETRESET => ENETRESET,
- libc::ECONNABORTED => ECONNABORTED,
- libc::ECONNRESET => ECONNRESET,
- libc::ENOBUFS => ENOBUFS,
- libc::EISCONN => EISCONN,
- libc::ENOTCONN => ENOTCONN,
- libc::ESHUTDOWN => ESHUTDOWN,
- libc::ETOOMANYREFS => ETOOMANYREFS,
- libc::ETIMEDOUT => ETIMEDOUT,
- libc::ECONNREFUSED => ECONNREFUSED,
- libc::ELOOP => ELOOP,
- libc::ENAMETOOLONG => ENAMETOOLONG,
- libc::EHOSTDOWN => EHOSTDOWN,
- libc::EHOSTUNREACH => EHOSTUNREACH,
- libc::ENOTEMPTY => ENOTEMPTY,
- libc::EPROCLIM => EPROCLIM,
- libc::EUSERS => EUSERS,
- libc::EDQUOT => EDQUOT,
- libc::ESTALE => ESTALE,
- libc::EREMOTE => EREMOTE,
- libc::EBADRPC => EBADRPC,
- libc::ERPCMISMATCH => ERPCMISMATCH,
- libc::EPROGUNAVAIL => EPROGUNAVAIL,
- libc::EPROGMISMATCH => EPROGMISMATCH,
- libc::EPROCUNAVAIL => EPROCUNAVAIL,
- libc::ENOLCK => ENOLCK,
- libc::ENOSYS => ENOSYS,
- libc::EFTYPE => EFTYPE,
- libc::EAUTH => EAUTH,
- libc::ENEEDAUTH => ENEEDAUTH,
- libc::EIDRM => EIDRM,
- libc::ENOMSG => ENOMSG,
- libc::EOVERFLOW => EOVERFLOW,
- libc::EILSEQ => EILSEQ,
- libc::ENOTSUP => ENOTSUP,
- libc::ECANCELED => ECANCELED,
- libc::EBADMSG => EBADMSG,
- libc::ENODATA => ENODATA,
- libc::ENOSR => ENOSR,
- libc::ENOSTR => ENOSTR,
- libc::ETIME => ETIME,
- libc::ENOATTR => ENOATTR,
- libc::EMULTIHOP => EMULTIHOP,
- libc::ENOLINK => ENOLINK,
- libc::EPROTO => EPROTO,
- _ => UnknownErrno,
- }
- }
-}
-
-#[cfg(target_os = "redox")]
-mod consts {
- #[derive(Clone, Copy, Debug, Eq, PartialEq)]
- #[repr(i32)]
- pub enum Errno {
- UnknownErrno = 0,
- EPERM = libc::EPERM,
- ENOENT = libc::ENOENT,
- ESRCH = libc::ESRCH,
- EINTR = libc::EINTR,
- EIO = libc::EIO,
- ENXIO = libc::ENXIO,
- E2BIG = libc::E2BIG,
- ENOEXEC = libc::ENOEXEC,
- EBADF = libc::EBADF,
- ECHILD = libc::ECHILD,
- EDEADLK = libc::EDEADLK,
- ENOMEM = libc::ENOMEM,
- EACCES = libc::EACCES,
- EFAULT = libc::EFAULT,
- ENOTBLK = libc::ENOTBLK,
- EBUSY = libc::EBUSY,
- EEXIST = libc::EEXIST,
- EXDEV = libc::EXDEV,
- ENODEV = libc::ENODEV,
- ENOTDIR = libc::ENOTDIR,
- EISDIR = libc::EISDIR,
- EINVAL = libc::EINVAL,
- ENFILE = libc::ENFILE,
- EMFILE = libc::EMFILE,
- ENOTTY = libc::ENOTTY,
- ETXTBSY = libc::ETXTBSY,
- EFBIG = libc::EFBIG,
- ENOSPC = libc::ENOSPC,
- ESPIPE = libc::ESPIPE,
- EROFS = libc::EROFS,
- EMLINK = libc::EMLINK,
- EPIPE = libc::EPIPE,
- EDOM = libc::EDOM,
- ERANGE = libc::ERANGE,
- EAGAIN = libc::EAGAIN,
- EINPROGRESS = libc::EINPROGRESS,
- EALREADY = libc::EALREADY,
- ENOTSOCK = libc::ENOTSOCK,
- EDESTADDRREQ = libc::EDESTADDRREQ,
- EMSGSIZE = libc::EMSGSIZE,
- EPROTOTYPE = libc::EPROTOTYPE,
- ENOPROTOOPT = libc::ENOPROTOOPT,
- EPROTONOSUPPORT = libc::EPROTONOSUPPORT,
- ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT,
- EOPNOTSUPP = libc::EOPNOTSUPP,
- EPFNOSUPPORT = libc::EPFNOSUPPORT,
- EAFNOSUPPORT = libc::EAFNOSUPPORT,
- EADDRINUSE = libc::EADDRINUSE,
- EADDRNOTAVAIL = libc::EADDRNOTAVAIL,
- ENETDOWN = libc::ENETDOWN,
- ENETUNREACH = libc::ENETUNREACH,
- ENETRESET = libc::ENETRESET,
- ECONNABORTED = libc::ECONNABORTED,
- ECONNRESET = libc::ECONNRESET,
- ENOBUFS = libc::ENOBUFS,
- EISCONN = libc::EISCONN,
- ENOTCONN = libc::ENOTCONN,
- ESHUTDOWN = libc::ESHUTDOWN,
- ETOOMANYREFS = libc::ETOOMANYREFS,
- ETIMEDOUT = libc::ETIMEDOUT,
- ECONNREFUSED = libc::ECONNREFUSED,
- ELOOP = libc::ELOOP,
- ENAMETOOLONG = libc::ENAMETOOLONG,
- EHOSTDOWN = libc::EHOSTDOWN,
- EHOSTUNREACH = libc::EHOSTUNREACH,
- ENOTEMPTY = libc::ENOTEMPTY,
- EUSERS = libc::EUSERS,
- EDQUOT = libc::EDQUOT,
- ESTALE = libc::ESTALE,
- EREMOTE = libc::EREMOTE,
- ENOLCK = libc::ENOLCK,
- ENOSYS = libc::ENOSYS,
- EIDRM = libc::EIDRM,
- ENOMSG = libc::ENOMSG,
- EOVERFLOW = libc::EOVERFLOW,
- EILSEQ = libc::EILSEQ,
- ECANCELED = libc::ECANCELED,
- EBADMSG = libc::EBADMSG,
- ENODATA = libc::ENODATA,
- ENOSR = libc::ENOSR,
- ENOSTR = libc::ENOSTR,
- ETIME = libc::ETIME,
- EMULTIHOP = libc::EMULTIHOP,
- ENOLINK = libc::ENOLINK,
- EPROTO = libc::EPROTO,
- }
-
- pub const ELAST: Errno = Errno::UnknownErrno;
- pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-
- pub const EL2NSYNC: Errno = Errno::UnknownErrno;
-
- pub fn from_i32(e: i32) -> Errno {
- use self::Errno::*;
-
- match e {
- libc::EPERM => EPERM,
- libc::ENOENT => ENOENT,
- libc::ESRCH => ESRCH,
- libc::EINTR => EINTR,
- libc::EIO => EIO,
- libc::ENXIO => ENXIO,
- libc::E2BIG => E2BIG,
- libc::ENOEXEC => ENOEXEC,
- libc::EBADF => EBADF,
- libc::ECHILD => ECHILD,
- libc::EDEADLK => EDEADLK,
- libc::ENOMEM => ENOMEM,
- libc::EACCES => EACCES,
- libc::EFAULT => EFAULT,
- libc::ENOTBLK => ENOTBLK,
- libc::EBUSY => EBUSY,
- libc::EEXIST => EEXIST,
- libc::EXDEV => EXDEV,
- libc::ENODEV => ENODEV,
- libc::ENOTDIR => ENOTDIR,
- libc::EISDIR => EISDIR,
- libc::EINVAL => EINVAL,
- libc::ENFILE => ENFILE,
- libc::EMFILE => EMFILE,
- libc::ENOTTY => ENOTTY,
- libc::ETXTBSY => ETXTBSY,
- libc::EFBIG => EFBIG,
- libc::ENOSPC => ENOSPC,
- libc::ESPIPE => ESPIPE,
- libc::EROFS => EROFS,
- libc::EMLINK => EMLINK,
- libc::EPIPE => EPIPE,
- libc::EDOM => EDOM,
- libc::ERANGE => ERANGE,
- libc::EAGAIN => EAGAIN,
- libc::EINPROGRESS => EINPROGRESS,
- libc::EALREADY => EALREADY,
- libc::ENOTSOCK => ENOTSOCK,
- libc::EDESTADDRREQ => EDESTADDRREQ,
- libc::EMSGSIZE => EMSGSIZE,
- libc::EPROTOTYPE => EPROTOTYPE,
- libc::ENOPROTOOPT => ENOPROTOOPT,
- libc::EPROTONOSUPPORT => EPROTONOSUPPORT,
- libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT,
- libc::EOPNOTSUPP => EOPNOTSUPP,
- libc::EPFNOSUPPORT => EPFNOSUPPORT,
- libc::EAFNOSUPPORT => EAFNOSUPPORT,
- libc::EADDRINUSE => EADDRINUSE,
- libc::EADDRNOTAVAIL => EADDRNOTAVAIL,
- libc::ENETDOWN => ENETDOWN,
- libc::ENETUNREACH => ENETUNREACH,
- libc::ENETRESET => ENETRESET,
- libc::ECONNABORTED => ECONNABORTED,
- libc::ECONNRESET => ECONNRESET,
- libc::ENOBUFS => ENOBUFS,
- libc::EISCONN => EISCONN,
- libc::ENOTCONN => ENOTCONN,
- libc::ESHUTDOWN => ESHUTDOWN,
- libc::ETOOMANYREFS => ETOOMANYREFS,
- libc::ETIMEDOUT => ETIMEDOUT,
- libc::ECONNREFUSED => ECONNREFUSED,
- libc::ELOOP => ELOOP,
- libc::ENAMETOOLONG => ENAMETOOLONG,
- libc::EHOSTDOWN => EHOSTDOWN,
- libc::EHOSTUNREACH => EHOSTUNREACH,
- libc::ENOTEMPTY => ENOTEMPTY,
- libc::EUSERS => EUSERS,
- libc::EDQUOT => EDQUOT,
- libc::ESTALE => ESTALE,
- libc::EREMOTE => EREMOTE,
- libc::ENOLCK => ENOLCK,
- libc::ENOSYS => ENOSYS,
- libc::EIDRM => EIDRM,
- libc::ENOMSG => ENOMSG,
- libc::EOVERFLOW => EOVERFLOW,
- libc::EILSEQ => EILSEQ,
- libc::ECANCELED => ECANCELED,
- libc::EBADMSG => EBADMSG,
- libc::ENODATA => ENODATA,
- libc::ENOSR => ENOSR,
- libc::ENOSTR => ENOSTR,
- libc::ETIME => ETIME,
- libc::EMULTIHOP => EMULTIHOP,
- libc::ENOLINK => ENOLINK,
- libc::EPROTO => EPROTO,
- _ => UnknownErrno,
- }
- }
-}
diff --git a/vendor/nix-0.20.0/src/fcntl.rs b/vendor/nix-0.20.0/src/fcntl.rs
deleted file mode 100644
index d2242da..0000000
--- a/vendor/nix-0.20.0/src/fcntl.rs
+++ /dev/null
@@ -1,636 +0,0 @@
-use crate::errno::Errno;
-use libc::{self, c_char, c_int, c_uint, size_t, ssize_t};
-use std::ffi::OsString;
-#[cfg(not(target_os = "redox"))]
-use std::os::raw;
-use std::os::unix::ffi::OsStringExt;
-use std::os::unix::io::RawFd;
-use crate::sys::stat::Mode;
-use crate::{NixPath, Result};
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-use std::ptr; // For splice and copy_file_range
-#[cfg(any(target_os = "android", target_os = "linux"))]
-use crate::sys::uio::IoVec; // For vmsplice
-
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- any(target_os = "wasi", target_env = "wasi"),
- target_env = "uclibc",
- target_os = "freebsd"
-))]
-pub use self::posix_fadvise::*;
-
-#[cfg(not(target_os = "redox"))]
-libc_bitflags! {
- pub struct AtFlags: c_int {
- AT_REMOVEDIR;
- AT_SYMLINK_FOLLOW;
- AT_SYMLINK_NOFOLLOW;
- #[cfg(any(target_os = "android", target_os = "linux"))]
- AT_NO_AUTOMOUNT;
- #[cfg(any(target_os = "android", target_os = "linux"))]
- AT_EMPTY_PATH;
- }
-}
-
-libc_bitflags!(
- /// Configuration options for opened files.
- pub struct OFlag: c_int {
- /// Mask for the access mode of the file.
- O_ACCMODE;
- /// Use alternate I/O semantics.
- #[cfg(target_os = "netbsd")]
- O_ALT_IO;
- /// Open the file in append-only mode.
- O_APPEND;
- /// Generate a signal when input or output becomes possible.
- O_ASYNC;
- /// Closes the file descriptor once an `execve` call is made.
- ///
- /// Also sets the file offset to the beginning of the file.
- O_CLOEXEC;
- /// Create the file if it does not exist.
- O_CREAT;
- /// Try to minimize cache effects of the I/O for this file.
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd"))]
- O_DIRECT;
- /// If the specified path isn't a directory, fail.
- O_DIRECTORY;
- /// Implicitly follow each `write()` with an `fdatasync()`.
- #[cfg(any(target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- O_DSYNC;
- /// Error out if a file was not created.
- O_EXCL;
- /// Open for execute only.
- #[cfg(target_os = "freebsd")]
- O_EXEC;
- /// Open with an exclusive file lock.
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "redox"))]
- O_EXLOCK;
- /// Same as `O_SYNC`.
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- all(target_os = "linux", not(target_env = "musl")),
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "redox"))]
- O_FSYNC;
- /// Allow files whose sizes can't be represented in an `off_t` to be opened.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- O_LARGEFILE;
- /// Do not update the file last access time during `read(2)`s.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- O_NOATIME;
- /// Don't attach the device as the process' controlling terminal.
- #[cfg(not(target_os = "redox"))]
- O_NOCTTY;
- /// Same as `O_NONBLOCK`.
- #[cfg(not(target_os = "redox"))]
- O_NDELAY;
- /// `open()` will fail if the given path is a symbolic link.
- O_NOFOLLOW;
- /// When possible, open the file in nonblocking mode.
- O_NONBLOCK;
- /// Don't deliver `SIGPIPE`.
- #[cfg(target_os = "netbsd")]
- O_NOSIGPIPE;
- /// Obtain a file descriptor for low-level access.
- ///
- /// The file itself is not opened and other file operations will fail.
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
- O_PATH;
- /// Only allow reading.
- ///
- /// This should not be combined with `O_WRONLY` or `O_RDWR`.
- O_RDONLY;
- /// Allow both reading and writing.
- ///
- /// This should not be combined with `O_WRONLY` or `O_RDONLY`.
- O_RDWR;
- /// Similar to `O_DSYNC` but applies to `read`s instead.
- #[cfg(any(target_os = "linux", target_os = "netbsd", target_os = "openbsd"))]
- O_RSYNC;
- /// Skip search permission checks.
- #[cfg(target_os = "netbsd")]
- O_SEARCH;
- /// Open with a shared file lock.
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "redox"))]
- O_SHLOCK;
- /// Implicitly follow each `write()` with an `fsync()`.
- #[cfg(not(target_os = "redox"))]
- O_SYNC;
- /// Create an unnamed temporary file.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- O_TMPFILE;
- /// Truncate an existing regular file to 0 length if it allows writing.
- O_TRUNC;
- /// Restore default TTY attributes.
- #[cfg(target_os = "freebsd")]
- O_TTY_INIT;
- /// Only allow writing.
- ///
- /// This should not be combined with `O_RDONLY` or `O_RDWR`.
- O_WRONLY;
- }
-);
-
-// The conversion is not identical on all operating systems.
-#[allow(clippy::identity_conversion)]
-pub fn open<P: ?Sized + NixPath>(path: &P, oflag: OFlag, mode: Mode) -> Result<RawFd> {
- let fd = path.with_nix_path(|cstr| {
- unsafe { libc::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
- })?;
-
- Errno::result(fd)
-}
-
-// The conversion is not identical on all operating systems.
-#[allow(clippy::identity_conversion)]
-#[cfg(not(target_os = "redox"))]
-pub fn openat<P: ?Sized + NixPath>(
- dirfd: RawFd,
- path: &P,
- oflag: OFlag,
- mode: Mode,
-) -> Result<RawFd> {
- let fd = path.with_nix_path(|cstr| {
- unsafe { libc::openat(dirfd, cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
- })?;
- Errno::result(fd)
-}
-
-#[cfg(not(target_os = "redox"))]
-pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
- old_dirfd: Option<RawFd>,
- old_path: &P1,
- new_dirfd: Option<RawFd>,
- new_path: &P2,
-) -> Result<()> {
- let res = old_path.with_nix_path(|old_cstr| {
- new_path.with_nix_path(|new_cstr| unsafe {
- libc::renameat(
- at_rawfd(old_dirfd),
- old_cstr.as_ptr(),
- at_rawfd(new_dirfd),
- new_cstr.as_ptr(),
- )
- })
- })??;
- Errno::result(res).map(drop)
-}
-
-fn wrap_readlink_result(mut v: Vec<u8>, len: ssize_t) -> Result<OsString> {
- unsafe { v.set_len(len as usize) }
- v.shrink_to_fit();
- Ok(OsString::from_vec(v.to_vec()))
-}
-
-fn readlink_maybe_at<P: ?Sized + NixPath>(
- dirfd: Option<RawFd>,
- path: &P,
- v: &mut Vec<u8>,
-) -> Result<libc::ssize_t> {
- path.with_nix_path(|cstr| unsafe {
- match dirfd {
- #[cfg(target_os = "redox")]
- Some(_) => unreachable!(),
- #[cfg(not(target_os = "redox"))]
- Some(dirfd) => libc::readlinkat(
- dirfd,
- cstr.as_ptr(),
- v.as_mut_ptr() as *mut c_char,
- v.capacity() as size_t,
- ),
- None => libc::readlink(
- cstr.as_ptr(),
- v.as_mut_ptr() as *mut c_char,
- v.capacity() as size_t,
- ),
- }
- })
-}
-
-fn inner_readlink<P: ?Sized + NixPath>(dirfd: Option<RawFd>, path: &P) -> Result<OsString> {
- let mut v = Vec::with_capacity(libc::PATH_MAX as usize);
- // simple case: result is strictly less than `PATH_MAX`
- let res = readlink_maybe_at(dirfd, path, &mut v)?;
- let len = Errno::result(res)?;
- debug_assert!(len >= 0);
- if (len as usize) < v.capacity() {
- return wrap_readlink_result(v, res);
- }
- // Uh oh, the result is too long...
- // Let's try to ask lstat how many bytes to allocate.
- let reported_size = super::sys::stat::lstat(path)
- .and_then(|x| Ok(x.st_size))
- .unwrap_or(0);
- let mut try_size = if reported_size > 0 {
- // Note: even if `lstat`'s apparently valid answer turns out to be
- // wrong, we will still read the full symlink no matter what.
- reported_size as usize + 1
- } else {
- // If lstat doesn't cooperate, or reports an error, be a little less
- // precise.
- (libc::PATH_MAX as usize).max(128) << 1
- };
- loop {
- v.reserve_exact(try_size);
- let res = readlink_maybe_at(dirfd, path, &mut v)?;
- let len = Errno::result(res)?;
- debug_assert!(len >= 0);
- if (len as usize) < v.capacity() {
- break wrap_readlink_result(v, res);
- } else {
- // Ugh! Still not big enough!
- match try_size.checked_shl(1) {
- Some(next_size) => try_size = next_size,
- // It's absurd that this would happen, but handle it sanely
- // anyway.
- None => break Err(super::Error::Sys(Errno::ENAMETOOLONG)),
- }
- }
- }
-}
-
-pub fn readlink<P: ?Sized + NixPath>(path: &P) -> Result<OsString> {
- inner_readlink(None, path)
-}
-
-#[cfg(not(target_os = "redox"))]
-pub fn readlinkat<P: ?Sized + NixPath>(dirfd: RawFd, path: &P) -> Result<OsString> {
- inner_readlink(Some(dirfd), path)
-}
-
-/// Computes the raw fd consumed by a function of the form `*at`.
-#[cfg(not(target_os = "redox"))]
-pub(crate) fn at_rawfd(fd: Option<RawFd>) -> raw::c_int {
- match fd {
- None => libc::AT_FDCWD,
- Some(fd) => fd,
- }
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-libc_bitflags!(
- /// Additional flags for file sealing, which allows for limiting operations on a file.
- pub struct SealFlag: c_int {
- /// Prevents further calls to `fcntl()` with `F_ADD_SEALS`.
- F_SEAL_SEAL;
- /// The file cannot be reduced in size.
- F_SEAL_SHRINK;
- /// The size of the file cannot be increased.
- F_SEAL_GROW;
- /// The file contents cannot be modified.
- F_SEAL_WRITE;
- }
-);
-
-libc_bitflags!(
- /// Additional configuration flags for `fcntl`'s `F_SETFD`.
- pub struct FdFlag: c_int {
- /// The file descriptor will automatically be closed during a successful `execve(2)`.
- FD_CLOEXEC;
- }
-);
-
-#[cfg(not(target_os = "redox"))]
-#[derive(Debug, Eq, Hash, PartialEq)]
-pub enum FcntlArg<'a> {
- F_DUPFD(RawFd),
- F_DUPFD_CLOEXEC(RawFd),
- F_GETFD,
- F_SETFD(FdFlag), // FD_FLAGS
- F_GETFL,
- F_SETFL(OFlag), // O_NONBLOCK
- F_SETLK(&'a libc::flock),
- F_SETLKW(&'a libc::flock),
- F_GETLK(&'a mut libc::flock),
- #[cfg(any(target_os = "linux", target_os = "android"))]
- F_OFD_SETLK(&'a libc::flock),
- #[cfg(any(target_os = "linux", target_os = "android"))]
- F_OFD_SETLKW(&'a libc::flock),
- #[cfg(any(target_os = "linux", target_os = "android"))]
- F_OFD_GETLK(&'a mut libc::flock),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- F_ADD_SEALS(SealFlag),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- F_GET_SEALS,
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- F_FULLFSYNC,
- #[cfg(any(target_os = "linux", target_os = "android"))]
- F_GETPIPE_SZ,
- #[cfg(any(target_os = "linux", target_os = "android"))]
- F_SETPIPE_SZ(c_int),
- // TODO: Rest of flags
-}
-
-#[cfg(target_os = "redox")]
-#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
-pub enum FcntlArg {
- F_DUPFD(RawFd),
- F_DUPFD_CLOEXEC(RawFd),
- F_GETFD,
- F_SETFD(FdFlag), // FD_FLAGS
- F_GETFL,
- F_SETFL(OFlag), // O_NONBLOCK
-}
-pub use self::FcntlArg::*;
-
-// TODO: Figure out how to handle value fcntl returns
-pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
- let res = unsafe {
- match arg {
- F_DUPFD(rawfd) => libc::fcntl(fd, libc::F_DUPFD, rawfd),
- F_DUPFD_CLOEXEC(rawfd) => libc::fcntl(fd, libc::F_DUPFD_CLOEXEC, rawfd),
- F_GETFD => libc::fcntl(fd, libc::F_GETFD),
- F_SETFD(flag) => libc::fcntl(fd, libc::F_SETFD, flag.bits()),
- F_GETFL => libc::fcntl(fd, libc::F_GETFL),
- F_SETFL(flag) => libc::fcntl(fd, libc::F_SETFL, flag.bits()),
- #[cfg(not(target_os = "redox"))]
- F_SETLK(flock) => libc::fcntl(fd, libc::F_SETLK, flock),
- #[cfg(not(target_os = "redox"))]
- F_SETLKW(flock) => libc::fcntl(fd, libc::F_SETLKW, flock),
- #[cfg(not(target_os = "redox"))]
- F_GETLK(flock) => libc::fcntl(fd, libc::F_GETLK, flock),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- F_OFD_SETLK(flock) => libc::fcntl(fd, libc::F_OFD_SETLK, flock),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- F_OFD_SETLKW(flock) => libc::fcntl(fd, libc::F_OFD_SETLKW, flock),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- F_OFD_GETLK(flock) => libc::fcntl(fd, libc::F_OFD_GETLK, flock),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- F_ADD_SEALS(flag) => libc::fcntl(fd, libc::F_ADD_SEALS, flag.bits()),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- F_GET_SEALS => libc::fcntl(fd, libc::F_GET_SEALS),
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- F_FULLFSYNC => libc::fcntl(fd, libc::F_FULLFSYNC),
- #[cfg(any(target_os = "linux", target_os = "android"))]
- F_GETPIPE_SZ => libc::fcntl(fd, libc::F_GETPIPE_SZ),
- #[cfg(any(target_os = "linux", target_os = "android"))]
- F_SETPIPE_SZ(size) => libc::fcntl(fd, libc::F_SETPIPE_SZ, size),
- }
- };
-
- Errno::result(res)
-}
-
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum FlockArg {
- LockShared,
- LockExclusive,
- Unlock,
- LockSharedNonblock,
- LockExclusiveNonblock,
- UnlockNonblock,
-}
-
-#[cfg(not(target_os = "redox"))]
-pub fn flock(fd: RawFd, arg: FlockArg) -> Result<()> {
- use self::FlockArg::*;
-
- let res = unsafe {
- match arg {
- LockShared => libc::flock(fd, libc::LOCK_SH),
- LockExclusive => libc::flock(fd, libc::LOCK_EX),
- Unlock => libc::flock(fd, libc::LOCK_UN),
- LockSharedNonblock => libc::flock(fd, libc::LOCK_SH | libc::LOCK_NB),
- LockExclusiveNonblock => libc::flock(fd, libc::LOCK_EX | libc::LOCK_NB),
- UnlockNonblock => libc::flock(fd, libc::LOCK_UN | libc::LOCK_NB),
- }
- };
-
- Errno::result(res).map(drop)
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-libc_bitflags! {
- /// Additional flags to `splice` and friends.
- pub struct SpliceFFlags: c_uint {
- /// Request that pages be moved instead of copied.
- ///
- /// Not applicable to `vmsplice`.
- SPLICE_F_MOVE;
- /// Do not block on I/O.
- SPLICE_F_NONBLOCK;
- /// Hint that more data will be coming in a subsequent splice.
- ///
- /// Not applicable to `vmsplice`.
- SPLICE_F_MORE;
- /// Gift the user pages to the kernel.
- ///
- /// Not applicable to `splice`.
- SPLICE_F_GIFT;
- }
-}
-
-/// Copy a range of data from one file to another
-///
-/// The `copy_file_range` system call performs an in-kernel copy between
-/// file descriptors `fd_in` and `fd_out` without the additional cost of
-/// transferring data from the kernel to user space and then back into the
-/// kernel. It copies up to `len` bytes of data from file descriptor `fd_in` to
-/// file descriptor `fd_out`, overwriting any data that exists within the
-/// requested range of the target file.
-///
-/// If the `off_in` and/or `off_out` arguments are used, the values
-/// will be mutated to reflect the new position within the file after
-/// copying. If they are not used, the relevant filedescriptors will be seeked
-/// to the new position.
-///
-/// On successful completion the number of bytes actually copied will be
-/// returned.
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub fn copy_file_range(
- fd_in: RawFd,
- off_in: Option<&mut libc::loff_t>,
- fd_out: RawFd,
- off_out: Option<&mut libc::loff_t>,
- len: usize,
-) -> Result<usize> {
- let off_in = off_in
- .map(|offset| offset as *mut libc::loff_t)
- .unwrap_or(ptr::null_mut());
- let off_out = off_out
- .map(|offset| offset as *mut libc::loff_t)
- .unwrap_or(ptr::null_mut());
-
- let ret = unsafe {
- libc::syscall(
- libc::SYS_copy_file_range,
- fd_in,
- off_in,
- fd_out,
- off_out,
- len,
- 0,
- )
- };
- Errno::result(ret).map(|r| r as usize)
-}
-
-#[cfg(any(target_os = "linux", target_os = "android"))]
-pub fn splice(
- fd_in: RawFd,
- off_in: Option<&mut libc::loff_t>,
- fd_out: RawFd,
- off_out: Option<&mut libc::loff_t>,
- len: usize,
- flags: SpliceFFlags,
-) -> Result<usize> {
- let off_in = off_in
- .map(|offset| offset as *mut libc::loff_t)
- .unwrap_or(ptr::null_mut());
- let off_out = off_out
- .map(|offset| offset as *mut libc::loff_t)
- .unwrap_or(ptr::null_mut());
-
- let ret = unsafe { libc::splice(fd_in, off_in, fd_out, off_out, len, flags.bits()) };
- Errno::result(ret).map(|r| r as usize)
-}
-
-#[cfg(any(target_os = "linux", target_os = "android"))]
-pub fn tee(fd_in: RawFd, fd_out: RawFd, len: usize, flags: SpliceFFlags) -> Result<usize> {
- let ret = unsafe { libc::tee(fd_in, fd_out, len, flags.bits()) };
- Errno::result(ret).map(|r| r as usize)
-}
-
-#[cfg(any(target_os = "linux", target_os = "android"))]
-pub fn vmsplice(fd: RawFd, iov: &[IoVec<&[u8]>], flags: SpliceFFlags) -> Result<usize> {
- let ret = unsafe {
- libc::vmsplice(
- fd,
- iov.as_ptr() as *const libc::iovec,
- iov.len(),
- flags.bits(),
- )
- };
- Errno::result(ret).map(|r| r as usize)
-}
-
-#[cfg(any(target_os = "linux"))]
-libc_bitflags!(
- /// Mode argument flags for fallocate determining operation performed on a given range.
- pub struct FallocateFlags: c_int {
- /// File size is not changed.
- ///
- /// offset + len can be greater than file size.
- FALLOC_FL_KEEP_SIZE;
- /// Deallocates space by creating a hole.
- ///
- /// Must be ORed with FALLOC_FL_KEEP_SIZE. Byte range starts at offset and continues for len bytes.
- FALLOC_FL_PUNCH_HOLE;
- /// Removes byte range from a file without leaving a hole.
- ///
- /// Byte range to collapse starts at offset and continues for len bytes.
- FALLOC_FL_COLLAPSE_RANGE;
- /// Zeroes space in specified byte range.
- ///
- /// Byte range starts at offset and continues for len bytes.
- FALLOC_FL_ZERO_RANGE;
- /// Increases file space by inserting a hole within the file size.
- ///
- /// Does not overwrite existing data. Hole starts at offset and continues for len bytes.
- FALLOC_FL_INSERT_RANGE;
- /// Shared file data extants are made private to the file.
- ///
- /// Gaurantees that a subsequent write will not fail due to lack of space.
- FALLOC_FL_UNSHARE_RANGE;
- }
-);
-
-/// Manipulates file space.
-///
-/// Allows the caller to directly manipulate the allocated disk space for the
-/// file referred to by fd.
-#[cfg(any(target_os = "linux"))]
-pub fn fallocate(
- fd: RawFd,
- mode: FallocateFlags,
- offset: libc::off_t,
- len: libc::off_t,
-) -> Result<()> {
- let res = unsafe { libc::fallocate(fd, mode.bits(), offset, len) };
- Errno::result(res).map(drop)
-}
-
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- any(target_os = "wasi", target_env = "wasi"),
- target_env = "uclibc",
- target_os = "freebsd"
-))]
-mod posix_fadvise {
- use crate::errno::Errno;
- use libc;
- use std::os::unix::io::RawFd;
- use crate::Result;
-
- libc_enum! {
- #[repr(i32)]
- pub enum PosixFadviseAdvice {
- POSIX_FADV_NORMAL,
- POSIX_FADV_SEQUENTIAL,
- POSIX_FADV_RANDOM,
- POSIX_FADV_NOREUSE,
- POSIX_FADV_WILLNEED,
- POSIX_FADV_DONTNEED,
- }
- }
-
- pub fn posix_fadvise(
- fd: RawFd,
- offset: libc::off_t,
- len: libc::off_t,
- advice: PosixFadviseAdvice,
- ) -> Result<libc::c_int> {
- let res = unsafe { libc::posix_fadvise(fd, offset, len, advice as libc::c_int) };
- Errno::result(res)
- }
-}
-
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- any(target_os = "wasi", target_env = "wasi"),
- target_os = "freebsd"
-))]
-pub fn posix_fallocate(fd: RawFd, offset: libc::off_t, len: libc::off_t) -> Result<()> {
- let res = unsafe { libc::posix_fallocate(fd, offset, len) };
- match Errno::result(res) {
- Err(err) => Err(err),
- Ok(0) => Ok(()),
- Ok(errno) => Err(crate::Error::Sys(Errno::from_i32(errno))),
- }
-}
diff --git a/vendor/nix-0.20.0/src/features.rs b/vendor/nix-0.20.0/src/features.rs
deleted file mode 100644
index 6b1cff5..0000000
--- a/vendor/nix-0.20.0/src/features.rs
+++ /dev/null
@@ -1,106 +0,0 @@
-//! Feature tests for OS functionality
-pub use self::os::*;
-
-#[cfg(any(target_os = "linux", target_os = "android"))]
-mod os {
- use crate::sys::utsname::uname;
-
- // Features:
- // * atomic cloexec on socket: 2.6.27
- // * pipe2: 2.6.27
- // * accept4: 2.6.28
-
- static VERS_UNKNOWN: usize = 1;
- static VERS_2_6_18: usize = 2;
- static VERS_2_6_27: usize = 3;
- static VERS_2_6_28: usize = 4;
- static VERS_3: usize = 5;
-
- #[inline]
- fn digit(dst: &mut usize, b: u8) {
- *dst *= 10;
- *dst += (b - b'0') as usize;
- }
-
- fn parse_kernel_version() -> usize {
- let u = uname();
-
- let mut curr: usize = 0;
- let mut major: usize = 0;
- let mut minor: usize = 0;
- let mut patch: usize = 0;
-
- for b in u.release().bytes() {
- if curr >= 3 {
- break;
- }
-
- match b {
- b'.' | b'-' => {
- curr += 1;
- }
- b'0'..=b'9' => {
- match curr {
- 0 => digit(&mut major, b),
- 1 => digit(&mut minor, b),
- _ => digit(&mut patch, b),
- }
- }
- _ => break,
- }
- }
-
- if major >= 3 {
- VERS_3
- } else if major >= 2 {
- if minor >= 7 {
- VERS_UNKNOWN
- } else if minor >= 6 {
- if patch >= 28 {
- VERS_2_6_28
- } else if patch >= 27 {
- VERS_2_6_27
- } else {
- VERS_2_6_18
- }
- } else {
- VERS_UNKNOWN
- }
- } else {
- VERS_UNKNOWN
- }
- }
-
- fn kernel_version() -> usize {
- static mut KERNEL_VERS: usize = 0;
-
- unsafe {
- if KERNEL_VERS == 0 {
- KERNEL_VERS = parse_kernel_version();
- }
-
- KERNEL_VERS
- }
- }
-
- /// Check if the OS supports atomic close-on-exec for sockets
- pub fn socket_atomic_cloexec() -> bool {
- kernel_version() >= VERS_2_6_27
- }
-
- #[test]
- pub fn test_parsing_kernel_version() {
- assert!(kernel_version() > 0);
- }
-}
-
-#[cfg(any(target_os = "macos", target_os = "freebsd",
- target_os = "dragonfly", target_os = "ios",
- target_os = "openbsd", target_os = "netbsd",
- target_os = "redox", target_os = "fuchsia"))]
-mod os {
- /// Check if the OS supports atomic close-on-exec for sockets
- pub fn socket_atomic_cloexec() -> bool {
- false
- }
-}
diff --git a/vendor/nix-0.20.0/src/ifaddrs.rs b/vendor/nix-0.20.0/src/ifaddrs.rs
deleted file mode 100644
index ed6328f..0000000
--- a/vendor/nix-0.20.0/src/ifaddrs.rs
+++ /dev/null
@@ -1,147 +0,0 @@
-//! Query network interface addresses
-//!
-//! Uses the Linux and/or BSD specific function `getifaddrs` to query the list
-//! of interfaces and their associated addresses.
-
-use cfg_if::cfg_if;
-use std::ffi;
-use std::iter::Iterator;
-use std::mem;
-use std::option::Option;
-
-use crate::{Result, Errno};
-use crate::sys::socket::SockAddr;
-use crate::net::if_::*;
-
-/// Describes a single address for an interface as returned by `getifaddrs`.
-#[derive(Clone, Debug, Eq, Hash, PartialEq)]
-pub struct InterfaceAddress {
- /// Name of the network interface
- pub interface_name: String,
- /// Flags as from `SIOCGIFFLAGS` ioctl
- pub flags: InterfaceFlags,
- /// Network address of this interface
- pub address: Option<SockAddr>,
- /// Netmask of this interface
- pub netmask: Option<SockAddr>,
- /// Broadcast address of this interface, if applicable
- pub broadcast: Option<SockAddr>,
- /// Point-to-point destination address
- pub destination: Option<SockAddr>,
-}
-
-cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "fuchsia", target_os = "linux"))] {
- fn get_ifu_from_sockaddr(info: &libc::ifaddrs) -> *const libc::sockaddr {
- info.ifa_ifu
- }
- } else {
- fn get_ifu_from_sockaddr(info: &libc::ifaddrs) -> *const libc::sockaddr {
- info.ifa_dstaddr
- }
- }
-}
-
-impl InterfaceAddress {
- /// Create an `InterfaceAddress` from the libc struct.
- fn from_libc_ifaddrs(info: &libc::ifaddrs) -> InterfaceAddress {
- let ifname = unsafe { ffi::CStr::from_ptr(info.ifa_name) };
- let address = unsafe { SockAddr::from_libc_sockaddr(info.ifa_addr) };
- let netmask = unsafe { SockAddr::from_libc_sockaddr(info.ifa_netmask) };
- let mut addr = InterfaceAddress {
- interface_name: ifname.to_string_lossy().to_string(),
- flags: InterfaceFlags::from_bits_truncate(info.ifa_flags as i32),
- address,
- netmask,
- broadcast: None,
- destination: None,
- };
-
- let ifu = get_ifu_from_sockaddr(info);
- if addr.flags.contains(InterfaceFlags::IFF_POINTOPOINT) {
- addr.destination = unsafe { SockAddr::from_libc_sockaddr(ifu) };
- } else if addr.flags.contains(InterfaceFlags::IFF_BROADCAST) {
- addr.broadcast = unsafe { SockAddr::from_libc_sockaddr(ifu) };
- }
-
- addr
- }
-}
-
-/// Holds the results of `getifaddrs`.
-///
-/// Use the function `getifaddrs` to create this Iterator. Note that the
-/// actual list of interfaces can be iterated once and will be freed as
-/// soon as the Iterator goes out of scope.
-#[derive(Debug, Eq, Hash, PartialEq)]
-pub struct InterfaceAddressIterator {
- base: *mut libc::ifaddrs,
- next: *mut libc::ifaddrs,
-}
-
-impl Drop for InterfaceAddressIterator {
- fn drop(&mut self) {
- unsafe { libc::freeifaddrs(self.base) };
- }
-}
-
-impl Iterator for InterfaceAddressIterator {
- type Item = InterfaceAddress;
- fn next(&mut self) -> Option<<Self as Iterator>::Item> {
- match unsafe { self.next.as_ref() } {
- Some(ifaddr) => {
- self.next = ifaddr.ifa_next;
- Some(InterfaceAddress::from_libc_ifaddrs(ifaddr))
- }
- None => None,
- }
- }
-}
-
-/// Get interface addresses using libc's `getifaddrs`
-///
-/// Note that the underlying implementation differs between OSes. Only the
-/// most common address families are supported by the nix crate (due to
-/// lack of time and complexity of testing). The address family is encoded
-/// in the specific variant of `SockAddr` returned for the fields `address`,
-/// `netmask`, `broadcast`, and `destination`. For any entry not supported,
-/// the returned list will contain a `None` entry.
-///
-/// # Example
-/// ```
-/// let addrs = nix::ifaddrs::getifaddrs().unwrap();
-/// for ifaddr in addrs {
-/// match ifaddr.address {
-/// Some(address) => {
-/// println!("interface {} address {}",
-/// ifaddr.interface_name, address);
-/// },
-/// None => {
-/// println!("interface {} with unsupported address family",
-/// ifaddr.interface_name);
-/// }
-/// }
-/// }
-/// ```
-pub fn getifaddrs() -> Result<InterfaceAddressIterator> {
- let mut addrs = mem::MaybeUninit::<*mut libc::ifaddrs>::uninit();
- unsafe {
- Errno::result(libc::getifaddrs(addrs.as_mut_ptr())).map(|_| {
- InterfaceAddressIterator {
- base: addrs.assume_init(),
- next: addrs.assume_init(),
- }
- })
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- // Only checks if `getifaddrs` can be invoked without panicking.
- #[test]
- fn test_getifaddrs() {
- let _ = getifaddrs();
- }
-}
diff --git a/vendor/nix-0.20.0/src/kmod.rs b/vendor/nix-0.20.0/src/kmod.rs
deleted file mode 100644
index 8789cb6..0000000
--- a/vendor/nix-0.20.0/src/kmod.rs
+++ /dev/null
@@ -1,123 +0,0 @@
-//! Load and unload kernel modules.
-//!
-//! For more details see
-
-use libc;
-use std::ffi::CStr;
-use std::os::unix::io::AsRawFd;
-
-use crate::errno::Errno;
-use crate::Result;
-
-/// Loads a kernel module from a buffer.
-///
-/// It loads an ELF image into kernel space,
-/// performs any necessary symbol relocations,
-/// initializes module parameters to values provided by the caller,
-/// and then runs the module's init function.
-///
-/// This function requires `CAP_SYS_MODULE` privilege.
-///
-/// The `module_image` argument points to a buffer containing the binary image
-/// to be loaded. The buffer should contain a valid ELF image
-/// built for the running kernel.
-///
-/// The `param_values` argument is a string containing space-delimited specifications
-/// of the values for module parameters.
-/// Each of the parameter specifications has the form:
-///
-/// `name[=value[,value...]]`
-///
-/// # Example
-///
-/// ```no_run
-/// use std::fs::File;
-/// use std::io::Read;
-/// use std::ffi::CString;
-/// use nix::kmod::init_module;
-///
-/// let mut f = File::open("mykernel.ko").unwrap();
-/// let mut contents: Vec<u8> = Vec::new();
-/// f.read_to_end(&mut contents).unwrap();
-/// init_module(&mut contents, &CString::new("who=Rust when=Now,12").unwrap()).unwrap();
-/// ```
-///
-/// See [`man init_module(2)`](http://man7.org/linux/man-pages/man2/init_module.2.html) for more information.
-pub fn init_module(module_image: &[u8], param_values: &CStr) -> Result<()> {
- let res = unsafe {
- libc::syscall(
- libc::SYS_init_module,
- module_image.as_ptr(),
- module_image.len(),
- param_values.as_ptr(),
- )
- };
-
- Errno::result(res).map(drop)
-}
-
-libc_bitflags!(
- /// Flags used by the `finit_module` function.
- pub struct ModuleInitFlags: libc::c_uint {
- /// Ignore symbol version hashes.
- MODULE_INIT_IGNORE_MODVERSIONS;
- /// Ignore kernel version magic.
- MODULE_INIT_IGNORE_VERMAGIC;
- }
-);
-
-/// Loads a kernel module from a given file descriptor.
-///
-/// # Example
-///
-/// ```no_run
-/// use std::fs::File;
-/// use std::ffi::CString;
-/// use nix::kmod::{finit_module, ModuleInitFlags};
-///
-/// let f = File::open("mymod.ko").unwrap();
-/// finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()).unwrap();
-/// ```
-///
-/// See [`man init_module(2)`](http://man7.org/linux/man-pages/man2/init_module.2.html) for more information.
-pub fn finit_module<T: AsRawFd>(fd: &T, param_values: &CStr, flags: ModuleInitFlags) -> Result<()> {
- let res = unsafe {
- libc::syscall(
- libc::SYS_finit_module,
- fd.as_raw_fd(),
- param_values.as_ptr(),
- flags.bits(),
- )
- };
-
- Errno::result(res).map(drop)
-}
-
-libc_bitflags!(
- /// Flags used by `delete_module`.
- ///
- /// See [`man delete_module(2)`](http://man7.org/linux/man-pages/man2/delete_module.2.html)
- /// for a detailed description how these flags work.
- pub struct DeleteModuleFlags: libc::c_int {
- O_NONBLOCK;
- O_TRUNC;
- }
-);
-
-/// Unloads the kernel module with the given name.
-///
-/// # Example
-///
-/// ```no_run
-/// use std::ffi::CString;
-/// use nix::kmod::{delete_module, DeleteModuleFlags};
-///
-/// delete_module(&CString::new("mymod").unwrap(), DeleteModuleFlags::O_NONBLOCK).unwrap();
-/// ```
-///
-/// See [`man delete_module(2)`](http://man7.org/linux/man-pages/man2/delete_module.2.html) for more information.
-pub fn delete_module(name: &CStr, flags: DeleteModuleFlags) -> Result<()> {
- let res = unsafe { libc::syscall(libc::SYS_delete_module, name.as_ptr(), flags.bits()) };
-
- Errno::result(res).map(drop)
-}
diff --git a/vendor/nix-0.20.0/src/lib.rs b/vendor/nix-0.20.0/src/lib.rs
deleted file mode 100644
index e62c158..0000000
--- a/vendor/nix-0.20.0/src/lib.rs
+++ /dev/null
@@ -1,282 +0,0 @@
-//! Rust friendly bindings to the various *nix system functions.
-//!
-//! Modules are structured according to the C header file that they would be
-//! defined in.
-#![crate_name = "nix"]
-#![cfg(unix)]
-#![allow(non_camel_case_types)]
-// latest bitflags triggers a rustc bug with cross-crate macro expansions causing dead_code
-// warnings even though the macro expands into something with allow(dead_code)
-#![allow(dead_code)]
-#![cfg_attr(test, deny(warnings))]
-#![recursion_limit = "500"]
-#![deny(unused)]
-#![deny(unstable_features)]
-#![deny(missing_copy_implementations)]
-#![deny(missing_debug_implementations)]
-
-// Re-exported external crates
-pub use libc;
-
-// Private internal modules
-#[macro_use] mod macros;
-
-// Public crates
-#[cfg(not(target_os = "redox"))]
-pub mod dir;
-pub mod env;
-pub mod errno;
-#[deny(missing_docs)]
-pub mod features;
-pub mod fcntl;
-#[deny(missing_docs)]
-#[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
-pub mod ifaddrs;
-#[cfg(any(target_os = "android",
- target_os = "linux"))]
-pub mod kmod;
-#[cfg(any(target_os = "android",
- target_os = "linux"))]
-pub mod mount;
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "fushsia",
- target_os = "linux",
- target_os = "netbsd"))]
-pub mod mqueue;
-#[deny(missing_docs)]
-#[cfg(not(target_os = "redox"))]
-pub mod net;
-#[deny(missing_docs)]
-pub mod poll;
-#[deny(missing_docs)]
-#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-pub mod pty;
-pub mod sched;
-pub mod sys;
-pub mod time;
-// This can be implemented for other platforms as soon as libc
-// provides bindings for them.
-#[cfg(all(target_os = "linux",
- any(target_arch = "x86", target_arch = "x86_64")))]
-pub mod ucontext;
-pub mod unistd;
-
-/*
- *
- * ===== Result / Error =====
- *
- */
-
-use libc::{c_char, PATH_MAX};
-
-use std::{error, fmt, ptr, result};
-use std::ffi::{CStr, OsStr};
-use std::os::unix::ffi::OsStrExt;
-use std::path::{Path, PathBuf};
-
-use errno::Errno;
-
-/// Nix Result Type
-pub type Result<T> = result::Result<T, Error>;
-
-/// Nix Error Type
-///
-/// The nix error type provides a common way of dealing with
-/// various system system/libc calls that might fail. Each
-/// error has a corresponding errno (usually the one from the
-/// underlying OS) to which it can be mapped in addition to
-/// implementing other common traits.
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub enum Error {
- Sys(Errno),
- InvalidPath,
- /// The operation involved a conversion to Rust's native String type, which failed because the
- /// string did not contain all valid UTF-8.
- InvalidUtf8,
- /// The operation is not supported by Nix, in this instance either use the libc bindings or
- /// consult the module documentation to see if there is a more appropriate interface available.
- UnsupportedOperation,
-}
-
-impl Error {
- /// Convert this `Error` to an [`Errno`](enum.Errno.html).
- ///
- /// # Example
- ///
- /// ```
- /// # use nix::Error;
- /// # use nix::errno::Errno;
- /// let e = Error::from(Errno::EPERM);
- /// assert_eq!(Some(Errno::EPERM), e.as_errno());
- /// ```
- pub fn as_errno(self) -> Option<Errno> {
- if let Error::Sys(e) = self {
- Some(e)
- } else {
- None
- }
- }
-
- /// Create a nix Error from a given errno
- pub fn from_errno(errno: Errno) -> Error {
- Error::Sys(errno)
- }
-
- /// Get the current errno and convert it to a nix Error
- pub fn last() -> Error {
- Error::Sys(Errno::last())
- }
-
- /// Create a new invalid argument error (`EINVAL`)
- pub fn invalid_argument() -> Error {
- Error::Sys(Errno::EINVAL)
- }
-
-}
-
-impl From<Errno> for Error {
- fn from(errno: Errno) -> Error { Error::from_errno(errno) }
-}
-
-impl From<std::string::FromUtf8Error> for Error {
- fn from(_: std::string::FromUtf8Error) -> Error { Error::InvalidUtf8 }
-}
-
-impl error::Error for Error {}
-
-impl fmt::Display for Error {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- Error::InvalidPath => write!(f, "Invalid path"),
- Error::InvalidUtf8 => write!(f, "Invalid UTF-8 string"),
- Error::UnsupportedOperation => write!(f, "Unsupported Operation"),
- Error::Sys(errno) => write!(f, "{:?}: {}", errno, errno.desc()),
- }
- }
-}
-
-pub trait NixPath {
- fn is_empty(&self) -> bool;
-
- fn len(&self) -> usize;
-
- fn with_nix_path<T, F>(&self, f: F) -> Result<T>
- where F: FnOnce(&CStr) -> T;
-}
-
-impl NixPath for str {
- fn is_empty(&self) -> bool {
- NixPath::is_empty(OsStr::new(self))
- }
-
- fn len(&self) -> usize {
- NixPath::len(OsStr::new(self))
- }
-
- fn with_nix_path<T, F>(&self, f: F) -> Result<T>
- where F: FnOnce(&CStr) -> T {
- OsStr::new(self).with_nix_path(f)
- }
-}
-
-impl NixPath for OsStr {
- fn is_empty(&self) -> bool {
- self.as_bytes().is_empty()
- }
-
- fn len(&self) -> usize {
- self.as_bytes().len()
- }
-
- fn with_nix_path<T, F>(&self, f: F) -> Result<T>
- where F: FnOnce(&CStr) -> T {
- self.as_bytes().with_nix_path(f)
- }
-}
-
-impl NixPath for CStr {
- fn is_empty(&self) -> bool {
- self.to_bytes().is_empty()
- }
-
- fn len(&self) -> usize {
- self.to_bytes().len()
- }
-
- fn with_nix_path<T, F>(&self, f: F) -> Result<T>
- where F: FnOnce(&CStr) -> T {
- // Equivalence with the [u8] impl.
- if self.len() >= PATH_MAX as usize {
- return Err(Error::InvalidPath);
- }
-
- Ok(f(self))
- }
-}
-
-impl NixPath for [u8] {
- fn is_empty(&self) -> bool {
- self.is_empty()
- }
-
- fn len(&self) -> usize {
- self.len()
- }
-
- fn with_nix_path<T, F>(&self, f: F) -> Result<T>
- where F: FnOnce(&CStr) -> T {
- let mut buf = [0u8; PATH_MAX as usize];
-
- if self.len() >= PATH_MAX as usize {
- return Err(Error::InvalidPath);
- }
-
- match self.iter().position(|b| *b == 0) {
- Some(_) => Err(Error::InvalidPath),
- None => {
- unsafe {
- // TODO: Replace with bytes::copy_memory. rust-lang/rust#24028
- ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len());
- Ok(f(CStr::from_ptr(buf.as_ptr() as *const c_char)))
- }
-
- }
- }
- }
-}
-
-impl NixPath for Path {
- fn is_empty(&self) -> bool {
- NixPath::is_empty(self.as_os_str())
- }
-
- fn len(&self) -> usize {
- NixPath::len(self.as_os_str())
- }
-
- fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
- self.as_os_str().with_nix_path(f)
- }
-}
-
-impl NixPath for PathBuf {
- fn is_empty(&self) -> bool {
- NixPath::is_empty(self.as_os_str())
- }
-
- fn len(&self) -> usize {
- NixPath::len(self.as_os_str())
- }
-
- fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
- self.as_os_str().with_nix_path(f)
- }
-}
diff --git a/vendor/nix-0.20.0/src/macros.rs b/vendor/nix-0.20.0/src/macros.rs
deleted file mode 100644
index feb02ea..0000000
--- a/vendor/nix-0.20.0/src/macros.rs
+++ /dev/null
@@ -1,218 +0,0 @@
-/// The `libc_bitflags!` macro helps with a common use case of defining a public bitflags type
-/// with values from the libc crate. It is used the same way as the `bitflags!` macro, except
-/// that only the name of the flag value has to be given.
-///
-/// The `libc` crate must be in scope with the name `libc`.
-///
-/// # Example
-/// ```
-/// libc_bitflags!{
-/// pub struct ProtFlags: libc::c_int {
-/// PROT_NONE;
-/// PROT_READ;
-/// /// PROT_WRITE enables write protect
-/// PROT_WRITE;
-/// PROT_EXEC;
-/// #[cfg(any(target_os = "linux", target_os = "android"))]
-/// PROT_GROWSDOWN;
-/// #[cfg(any(target_os = "linux", target_os = "android"))]
-/// PROT_GROWSUP;
-/// }
-/// }
-/// ```
-///
-/// Example with casting, due to a mistake in libc. In this example, the
-/// various flags have different types, so we cast the broken ones to the right
-/// type.
-///
-/// ```
-/// libc_bitflags!{
-/// pub struct SaFlags: libc::c_ulong {
-/// SA_NOCLDSTOP as libc::c_ulong;
-/// SA_NOCLDWAIT;
-/// SA_NODEFER as libc::c_ulong;
-/// SA_ONSTACK;
-/// SA_RESETHAND as libc::c_ulong;
-/// SA_RESTART as libc::c_ulong;
-/// SA_SIGINFO;
-/// }
-/// }
-/// ```
-macro_rules! libc_bitflags {
- (
- $(#[$outer:meta])*
- pub struct $BitFlags:ident: $T:ty {
- $(
- $(#[$inner:ident $($args:tt)*])*
- $Flag:ident $(as $cast:ty)*;
- )+
- }
- ) => {
- ::bitflags::bitflags! {
- $(#[$outer])*
- pub struct $BitFlags: $T {
- $(
- $(#[$inner $($args)*])*
- const $Flag = libc::$Flag $(as $cast)*;
- )+
- }
- }
- };
-}
-
-/// The `libc_enum!` macro helps with a common use case of defining an enum exclusively using
-/// values from the `libc` crate. This macro supports both `pub` and private `enum`s.
-///
-/// The `libc` crate must be in scope with the name `libc`.
-///
-/// # Example
-/// ```
-/// libc_enum!{
-/// pub enum ProtFlags {
-/// PROT_NONE,
-/// PROT_READ,
-/// PROT_WRITE,
-/// PROT_EXEC,
-/// #[cfg(any(target_os = "linux", target_os = "android"))]
-/// PROT_GROWSDOWN,
-/// #[cfg(any(target_os = "linux", target_os = "android"))]
-/// PROT_GROWSUP,
-/// }
-/// }
-/// ```
-macro_rules! libc_enum {
- // Exit rule.
- (@make_enum
- {
- $v:vis
- name: $BitFlags:ident,
- attrs: [$($attrs:tt)*],
- entries: [$($entries:tt)*],
- }
- ) => {
- $($attrs)*
- #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
- $v enum $BitFlags {
- $($entries)*
- }
- };
-
- // Done accumulating.
- (@accumulate_entries
- {
- $v:vis
- name: $BitFlags:ident,
- attrs: $attrs:tt,
- },
- $entries:tt;
- ) => {
- libc_enum! {
- @make_enum
- {
- $v
- name: $BitFlags,
- attrs: $attrs,
- entries: $entries,
- }
- }
- };
-
- // Munch an attr.
- (@accumulate_entries
- $prefix:tt,
- [$($entries:tt)*];
- #[$attr:meta] $($tail:tt)*
- ) => {
- libc_enum! {
- @accumulate_entries
- $prefix,
- [
- $($entries)*
- #[$attr]
- ];
- $($tail)*
- }
- };
-
- // Munch last ident if not followed by a comma.
- (@accumulate_entries
- $prefix:tt,
- [$($entries:tt)*];
- $entry:ident
- ) => {
- libc_enum! {
- @accumulate_entries
- $prefix,
- [
- $($entries)*
- $entry = libc::$entry,
- ];
- }
- };
-
- // Munch an ident; covers terminating comma case.
- (@accumulate_entries
- $prefix:tt,
- [$($entries:tt)*];
- $entry:ident, $($tail:tt)*
- ) => {
- libc_enum! {
- @accumulate_entries
- $prefix,
- [
- $($entries)*
- $entry = libc::$entry,
- ];
- $($tail)*
- }
- };
-
- // Munch an ident and cast it to the given type; covers terminating comma.
- (@accumulate_entries
- $prefix:tt,
- [$($entries:tt)*];
- $entry:ident as $ty:ty, $($tail:tt)*
- ) => {
- libc_enum! {
- @accumulate_entries
- $prefix,
- [
- $($entries)*
- $entry = libc::$entry as $ty,
- ];
- $($tail)*
- }
- };
-
- // Entry rule.
- (
- $(#[$attr:meta])*
- $v:vis enum $BitFlags:ident {
- $($vals:tt)*
- }
- ) => {
- libc_enum! {
- @accumulate_entries
- {
- $v
- name: $BitFlags,
- attrs: [$(#[$attr])*],
- },
- [];
- $($vals)*
- }
- };
-}
-
-/// A Rust version of the familiar C `offset_of` macro. It returns the byte
-/// offset of `field` within struct `ty`
-#[cfg(not(target_os = "redox"))]
-macro_rules! offset_of {
- ($ty:ty, $field:ident) => {{
- // Safe because we don't actually read from the dereferenced pointer
- #[allow(unused_unsafe)] // for when the macro is used in an unsafe block
- unsafe {
- &(*(ptr::null() as *const $ty)).$field as *const _ as usize
- }
- }}
-}
diff --git a/vendor/nix-0.20.0/src/mount.rs b/vendor/nix-0.20.0/src/mount.rs
deleted file mode 100644
index 2c54761..0000000
--- a/vendor/nix-0.20.0/src/mount.rs
+++ /dev/null
@@ -1,109 +0,0 @@
-use libc::{self, c_ulong, c_int};
-use crate::{Result, NixPath};
-use crate::errno::Errno;
-
-libc_bitflags!(
- pub struct MsFlags: c_ulong {
- /// Mount read-only
- MS_RDONLY;
- /// Ignore suid and sgid bits
- MS_NOSUID;
- /// Disallow access to device special files
- MS_NODEV;
- /// Disallow program execution
- MS_NOEXEC;
- /// Writes are synced at once
- MS_SYNCHRONOUS;
- /// Alter flags of a mounted FS
- MS_REMOUNT;
- /// Allow mandatory locks on a FS
- MS_MANDLOCK;
- /// Directory modifications are synchronous
- MS_DIRSYNC;
- /// Do not update access times
- MS_NOATIME;
- /// Do not update directory access times
- MS_NODIRATIME;
- /// Linux 2.4.0 - Bind directory at different place
- MS_BIND;
- MS_MOVE;
- MS_REC;
- MS_SILENT;
- MS_POSIXACL;
- MS_UNBINDABLE;
- MS_PRIVATE;
- MS_SLAVE;
- MS_SHARED;
- MS_RELATIME;
- MS_KERNMOUNT;
- MS_I_VERSION;
- MS_STRICTATIME;
- MS_ACTIVE;
- MS_NOUSER;
- MS_RMT_MASK;
- MS_MGC_VAL;
- MS_MGC_MSK;
- }
-);
-
-libc_bitflags!(
- pub struct MntFlags: c_int {
- MNT_FORCE;
- MNT_DETACH;
- MNT_EXPIRE;
- }
-);
-
-pub fn mount<P1: ?Sized + NixPath, P2: ?Sized + NixPath, P3: ?Sized + NixPath, P4: ?Sized + NixPath>(
- source: Option<&P1>,
- target: &P2,
- fstype: Option<&P3>,
- flags: MsFlags,
- data: Option<&P4>) -> Result<()> {
-
- fn with_opt_nix_path<P, T, F>(p: Option<&P>, f: F) -> Result<T>
- where P: ?Sized + NixPath,
- F: FnOnce(*const libc::c_char) -> T
- {
- match p {
- Some(path) => path.with_nix_path(|p_str| f(p_str.as_ptr())),
- None => Ok(f(std::ptr::null()))
- }
- }
-
- let res = with_opt_nix_path(source, |s| {
- target.with_nix_path(|t| {
- with_opt_nix_path(fstype, |ty| {
- with_opt_nix_path(data, |d| {
- unsafe {
- libc::mount(
- s,
- t.as_ptr(),
- ty,
- flags.bits,
- d as *const libc::c_void
- )
- }
- })
- })
- })
- })????;
-
- Errno::result(res).map(drop)
-}
-
-pub fn umount<P: ?Sized + NixPath>(target: &P) -> Result<()> {
- let res = target.with_nix_path(|cstr| {
- unsafe { libc::umount(cstr.as_ptr()) }
- })?;
-
- Errno::result(res).map(drop)
-}
-
-pub fn umount2<P: ?Sized + NixPath>(target: &P, flags: MntFlags) -> Result<()> {
- let res = target.with_nix_path(|cstr| {
- unsafe { libc::umount2(cstr.as_ptr(), flags.bits) }
- })?;
-
- Errno::result(res).map(drop)
-}
diff --git a/vendor/nix-0.20.0/src/mqueue.rs b/vendor/nix-0.20.0/src/mqueue.rs
deleted file mode 100644
index 0215de5..0000000
--- a/vendor/nix-0.20.0/src/mqueue.rs
+++ /dev/null
@@ -1,177 +0,0 @@
-//! Posix Message Queue functions
-//!
-//! [Further reading and details on the C API](http://man7.org/linux/man-pages/man7/mq_overview.7.html)
-
-use crate::Result;
-use crate::errno::Errno;
-
-use libc::{self, c_char, mqd_t, size_t};
-use std::ffi::CString;
-use crate::sys::stat::Mode;
-use std::mem;
-
-libc_bitflags!{
- pub struct MQ_OFlag: libc::c_int {
- O_RDONLY;
- O_WRONLY;
- O_RDWR;
- O_CREAT;
- O_EXCL;
- O_NONBLOCK;
- O_CLOEXEC;
- }
-}
-
-libc_bitflags!{
- pub struct FdFlag: libc::c_int {
- FD_CLOEXEC;
- }
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct MqAttr {
- mq_attr: libc::mq_attr,
-}
-
-// x32 compatibility
-// See https://sourceware.org/bugzilla/show_bug.cgi?id=21279
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
-pub type mq_attr_member_t = i64;
-#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
-pub type mq_attr_member_t = libc::c_long;
-
-impl MqAttr {
- pub fn new(mq_flags: mq_attr_member_t,
- mq_maxmsg: mq_attr_member_t,
- mq_msgsize: mq_attr_member_t,
- mq_curmsgs: mq_attr_member_t)
- -> MqAttr
- {
- let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
- unsafe {
- let p = attr.as_mut_ptr();
- (*p).mq_flags = mq_flags;
- (*p).mq_maxmsg = mq_maxmsg;
- (*p).mq_msgsize = mq_msgsize;
- (*p).mq_curmsgs = mq_curmsgs;
- MqAttr { mq_attr: attr.assume_init() }
- }
- }
-
- pub fn flags(&self) -> mq_attr_member_t {
- self.mq_attr.mq_flags
- }
-}
-
-
-/// Open a message queue
-///
-/// See also [`mq_open(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_open.html)
-// The mode.bits cast is only lossless on some OSes
-#[allow(clippy::cast_lossless)]
-pub fn mq_open(name: &CString,
- oflag: MQ_OFlag,
- mode: Mode,
- attr: Option<&MqAttr>)
- -> Result<mqd_t> {
- let res = match attr {
- Some(mq_attr) => unsafe {
- libc::mq_open(name.as_ptr(),
- oflag.bits(),
- mode.bits() as libc::c_int,
- &mq_attr.mq_attr as *const libc::mq_attr)
- },
- None => unsafe { libc::mq_open(name.as_ptr(), oflag.bits()) },
- };
- Errno::result(res)
-}
-
-/// Remove a message queue
-///
-/// See also [`mq_unlink(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_unlink.html)
-pub fn mq_unlink(name: &CString) -> Result<()> {
- let res = unsafe { libc::mq_unlink(name.as_ptr()) };
- Errno::result(res).map(drop)
-}
-
-/// Close a message queue
-///
-/// See also [`mq_close(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_close.html)
-pub fn mq_close(mqdes: mqd_t) -> Result<()> {
- let res = unsafe { libc::mq_close(mqdes) };
- Errno::result(res).map(drop)
-}
-
-/// Receive a message from a message queue
-///
-/// See also [`mq_receive(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html)
-pub fn mq_receive(mqdes: mqd_t, message: &mut [u8], msg_prio: &mut u32) -> Result<usize> {
- let len = message.len() as size_t;
- let res = unsafe {
- libc::mq_receive(mqdes,
- message.as_mut_ptr() as *mut c_char,
- len,
- msg_prio as *mut u32)
- };
- Errno::result(res).map(|r| r as usize)
-}
-
-/// Send a message to a message queue
-///
-/// See also [`mq_send(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html)
-pub fn mq_send(mqdes: mqd_t, message: &[u8], msq_prio: u32) -> Result<()> {
- let res = unsafe {
- libc::mq_send(mqdes,
- message.as_ptr() as *const c_char,
- message.len(),
- msq_prio)
- };
- Errno::result(res).map(drop)
-}
-
-/// Get message queue attributes
-///
-/// See also [`mq_getattr(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_getattr.html)
-pub fn mq_getattr(mqd: mqd_t) -> Result<MqAttr> {
- let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
- let res = unsafe { libc::mq_getattr(mqd, attr.as_mut_ptr()) };
- Errno::result(res).map(|_| unsafe{MqAttr { mq_attr: attr.assume_init() }})
-}
-
-/// Set the attributes of the message queue. Only `O_NONBLOCK` can be set, everything else will be ignored
-/// Returns the old attributes
-/// It is recommend to use the `mq_set_nonblock()` and `mq_remove_nonblock()` convenience functions as they are easier to use
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_setattr.html)
-pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result<MqAttr> {
- let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
- let res = unsafe {
- libc::mq_setattr(mqd, &newattr.mq_attr as *const libc::mq_attr, attr.as_mut_ptr())
- };
- Errno::result(res).map(|_| unsafe{ MqAttr { mq_attr: attr.assume_init() }})
-}
-
-/// Convenience function.
-/// Sets the `O_NONBLOCK` attribute for a given message queue descriptor
-/// Returns the old attributes
-pub fn mq_set_nonblock(mqd: mqd_t) -> Result<MqAttr> {
- let oldattr = mq_getattr(mqd)?;
- let newattr = MqAttr::new(mq_attr_member_t::from(MQ_OFlag::O_NONBLOCK.bits()),
- oldattr.mq_attr.mq_maxmsg,
- oldattr.mq_attr.mq_msgsize,
- oldattr.mq_attr.mq_curmsgs);
- mq_setattr(mqd, &newattr)
-}
-
-/// Convenience function.
-/// Removes `O_NONBLOCK` attribute for a given message queue descriptor
-/// Returns the old attributes
-pub fn mq_remove_nonblock(mqd: mqd_t) -> Result<MqAttr> {
- let oldattr = mq_getattr(mqd)?;
- let newattr = MqAttr::new(0,
- oldattr.mq_attr.mq_maxmsg,
- oldattr.mq_attr.mq_msgsize,
- oldattr.mq_attr.mq_curmsgs);
- mq_setattr(mqd, &newattr)
-}
diff --git a/vendor/nix-0.20.0/src/net/if_.rs b/vendor/nix-0.20.0/src/net/if_.rs
deleted file mode 100644
index 9636488..0000000
--- a/vendor/nix-0.20.0/src/net/if_.rs
+++ /dev/null
@@ -1,267 +0,0 @@
-//! Network interface name resolution.
-//!
-//! Uses Linux and/or POSIX functions to resolve interface names like "eth0"
-//! or "socan1" into device numbers.
-
-use libc::c_uint;
-use crate::{Result, Error, NixPath};
-
-/// Resolve an interface into a interface number.
-pub fn if_nametoindex<P: ?Sized + NixPath>(name: &P) -> Result<c_uint> {
- let if_index = name.with_nix_path(|name| unsafe { libc::if_nametoindex(name.as_ptr()) })?;
-
- if if_index == 0 {
- Err(Error::last())
- } else {
- Ok(if_index)
- }
-}
-
-libc_bitflags!(
- /// Standard interface flags, used by `getifaddrs`
- pub struct InterfaceFlags: libc::c_int {
- /// Interface is running. (see
- /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
- IFF_UP;
- /// Valid broadcast address set. (see
- /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
- IFF_BROADCAST;
- /// Internal debugging flag. (see
- /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
- IFF_DEBUG;
- /// Interface is a loopback interface. (see
- /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
- IFF_LOOPBACK;
- /// Interface is a point-to-point link. (see
- /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
- IFF_POINTOPOINT;
- /// Avoid use of trailers. (see
- /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
- #[cfg(any(target_os = "android",
- target_os = "fuchsia",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "solaris"))]
- IFF_NOTRAILERS;
- /// Interface manages own routes.
- #[cfg(any(target_os = "dragonfly"))]
- IFF_SMART;
- /// Resources allocated. (see
- /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "fuchsia",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"))]
- IFF_RUNNING;
- /// No arp protocol, L2 destination address not set. (see
- /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
- IFF_NOARP;
- /// Interface is in promiscuous mode. (see
- /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
- IFF_PROMISC;
- /// Receive all multicast packets. (see
- /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
- IFF_ALLMULTI;
- /// Master of a load balancing bundle. (see
- /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- IFF_MASTER;
- /// transmission in progress, tx hardware queue is full
- #[cfg(any(target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "ios"))]
- IFF_OACTIVE;
- /// Protocol code on board.
- #[cfg(target_os = "solaris")]
- IFF_INTELLIGENT;
- /// Slave of a load balancing bundle. (see
- /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- IFF_SLAVE;
- /// Can't hear own transmissions.
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "osx"))]
- IFF_SIMPLEX;
- /// Supports multicast. (see
- /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
- IFF_MULTICAST;
- /// Per link layer defined bit.
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "ios"))]
- IFF_LINK0;
- /// Multicast using broadcast.
- #[cfg(any(target_os = "solaris"))]
- IFF_MULTI_BCAST;
- /// Is able to select media type via ifmap. (see
- /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- IFF_PORTSEL;
- /// Per link layer defined bit.
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "ios"))]
- IFF_LINK1;
- /// Non-unique address.
- #[cfg(any(target_os = "solaris"))]
- IFF_UNNUMBERED;
- /// Auto media selection active. (see
- /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- IFF_AUTOMEDIA;
- /// Per link layer defined bit.
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "ios"))]
- IFF_LINK2;
- /// Use alternate physical connection.
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "ios"))]
- IFF_ALTPHYS;
- /// DHCP controlls interface.
- #[cfg(any(target_os = "solaris"))]
- IFF_DHCPRUNNING;
- /// The addresses are lost when the interface goes down. (see
- /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- IFF_DYNAMIC;
- /// Do not advertise.
- #[cfg(any(target_os = "solaris"))]
- IFF_PRIVATE;
- /// Driver signals L1 up. Volatile.
- #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
- IFF_LOWER_UP;
- /// Interface is in polling mode.
- #[cfg(any(target_os = "dragonfly"))]
- IFF_POLLING_COMPAT;
- /// Unconfigurable using ioctl(2).
- #[cfg(any(target_os = "freebsd"))]
- IFF_CANTCONFIG;
- /// Do not transmit packets.
- #[cfg(any(target_os = "solaris"))]
- IFF_NOXMIT;
- /// Driver signals dormant. Volatile.
- #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
- IFF_DORMANT;
- /// User-requested promisc mode.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- IFF_PPROMISC;
- /// Just on-link subnet.
- #[cfg(any(target_os = "solaris"))]
- IFF_NOLOCAL;
- /// Echo sent packets. Volatile.
- #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
- IFF_ECHO;
- /// User-requested monitor mode.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- IFF_MONITOR;
- /// Address is deprecated.
- #[cfg(any(target_os = "solaris"))]
- IFF_DEPRECATED;
- /// Static ARP.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- IFF_STATICARP;
- /// Address from stateless addrconf.
- #[cfg(any(target_os = "solaris"))]
- IFF_ADDRCONF;
- /// Interface is in polling mode.
- #[cfg(any(target_os = "dragonfly"))]
- IFF_NPOLLING;
- /// Router on interface.
- #[cfg(any(target_os = "solaris"))]
- IFF_ROUTER;
- /// Interface is in polling mode.
- #[cfg(any(target_os = "dragonfly"))]
- IFF_IDIRECT;
- /// Interface is winding down
- #[cfg(any(target_os = "freebsd"))]
- IFF_DYING;
- /// No NUD on interface.
- #[cfg(any(target_os = "solaris"))]
- IFF_NONUD;
- /// Interface is being renamed
- #[cfg(any(target_os = "freebsd"))]
- IFF_RENAMING;
- /// Anycast address.
- #[cfg(any(target_os = "solaris"))]
- IFF_ANYCAST;
- /// Don't exchange routing info.
- #[cfg(any(target_os = "solaris"))]
- IFF_NORTEXCH;
- /// Do not provide packet information
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- IFF_NO_PI as libc::c_int;
- /// TUN device (no Ethernet headers)
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- IFF_TUN as libc::c_int;
- /// TAP device
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- IFF_TAP as libc::c_int;
- /// IPv4 interface.
- #[cfg(any(target_os = "solaris"))]
- IFF_IPV4;
- /// IPv6 interface.
- #[cfg(any(target_os = "solaris"))]
- IFF_IPV6;
- /// in.mpathd test address
- #[cfg(any(target_os = "solaris"))]
- IFF_NOFAILOVER;
- /// Interface has failed
- #[cfg(any(target_os = "solaris"))]
- IFF_FAILED;
- /// Interface is a hot-spare
- #[cfg(any(target_os = "solaris"))]
- IFF_STANDBY;
- /// Functioning but not used
- #[cfg(any(target_os = "solaris"))]
- IFF_INACTIVE;
- /// Interface is offline
- #[cfg(any(target_os = "solaris"))]
- IFF_OFFLINE;
- #[cfg(any(target_os = "solaris"))]
- IFF_COS_ENABLED;
- /// Prefer as source addr.
- #[cfg(any(target_os = "solaris"))]
- IFF_PREFERRED;
- /// RFC3041
- #[cfg(any(target_os = "solaris"))]
- IFF_TEMPORARY;
- /// MTU set with SIOCSLIFMTU
- #[cfg(any(target_os = "solaris"))]
- IFF_FIXEDMTU;
- /// Cannot send / receive packets
- #[cfg(any(target_os = "solaris"))]
- IFF_VIRTUAL;
- /// Local address in use
- #[cfg(any(target_os = "solaris"))]
- IFF_DUPLICATE;
- /// IPMP IP interface
- #[cfg(any(target_os = "solaris"))]
- IFF_IPMP;
- }
-);
diff --git a/vendor/nix-0.20.0/src/net/mod.rs b/vendor/nix-0.20.0/src/net/mod.rs
deleted file mode 100644
index 079fcfd..0000000
--- a/vendor/nix-0.20.0/src/net/mod.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//! Functionality involving network interfaces
-// To avoid clashing with the keyword "if", we use "if_" as the module name.
-// The original header is called "net/if.h".
-pub mod if_;
diff --git a/vendor/nix-0.20.0/src/poll.rs b/vendor/nix-0.20.0/src/poll.rs
deleted file mode 100644
index be5bf22..0000000
--- a/vendor/nix-0.20.0/src/poll.rs
+++ /dev/null
@@ -1,146 +0,0 @@
-//! Wait for events to trigger on specific file descriptors
-#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
-use crate::sys::time::TimeSpec;
-#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
-use crate::sys::signal::SigSet;
-use std::os::unix::io::RawFd;
-
-use crate::Result;
-use crate::errno::Errno;
-
-/// This is a wrapper around `libc::pollfd`.
-///
-/// It's meant to be used as an argument to the [`poll`](fn.poll.html) and
-/// [`ppoll`](fn.ppoll.html) functions to specify the events of interest
-/// for a specific file descriptor.
-///
-/// After a call to `poll` or `ppoll`, the events that occured can be
-/// retrieved by calling [`revents()`](#method.revents) on the `PollFd`.
-#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct PollFd {
- pollfd: libc::pollfd,
-}
-
-impl PollFd {
- /// Creates a new `PollFd` specifying the events of interest
- /// for a given file descriptor.
- pub fn new(fd: RawFd, events: PollFlags) -> PollFd {
- PollFd {
- pollfd: libc::pollfd {
- fd,
- events: events.bits(),
- revents: PollFlags::empty().bits(),
- },
- }
- }
-
- /// Returns the events that occured in the last call to `poll` or `ppoll`.
- pub fn revents(self) -> Option<PollFlags> {
- PollFlags::from_bits(self.pollfd.revents)
- }
-}
-
-libc_bitflags! {
- /// These flags define the different events that can be monitored by `poll` and `ppoll`
- pub struct PollFlags: libc::c_short {
- /// There is data to read.
- POLLIN;
- /// There is some exceptional condition on the file descriptor.
- ///
- /// Possibilities include:
- ///
- /// * There is out-of-band data on a TCP socket (see
- /// [tcp(7)](http://man7.org/linux/man-pages/man7/tcp.7.html)).
- /// * A pseudoterminal master in packet mode has seen a state
- /// change on the slave (see
- /// [ioctl_tty(2)](http://man7.org/linux/man-pages/man2/ioctl_tty.2.html)).
- /// * A cgroup.events file has been modified (see
- /// [cgroups(7)](http://man7.org/linux/man-pages/man7/cgroups.7.html)).
- POLLPRI;
- /// Writing is now possible, though a write larger that the
- /// available space in a socket or pipe will still block (unless
- /// `O_NONBLOCK` is set).
- POLLOUT;
- /// Equivalent to [`POLLIN`](constant.POLLIN.html)
- #[cfg(not(target_os = "redox"))]
- POLLRDNORM;
- #[cfg(not(target_os = "redox"))]
- /// Equivalent to [`POLLOUT`](constant.POLLOUT.html)
- POLLWRNORM;
- /// Priority band data can be read (generally unused on Linux).
- #[cfg(not(target_os = "redox"))]
- POLLRDBAND;
- /// Priority data may be written.
- #[cfg(not(target_os = "redox"))]
- POLLWRBAND;
- /// Error condition (only returned in
- /// [`PollFd::revents`](struct.PollFd.html#method.revents);
- /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)).
- /// This bit is also set for a file descriptor referring to the
- /// write end of a pipe when the read end has been closed.
- POLLERR;
- /// Hang up (only returned in [`PollFd::revents`](struct.PollFd.html#method.revents);
- /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)).
- /// Note that when reading from a channel such as a pipe or a stream
- /// socket, this event merely indicates that the peer closed its
- /// end of the channel. Subsequent reads from the channel will
- /// return 0 (end of file) only after all outstanding data in the
- /// channel has been consumed.
- POLLHUP;
- /// Invalid request: `fd` not open (only returned in
- /// [`PollFd::revents`](struct.PollFd.html#method.revents);
- /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)).
- POLLNVAL;
- }
-}
-
-/// `poll` waits for one of a set of file descriptors to become ready to perform I/O.
-/// ([`poll(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html))
-///
-/// `fds` contains all [`PollFd`](struct.PollFd.html) to poll.
-/// The function will return as soon as any event occur for any of these `PollFd`s.
-///
-/// The `timeout` argument specifies the number of milliseconds that `poll()`
-/// should block waiting for a file descriptor to become ready. The call
-/// will block until either:
-///
-/// * a file descriptor becomes ready;
-/// * the call is interrupted by a signal handler; or
-/// * the timeout expires.
-///
-/// Note that the timeout interval will be rounded up to the system clock
-/// granularity, and kernel scheduling delays mean that the blocking
-/// interval may overrun by a small amount. Specifying a negative value
-/// in timeout means an infinite timeout. Specifying a timeout of zero
-/// causes `poll()` to return immediately, even if no file descriptors are
-/// ready.
-pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result<libc::c_int> {
- let res = unsafe {
- libc::poll(fds.as_mut_ptr() as *mut libc::pollfd,
- fds.len() as libc::nfds_t,
- timeout)
- };
-
- Errno::result(res)
-}
-
-/// `ppoll()` allows an application to safely wait until either a file
-/// descriptor becomes ready or until a signal is caught.
-/// ([`poll(2)`](http://man7.org/linux/man-pages/man2/poll.2.html))
-///
-/// `ppoll` behaves like `poll`, but let you specify what signals may interrupt it
-/// with the `sigmask` argument. If you want `ppoll` to block indefinitely,
-/// specify `None` as `timeout` (it is like `timeout = -1` for `poll`).
-///
-#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
-pub fn ppoll(fds: &mut [PollFd], timeout: Option<TimeSpec>, sigmask: SigSet) -> Result<libc::c_int> {
- let timeout = timeout.as_ref().map_or(core::ptr::null(), |r| r.as_ref());
- let res = unsafe {
- libc::ppoll(fds.as_mut_ptr() as *mut libc::pollfd,
- fds.len() as libc::nfds_t,
- timeout,
- sigmask.as_ref())
- };
- Errno::result(res)
-}
diff --git a/vendor/nix-0.20.0/src/pty.rs b/vendor/nix-0.20.0/src/pty.rs
deleted file mode 100644
index d67518f..0000000
--- a/vendor/nix-0.20.0/src/pty.rs
+++ /dev/null
@@ -1,342 +0,0 @@
-//! Create master and slave virtual pseudo-terminals (PTYs)
-
-pub use libc::pid_t as SessionId;
-pub use libc::winsize as Winsize;
-
-use std::ffi::CStr;
-use std::io;
-use std::mem;
-use std::os::unix::prelude::*;
-
-use crate::sys::termios::Termios;
-use crate::unistd::{self, ForkResult, Pid};
-use crate::{Result, Error, fcntl};
-use crate::errno::Errno;
-
-/// Representation of a master/slave pty pair
-///
-/// This is returned by `openpty`. Note that this type does *not* implement `Drop`, so the user
-/// must manually close the file descriptors.
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct OpenptyResult {
- /// The master port in a virtual pty pair
- pub master: RawFd,
- /// The slave port in a virtual pty pair
- pub slave: RawFd,
-}
-
-/// Representation of a master with a forked pty
-///
-/// This is returned by `forkpty`. Note that this type does *not* implement `Drop`, so the user
-/// must manually close the file descriptors.
-#[derive(Clone, Copy, Debug)]
-pub struct ForkptyResult {
- /// The master port in a virtual pty pair
- pub master: RawFd,
- /// Metadata about forked process
- pub fork_result: ForkResult,
-}
-
-
-/// Representation of the Master device in a master/slave pty pair
-///
-/// While this datatype is a thin wrapper around `RawFd`, it enforces that the available PTY
-/// functions are given the correct file descriptor. Additionally this type implements `Drop`,
-/// so that when it's consumed or goes out of scope, it's automatically cleaned-up.
-#[derive(Debug, Eq, Hash, PartialEq)]
-pub struct PtyMaster(RawFd);
-
-impl AsRawFd for PtyMaster {
- fn as_raw_fd(&self) -> RawFd {
- self.0
- }
-}
-
-impl IntoRawFd for PtyMaster {
- fn into_raw_fd(self) -> RawFd {
- let fd = self.0;
- mem::forget(self);
- fd
- }
-}
-
-impl Drop for PtyMaster {
- fn drop(&mut self) {
- // On drop, we ignore errors like EINTR and EIO because there's no clear
- // way to handle them, we can't return anything, and (on FreeBSD at
- // least) the file descriptor is deallocated in these cases. However,
- // we must panic on EBADF, because it is always an error to close an
- // invalid file descriptor. That frequently indicates a double-close
- // condition, which can cause confusing errors for future I/O
- // operations.
- let e = unistd::close(self.0);
- if e == Err(Error::Sys(Errno::EBADF)) {
- panic!("Closing an invalid file descriptor!");
- };
- }
-}
-
-impl io::Read for PtyMaster {
- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- unistd::read(self.0, buf).map_err(|e| e.as_errno().unwrap().into())
- }
-}
-
-impl io::Write for PtyMaster {
- fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- unistd::write(self.0, buf).map_err(|e| e.as_errno().unwrap().into())
- }
- fn flush(&mut self) -> io::Result<()> {
- Ok(())
- }
-}
-
-/// Grant access to a slave pseudoterminal (see
-/// [`grantpt(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/grantpt.html))
-///
-/// `grantpt()` changes the mode and owner of the slave pseudoterminal device corresponding to the
-/// master pseudoterminal referred to by `fd`. This is a necessary step towards opening the slave.
-#[inline]
-pub fn grantpt(fd: &PtyMaster) -> Result<()> {
- if unsafe { libc::grantpt(fd.as_raw_fd()) } < 0 {
- return Err(Error::last());
- }
-
- Ok(())
-}
-
-/// Open a pseudoterminal device (see
-/// [`posix_openpt(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_openpt.html))
-///
-/// `posix_openpt()` returns a file descriptor to an existing unused pseuterminal master device.
-///
-/// # Examples
-///
-/// A common use case with this function is to open both a master and slave PTY pair. This can be
-/// done as follows:
-///
-/// ```
-/// use std::path::Path;
-/// use nix::fcntl::{OFlag, open};
-/// use nix::pty::{grantpt, posix_openpt, ptsname, unlockpt};
-/// use nix::sys::stat::Mode;
-///
-/// # #[allow(dead_code)]
-/// # fn run() -> nix::Result<()> {
-/// // Open a new PTY master
-/// let master_fd = posix_openpt(OFlag::O_RDWR)?;
-///
-/// // Allow a slave to be generated for it
-/// grantpt(&master_fd)?;
-/// unlockpt(&master_fd)?;
-///
-/// // Get the name of the slave
-/// let slave_name = unsafe { ptsname(&master_fd) }?;
-///
-/// // Try to open the slave
-/// let _slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, Mode::empty())?;
-/// # Ok(())
-/// # }
-/// ```
-#[inline]
-pub fn posix_openpt(flags: fcntl::OFlag) -> Result<PtyMaster> {
- let fd = unsafe {
- libc::posix_openpt(flags.bits())
- };
-
- if fd < 0 {
- return Err(Error::last());
- }
-
- Ok(PtyMaster(fd))
-}
-
-/// Get the name of the slave pseudoterminal (see
-/// [`ptsname(3)`](http://man7.org/linux/man-pages/man3/ptsname.3.html))
-///
-/// `ptsname()` returns the name of the slave pseudoterminal device corresponding to the master
-/// referred to by `fd`.
-///
-/// This value is useful for opening the slave pty once the master has already been opened with
-/// `posix_openpt()`.
-///
-/// # Safety
-///
-/// `ptsname()` mutates global variables and is *not* threadsafe.
-/// Mutating global variables is always considered `unsafe` by Rust and this
-/// function is marked as `unsafe` to reflect that.
-///
-/// For a threadsafe and non-`unsafe` alternative on Linux, see `ptsname_r()`.
-#[inline]
-pub unsafe fn ptsname(fd: &PtyMaster) -> Result<String> {
- let name_ptr = libc::ptsname(fd.as_raw_fd());
- if name_ptr.is_null() {
- return Err(Error::last());
- }
-
- let name = CStr::from_ptr(name_ptr);
- Ok(name.to_string_lossy().into_owned())
-}
-
-/// Get the name of the slave pseudoterminal (see
-/// [`ptsname(3)`](http://man7.org/linux/man-pages/man3/ptsname.3.html))
-///
-/// `ptsname_r()` returns the name of the slave pseudoterminal device corresponding to the master
-/// referred to by `fd`. This is the threadsafe version of `ptsname()`, but it is not part of the
-/// POSIX standard and is instead a Linux-specific extension.
-///
-/// This value is useful for opening the slave ptty once the master has already been opened with
-/// `posix_openpt()`.
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[inline]
-pub fn ptsname_r(fd: &PtyMaster) -> Result<String> {
- let mut name_buf = vec![0u8; 64];
- let name_buf_ptr = name_buf.as_mut_ptr() as *mut libc::c_char;
- if unsafe { libc::ptsname_r(fd.as_raw_fd(), name_buf_ptr, name_buf.capacity()) } != 0 {
- return Err(Error::last());
- }
-
- // Find the first null-character terminating this string. This is guaranteed to succeed if the
- // return value of `libc::ptsname_r` is 0.
- let null_index = name_buf.iter().position(|c| *c == b'\0').unwrap();
- name_buf.truncate(null_index);
-
- let name = String::from_utf8(name_buf)?;
- Ok(name)
-}
-
-/// Unlock a pseudoterminal master/slave pseudoterminal pair (see
-/// [`unlockpt(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlockpt.html))
-///
-/// `unlockpt()` unlocks the slave pseudoterminal device corresponding to the master pseudoterminal
-/// referred to by `fd`. This must be called before trying to open the slave side of a
-/// pseuoterminal.
-#[inline]
-pub fn unlockpt(fd: &PtyMaster) -> Result<()> {
- if unsafe { libc::unlockpt(fd.as_raw_fd()) } < 0 {
- return Err(Error::last());
- }
-
- Ok(())
-}
-
-
-/// Create a new pseudoterminal, returning the slave and master file descriptors
-/// in `OpenptyResult`
-/// (see [`openpty`](http://man7.org/linux/man-pages/man3/openpty.3.html)).
-///
-/// If `winsize` is not `None`, the window size of the slave will be set to
-/// the values in `winsize`. If `termios` is not `None`, the pseudoterminal's
-/// terminal settings of the slave will be set to the values in `termios`.
-#[inline]
-pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>>>(winsize: T, termios: U) -> Result<OpenptyResult> {
- use std::ptr;
-
- let mut slave = mem::MaybeUninit::<libc::c_int>::uninit();
- let mut master = mem::MaybeUninit::<libc::c_int>::uninit();
- let ret = {
- match (termios.into(), winsize.into()) {
- (Some(termios), Some(winsize)) => {
- let inner_termios = termios.get_libc_termios();
- unsafe {
- libc::openpty(
- master.as_mut_ptr(),
- slave.as_mut_ptr(),
- ptr::null_mut(),
- &*inner_termios as *const libc::termios as *mut _,
- winsize as *const Winsize as *mut _,
- )
- }
- }
- (None, Some(winsize)) => {
- unsafe {
- libc::openpty(
- master.as_mut_ptr(),
- slave.as_mut_ptr(),
- ptr::null_mut(),
- ptr::null_mut(),
- winsize as *const Winsize as *mut _,
- )
- }
- }
- (Some(termios), None) => {
- let inner_termios = termios.get_libc_termios();
- unsafe {
- libc::openpty(
- master.as_mut_ptr(),
- slave.as_mut_ptr(),
- ptr::null_mut(),
- &*inner_termios as *const libc::termios as *mut _,
- ptr::null_mut(),
- )
- }
- }
- (None, None) => {
- unsafe {
- libc::openpty(
- master.as_mut_ptr(),
- slave.as_mut_ptr(),
- ptr::null_mut(),
- ptr::null_mut(),
- ptr::null_mut(),
- )
- }
- }
- }
- };
-
- Errno::result(ret)?;
-
- unsafe {
- Ok(OpenptyResult {
- master: master.assume_init(),
- slave: slave.assume_init(),
- })
- }
-}
-
-/// Create a new pseudoterminal, returning the master file descriptor and forked pid.
-/// in `ForkptyResult`
-/// (see [`forkpty`](http://man7.org/linux/man-pages/man3/forkpty.3.html)).
-///
-/// If `winsize` is not `None`, the window size of the slave will be set to
-/// the values in `winsize`. If `termios` is not `None`, the pseudoterminal's
-/// terminal settings of the slave will be set to the values in `termios`.
-pub fn forkpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>>>(
- winsize: T,
- termios: U,
-) -> Result<ForkptyResult> {
- use std::ptr;
-
- let mut master = mem::MaybeUninit::<libc::c_int>::uninit();
-
- let term = match termios.into() {
- Some(termios) => {
- let inner_termios = termios.get_libc_termios();
- &*inner_termios as *const libc::termios as *mut _
- },
- None => ptr::null_mut(),
- };
-
- let win = winsize
- .into()
- .map(|ws| ws as *const Winsize as *mut _)
- .unwrap_or(ptr::null_mut());
-
- let res = unsafe {
- libc::forkpty(master.as_mut_ptr(), ptr::null_mut(), term, win)
- };
-
- let fork_result = Errno::result(res).map(|res| match res {
- 0 => ForkResult::Child,
- res => ForkResult::Parent { child: Pid::from_raw(res) },
- })?;
-
- unsafe {
- Ok(ForkptyResult {
- master: master.assume_init(),
- fork_result,
- })
- }
-}
-
diff --git a/vendor/nix-0.20.0/src/sched.rs b/vendor/nix-0.20.0/src/sched.rs
deleted file mode 100644
index 3b48b4a..0000000
--- a/vendor/nix-0.20.0/src/sched.rs
+++ /dev/null
@@ -1,227 +0,0 @@
-use crate::{Errno, Result};
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use self::sched_linux_like::*;
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-mod sched_linux_like {
- use crate::errno::Errno;
- use libc::{self, c_int, c_void};
- use std::mem;
- use std::option::Option;
- use std::os::unix::io::RawFd;
- use crate::unistd::Pid;
- use crate::{Error, Result};
-
- // For some functions taking with a parameter of type CloneFlags,
- // only a subset of these flags have an effect.
- libc_bitflags! {
- pub struct CloneFlags: c_int {
- CLONE_VM;
- CLONE_FS;
- CLONE_FILES;
- CLONE_SIGHAND;
- CLONE_PTRACE;
- CLONE_VFORK;
- CLONE_PARENT;
- CLONE_THREAD;
- CLONE_NEWNS;
- CLONE_SYSVSEM;
- CLONE_SETTLS;
- CLONE_PARENT_SETTID;
- CLONE_CHILD_CLEARTID;
- CLONE_DETACHED;
- CLONE_UNTRACED;
- CLONE_CHILD_SETTID;
- CLONE_NEWCGROUP;
- CLONE_NEWUTS;
- CLONE_NEWIPC;
- CLONE_NEWUSER;
- CLONE_NEWPID;
- CLONE_NEWNET;
- CLONE_IO;
- }
- }
-
- pub type CloneCb<'a> = Box<dyn FnMut() -> isize + 'a>;
-
- /// CpuSet represent a bit-mask of CPUs.
- /// CpuSets are used by sched_setaffinity and
- /// sched_getaffinity for example.
- ///
- /// This is a wrapper around `libc::cpu_set_t`.
- #[repr(C)]
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct CpuSet {
- cpu_set: libc::cpu_set_t,
- }
-
- impl CpuSet {
- /// Create a new and empty CpuSet.
- pub fn new() -> CpuSet {
- CpuSet {
- cpu_set: unsafe { mem::zeroed() },
- }
- }
-
- /// Test to see if a CPU is in the CpuSet.
- /// `field` is the CPU id to test
- pub fn is_set(&self, field: usize) -> Result<bool> {
- if field >= CpuSet::count() {
- Err(Error::Sys(Errno::EINVAL))
- } else {
- Ok(unsafe { libc::CPU_ISSET(field, &self.cpu_set) })
- }
- }
-
- /// Add a CPU to CpuSet.
- /// `field` is the CPU id to add
- pub fn set(&mut self, field: usize) -> Result<()> {
- if field >= CpuSet::count() {
- Err(Error::Sys(Errno::EINVAL))
- } else {
- unsafe { libc::CPU_SET(field, &mut self.cpu_set); }
- Ok(())
- }
- }
-
- /// Remove a CPU from CpuSet.
- /// `field` is the CPU id to remove
- pub fn unset(&mut self, field: usize) -> Result<()> {
- if field >= CpuSet::count() {
- Err(Error::Sys(Errno::EINVAL))
- } else {
- unsafe { libc::CPU_CLR(field, &mut self.cpu_set);}
- Ok(())
- }
- }
-
- /// Return the maximum number of CPU in CpuSet
- pub fn count() -> usize {
- 8 * mem::size_of::<libc::cpu_set_t>()
- }
- }
-
- impl Default for CpuSet {
- fn default() -> Self {
- Self::new()
- }
- }
-
- /// `sched_setaffinity` set a thread's CPU affinity mask
- /// ([`sched_setaffinity(2)`](http://man7.org/linux/man-pages/man2/sched_setaffinity.2.html))
- ///
- /// `pid` is the thread ID to update.
- /// If pid is zero, then the calling thread is updated.
- ///
- /// The `cpuset` argument specifies the set of CPUs on which the thread
- /// will be eligible to run.
- ///
- /// # Example
- ///
- /// Binding the current thread to CPU 0 can be done as follows:
- ///
- /// ```rust,no_run
- /// use nix::sched::{CpuSet, sched_setaffinity};
- /// use nix::unistd::Pid;
- ///
- /// let mut cpu_set = CpuSet::new();
- /// cpu_set.set(0);
- /// sched_setaffinity(Pid::from_raw(0), &cpu_set);
- /// ```
- pub fn sched_setaffinity(pid: Pid, cpuset: &CpuSet) -> Result<()> {
- let res = unsafe {
- libc::sched_setaffinity(
- pid.into(),
- mem::size_of::<CpuSet>() as libc::size_t,
- &cpuset.cpu_set,
- )
- };
-
- Errno::result(res).map(drop)
- }
-
- /// `sched_getaffinity` get a thread's CPU affinity mask
- /// ([`sched_getaffinity(2)`](http://man7.org/linux/man-pages/man2/sched_getaffinity.2.html))
- ///
- /// `pid` is the thread ID to check.
- /// If pid is zero, then the calling thread is checked.
- ///
- /// Returned `cpuset` is the set of CPUs on which the thread
- /// is eligible to run.
- ///
- /// # Example
- ///
- /// Checking if the current thread can run on CPU 0 can be done as follows:
- ///
- /// ```rust,no_run
- /// use nix::sched::sched_getaffinity;
- /// use nix::unistd::Pid;
- ///
- /// let cpu_set = sched_getaffinity(Pid::from_raw(0)).unwrap();
- /// if cpu_set.is_set(0).unwrap() {
- /// println!("Current thread can run on CPU 0");
- /// }
- /// ```
- pub fn sched_getaffinity(pid: Pid) -> Result<CpuSet> {
- let mut cpuset = CpuSet::new();
- let res = unsafe {
- libc::sched_getaffinity(
- pid.into(),
- mem::size_of::<CpuSet>() as libc::size_t,
- &mut cpuset.cpu_set,
- )
- };
-
- Errno::result(res).and(Ok(cpuset))
- }
-
- pub fn clone(
- mut cb: CloneCb,
- stack: &mut [u8],
- flags: CloneFlags,
- signal: Option<c_int>,
- ) -> Result<Pid> {
- extern "C" fn callback(data: *mut CloneCb) -> c_int {
- let cb: &mut CloneCb = unsafe { &mut *data };
- (*cb)() as c_int
- }
-
- let res = unsafe {
- let combined = flags.bits() | signal.unwrap_or(0);
- let ptr = stack.as_mut_ptr().add(stack.len());
- let ptr_aligned = ptr.sub(ptr as usize % 16);
- libc::clone(
- mem::transmute(
- callback as extern "C" fn(*mut Box<dyn FnMut() -> isize>) -> i32,
- ),
- ptr_aligned as *mut c_void,
- combined,
- &mut cb as *mut _ as *mut c_void,
- )
- };
-
- Errno::result(res).map(Pid::from_raw)
- }
-
- pub fn unshare(flags: CloneFlags) -> Result<()> {
- let res = unsafe { libc::unshare(flags.bits()) };
-
- Errno::result(res).map(drop)
- }
-
- pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> {
- let res = unsafe { libc::setns(fd, nstype.bits()) };
-
- Errno::result(res).map(drop)
- }
-}
-
-/// Explicitly yield the processor to other threads.
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sched_yield.html)
-pub fn sched_yield() -> Result<()> {
- let res = unsafe { libc::sched_yield() };
-
- Errno::result(res).map(drop)
-}
diff --git a/vendor/nix-0.20.0/src/sys/aio.rs b/vendor/nix-0.20.0/src/sys/aio.rs
deleted file mode 100644
index 1afdb35..0000000
--- a/vendor/nix-0.20.0/src/sys/aio.rs
+++ /dev/null
@@ -1,1246 +0,0 @@
-// vim: tw=80
-//! POSIX Asynchronous I/O
-//!
-//! The POSIX AIO interface is used for asynchronous I/O on files and disk-like
-//! devices. It supports [`read`](struct.AioCb.html#method.read),
-//! [`write`](struct.AioCb.html#method.write), and
-//! [`fsync`](struct.AioCb.html#method.fsync) operations. Completion
-//! notifications can optionally be delivered via
-//! [signals](../signal/enum.SigevNotify.html#variant.SigevSignal), via the
-//! [`aio_suspend`](fn.aio_suspend.html) function, or via polling. Some
-//! platforms support other completion
-//! notifications, such as
-//! [kevent](../signal/enum.SigevNotify.html#variant.SigevKevent).
-//!
-//! Multiple operations may be submitted in a batch with
-//! [`lio_listio`](fn.lio_listio.html), though the standard does not guarantee
-//! that they will be executed atomically.
-//!
-//! Outstanding operations may be cancelled with
-//! [`cancel`](struct.AioCb.html#method.cancel) or
-//! [`aio_cancel_all`](fn.aio_cancel_all.html), though the operating system may
-//! not support this for all filesystems and devices.
-
-use crate::{Error, Result};
-use crate::errno::Errno;
-use std::os::unix::io::RawFd;
-use libc::{c_void, off_t, size_t};
-use std::borrow::{Borrow, BorrowMut};
-use std::fmt;
-use std::fmt::Debug;
-use std::marker::PhantomData;
-use std::mem;
-use std::ptr::{null, null_mut};
-use crate::sys::signal::*;
-use std::thread;
-use crate::sys::time::TimeSpec;
-
-libc_enum! {
- /// Mode for `AioCb::fsync`. Controls whether only data or both data and
- /// metadata are synced.
- #[repr(i32)]
- pub enum AioFsyncMode {
- /// do it like `fsync`
- O_SYNC,
- /// on supported operating systems only, do it like `fdatasync`
- #[cfg(any(target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- O_DSYNC
- }
-}
-
-libc_enum! {
- /// When used with [`lio_listio`](fn.lio_listio.html), determines whether a
- /// given `aiocb` should be used for a read operation, a write operation, or
- /// ignored. Has no effect for any other aio functions.
- #[repr(i32)]
- pub enum LioOpcode {
- LIO_NOP,
- LIO_WRITE,
- LIO_READ,
- }
-}
-
-libc_enum! {
- /// Mode for [`lio_listio`](fn.lio_listio.html)
- #[repr(i32)]
- pub enum LioMode {
- /// Requests that [`lio_listio`](fn.lio_listio.html) block until all
- /// requested operations have been completed
- LIO_WAIT,
- /// Requests that [`lio_listio`](fn.lio_listio.html) return immediately
- LIO_NOWAIT,
- }
-}
-
-/// Return values for [`AioCb::cancel`](struct.AioCb.html#method.cancel) and
-/// [`aio_cancel_all`](fn.aio_cancel_all.html)
-#[repr(i32)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum AioCancelStat {
- /// All outstanding requests were canceled
- AioCanceled = libc::AIO_CANCELED,
- /// Some requests were not canceled. Their status should be checked with
- /// `AioCb::error`
- AioNotCanceled = libc::AIO_NOTCANCELED,
- /// All of the requests have already finished
- AioAllDone = libc::AIO_ALLDONE,
-}
-
-/// Owns (uniquely or shared) a memory buffer to keep it from `Drop`ing while
-/// the kernel has a pointer to it.
-pub enum Buffer<'a> {
- /// No buffer to own.
- ///
- /// Used for operations like `aio_fsync` that have no data, or for unsafe
- /// operations that work with raw pointers.
- None,
- /// Keeps a reference to a slice
- Phantom(PhantomData<&'a mut [u8]>),
- /// Generic thing that keeps a buffer from dropping
- BoxedSlice(Box<dyn Borrow<[u8]>>),
- /// Generic thing that keeps a mutable buffer from dropping
- BoxedMutSlice(Box<dyn BorrowMut<[u8]>>),
-}
-
-impl<'a> Debug for Buffer<'a> {
- // Note: someday it may be possible to Derive Debug for a trait object, but
- // not today.
- // https://github.com/rust-lang/rust/issues/1563
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- Buffer::None => write!(fmt, "None"),
- Buffer::Phantom(p) => p.fmt(fmt),
- Buffer::BoxedSlice(ref bs) => {
- let borrowed : &dyn Borrow<[u8]> = bs.borrow();
- write!(fmt, "BoxedSlice({:?})",
- borrowed as *const dyn Borrow<[u8]>)
- },
- Buffer::BoxedMutSlice(ref bms) => {
- let borrowed : &dyn BorrowMut<[u8]> = bms.borrow();
- write!(fmt, "BoxedMutSlice({:?})",
- borrowed as *const dyn BorrowMut<[u8]>)
- }
- }
- }
-}
-
-/// AIO Control Block.
-///
-/// The basic structure used by all aio functions. Each `AioCb` represents one
-/// I/O request.
-pub struct AioCb<'a> {
- aiocb: libc::aiocb,
- /// Tracks whether the buffer pointed to by `libc::aiocb.aio_buf` is mutable
- mutable: bool,
- /// Could this `AioCb` potentially have any in-kernel state?
- in_progress: bool,
- /// Optionally keeps a reference to the data.
- ///
- /// Used to keep buffers from `Drop`'ing, and may be returned once the
- /// `AioCb` is completed by [`buffer`](#method.buffer).
- buffer: Buffer<'a>
-}
-
-impl<'a> AioCb<'a> {
- /// Remove the inner `Buffer` and return it
- ///
- /// It is an error to call this method while the `AioCb` is still in
- /// progress.
- pub fn buffer(&mut self) -> Buffer<'a> {
- assert!(!self.in_progress);
- let mut x = Buffer::None;
- mem::swap(&mut self.buffer, &mut x);
- x
- }
-
- /// Remove the inner boxed slice, if any, and return it.
- ///
- /// The returned value will be the argument that was passed to
- /// `from_boxed_slice` when this `AioCb` was created.
- ///
- /// It is an error to call this method while the `AioCb` is still in
- /// progress.
- pub fn boxed_slice(&mut self) -> Option<Box<dyn Borrow<[u8]>>> {
- assert!(!self.in_progress, "Can't remove the buffer from an AioCb that's still in-progress. Did you forget to call aio_return?");
- if let Buffer::BoxedSlice(_) = self.buffer {
- let mut oldbuffer = Buffer::None;
- mem::swap(&mut self.buffer, &mut oldbuffer);
- if let Buffer::BoxedSlice(inner) = oldbuffer {
- Some(inner)
- } else {
- unreachable!();
- }
- } else {
- None
- }
- }
-
- /// Remove the inner boxed mutable slice, if any, and return it.
- ///
- /// The returned value will be the argument that was passed to
- /// `from_boxed_mut_slice` when this `AioCb` was created.
- ///
- /// It is an error to call this method while the `AioCb` is still in
- /// progress.
- pub fn boxed_mut_slice(&mut self) -> Option<Box<dyn BorrowMut<[u8]>>> {
- assert!(!self.in_progress, "Can't remove the buffer from an AioCb that's still in-progress. Did you forget to call aio_return?");
- if let Buffer::BoxedMutSlice(_) = self.buffer {
- let mut oldbuffer = Buffer::None;
- mem::swap(&mut self.buffer, &mut oldbuffer);
- if let Buffer::BoxedMutSlice(inner) = oldbuffer {
- Some(inner)
- } else {
- unreachable!();
- }
- } else {
- None
- }
- }
-
- /// Returns the underlying file descriptor associated with the `AioCb`
- pub fn fd(&self) -> RawFd {
- self.aiocb.aio_fildes
- }
-
- /// Constructs a new `AioCb` with no associated buffer.
- ///
- /// The resulting `AioCb` structure is suitable for use with `AioCb::fsync`.
- ///
- /// # Parameters
- ///
- /// * `fd`: File descriptor. Required for all aio functions.
- /// * `prio`: If POSIX Prioritized IO is supported, then the
- /// operation will be prioritized at the process's
- /// priority level minus `prio`.
- /// * `sigev_notify`: Determines how you will be notified of event
- /// completion.
- ///
- /// # Examples
- ///
- /// Create an `AioCb` from a raw file descriptor and use it for an
- /// [`fsync`](#method.fsync) operation.
- ///
- /// ```
- /// # use nix::errno::Errno;
- /// # use nix::Error;
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify::SigevNone;
- /// # use std::{thread, time};
- /// # use std::os::unix::io::AsRawFd;
- /// # use tempfile::tempfile;
- /// # fn main() {
- /// let f = tempfile().unwrap();
- /// let mut aiocb = AioCb::from_fd( f.as_raw_fd(), 0, SigevNone);
- /// aiocb.fsync(AioFsyncMode::O_SYNC).expect("aio_fsync failed early");
- /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
- /// thread::sleep(time::Duration::from_millis(10));
- /// }
- /// aiocb.aio_return().expect("aio_fsync failed late");
- /// # }
- /// ```
- pub fn from_fd(fd: RawFd, prio: libc::c_int,
- sigev_notify: SigevNotify) -> AioCb<'a> {
- let mut a = AioCb::common_init(fd, prio, sigev_notify);
- a.aio_offset = 0;
- a.aio_nbytes = 0;
- a.aio_buf = null_mut();
-
- AioCb {
- aiocb: a,
- mutable: false,
- in_progress: false,
- buffer: Buffer::None
- }
- }
-
- /// Constructs a new `AioCb` from a mutable slice.
- ///
- /// The resulting `AioCb` will be suitable for both read and write
- /// operations, but only if the borrow checker can guarantee that the slice
- /// will outlive the `AioCb`. That will usually be the case if the `AioCb`
- /// is stack-allocated. If the borrow checker gives you trouble, try using
- /// [`from_boxed_mut_slice`](#method.from_boxed_mut_slice) instead.
- ///
- /// # Parameters
- ///
- /// * `fd`: File descriptor. Required for all aio functions.
- /// * `offs`: File offset
- /// * `buf`: A memory buffer
- /// * `prio`: If POSIX Prioritized IO is supported, then the
- /// operation will be prioritized at the process's
- /// priority level minus `prio`
- /// * `sigev_notify`: Determines how you will be notified of event
- /// completion.
- /// * `opcode`: This field is only used for `lio_listio`. It
- /// determines which operation to use for this individual
- /// aiocb
- ///
- /// # Examples
- ///
- /// Create an `AioCb` from a mutable slice and read into it.
- ///
- /// ```
- /// # use nix::errno::Errno;
- /// # use nix::Error;
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify;
- /// # use std::{thread, time};
- /// # use std::io::Write;
- /// # use std::os::unix::io::AsRawFd;
- /// # use tempfile::tempfile;
- /// # fn main() {
- /// const INITIAL: &[u8] = b"abcdef123456";
- /// const LEN: usize = 4;
- /// let mut rbuf = vec![0; LEN];
- /// let mut f = tempfile().unwrap();
- /// f.write_all(INITIAL).unwrap();
- /// {
- /// let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(),
- /// 2, //offset
- /// &mut rbuf,
- /// 0, //priority
- /// SigevNotify::SigevNone,
- /// LioOpcode::LIO_NOP);
- /// aiocb.read().unwrap();
- /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
- /// thread::sleep(time::Duration::from_millis(10));
- /// }
- /// assert_eq!(aiocb.aio_return().unwrap() as usize, LEN);
- /// }
- /// assert_eq!(rbuf, b"cdef");
- /// # }
- /// ```
- pub fn from_mut_slice(fd: RawFd, offs: off_t, buf: &'a mut [u8],
- prio: libc::c_int, sigev_notify: SigevNotify,
- opcode: LioOpcode) -> AioCb<'a> {
- let mut a = AioCb::common_init(fd, prio, sigev_notify);
- a.aio_offset = offs;
- a.aio_nbytes = buf.len() as size_t;
- a.aio_buf = buf.as_ptr() as *mut c_void;
- a.aio_lio_opcode = opcode as libc::c_int;
-
- AioCb {
- aiocb: a,
- mutable: true,
- in_progress: false,
- buffer: Buffer::Phantom(PhantomData),
- }
- }
-
- /// The safest and most flexible way to create an `AioCb`.
- ///
- /// Unlike [`from_slice`], this method returns a structure suitable for
- /// placement on the heap. It may be used for write operations, but not
- /// read operations. Unlike `from_ptr`, this method will ensure that the
- /// buffer doesn't `drop` while the kernel is still processing it. Any
- /// object that can be borrowed as a boxed slice will work.
- ///
- /// # Parameters
- ///
- /// * `fd`: File descriptor. Required for all aio functions.
- /// * `offs`: File offset
- /// * `buf`: A boxed slice-like object
- /// * `prio`: If POSIX Prioritized IO is supported, then the
- /// operation will be prioritized at the process's
- /// priority level minus `prio`
- /// * `sigev_notify`: Determines how you will be notified of event
- /// completion.
- /// * `opcode`: This field is only used for `lio_listio`. It
- /// determines which operation to use for this individual
- /// aiocb
- ///
- /// # Examples
- ///
- /// Create an `AioCb` from a Vector and use it for writing
- ///
- /// ```
- /// # use nix::errno::Errno;
- /// # use nix::Error;
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify;
- /// # use std::{thread, time};
- /// # use std::io::Write;
- /// # use std::os::unix::io::AsRawFd;
- /// # use tempfile::tempfile;
- /// # fn main() {
- /// let wbuf = Box::new(Vec::from("CDEF"));
- /// let expected_len = wbuf.len();
- /// let mut f = tempfile().unwrap();
- /// let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
- /// 2, //offset
- /// wbuf,
- /// 0, //priority
- /// SigevNotify::SigevNone,
- /// LioOpcode::LIO_NOP);
- /// aiocb.write().unwrap();
- /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
- /// thread::sleep(time::Duration::from_millis(10));
- /// }
- /// assert_eq!(aiocb.aio_return().unwrap() as usize, expected_len);
- /// # }
- /// ```
- ///
- /// Create an `AioCb` from a `Bytes` object
- ///
- /// ```
- /// # use bytes::Bytes;
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify;
- /// # use std::os::unix::io::AsRawFd;
- /// # use tempfile::tempfile;
- /// # fn main() {
- /// let wbuf = Box::new(Bytes::from(&b"CDEF"[..]));
- /// let mut f = tempfile().unwrap();
- /// let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
- /// 2, //offset
- /// wbuf,
- /// 0, //priority
- /// SigevNotify::SigevNone,
- /// LioOpcode::LIO_NOP);
- /// # }
- /// ```
- ///
- /// If a library needs to work with buffers that aren't `Box`ed, it can
- /// create a `Box`ed container for use with this method. Here's an example
- /// using an un`Box`ed `Bytes` object.
- ///
- /// ```
- /// # use bytes::Bytes;
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify;
- /// # use std::borrow::Borrow;
- /// # use std::os::unix::io::AsRawFd;
- /// # use tempfile::tempfile;
- /// struct BytesContainer(Bytes);
- /// impl Borrow<[u8]> for BytesContainer {
- /// fn borrow(&self) -> &[u8] {
- /// self.0.as_ref()
- /// }
- /// }
- /// fn main() {
- /// let wbuf = Bytes::from(&b"CDEF"[..]);
- /// let boxed_wbuf = Box::new(BytesContainer(wbuf));
- /// let mut f = tempfile().unwrap();
- /// let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
- /// 2, //offset
- /// boxed_wbuf,
- /// 0, //priority
- /// SigevNotify::SigevNone,
- /// LioOpcode::LIO_NOP);
- /// }
- /// ```
- ///
- /// [`from_slice`]: #method.from_slice
- pub fn from_boxed_slice(fd: RawFd, offs: off_t, buf: Box<dyn Borrow<[u8]>>,
- prio: libc::c_int, sigev_notify: SigevNotify,
- opcode: LioOpcode) -> AioCb<'a> {
- let mut a = AioCb::common_init(fd, prio, sigev_notify);
- {
- let borrowed : &dyn Borrow<[u8]> = buf.borrow();
- let slice : &[u8] = borrowed.borrow();
- a.aio_nbytes = slice.len() as size_t;
- a.aio_buf = slice.as_ptr() as *mut c_void;
- }
- a.aio_offset = offs;
- a.aio_lio_opcode = opcode as libc::c_int;
-
- AioCb {
- aiocb: a,
- mutable: false,
- in_progress: false,
- buffer: Buffer::BoxedSlice(buf),
- }
- }
-
- /// The safest and most flexible way to create an `AioCb` for reading.
- ///
- /// Like [`from_boxed_slice`], but the slice is a mutable one. More
- /// flexible than [`from_mut_slice`], because a wide range of objects can be
- /// used.
- ///
- /// # Examples
- ///
- /// Create an `AioCb` from a Vector and use it for reading
- ///
- /// ```
- /// # use nix::errno::Errno;
- /// # use nix::Error;
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify;
- /// # use std::{thread, time};
- /// # use std::io::Write;
- /// # use std::os::unix::io::AsRawFd;
- /// # use tempfile::tempfile;
- /// # fn main() {
- /// const INITIAL: &[u8] = b"abcdef123456";
- /// const LEN: usize = 4;
- /// let rbuf = Box::new(vec![0; LEN]);
- /// let mut f = tempfile().unwrap();
- /// f.write_all(INITIAL).unwrap();
- /// let mut aiocb = AioCb::from_boxed_mut_slice( f.as_raw_fd(),
- /// 2, //offset
- /// rbuf,
- /// 0, //priority
- /// SigevNotify::SigevNone,
- /// LioOpcode::LIO_NOP);
- /// aiocb.read().unwrap();
- /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
- /// thread::sleep(time::Duration::from_millis(10));
- /// }
- /// assert_eq!(aiocb.aio_return().unwrap() as usize, LEN);
- /// let mut buffer = aiocb.boxed_mut_slice().unwrap();
- /// const EXPECT: &[u8] = b"cdef";
- /// assert_eq!(buffer.borrow_mut(), EXPECT);
- /// # }
- /// ```
- ///
- /// [`from_boxed_slice`]: #method.from_boxed_slice
- /// [`from_mut_slice`]: #method.from_mut_slice
- pub fn from_boxed_mut_slice(fd: RawFd, offs: off_t,
- mut buf: Box<dyn BorrowMut<[u8]>>,
- prio: libc::c_int, sigev_notify: SigevNotify,
- opcode: LioOpcode) -> AioCb<'a> {
- let mut a = AioCb::common_init(fd, prio, sigev_notify);
- {
- let borrowed : &mut dyn BorrowMut<[u8]> = buf.borrow_mut();
- let slice : &mut [u8] = borrowed.borrow_mut();
- a.aio_nbytes = slice.len() as size_t;
- a.aio_buf = slice.as_mut_ptr() as *mut c_void;
- }
- a.aio_offset = offs;
- a.aio_lio_opcode = opcode as libc::c_int;
-
- AioCb {
- aiocb: a,
- mutable: true,
- in_progress: false,
- buffer: Buffer::BoxedMutSlice(buf),
- }
- }
-
- /// Constructs a new `AioCb` from a mutable raw pointer
- ///
- /// Unlike `from_mut_slice`, this method returns a structure suitable for
- /// placement on the heap. It may be used for both reads and writes. Due
- /// to its unsafety, this method is not recommended. It is most useful when
- /// heap allocation is required but for some reason the data cannot be
- /// wrapped in a `struct` that implements `BorrowMut<[u8]>`
- ///
- /// # Parameters
- ///
- /// * `fd`: File descriptor. Required for all aio functions.
- /// * `offs`: File offset
- /// * `buf`: Pointer to the memory buffer
- /// * `len`: Length of the buffer pointed to by `buf`
- /// * `prio`: If POSIX Prioritized IO is supported, then the
- /// operation will be prioritized at the process's
- /// priority level minus `prio`
- /// * `sigev_notify`: Determines how you will be notified of event
- /// completion.
- /// * `opcode`: This field is only used for `lio_listio`. It
- /// determines which operation to use for this individual
- /// aiocb
- ///
- /// # Safety
- ///
- /// The caller must ensure that the storage pointed to by `buf` outlives the
- /// `AioCb`. The lifetime checker can't help here.
- pub unsafe fn from_mut_ptr(fd: RawFd, offs: off_t,
- buf: *mut c_void, len: usize,
- prio: libc::c_int, sigev_notify: SigevNotify,
- opcode: LioOpcode) -> AioCb<'a> {
- let mut a = AioCb::common_init(fd, prio, sigev_notify);
- a.aio_offset = offs;
- a.aio_nbytes = len;
- a.aio_buf = buf;
- a.aio_lio_opcode = opcode as libc::c_int;
-
- AioCb {
- aiocb: a,
- mutable: true,
- in_progress: false,
- buffer: Buffer::None
- }
- }
-
- /// Constructs a new `AioCb` from a raw pointer.
- ///
- /// Unlike `from_slice`, this method returns a structure suitable for
- /// placement on the heap. Due to its unsafety, this method is not
- /// recommended. It is most useful when heap allocation is required but for
- /// some reason the data cannot be wrapped in a `struct` that implements
- /// `Borrow<[u8]>`
- ///
- /// # Parameters
- ///
- /// * `fd`: File descriptor. Required for all aio functions.
- /// * `offs`: File offset
- /// * `buf`: Pointer to the memory buffer
- /// * `len`: Length of the buffer pointed to by `buf`
- /// * `prio`: If POSIX Prioritized IO is supported, then the
- /// operation will be prioritized at the process's
- /// priority level minus `prio`
- /// * `sigev_notify`: Determines how you will be notified of event
- /// completion.
- /// * `opcode`: This field is only used for `lio_listio`. It
- /// determines which operation to use for this individual
- /// aiocb
- ///
- /// # Safety
- ///
- /// The caller must ensure that the storage pointed to by `buf` outlives the
- /// `AioCb`. The lifetime checker can't help here.
- pub unsafe fn from_ptr(fd: RawFd, offs: off_t,
- buf: *const c_void, len: usize,
- prio: libc::c_int, sigev_notify: SigevNotify,
- opcode: LioOpcode) -> AioCb<'a> {
- let mut a = AioCb::common_init(fd, prio, sigev_notify);
- a.aio_offset = offs;
- a.aio_nbytes = len;
- // casting a const ptr to a mutable ptr here is ok, because we set the
- // AioCb's mutable field to false
- a.aio_buf = buf as *mut c_void;
- a.aio_lio_opcode = opcode as libc::c_int;
-
- AioCb {
- aiocb: a,
- mutable: false,
- in_progress: false,
- buffer: Buffer::None
- }
- }
-
- /// Like `from_mut_slice`, but works on constant slices rather than
- /// mutable slices.
- ///
- /// An `AioCb` created this way cannot be used with `read`, and its
- /// `LioOpcode` cannot be set to `LIO_READ`. This method is useful when
- /// writing a const buffer with `AioCb::write`, since `from_mut_slice` can't
- /// work with const buffers.
- ///
- /// # Examples
- ///
- /// Construct an `AioCb` from a slice and use it for writing.
- ///
- /// ```
- /// # use nix::errno::Errno;
- /// # use nix::Error;
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify;
- /// # use std::{thread, time};
- /// # use std::os::unix::io::AsRawFd;
- /// # use tempfile::tempfile;
- /// # fn main() {
- /// const WBUF: &[u8] = b"abcdef123456";
- /// let mut f = tempfile().unwrap();
- /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
- /// 2, //offset
- /// WBUF,
- /// 0, //priority
- /// SigevNotify::SigevNone,
- /// LioOpcode::LIO_NOP);
- /// aiocb.write().unwrap();
- /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
- /// thread::sleep(time::Duration::from_millis(10));
- /// }
- /// assert_eq!(aiocb.aio_return().unwrap() as usize, WBUF.len());
- /// # }
- /// ```
- // Note: another solution to the problem of writing const buffers would be
- // to genericize AioCb for both &mut [u8] and &[u8] buffers. AioCb::read
- // could take the former and AioCb::write could take the latter. However,
- // then lio_listio wouldn't work, because that function needs a slice of
- // AioCb, and they must all be of the same type.
- pub fn from_slice(fd: RawFd, offs: off_t, buf: &'a [u8],
- prio: libc::c_int, sigev_notify: SigevNotify,
- opcode: LioOpcode) -> AioCb {
- let mut a = AioCb::common_init(fd, prio, sigev_notify);
- a.aio_offset = offs;
- a.aio_nbytes = buf.len() as size_t;
- // casting an immutable buffer to a mutable pointer looks unsafe,
- // but technically its only unsafe to dereference it, not to create
- // it.
- a.aio_buf = buf.as_ptr() as *mut c_void;
- assert!(opcode != LioOpcode::LIO_READ, "Can't read into an immutable buffer");
- a.aio_lio_opcode = opcode as libc::c_int;
-
- AioCb {
- aiocb: a,
- mutable: false,
- in_progress: false,
- buffer: Buffer::None,
- }
- }
-
- fn common_init(fd: RawFd, prio: libc::c_int,
- sigev_notify: SigevNotify) -> libc::aiocb {
- // Use mem::zeroed instead of explicitly zeroing each field, because the
- // number and name of reserved fields is OS-dependent. On some OSes,
- // some reserved fields are used the kernel for state, and must be
- // explicitly zeroed when allocated.
- let mut a = unsafe { mem::zeroed::<libc::aiocb>()};
- a.aio_fildes = fd;
- a.aio_reqprio = prio;
- a.aio_sigevent = SigEvent::new(sigev_notify).sigevent();
- a
- }
-
- /// Update the notification settings for an existing `aiocb`
- pub fn set_sigev_notify(&mut self, sigev_notify: SigevNotify) {
- self.aiocb.aio_sigevent = SigEvent::new(sigev_notify).sigevent();
- }
-
- /// Cancels an outstanding AIO request.
- ///
- /// The operating system is not required to implement cancellation for all
- /// file and device types. Even if it does, there is no guarantee that the
- /// operation has not already completed. So the caller must check the
- /// result and handle operations that were not canceled or that have already
- /// completed.
- ///
- /// # Examples
- ///
- /// Cancel an outstanding aio operation. Note that we must still call
- /// `aio_return` to free resources, even though we don't care about the
- /// result.
- ///
- /// ```
- /// # use nix::errno::Errno;
- /// # use nix::Error;
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify;
- /// # use std::{thread, time};
- /// # use std::io::Write;
- /// # use std::os::unix::io::AsRawFd;
- /// # use tempfile::tempfile;
- /// # fn main() {
- /// let wbuf = b"CDEF";
- /// let mut f = tempfile().unwrap();
- /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
- /// 2, //offset
- /// &wbuf[..],
- /// 0, //priority
- /// SigevNotify::SigevNone,
- /// LioOpcode::LIO_NOP);
- /// aiocb.write().unwrap();
- /// let cs = aiocb.cancel().unwrap();
- /// if cs == AioCancelStat::AioNotCanceled {
- /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
- /// thread::sleep(time::Duration::from_millis(10));
- /// }
- /// }
- /// // Must call `aio_return`, but ignore the result
- /// let _ = aiocb.aio_return();
- /// # }
- /// ```
- ///
- /// # References
- ///
- /// [aio_cancel](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
- pub fn cancel(&mut self) -> Result<AioCancelStat> {
- match unsafe { libc::aio_cancel(self.aiocb.aio_fildes, &mut self.aiocb) } {
- libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled),
- libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled),
- libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone),
- -1 => Err(Error::last()),
- _ => panic!("unknown aio_cancel return value")
- }
- }
-
- /// Retrieve error status of an asynchronous operation.
- ///
- /// If the request has not yet completed, returns `EINPROGRESS`. Otherwise,
- /// returns `Ok` or any other error.
- ///
- /// # Examples
- ///
- /// Issue an aio operation and use `error` to poll for completion. Polling
- /// is an alternative to `aio_suspend`, used by most of the other examples.
- ///
- /// ```
- /// # use nix::errno::Errno;
- /// # use nix::Error;
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify;
- /// # use std::{thread, time};
- /// # use std::os::unix::io::AsRawFd;
- /// # use tempfile::tempfile;
- /// # fn main() {
- /// const WBUF: &[u8] = b"abcdef123456";
- /// let mut f = tempfile().unwrap();
- /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
- /// 2, //offset
- /// WBUF,
- /// 0, //priority
- /// SigevNotify::SigevNone,
- /// LioOpcode::LIO_NOP);
- /// aiocb.write().unwrap();
- /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
- /// thread::sleep(time::Duration::from_millis(10));
- /// }
- /// assert_eq!(aiocb.aio_return().unwrap() as usize, WBUF.len());
- /// # }
- /// ```
- ///
- /// # References
- ///
- /// [aio_error](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_error.html)
- pub fn error(&mut self) -> Result<()> {
- match unsafe { libc::aio_error(&mut self.aiocb as *mut libc::aiocb) } {
- 0 => Ok(()),
- num if num > 0 => Err(Error::from_errno(Errno::from_i32(num))),
- -1 => Err(Error::last()),
- num => panic!("unknown aio_error return value {:?}", num)
- }
- }
-
- /// An asynchronous version of `fsync(2)`.
- ///
- /// # References
- ///
- /// [aio_fsync](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_fsync.html)
- pub fn fsync(&mut self, mode: AioFsyncMode) -> Result<()> {
- let p: *mut libc::aiocb = &mut self.aiocb;
- Errno::result(unsafe {
- libc::aio_fsync(mode as libc::c_int, p)
- }).map(|_| {
- self.in_progress = true;
- })
- }
-
- /// Returns the `aiocb`'s `LioOpcode` field
- ///
- /// If the value cannot be represented as an `LioOpcode`, returns `None`
- /// instead.
- pub fn lio_opcode(&self) -> Option<LioOpcode> {
- match self.aiocb.aio_lio_opcode {
- libc::LIO_READ => Some(LioOpcode::LIO_READ),
- libc::LIO_WRITE => Some(LioOpcode::LIO_WRITE),
- libc::LIO_NOP => Some(LioOpcode::LIO_NOP),
- _ => None
- }
- }
-
- /// Returns the requested length of the aio operation in bytes
- ///
- /// This method returns the *requested* length of the operation. To get the
- /// number of bytes actually read or written by a completed operation, use
- /// `aio_return` instead.
- pub fn nbytes(&self) -> usize {
- self.aiocb.aio_nbytes
- }
-
- /// Returns the file offset stored in the `AioCb`
- pub fn offset(&self) -> off_t {
- self.aiocb.aio_offset
- }
-
- /// Returns the priority of the `AioCb`
- pub fn priority(&self) -> libc::c_int {
- self.aiocb.aio_reqprio
- }
-
- /// Asynchronously reads from a file descriptor into a buffer
- ///
- /// # References
- ///
- /// [aio_read](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_read.html)
- pub fn read(&mut self) -> Result<()> {
- assert!(self.mutable, "Can't read into an immutable buffer");
- let p: *mut libc::aiocb = &mut self.aiocb;
- Errno::result(unsafe {
- libc::aio_read(p)
- }).map(|_| {
- self.in_progress = true;
- })
- }
-
- /// Returns the `SigEvent` stored in the `AioCb`
- pub fn sigevent(&self) -> SigEvent {
- SigEvent::from(&self.aiocb.aio_sigevent)
- }
-
- /// Retrieve return status of an asynchronous operation.
- ///
- /// Should only be called once for each `AioCb`, after `AioCb::error`
- /// indicates that it has completed. The result is the same as for the
- /// synchronous `read(2)`, `write(2)`, of `fsync(2)` functions.
- ///
- /// # References
- ///
- /// [aio_return](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_return.html)
- // Note: this should be just `return`, but that's a reserved word
- pub fn aio_return(&mut self) -> Result<isize> {
- let p: *mut libc::aiocb = &mut self.aiocb;
- self.in_progress = false;
- Errno::result(unsafe { libc::aio_return(p) })
- }
-
- /// Asynchronously writes from a buffer to a file descriptor
- ///
- /// # References
- ///
- /// [aio_write](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_write.html)
- pub fn write(&mut self) -> Result<()> {
- let p: *mut libc::aiocb = &mut self.aiocb;
- Errno::result(unsafe {
- libc::aio_write(p)
- }).map(|_| {
- self.in_progress = true;
- })
- }
-
-}
-
-/// Cancels outstanding AIO requests for a given file descriptor.
-///
-/// # Examples
-///
-/// Issue an aio operation, then cancel all outstanding operations on that file
-/// descriptor.
-///
-/// ```
-/// # use nix::errno::Errno;
-/// # use nix::Error;
-/// # use nix::sys::aio::*;
-/// # use nix::sys::signal::SigevNotify;
-/// # use std::{thread, time};
-/// # use std::io::Write;
-/// # use std::os::unix::io::AsRawFd;
-/// # use tempfile::tempfile;
-/// # fn main() {
-/// let wbuf = b"CDEF";
-/// let mut f = tempfile().unwrap();
-/// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
-/// 2, //offset
-/// &wbuf[..],
-/// 0, //priority
-/// SigevNotify::SigevNone,
-/// LioOpcode::LIO_NOP);
-/// aiocb.write().unwrap();
-/// let cs = aio_cancel_all(f.as_raw_fd()).unwrap();
-/// if cs == AioCancelStat::AioNotCanceled {
-/// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
-/// thread::sleep(time::Duration::from_millis(10));
-/// }
-/// }
-/// // Must call `aio_return`, but ignore the result
-/// let _ = aiocb.aio_return();
-/// # }
-/// ```
-///
-/// # References
-///
-/// [`aio_cancel`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
-pub fn aio_cancel_all(fd: RawFd) -> Result<AioCancelStat> {
- match unsafe { libc::aio_cancel(fd, null_mut()) } {
- libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled),
- libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled),
- libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone),
- -1 => Err(Error::last()),
- _ => panic!("unknown aio_cancel return value")
- }
-}
-
-/// Suspends the calling process until at least one of the specified `AioCb`s
-/// has completed, a signal is delivered, or the timeout has passed.
-///
-/// If `timeout` is `None`, `aio_suspend` will block indefinitely.
-///
-/// # Examples
-///
-/// Use `aio_suspend` to block until an aio operation completes.
-///
-/// ```
-/// # use nix::sys::aio::*;
-/// # use nix::sys::signal::SigevNotify;
-/// # use std::os::unix::io::AsRawFd;
-/// # use tempfile::tempfile;
-/// # fn main() {
-/// const WBUF: &[u8] = b"abcdef123456";
-/// let mut f = tempfile().unwrap();
-/// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
-/// 2, //offset
-/// WBUF,
-/// 0, //priority
-/// SigevNotify::SigevNone,
-/// LioOpcode::LIO_NOP);
-/// aiocb.write().unwrap();
-/// aio_suspend(&[&aiocb], None).expect("aio_suspend failed");
-/// assert_eq!(aiocb.aio_return().unwrap() as usize, WBUF.len());
-/// # }
-/// ```
-/// # References
-///
-/// [`aio_suspend`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_suspend.html)
-pub fn aio_suspend(list: &[&AioCb], timeout: Option<TimeSpec>) -> Result<()> {
- let plist = list as *const [&AioCb] as *const [*const libc::aiocb];
- let p = plist as *const *const libc::aiocb;
- let timep = match timeout {
- None => null::<libc::timespec>(),
- Some(x) => x.as_ref() as *const libc::timespec
- };
- Errno::result(unsafe {
- libc::aio_suspend(p, list.len() as i32, timep)
- }).map(drop)
-}
-
-impl<'a> Debug for AioCb<'a> {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_struct("AioCb")
- .field("aiocb", &self.aiocb)
- .field("mutable", &self.mutable)
- .field("in_progress", &self.in_progress)
- .finish()
- }
-}
-
-impl<'a> Drop for AioCb<'a> {
- /// If the `AioCb` has no remaining state in the kernel, just drop it.
- /// Otherwise, dropping constitutes a resource leak, which is an error
- fn drop(&mut self) {
- assert!(thread::panicking() || !self.in_progress,
- "Dropped an in-progress AioCb");
- }
-}
-
-/// LIO Control Block.
-///
-/// The basic structure used to issue multiple AIO operations simultaneously.
-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-pub struct LioCb<'a> {
- /// A collection of [`AioCb`]s. All of these will be issued simultaneously
- /// by the [`listio`] method.
- ///
- /// [`AioCb`]: struct.AioCb.html
- /// [`listio`]: #method.listio
- pub aiocbs: Vec<AioCb<'a>>,
-
- /// The actual list passed to `libc::lio_listio`.
- ///
- /// It must live for as long as any of the operations are still being
- /// processesed, because the aio subsystem uses its address as a unique
- /// identifier.
- list: Vec<*mut libc::aiocb>,
-
- /// A partial set of results. This field will get populated by
- /// `listio_resubmit` when an `LioCb` is resubmitted after an error
- results: Vec<Option<Result<isize>>>
-}
-
-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-impl<'a> LioCb<'a> {
- /// Initialize an empty `LioCb`
- pub fn with_capacity(capacity: usize) -> LioCb<'a> {
- LioCb {
- aiocbs: Vec::with_capacity(capacity),
- list: Vec::with_capacity(capacity),
- results: Vec::with_capacity(capacity)
- }
- }
-
- /// Submits multiple asynchronous I/O requests with a single system call.
- ///
- /// They are not guaranteed to complete atomically, and the order in which
- /// the requests are carried out is not specified. Reads, writes, and
- /// fsyncs may be freely mixed.
- ///
- /// This function is useful for reducing the context-switch overhead of
- /// submitting many AIO operations. It can also be used with
- /// `LioMode::LIO_WAIT` to block on the result of several independent
- /// operations. Used that way, it is often useful in programs that
- /// otherwise make little use of AIO.
- ///
- /// # Examples
- ///
- /// Use `listio` to submit an aio operation and wait for its completion. In
- /// this case, there is no need to use [`aio_suspend`] to wait or
- /// [`AioCb::error`] to poll.
- ///
- /// ```
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify;
- /// # use std::os::unix::io::AsRawFd;
- /// # use tempfile::tempfile;
- /// # fn main() {
- /// const WBUF: &[u8] = b"abcdef123456";
- /// let mut f = tempfile().unwrap();
- /// let mut liocb = LioCb::with_capacity(1);
- /// liocb.aiocbs.push(AioCb::from_slice( f.as_raw_fd(),
- /// 2, //offset
- /// WBUF,
- /// 0, //priority
- /// SigevNotify::SigevNone,
- /// LioOpcode::LIO_WRITE));
- /// liocb.listio(LioMode::LIO_WAIT,
- /// SigevNotify::SigevNone).unwrap();
- /// assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
- /// # }
- /// ```
- ///
- /// # References
- ///
- /// [`lio_listio`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html)
- ///
- /// [`aio_suspend`]: fn.aio_suspend.html
- /// [`AioCb::error`]: struct.AioCb.html#method.error
- pub fn listio(&mut self, mode: LioMode,
- sigev_notify: SigevNotify) -> Result<()> {
- let sigev = SigEvent::new(sigev_notify);
- let sigevp = &mut sigev.sigevent() as *mut libc::sigevent;
- self.list.clear();
- for a in &mut self.aiocbs {
- a.in_progress = true;
- self.list.push(a as *mut AioCb<'a>
- as *mut libc::aiocb);
- }
- let p = self.list.as_ptr();
- Errno::result(unsafe {
- libc::lio_listio(mode as i32, p, self.list.len() as i32, sigevp)
- }).map(drop)
- }
-
- /// Resubmits any incomplete operations with [`lio_listio`].
- ///
- /// Sometimes, due to system resource limitations, an `lio_listio` call will
- /// return `EIO`, or `EAGAIN`. Or, if a signal is received, it may return
- /// `EINTR`. In any of these cases, only a subset of its constituent
- /// operations will actually have been initiated. `listio_resubmit` will
- /// resubmit any operations that are still uninitiated.
- ///
- /// After calling `listio_resubmit`, results should be collected by
- /// [`LioCb::aio_return`].
- ///
- /// # Examples
- /// ```no_run
- /// # use nix::Error;
- /// # use nix::errno::Errno;
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify;
- /// # use std::os::unix::io::AsRawFd;
- /// # use std::{thread, time};
- /// # use tempfile::tempfile;
- /// # fn main() {
- /// const WBUF: &[u8] = b"abcdef123456";
- /// let mut f = tempfile().unwrap();
- /// let mut liocb = LioCb::with_capacity(1);
- /// liocb.aiocbs.push(AioCb::from_slice( f.as_raw_fd(),
- /// 2, //offset
- /// WBUF,
- /// 0, //priority
- /// SigevNotify::SigevNone,
- /// LioOpcode::LIO_WRITE));
- /// let mut err = liocb.listio(LioMode::LIO_WAIT, SigevNotify::SigevNone);
- /// while err == Err(Error::Sys(Errno::EIO)) ||
- /// err == Err(Error::Sys(Errno::EAGAIN)) {
- /// thread::sleep(time::Duration::from_millis(10));
- /// err = liocb.listio_resubmit(LioMode::LIO_WAIT, SigevNotify::SigevNone);
- /// }
- /// assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
- /// # }
- /// ```
- ///
- /// # References
- ///
- /// [`lio_listio`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html)
- ///
- /// [`lio_listio`]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html
- /// [`LioCb::aio_return`]: struct.LioCb.html#method.aio_return
- // Note: the addresses of any EINPROGRESS or EOK aiocbs _must_ not be
- // changed by this method, because the kernel relies on their addresses
- // being stable.
- // Note: aiocbs that are Ok(()) must be finalized by aio_return, or else the
- // sigev_notify will immediately refire.
- pub fn listio_resubmit(&mut self, mode:LioMode,
- sigev_notify: SigevNotify) -> Result<()> {
- let sigev = SigEvent::new(sigev_notify);
- let sigevp = &mut sigev.sigevent() as *mut libc::sigevent;
- self.list.clear();
-
- while self.results.len() < self.aiocbs.len() {
- self.results.push(None);
- }
-
- for (i, a) in self.aiocbs.iter_mut().enumerate() {
- if self.results[i].is_some() {
- // Already collected final status for this operation
- continue;
- }
- match a.error() {
- Ok(()) => {
- // aiocb is complete; collect its status and don't resubmit
- self.results[i] = Some(a.aio_return());
- },
- Err(Error::Sys(Errno::EAGAIN)) => {
- self.list.push(a as *mut AioCb<'a> as *mut libc::aiocb);
- },
- Err(Error::Sys(Errno::EINPROGRESS)) => {
- // aiocb is was successfully queued; no need to do anything
- },
- Err(Error::Sys(Errno::EINVAL)) => panic!(
- "AioCb was never submitted, or already finalized"),
- _ => unreachable!()
- }
- }
- let p = self.list.as_ptr();
- Errno::result(unsafe {
- libc::lio_listio(mode as i32, p, self.list.len() as i32, sigevp)
- }).map(drop)
- }
-
- /// Collect final status for an individual `AioCb` submitted as part of an
- /// `LioCb`.
- ///
- /// This is just like [`AioCb::aio_return`], except it takes into account
- /// operations that were restarted by [`LioCb::listio_resubmit`]
- ///
- /// [`AioCb::aio_return`]: struct.AioCb.html#method.aio_return
- /// [`LioCb::listio_resubmit`]: #method.listio_resubmit
- pub fn aio_return(&mut self, i: usize) -> Result<isize> {
- if i >= self.results.len() || self.results[i].is_none() {
- self.aiocbs[i].aio_return()
- } else {
- self.results[i].unwrap()
- }
- }
-
- /// Retrieve error status of an individual `AioCb` submitted as part of an
- /// `LioCb`.
- ///
- /// This is just like [`AioCb::error`], except it takes into account
- /// operations that were restarted by [`LioCb::listio_resubmit`]
- ///
- /// [`AioCb::error`]: struct.AioCb.html#method.error
- /// [`LioCb::listio_resubmit`]: #method.listio_resubmit
- pub fn error(&mut self, i: usize) -> Result<()> {
- if i >= self.results.len() || self.results[i].is_none() {
- self.aiocbs[i].error()
- } else {
- Ok(())
- }
- }
-}
-
-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-impl<'a> Debug for LioCb<'a> {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_struct("LioCb")
- .field("aiocbs", &self.aiocbs)
- .finish()
- }
-}
-
-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-impl<'a> From<Vec<AioCb<'a>>> for LioCb<'a> {
- fn from(src: Vec<AioCb<'a>>) -> LioCb<'a> {
- LioCb {
- list: Vec::with_capacity(src.capacity()),
- results: Vec::with_capacity(src.capacity()),
- aiocbs: src,
- }
- }
-}
diff --git a/vendor/nix-0.20.0/src/sys/epoll.rs b/vendor/nix-0.20.0/src/sys/epoll.rs
deleted file mode 100644
index 2437bbe..0000000
--- a/vendor/nix-0.20.0/src/sys/epoll.rs
+++ /dev/null
@@ -1,109 +0,0 @@
-use crate::Result;
-use crate::errno::Errno;
-use libc::{self, c_int};
-use std::os::unix::io::RawFd;
-use std::ptr;
-use std::mem;
-use crate::Error;
-
-libc_bitflags!(
- pub struct EpollFlags: c_int {
- EPOLLIN;
- EPOLLPRI;
- EPOLLOUT;
- EPOLLRDNORM;
- EPOLLRDBAND;
- EPOLLWRNORM;
- EPOLLWRBAND;
- EPOLLMSG;
- EPOLLERR;
- EPOLLHUP;
- EPOLLRDHUP;
- #[cfg(target_os = "linux")] // Added in 4.5; not in Android.
- EPOLLEXCLUSIVE;
- #[cfg(not(target_arch = "mips"))]
- EPOLLWAKEUP;
- EPOLLONESHOT;
- EPOLLET;
- }
-);
-
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-#[repr(i32)]
-pub enum EpollOp {
- EpollCtlAdd = libc::EPOLL_CTL_ADD,
- EpollCtlDel = libc::EPOLL_CTL_DEL,
- EpollCtlMod = libc::EPOLL_CTL_MOD,
-}
-
-libc_bitflags!{
- pub struct EpollCreateFlags: c_int {
- EPOLL_CLOEXEC;
- }
-}
-
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-#[repr(transparent)]
-pub struct EpollEvent {
- event: libc::epoll_event,
-}
-
-impl EpollEvent {
- pub fn new(events: EpollFlags, data: u64) -> Self {
- EpollEvent { event: libc::epoll_event { events: events.bits() as u32, u64: data } }
- }
-
- pub fn empty() -> Self {
- unsafe { mem::zeroed::<EpollEvent>() }
- }
-
- pub fn events(&self) -> EpollFlags {
- EpollFlags::from_bits(self.event.events as c_int).unwrap()
- }
-
- pub fn data(&self) -> u64 {
- self.event.u64
- }
-}
-
-#[inline]
-pub fn epoll_create() -> Result<RawFd> {
- let res = unsafe { libc::epoll_create(1024) };
-
- Errno::result(res)
-}
-
-#[inline]
-pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
- let res = unsafe { libc::epoll_create1(flags.bits()) };
-
- Errno::result(res)
-}
-
-#[inline]
-pub fn epoll_ctl<'a, T>(epfd: RawFd, op: EpollOp, fd: RawFd, event: T) -> Result<()>
- where T: Into<Option<&'a mut EpollEvent>>
-{
- let mut event: Option<&mut EpollEvent> = event.into();
- if event.is_none() && op != EpollOp::EpollCtlDel {
- Err(Error::Sys(Errno::EINVAL))
- } else {
- let res = unsafe {
- if let Some(ref mut event) = event {
- libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event)
- } else {
- libc::epoll_ctl(epfd, op as c_int, fd, ptr::null_mut())
- }
- };
- Errno::result(res).map(drop)
- }
-}
-
-#[inline]
-pub fn epoll_wait(epfd: RawFd, events: &mut [EpollEvent], timeout_ms: isize) -> Result<usize> {
- let res = unsafe {
- libc::epoll_wait(epfd, events.as_mut_ptr() as *mut libc::epoll_event, events.len() as c_int, timeout_ms as c_int)
- };
-
- Errno::result(res).map(|r| r as usize)
-}
diff --git a/vendor/nix-0.20.0/src/sys/event.rs b/vendor/nix-0.20.0/src/sys/event.rs
deleted file mode 100644
index 8050af3..0000000
--- a/vendor/nix-0.20.0/src/sys/event.rs
+++ /dev/null
@@ -1,330 +0,0 @@
-/* TOOD: Implement for other kqueue based systems
- */
-
-use crate::{Errno, Result};
-#[cfg(not(target_os = "netbsd"))]
-use libc::{timespec, time_t, c_int, c_long, intptr_t, uintptr_t};
-#[cfg(target_os = "netbsd")]
-use libc::{timespec, time_t, c_long, intptr_t, uintptr_t, size_t};
-use std::os::unix::io::RawFd;
-use std::ptr;
-use std::mem;
-
-// Redefine kevent in terms of programmer-friendly enums and bitfields.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct KEvent {
- kevent: libc::kevent,
-}
-
-#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
- target_os = "ios", target_os = "macos",
- target_os = "openbsd"))]
-type type_of_udata = *mut libc::c_void;
-#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
- target_os = "ios", target_os = "macos"))]
-type type_of_data = intptr_t;
-#[cfg(any(target_os = "netbsd"))]
-type type_of_udata = intptr_t;
-#[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
-type type_of_data = i64;
-
-#[cfg(target_os = "netbsd")]
-type type_of_event_filter = u32;
-#[cfg(not(target_os = "netbsd"))]
-type type_of_event_filter = i16;
-libc_enum! {
- #[cfg_attr(target_os = "netbsd", repr(u32))]
- #[cfg_attr(not(target_os = "netbsd"), repr(i16))]
- pub enum EventFilter {
- EVFILT_AIO,
- /// Returns whenever there is no remaining data in the write buffer
- #[cfg(target_os = "freebsd")]
- EVFILT_EMPTY,
- #[cfg(target_os = "dragonfly")]
- EVFILT_EXCEPT,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos"))]
- EVFILT_FS,
- #[cfg(target_os = "freebsd")]
- EVFILT_LIO,
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- EVFILT_MACHPORT,
- EVFILT_PROC,
- /// Returns events associated with the process referenced by a given
- /// process descriptor, created by `pdfork()`. The events to monitor are:
- ///
- /// - NOTE_EXIT: the process has exited. The exit status will be stored in data.
- #[cfg(target_os = "freebsd")]
- EVFILT_PROCDESC,
- EVFILT_READ,
- /// Returns whenever an asynchronous `sendfile()` call completes.
- #[cfg(target_os = "freebsd")]
- EVFILT_SENDFILE,
- EVFILT_SIGNAL,
- EVFILT_TIMER,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos"))]
- EVFILT_USER,
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- EVFILT_VM,
- EVFILT_VNODE,
- EVFILT_WRITE,
- }
-}
-
-#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
- target_os = "ios", target_os = "macos",
- target_os = "openbsd"))]
-pub type type_of_event_flag = u16;
-#[cfg(any(target_os = "netbsd"))]
-pub type type_of_event_flag = u32;
-libc_bitflags!{
- pub struct EventFlag: type_of_event_flag {
- EV_ADD;
- EV_CLEAR;
- EV_DELETE;
- EV_DISABLE;
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
- target_os = "ios", target_os = "macos",
- target_os = "netbsd", target_os = "openbsd"))]
- EV_DISPATCH;
- #[cfg(target_os = "freebsd")]
- EV_DROP;
- EV_ENABLE;
- EV_EOF;
- EV_ERROR;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- EV_FLAG0;
- EV_FLAG1;
- #[cfg(target_os = "dragonfly")]
- EV_NODATA;
- EV_ONESHOT;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- EV_OOBAND;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- EV_POLL;
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
- target_os = "ios", target_os = "macos",
- target_os = "netbsd", target_os = "openbsd"))]
- EV_RECEIPT;
- EV_SYSFLAGS;
- }
-}
-
-libc_bitflags!(
- pub struct FilterFlag: u32 {
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- NOTE_ABSOLUTE;
- NOTE_ATTRIB;
- NOTE_CHILD;
- NOTE_DELETE;
- #[cfg(target_os = "openbsd")]
- NOTE_EOF;
- NOTE_EXEC;
- NOTE_EXIT;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- NOTE_EXITSTATUS;
- NOTE_EXTEND;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
- NOTE_FFAND;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
- NOTE_FFCOPY;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
- NOTE_FFCTRLMASK;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
- NOTE_FFLAGSMASK;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
- NOTE_FFNOP;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
- NOTE_FFOR;
- NOTE_FORK;
- NOTE_LINK;
- NOTE_LOWAT;
- #[cfg(target_os = "freebsd")]
- NOTE_MSECONDS;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- NOTE_NONE;
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
- NOTE_NSECONDS;
- #[cfg(target_os = "dragonfly")]
- NOTE_OOB;
- NOTE_PCTRLMASK;
- NOTE_PDATAMASK;
- NOTE_RENAME;
- NOTE_REVOKE;
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
- NOTE_SECONDS;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- NOTE_SIGNAL;
- NOTE_TRACK;
- NOTE_TRACKERR;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
- NOTE_TRIGGER;
- #[cfg(target_os = "openbsd")]
- NOTE_TRUNCATE;
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
- NOTE_USECONDS;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- NOTE_VM_ERROR;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- NOTE_VM_PRESSURE;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- NOTE_VM_PRESSURE_SUDDEN_TERMINATE;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- NOTE_VM_PRESSURE_TERMINATE;
- NOTE_WRITE;
- }
-);
-
-pub fn kqueue() -> Result<RawFd> {
- let res = unsafe { libc::kqueue() };
-
- Errno::result(res)
-}
-
-
-// KEvent can't derive Send because on some operating systems, udata is defined
-// as a void*. However, KEvent's public API always treats udata as an intptr_t,
-// which is safe to Send.
-unsafe impl Send for KEvent {
-}
-
-impl KEvent {
- pub fn new(ident: uintptr_t, filter: EventFilter, flags: EventFlag,
- fflags:FilterFlag, data: intptr_t, udata: intptr_t) -> KEvent {
- KEvent { kevent: libc::kevent {
- ident,
- filter: filter as type_of_event_filter,
- flags: flags.bits(),
- fflags: fflags.bits(),
- data: data as type_of_data,
- udata: udata as type_of_udata
- } }
- }
-
- pub fn ident(&self) -> uintptr_t {
- self.kevent.ident
- }
-
- pub fn filter(&self) -> EventFilter {
- unsafe { mem::transmute(self.kevent.filter as type_of_event_filter) }
- }
-
- pub fn flags(&self) -> EventFlag {
- EventFlag::from_bits(self.kevent.flags).unwrap()
- }
-
- pub fn fflags(&self) -> FilterFlag {
- FilterFlag::from_bits(self.kevent.fflags).unwrap()
- }
-
- pub fn data(&self) -> intptr_t {
- self.kevent.data as intptr_t
- }
-
- pub fn udata(&self) -> intptr_t {
- self.kevent.udata as intptr_t
- }
-}
-
-pub fn kevent(kq: RawFd,
- changelist: &[KEvent],
- eventlist: &mut [KEvent],
- timeout_ms: usize) -> Result<usize> {
-
- // Convert ms to timespec
- let timeout = timespec {
- tv_sec: (timeout_ms / 1000) as time_t,
- tv_nsec: ((timeout_ms % 1000) * 1_000_000) as c_long
- };
-
- kevent_ts(kq, changelist, eventlist, Some(timeout))
-}
-
-#[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "openbsd"))]
-type type_of_nchanges = c_int;
-#[cfg(target_os = "netbsd")]
-type type_of_nchanges = size_t;
-
-pub fn kevent_ts(kq: RawFd,
- changelist: &[KEvent],
- eventlist: &mut [KEvent],
- timeout_opt: Option<timespec>) -> Result<usize> {
-
- let res = unsafe {
- libc::kevent(
- kq,
- changelist.as_ptr() as *const libc::kevent,
- changelist.len() as type_of_nchanges,
- eventlist.as_mut_ptr() as *mut libc::kevent,
- eventlist.len() as type_of_nchanges,
- if let Some(ref timeout) = timeout_opt {timeout as *const timespec} else {ptr::null()})
- };
-
- Errno::result(res).map(|r| r as usize)
-}
-
-#[inline]
-pub fn ev_set(ev: &mut KEvent,
- ident: usize,
- filter: EventFilter,
- flags: EventFlag,
- fflags: FilterFlag,
- udata: intptr_t) {
-
- ev.kevent.ident = ident as uintptr_t;
- ev.kevent.filter = filter as type_of_event_filter;
- ev.kevent.flags = flags.bits();
- ev.kevent.fflags = fflags.bits();
- ev.kevent.data = 0;
- ev.kevent.udata = udata as type_of_udata;
-}
-
-#[test]
-fn test_struct_kevent() {
- let udata : intptr_t = 12345;
-
- let actual = KEvent::new(0xdead_beef,
- EventFilter::EVFILT_READ,
- EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
- FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
- 0x1337,
- udata);
- assert_eq!(0xdead_beef, actual.ident());
- assert_eq!(libc::EVFILT_READ, actual.filter() as type_of_event_filter);
- assert_eq!(libc::EV_ONESHOT | libc::EV_ADD, actual.flags().bits());
- assert_eq!(libc::NOTE_CHILD | libc::NOTE_EXIT, actual.fflags().bits());
- assert_eq!(0x1337, actual.data() as type_of_data);
- assert_eq!(udata as type_of_udata, actual.udata() as type_of_udata);
- assert_eq!(mem::size_of::<libc::kevent>(), mem::size_of::<KEvent>());
-}
diff --git a/vendor/nix-0.20.0/src/sys/eventfd.rs b/vendor/nix-0.20.0/src/sys/eventfd.rs
deleted file mode 100644
index baaaa89..0000000
--- a/vendor/nix-0.20.0/src/sys/eventfd.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-use libc;
-use std::os::unix::io::RawFd;
-use crate::Result;
-use crate::errno::Errno;
-
-libc_bitflags! {
- pub struct EfdFlags: libc::c_int {
- EFD_CLOEXEC; // Since Linux 2.6.27
- EFD_NONBLOCK; // Since Linux 2.6.27
- EFD_SEMAPHORE; // Since Linux 2.6.30
- }
-}
-
-pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<RawFd> {
- let res = unsafe { libc::eventfd(initval, flags.bits()) };
-
- Errno::result(res).map(|r| r as RawFd)
-}
diff --git a/vendor/nix-0.20.0/src/sys/inotify.rs b/vendor/nix-0.20.0/src/sys/inotify.rs
deleted file mode 100644
index 4880a4a..0000000
--- a/vendor/nix-0.20.0/src/sys/inotify.rs
+++ /dev/null
@@ -1,233 +0,0 @@
-//! Monitoring API for filesystem events.
-//!
-//! Inotify is a Linux-only API to monitor filesystems events.
-//!
-//! For more documentation, please read [inotify(7)](http://man7.org/linux/man-pages/man7/inotify.7.html).
-//!
-//! # Examples
-//!
-//! Monitor all events happening in directory "test":
-//! ```no_run
-//! # use nix::sys::inotify::{AddWatchFlags,InitFlags,Inotify};
-//! #
-//! // We create a new inotify instance.
-//! let instance = Inotify::init(InitFlags::empty()).unwrap();
-//!
-//! // We add a new watch on directory "test" for all events.
-//! let wd = instance.add_watch("test", AddWatchFlags::IN_ALL_EVENTS).unwrap();
-//!
-//! loop {
-//! // We read from our inotify instance for events.
-//! let events = instance.read_events().unwrap();
-//! println!("Events: {:?}", events);
-//! }
-//! ```
-
-use libc::{
- c_char,
- c_int,
-};
-use std::ffi::{OsString,OsStr,CStr};
-use std::os::unix::ffi::OsStrExt;
-use std::mem::{MaybeUninit, size_of};
-use std::os::unix::io::{RawFd,AsRawFd,FromRawFd};
-use std::ptr;
-use crate::unistd::read;
-use crate::Result;
-use crate::NixPath;
-use crate::errno::Errno;
-
-libc_bitflags! {
- /// Configuration options for [`inotify_add_watch`](fn.inotify_add_watch.html).
- pub struct AddWatchFlags: u32 {
- IN_ACCESS;
- IN_MODIFY;
- IN_ATTRIB;
- IN_CLOSE_WRITE;
- IN_CLOSE_NOWRITE;
- IN_OPEN;
- IN_MOVED_FROM;
- IN_MOVED_TO;
- IN_CREATE;
- IN_DELETE;
- IN_DELETE_SELF;
- IN_MOVE_SELF;
-
- IN_UNMOUNT;
- IN_Q_OVERFLOW;
- IN_IGNORED;
-
- IN_CLOSE;
- IN_MOVE;
-
- IN_ONLYDIR;
- IN_DONT_FOLLOW;
-
- IN_ISDIR;
- IN_ONESHOT;
- IN_ALL_EVENTS;
- }
-}
-
-libc_bitflags! {
- /// Configuration options for [`inotify_init1`](fn.inotify_init1.html).
- pub struct InitFlags: c_int {
- IN_CLOEXEC;
- IN_NONBLOCK;
- }
-}
-
-/// An inotify instance. This is also a file descriptor, you can feed it to
-/// other interfaces consuming file descriptors, epoll for example.
-#[derive(Debug, Clone, Copy)]
-pub struct Inotify {
- fd: RawFd
-}
-
-/// This object is returned when you create a new watch on an inotify instance.
-/// It is then returned as part of an event once triggered. It allows you to
-/// know which watch triggered which event.
-#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)]
-pub struct WatchDescriptor {
- wd: i32
-}
-
-/// A single inotify event.
-///
-/// For more documentation see, [inotify(7)](http://man7.org/linux/man-pages/man7/inotify.7.html).
-#[derive(Debug)]
-pub struct InotifyEvent {
- /// Watch descriptor. This field corresponds to the watch descriptor you
- /// were issued when calling add_watch. It allows you to know which watch
- /// this event comes from.
- pub wd: WatchDescriptor,
- /// Event mask. This field is a bitfield describing the exact event that
- /// occured.
- pub mask: AddWatchFlags,
- /// This cookie is a number that allows you to connect related events. For
- /// now only IN_MOVED_FROM and IN_MOVED_TO can be connected.
- pub cookie: u32,
- /// Filename. This field exists only if the event was triggered for a file
- /// inside the watched directory.
- pub name: Option<OsString>
-}
-
-impl Inotify {
- /// Initialize a new inotify instance.
- ///
- /// Returns a Result containing an inotify instance.
- ///
- /// For more information see, [inotify_init(2)](http://man7.org/linux/man-pages/man2/inotify_init.2.html).
- pub fn init(flags: InitFlags) -> Result<Inotify> {
- let res = Errno::result(unsafe {
- libc::inotify_init1(flags.bits())
- });
-
- res.map(|fd| Inotify { fd })
- }
-
- /// Adds a new watch on the target file or directory.
- ///
- /// Returns a watch descriptor. This is not a File Descriptor!
- ///
- /// For more information see, [inotify_add_watch(2)](http://man7.org/linux/man-pages/man2/inotify_add_watch.2.html).
- pub fn add_watch<P: ?Sized + NixPath>(self,
- path: &P,
- mask: AddWatchFlags)
- -> Result<WatchDescriptor>
- {
- let res = path.with_nix_path(|cstr| {
- unsafe {
- libc::inotify_add_watch(self.fd, cstr.as_ptr(), mask.bits())
- }
- })?;
-
- Errno::result(res).map(|wd| WatchDescriptor { wd })
- }
-
- /// Removes an existing watch using the watch descriptor returned by
- /// inotify_add_watch.
- ///
- /// Returns an EINVAL error if the watch descriptor is invalid.
- ///
- /// For more information see, [inotify_rm_watch(2)](http://man7.org/linux/man-pages/man2/inotify_rm_watch.2.html).
- #[cfg(target_os = "linux")]
- pub fn rm_watch(self, wd: WatchDescriptor) -> Result<()> {
- let res = unsafe { libc::inotify_rm_watch(self.fd, wd.wd) };
-
- Errno::result(res).map(drop)
- }
-
- #[cfg(target_os = "android")]
- pub fn rm_watch(self, wd: WatchDescriptor) -> Result<()> {
- let res = unsafe { libc::inotify_rm_watch(self.fd, wd.wd as u32) };
-
- Errno::result(res).map(drop)
- }
-
- /// Reads a collection of events from the inotify file descriptor. This call
- /// can either be blocking or non blocking depending on whether IN_NONBLOCK
- /// was set at initialization.
- ///
- /// Returns as many events as available. If the call was non blocking and no
- /// events could be read then the EAGAIN error is returned.
- pub fn read_events(self) -> Result<Vec<InotifyEvent>> {
- let header_size = size_of::<libc::inotify_event>();
- const BUFSIZ: usize = 4096;
- let mut buffer = [0u8; BUFSIZ];
- let mut events = Vec::new();
- let mut offset = 0;
-
- let nread = read(self.fd, &mut buffer)?;
-
- while (nread - offset) >= header_size {
- let event = unsafe {
- let mut event = MaybeUninit::<libc::inotify_event>::uninit();
- ptr::copy_nonoverlapping(
- buffer.as_ptr().add(offset),
- event.as_mut_ptr() as *mut u8,
- (BUFSIZ - offset).min(header_size)
- );
- event.assume_init()
- };
-
- let name = match event.len {
- 0 => None,
- _ => {
- let ptr = unsafe {
- buffer
- .as_ptr()
- .add(offset + header_size)
- as *const c_char
- };
- let cstr = unsafe { CStr::from_ptr(ptr) };
-
- Some(OsStr::from_bytes(cstr.to_bytes()).to_owned())
- }
- };
-
- events.push(InotifyEvent {
- wd: WatchDescriptor { wd: event.wd },
- mask: AddWatchFlags::from_bits_truncate(event.mask),
- cookie: event.cookie,
- name
- });
-
- offset += header_size + event.len as usize;
- }
-
- Ok(events)
- }
-}
-
-impl AsRawFd for Inotify {
- fn as_raw_fd(&self) -> RawFd {
- self.fd
- }
-}
-
-impl FromRawFd for Inotify {
- unsafe fn from_raw_fd(fd: RawFd) -> Self {
- Inotify { fd }
- }
-}
diff --git a/vendor/nix-0.20.0/src/sys/ioctl/bsd.rs b/vendor/nix-0.20.0/src/sys/ioctl/bsd.rs
deleted file mode 100644
index f39c0eb..0000000
--- a/vendor/nix-0.20.0/src/sys/ioctl/bsd.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-/// The datatype used for the ioctl number
-#[doc(hidden)]
-pub type ioctl_num_type = ::libc::c_ulong;
-/// The datatype used for the 3rd argument
-#[doc(hidden)]
-pub type ioctl_param_type = ::libc::c_int;
-
-mod consts {
- use crate::sys::ioctl::ioctl_num_type;
- #[doc(hidden)]
- pub const VOID: ioctl_num_type = 0x2000_0000;
- #[doc(hidden)]
- pub const OUT: ioctl_num_type = 0x4000_0000;
- #[doc(hidden)]
- pub const IN: ioctl_num_type = 0x8000_0000;
- #[doc(hidden)]
- pub const INOUT: ioctl_num_type = IN|OUT;
- #[doc(hidden)]
- pub const IOCPARM_MASK: ioctl_num_type = 0x1fff;
-}
-
-pub use self::consts::*;
-
-#[macro_export]
-#[doc(hidden)]
-macro_rules! ioc {
- ($inout:expr, $group:expr, $num:expr, $len:expr) => (
- $inout | (($len as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::IOCPARM_MASK) << 16) | (($group as $crate::sys::ioctl::ioctl_num_type) << 8) | ($num as $crate::sys::ioctl::ioctl_num_type)
- )
-}
-
-/// Generate an ioctl request code for a command that passes no data.
-///
-/// This is equivalent to the `_IO()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_none!()` directly.
-///
-/// # Example
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// const KVMIO: u8 = 0xAE;
-/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03));
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_none {
- ($g:expr, $n:expr) => (ioc!($crate::sys::ioctl::VOID, $g, $n, 0))
-}
-
-/// Generate an ioctl request code for a command that passes an integer
-///
-/// This is equivalent to the `_IOWINT()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_write_int!()` directly.
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_write_int {
- ($g:expr, $n:expr) => (ioc!($crate::sys::ioctl::VOID, $g, $n, ::std::mem::size_of::<$crate::libc::c_int>()))
-}
-
-/// Generate an ioctl request code for a command that reads.
-///
-/// This is equivalent to the `_IOR()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_read!()` directly.
-///
-/// The read/write direction is relative to userland, so this
-/// command would be userland is reading and the kernel is
-/// writing.
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_read {
- ($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::OUT, $g, $n, $len))
-}
-
-/// Generate an ioctl request code for a command that writes.
-///
-/// This is equivalent to the `_IOW()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_write!()` directly.
-///
-/// The read/write direction is relative to userland, so this
-/// command would be userland is writing and the kernel is
-/// reading.
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_write {
- ($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::IN, $g, $n, $len))
-}
-
-/// Generate an ioctl request code for a command that reads and writes.
-///
-/// This is equivalent to the `_IOWR()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_readwrite!()` directly.
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_readwrite {
- ($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::INOUT, $g, $n, $len))
-}
diff --git a/vendor/nix-0.20.0/src/sys/ioctl/linux.rs b/vendor/nix-0.20.0/src/sys/ioctl/linux.rs
deleted file mode 100644
index 68ebaba..0000000
--- a/vendor/nix-0.20.0/src/sys/ioctl/linux.rs
+++ /dev/null
@@ -1,141 +0,0 @@
-/// The datatype used for the ioctl number
-#[cfg(any(target_os = "android", target_env = "musl"))]
-#[doc(hidden)]
-pub type ioctl_num_type = ::libc::c_int;
-#[cfg(not(any(target_os = "android", target_env = "musl")))]
-#[doc(hidden)]
-pub type ioctl_num_type = ::libc::c_ulong;
-/// The datatype used for the 3rd argument
-#[doc(hidden)]
-pub type ioctl_param_type = ::libc::c_ulong;
-
-#[doc(hidden)]
-pub const NRBITS: ioctl_num_type = 8;
-#[doc(hidden)]
-pub const TYPEBITS: ioctl_num_type = 8;
-
-#[cfg(any(target_arch = "mips", target_arch = "mips64", target_arch = "powerpc", target_arch = "powerpc64", target_arch = "sparc64"))]
-mod consts {
- #[doc(hidden)]
- pub const NONE: u8 = 1;
- #[doc(hidden)]
- pub const READ: u8 = 2;
- #[doc(hidden)]
- pub const WRITE: u8 = 4;
- #[doc(hidden)]
- pub const SIZEBITS: u8 = 13;
- #[doc(hidden)]
- pub const DIRBITS: u8 = 3;
-}
-
-// "Generic" ioctl protocol
-#[cfg(any(target_arch = "x86",
- target_arch = "arm",
- target_arch = "s390x",
- target_arch = "x86_64",
- target_arch = "aarch64",
- target_arch = "riscv64"))]
-mod consts {
- #[doc(hidden)]
- pub const NONE: u8 = 0;
- #[doc(hidden)]
- pub const READ: u8 = 2;
- #[doc(hidden)]
- pub const WRITE: u8 = 1;
- #[doc(hidden)]
- pub const SIZEBITS: u8 = 14;
- #[doc(hidden)]
- pub const DIRBITS: u8 = 2;
-}
-
-pub use self::consts::*;
-
-#[doc(hidden)]
-pub const NRSHIFT: ioctl_num_type = 0;
-#[doc(hidden)]
-pub const TYPESHIFT: ioctl_num_type = NRSHIFT + NRBITS as ioctl_num_type;
-#[doc(hidden)]
-pub const SIZESHIFT: ioctl_num_type = TYPESHIFT + TYPEBITS as ioctl_num_type;
-#[doc(hidden)]
-pub const DIRSHIFT: ioctl_num_type = SIZESHIFT + SIZEBITS as ioctl_num_type;
-
-#[doc(hidden)]
-pub const NRMASK: ioctl_num_type = (1 << NRBITS) - 1;
-#[doc(hidden)]
-pub const TYPEMASK: ioctl_num_type = (1 << TYPEBITS) - 1;
-#[doc(hidden)]
-pub const SIZEMASK: ioctl_num_type = (1 << SIZEBITS) - 1;
-#[doc(hidden)]
-pub const DIRMASK: ioctl_num_type = (1 << DIRBITS) - 1;
-
-/// Encode an ioctl command.
-#[macro_export]
-#[doc(hidden)]
-macro_rules! ioc {
- ($dir:expr, $ty:expr, $nr:expr, $sz:expr) => (
- (($dir as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::DIRMASK) << $crate::sys::ioctl::DIRSHIFT) |
- (($ty as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::TYPEMASK) << $crate::sys::ioctl::TYPESHIFT) |
- (($nr as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::NRMASK) << $crate::sys::ioctl::NRSHIFT) |
- (($sz as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::SIZEMASK) << $crate::sys::ioctl::SIZESHIFT))
-}
-
-/// Generate an ioctl request code for a command that passes no data.
-///
-/// This is equivalent to the `_IO()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_none!()` directly.
-///
-/// # Example
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// const KVMIO: u8 = 0xAE;
-/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03));
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_none {
- ($ty:expr, $nr:expr) => (ioc!($crate::sys::ioctl::NONE, $ty, $nr, 0))
-}
-
-/// Generate an ioctl request code for a command that reads.
-///
-/// This is equivalent to the `_IOR()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_read!()` directly.
-///
-/// The read/write direction is relative to userland, so this
-/// command would be userland is reading and the kernel is
-/// writing.
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_read {
- ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::READ, $ty, $nr, $sz))
-}
-
-/// Generate an ioctl request code for a command that writes.
-///
-/// This is equivalent to the `_IOW()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_write!()` directly.
-///
-/// The read/write direction is relative to userland, so this
-/// command would be userland is writing and the kernel is
-/// reading.
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_write {
- ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::WRITE, $ty, $nr, $sz))
-}
-
-/// Generate an ioctl request code for a command that reads and writes.
-///
-/// This is equivalent to the `_IOWR()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_readwrite!()` directly.
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_readwrite {
- ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::READ | $crate::sys::ioctl::WRITE, $ty, $nr, $sz))
-}
diff --git a/vendor/nix-0.20.0/src/sys/ioctl/mod.rs b/vendor/nix-0.20.0/src/sys/ioctl/mod.rs
deleted file mode 100644
index 8858a9d..0000000
--- a/vendor/nix-0.20.0/src/sys/ioctl/mod.rs
+++ /dev/null
@@ -1,776 +0,0 @@
-//! Provide helpers for making ioctl system calls.
-//!
-//! This library is pretty low-level and messy. `ioctl` is not fun.
-//!
-//! What is an `ioctl`?
-//! ===================
-//!
-//! The `ioctl` syscall is the grab-bag syscall on POSIX systems. Don't want to add a new
-//! syscall? Make it an `ioctl`! `ioctl` refers to both the syscall, and the commands that can be
-//! sent with it. `ioctl` stands for "IO control", and the commands are always sent to a file
-//! descriptor.
-//!
-//! It is common to see `ioctl`s used for the following purposes:
-//!
-//! * Provide read/write access to out-of-band data related to a device such as configuration
-//! (for instance, setting serial port options)
-//! * Provide a mechanism for performing full-duplex data transfers (for instance, xfer on SPI
-//! devices).
-//! * Provide access to control functions on a device (for example, on Linux you can send
-//! commands like pause, resume, and eject to the CDROM device.
-//! * Do whatever else the device driver creator thought made most sense.
-//!
-//! `ioctl`s are synchronous system calls and are similar to read and write calls in that regard.
-//! They operate on file descriptors and have an identifier that specifies what the ioctl is.
-//! Additionally they may read or write data and therefore need to pass along a data pointer.
-//! Besides the semantics of the ioctls being confusing, the generation of this identifer can also
-//! be difficult.
-//!
-//! Historically `ioctl` numbers were arbitrary hard-coded values. In Linux (before 2.6) and some
-//! unices this has changed to a more-ordered system where the ioctl numbers are partitioned into
-//! subcomponents (For linux this is documented in
-//! [`Documentation/ioctl/ioctl-number.rst`](https://elixir.bootlin.com/linux/latest/source/Documentation/userspace-api/ioctl/ioctl-number.rst)):
-//!
-//! * Number: The actual ioctl ID
-//! * Type: A grouping of ioctls for a common purpose or driver
-//! * Size: The size in bytes of the data that will be transferred
-//! * Direction: Whether there is any data and if it's read, write, or both
-//!
-//! Newer drivers should not generate complete integer identifiers for their `ioctl`s instead
-//! preferring to use the 4 components above to generate the final ioctl identifier. Because of
-//! how old `ioctl`s are, however, there are many hard-coded `ioctl` identifiers. These are
-//! commonly referred to as "bad" in `ioctl` documentation.
-//!
-//! Defining `ioctl`s
-//! =================
-//!
-//! This library provides several `ioctl_*!` macros for binding `ioctl`s. These generate public
-//! unsafe functions that can then be used for calling the ioctl. This macro has a few different
-//! ways it can be used depending on the specific ioctl you're working with.
-//!
-//! A simple `ioctl` is `SPI_IOC_RD_MODE`. This ioctl works with the SPI interface on Linux. This
-//! specific `ioctl` reads the mode of the SPI device as a `u8`. It's declared in
-//! `/include/uapi/linux/spi/spidev.h` as `_IOR(SPI_IOC_MAGIC, 1, __u8)`. Since it uses the `_IOR`
-//! macro, we know it's a `read` ioctl and can use the `ioctl_read!` macro as follows:
-//!
-//! ```
-//! # #[macro_use] extern crate nix;
-//! const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
-//! const SPI_IOC_TYPE_MODE: u8 = 1;
-//! ioctl_read!(spi_read_mode, SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, u8);
-//! # fn main() {}
-//! ```
-//!
-//! This generates the function:
-//!
-//! ```
-//! # #[macro_use] extern crate nix;
-//! # use std::mem;
-//! # use nix::{libc, Result};
-//! # use nix::errno::Errno;
-//! # use nix::libc::c_int as c_int;
-//! # const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
-//! # const SPI_IOC_TYPE_MODE: u8 = 1;
-//! pub unsafe fn spi_read_mode(fd: c_int, data: *mut u8) -> Result<c_int> {
-//! let res = libc::ioctl(fd, request_code_read!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, mem::size_of::<u8>()), data);
-//! Errno::result(res)
-//! }
-//! # fn main() {}
-//! ```
-//!
-//! The return value for the wrapper functions generated by the `ioctl_*!` macros are `nix::Error`s.
-//! These are generated by assuming the return value of the ioctl is `-1` on error and everything
-//! else is a valid return value. If this is not the case, `Result::map` can be used to map some
-//! of the range of "good" values (-Inf..-2, 0..Inf) into a smaller range in a helper function.
-//!
-//! Writing `ioctl`s generally use pointers as their data source and these should use the
-//! `ioctl_write_ptr!`. But in some cases an `int` is passed directly. For these `ioctl`s use the
-//! `ioctl_write_int!` macro. This variant does not take a type as the last argument:
-//!
-//! ```
-//! # #[macro_use] extern crate nix;
-//! const HCI_IOC_MAGIC: u8 = b'k';
-//! const HCI_IOC_HCIDEVUP: u8 = 1;
-//! ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
-//! # fn main() {}
-//! ```
-//!
-//! Some `ioctl`s don't transfer any data, and those should use `ioctl_none!`. This macro
-//! doesn't take a type and so it is declared similar to the `write_int` variant shown above.
-//!
-//! The mode for a given `ioctl` should be clear from the documentation if it has good
-//! documentation. Otherwise it will be clear based on the macro used to generate the `ioctl`
-//! number where `_IO`, `_IOR`, `_IOW`, and `_IOWR` map to "none", "read", "write_*", and "readwrite"
-//! respectively. To determine the specific `write_` variant to use you'll need to find
-//! what the argument type is supposed to be. If it's an `int`, then `write_int` should be used,
-//! otherwise it should be a pointer and `write_ptr` should be used. On Linux the
-//! [`ioctl_list` man page](http://man7.org/linux/man-pages/man2/ioctl_list.2.html) describes a
-//! large number of `ioctl`s and describes their argument data type.
-//!
-//! Using "bad" `ioctl`s
-//! --------------------
-//!
-//! As mentioned earlier, there are many old `ioctl`s that do not use the newer method of
-//! generating `ioctl` numbers and instead use hardcoded values. These can be used with the
-//! `ioctl_*_bad!` macros. This naming comes from the Linux kernel which refers to these
-//! `ioctl`s as "bad". These are a different variant as they bypass calling the macro that generates
-//! the ioctl number and instead use the defined value directly.
-//!
-//! For example the `TCGETS` `ioctl` reads a `termios` data structure for a given file descriptor.
-//! It's defined as `0x5401` in `ioctls.h` on Linux and can be implemented as:
-//!
-//! ```
-//! # #[macro_use] extern crate nix;
-//! # #[cfg(any(target_os = "android", target_os = "linux"))]
-//! # use nix::libc::TCGETS as TCGETS;
-//! # #[cfg(any(target_os = "android", target_os = "linux"))]
-//! # use nix::libc::termios as termios;
-//! # #[cfg(any(target_os = "android", target_os = "linux"))]
-//! ioctl_read_bad!(tcgets, TCGETS, termios);
-//! # fn main() {}
-//! ```
-//!
-//! The generated function has the same form as that generated by `ioctl_read!`:
-//!
-//! ```text
-//! pub unsafe fn tcgets(fd: c_int, data: *mut termios) -> Result<c_int>;
-//! ```
-//!
-//! Working with Arrays
-//! -------------------
-//!
-//! Some `ioctl`s work with entire arrays of elements. These are supported by the `ioctl_*_buf`
-//! family of macros: `ioctl_read_buf`, `ioctl_write_buf`, and `ioctl_readwrite_buf`. Note that
-//! there are no "bad" versions for working with buffers. The generated functions include a `len`
-//! argument to specify the number of elements (where the type of each element is specified in the
-//! macro).
-//!
-//! Again looking to the SPI `ioctl`s on Linux for an example, there is a `SPI_IOC_MESSAGE` `ioctl`
-//! that queues up multiple SPI messages by writing an entire array of `spi_ioc_transfer` structs.
-//! `linux/spi/spidev.h` defines a macro to calculate the `ioctl` number like:
-//!
-//! ```C
-//! #define SPI_IOC_MAGIC 'k'
-//! #define SPI_MSGSIZE(N) ...
-//! #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])
-//! ```
-//!
-//! The `SPI_MSGSIZE(N)` calculation is already handled by the `ioctl_*!` macros, so all that's
-//! needed to define this `ioctl` is:
-//!
-//! ```
-//! # #[macro_use] extern crate nix;
-//! const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
-//! const SPI_IOC_TYPE_MESSAGE: u8 = 0;
-//! # pub struct spi_ioc_transfer(u64);
-//! ioctl_write_buf!(spi_transfer, SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, spi_ioc_transfer);
-//! # fn main() {}
-//! ```
-//!
-//! This generates a function like:
-//!
-//! ```
-//! # #[macro_use] extern crate nix;
-//! # use std::mem;
-//! # use nix::{libc, Result};
-//! # use nix::errno::Errno;
-//! # use nix::libc::c_int as c_int;
-//! # const SPI_IOC_MAGIC: u8 = b'k';
-//! # const SPI_IOC_TYPE_MESSAGE: u8 = 0;
-//! # pub struct spi_ioc_transfer(u64);
-//! pub unsafe fn spi_message(fd: c_int, data: &mut [spi_ioc_transfer]) -> Result<c_int> {
-//! let res = libc::ioctl(fd,
-//! request_code_write!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, data.len() * mem::size_of::<spi_ioc_transfer>()),
-//! data);
-//! Errno::result(res)
-//! }
-//! # fn main() {}
-//! ```
-//!
-//! Finding `ioctl` Documentation
-//! -----------------------------
-//!
-//! For Linux, look at your system's headers. For example, `/usr/include/linux/input.h` has a lot
-//! of lines defining macros which use `_IO`, `_IOR`, `_IOW`, `_IOC`, and `_IOWR`. Some `ioctl`s are
-//! documented directly in the headers defining their constants, but others have more extensive
-//! documentation in man pages (like termios' `ioctl`s which are in `tty_ioctl(4)`).
-//!
-//! Documenting the Generated Functions
-//! ===================================
-//!
-//! In many cases, users will wish for the functions generated by the `ioctl`
-//! macro to be public and documented. For this reason, the generated functions
-//! are public by default. If you wish to hide the ioctl, you will need to put
-//! them in a private module.
-//!
-//! For documentation, it is possible to use doc comments inside the `ioctl_*!` macros. Here is an
-//! example :
-//!
-//! ```
-//! # #[macro_use] extern crate nix;
-//! # use nix::libc::c_int;
-//! ioctl_read! {
-//! /// Make the given terminal the controlling terminal of the calling process. The calling
-//! /// process must be a session leader and not have a controlling terminal already. If the
-//! /// terminal is already the controlling terminal of a different session group then the
-//! /// ioctl will fail with **EPERM**, unless the caller is root (more precisely: has the
-//! /// **CAP_SYS_ADMIN** capability) and arg equals 1, in which case the terminal is stolen
-//! /// and all processes that had it as controlling terminal lose it.
-//! tiocsctty, b't', 19, c_int
-//! }
-//!
-//! # fn main() {}
-//! ```
-use cfg_if::cfg_if;
-
-#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
-#[macro_use]
-mod linux;
-
-#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
-pub use self::linux::*;
-
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
-#[macro_use]
-mod bsd;
-
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
-pub use self::bsd::*;
-
-/// Convert raw ioctl return value to a Nix result
-#[macro_export]
-#[doc(hidden)]
-macro_rules! convert_ioctl_res {
- ($w:expr) => (
- {
- $crate::errno::Errno::result($w)
- }
- );
-}
-
-/// Generates a wrapper function for an ioctl that passes no data to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl identifier
-/// * The ioctl sequence number
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Example
-///
-/// The `videodev2` driver on Linux defines the `log_status` `ioctl` as:
-///
-/// ```C
-/// #define VIDIOC_LOG_STATUS _IO('V', 70)
-/// ```
-///
-/// This can be implemented in Rust like:
-///
-/// ```no_run
-/// # #[macro_use] extern crate nix;
-/// ioctl_none!(log_status, b'V', 70);
-/// fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_none {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_none!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type))
- }
- )
-}
-
-/// Generates a wrapper function for a "bad" ioctl that passes no data to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl request code
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Example
-///
-/// ```no_run
-/// # #[macro_use] extern crate nix;
-/// # use libc::TIOCNXCL;
-/// # use std::fs::File;
-/// # use std::os::unix::io::AsRawFd;
-/// ioctl_none_bad!(tiocnxcl, TIOCNXCL);
-/// fn main() {
-/// let file = File::open("/dev/ttyUSB0").unwrap();
-/// unsafe { tiocnxcl(file.as_raw_fd()) }.unwrap();
-/// }
-/// ```
-// TODO: add an example using request_code_*!()
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_none_bad {
- ($(#[$attr:meta])* $name:ident, $nr:expr) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type))
- }
- )
-}
-
-/// Generates a wrapper function for an ioctl that reads data from the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl identifier
-/// * The ioctl sequence number
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Example
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
-/// const SPI_IOC_TYPE_MODE: u8 = 1;
-/// ioctl_read!(spi_read_mode, SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, u8);
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_read {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: *mut $ty)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-/// Generates a wrapper function for a "bad" ioctl that reads data from the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl request code
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Example
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// # #[cfg(any(target_os = "android", target_os = "linux"))]
-/// ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios);
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_read_bad {
- ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: *mut $ty)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-/// Generates a wrapper function for an ioctl that writes data through a pointer to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl identifier
-/// * The ioctl sequence number
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *const DATA_TYPE) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Example
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// # pub struct v4l2_audio {}
-/// ioctl_write_ptr!(s_audio, b'V', 34, v4l2_audio);
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_write_ptr {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: *const $ty)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-/// Generates a wrapper function for a "bad" ioctl that writes data through a pointer to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl request code
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *const DATA_TYPE) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Example
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// # #[cfg(any(target_os = "android", target_os = "linux"))]
-/// ioctl_write_ptr_bad!(tcsets, libc::TCSETS, libc::termios);
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_write_ptr_bad {
- ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: *const $ty)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-cfg_if!{
- if #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] {
- /// Generates a wrapper function for a ioctl that writes an integer to the kernel.
- ///
- /// The arguments to this macro are:
- ///
- /// * The function name
- /// * The ioctl identifier
- /// * The ioctl sequence number
- ///
- /// The generated function has the following signature:
- ///
- /// ```rust,ignore
- /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: nix::sys::ioctl::ioctl_param_type) -> Result<libc::c_int>
- /// ```
- ///
- /// `nix::sys::ioctl::ioctl_param_type` depends on the OS:
- /// * BSD - `libc::c_int`
- /// * Linux - `libc::c_ulong`
- ///
- /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
- ///
- /// # Example
- ///
- /// ```
- /// # #[macro_use] extern crate nix;
- /// ioctl_write_int!(vt_activate, b'v', 4);
- /// # fn main() {}
- /// ```
- #[macro_export(local_inner_macros)]
- macro_rules! ioctl_write_int {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: $crate::sys::ioctl::ioctl_param_type)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write_int!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
- }
- } else {
- /// Generates a wrapper function for a ioctl that writes an integer to the kernel.
- ///
- /// The arguments to this macro are:
- ///
- /// * The function name
- /// * The ioctl identifier
- /// * The ioctl sequence number
- ///
- /// The generated function has the following signature:
- ///
- /// ```rust,ignore
- /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: nix::sys::ioctl::ioctl_param_type) -> Result<libc::c_int>
- /// ```
- ///
- /// `nix::sys::ioctl::ioctl_param_type` depends on the OS:
- /// * BSD - `libc::c_int`
- /// * Linux - `libc::c_ulong`
- ///
- /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
- ///
- /// # Example
- ///
- /// ```
- /// # #[macro_use] extern crate nix;
- /// const HCI_IOC_MAGIC: u8 = b'k';
- /// const HCI_IOC_HCIDEVUP: u8 = 1;
- /// ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
- /// # fn main() {}
- /// ```
- #[macro_export(local_inner_macros)]
- macro_rules! ioctl_write_int {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: $crate::sys::ioctl::ioctl_param_type)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$crate::libc::c_int>()) as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
- }
- }
-}
-
-/// Generates a wrapper function for a "bad" ioctl that writes an integer to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl request code
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: libc::c_int) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Examples
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// # #[cfg(any(target_os = "android", target_os = "linux"))]
-/// ioctl_write_int_bad!(tcsbrk, libc::TCSBRK);
-/// # fn main() {}
-/// ```
-///
-/// ```rust
-/// # #[macro_use] extern crate nix;
-/// const KVMIO: u8 = 0xAE;
-/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03));
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_write_int_bad {
- ($(#[$attr:meta])* $name:ident, $nr:expr) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: $crate::libc::c_int)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-/// Generates a wrapper function for an ioctl that reads and writes data to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl identifier
-/// * The ioctl sequence number
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Example
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// # pub struct v4l2_audio {}
-/// ioctl_readwrite!(enum_audio, b'V', 65, v4l2_audio);
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_readwrite {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: *mut $ty)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-/// Generates a wrapper function for a "bad" ioctl that reads and writes data to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl request code
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-// TODO: Find an example for ioctl_readwrite_bad
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_readwrite_bad {
- ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: *mut $ty)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-/// Generates a wrapper function for an ioctl that reads an array of elements from the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl identifier
-/// * The ioctl sequence number
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &mut [DATA_TYPE]) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-// TODO: Find an example for ioctl_read_buf
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_read_buf {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: &mut [$ty])
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-/// Generates a wrapper function for an ioctl that writes an array of elements to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl identifier
-/// * The ioctl sequence number
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &[DATA_TYPE]) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Examples
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
-/// const SPI_IOC_TYPE_MESSAGE: u8 = 0;
-/// # pub struct spi_ioc_transfer(u64);
-/// ioctl_write_buf!(spi_transfer, SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, spi_ioc_transfer);
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_write_buf {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: &[$ty])
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-/// Generates a wrapper function for an ioctl that reads and writes an array of elements to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl identifier
-/// * The ioctl sequence number
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &mut [DATA_TYPE]) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-// TODO: Find an example for readwrite_buf
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_readwrite_buf {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: &mut [$ty])
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
diff --git a/vendor/nix-0.20.0/src/sys/memfd.rs b/vendor/nix-0.20.0/src/sys/memfd.rs
deleted file mode 100644
index 51b7e6b..0000000
--- a/vendor/nix-0.20.0/src/sys/memfd.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use libc;
-use std::os::unix::io::RawFd;
-use crate::Result;
-use crate::errno::Errno;
-use std::ffi::CStr;
-
-libc_bitflags!(
- pub struct MemFdCreateFlag: libc::c_uint {
- MFD_CLOEXEC;
- MFD_ALLOW_SEALING;
- }
-);
-
-pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<RawFd> {
- let res = unsafe {
- libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags.bits())
- };
-
- Errno::result(res).map(|r| r as RawFd)
-}
diff --git a/vendor/nix-0.20.0/src/sys/mman.rs b/vendor/nix-0.20.0/src/sys/mman.rs
deleted file mode 100644
index 63a0779..0000000
--- a/vendor/nix-0.20.0/src/sys/mman.rs
+++ /dev/null
@@ -1,435 +0,0 @@
-use crate::{Error, Result};
-#[cfg(not(target_os = "android"))]
-use crate::NixPath;
-use crate::errno::Errno;
-#[cfg(not(target_os = "android"))]
-use crate::fcntl::OFlag;
-use libc::{self, c_int, c_void, size_t, off_t};
-#[cfg(not(target_os = "android"))]
-use crate::sys::stat::Mode;
-use std::os::unix::io::RawFd;
-
-libc_bitflags!{
- /// Desired memory protection of a memory mapping.
- pub struct ProtFlags: c_int {
- /// Pages cannot be accessed.
- PROT_NONE;
- /// Pages can be read.
- PROT_READ;
- /// Pages can be written.
- PROT_WRITE;
- /// Pages can be executed
- PROT_EXEC;
- /// Apply protection up to the end of a mapping that grows upwards.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- PROT_GROWSDOWN;
- /// Apply protection down to the beginning of a mapping that grows downwards.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- PROT_GROWSUP;
- }
-}
-
-libc_bitflags!{
- /// Additional parameters for `mmap()`.
- pub struct MapFlags: c_int {
- /// Compatibility flag. Ignored.
- MAP_FILE;
- /// Share this mapping. Mutually exclusive with `MAP_PRIVATE`.
- MAP_SHARED;
- /// Create a private copy-on-write mapping. Mutually exclusive with `MAP_SHARED`.
- MAP_PRIVATE;
- /// Place the mapping at exactly the address specified in `addr`.
- MAP_FIXED;
- /// Synonym for `MAP_ANONYMOUS`.
- MAP_ANON;
- /// The mapping is not backed by any file.
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))]
- MAP_ANONYMOUS;
- /// Put the mapping into the first 2GB of the process address space.
- #[cfg(any(all(any(target_os = "android", target_os = "linux"),
- any(target_arch = "x86", target_arch = "x86_64")),
- all(target_os = "linux", target_env = "musl", any(target_arch = "x86", target_arch = "x86_64")),
- all(target_os = "freebsd", target_pointer_width = "64")))]
- MAP_32BIT;
- /// Used for stacks; indicates to the kernel that the mapping should extend downward in memory.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MAP_GROWSDOWN;
- /// Compatibility flag. Ignored.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MAP_DENYWRITE;
- /// Compatibility flag. Ignored.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MAP_EXECUTABLE;
- /// Mark the mmaped region to be locked in the same way as `mlock(2)`.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MAP_LOCKED;
- /// Do not reserve swap space for this mapping.
- ///
- /// This was removed in FreeBSD 11.
- #[cfg(not(target_os = "freebsd"))]
- MAP_NORESERVE;
- /// Populate page tables for a mapping.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MAP_POPULATE;
- /// Only meaningful when used with `MAP_POPULATE`. Don't perform read-ahead.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MAP_NONBLOCK;
- /// Allocate the mapping using "huge pages."
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MAP_HUGETLB;
- /// Make use of 64KB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- MAP_HUGE_64KB;
- /// Make use of 512KB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- MAP_HUGE_512KB;
- /// Make use of 1MB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- MAP_HUGE_1MB;
- /// Make use of 2MB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- MAP_HUGE_2MB;
- /// Make use of 8MB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- MAP_HUGE_8MB;
- /// Make use of 16MB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- MAP_HUGE_16MB;
- /// Make use of 32MB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- MAP_HUGE_32MB;
- /// Make use of 256MB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- MAP_HUGE_256MB;
- /// Make use of 512MB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- MAP_HUGE_512MB;
- /// Make use of 1GB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- MAP_HUGE_1GB;
- /// Make use of 2GB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- MAP_HUGE_2GB;
- /// Make use of 16GB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- MAP_HUGE_16GB;
-
- /// Lock the mapped region into memory as with `mlock(2)`.
- #[cfg(target_os = "netbsd")]
- MAP_WIRED;
- /// Causes dirtied data in the specified range to be flushed to disk only when necessary.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- MAP_NOSYNC;
- /// Rename private pages to a file.
- ///
- /// This was removed in FreeBSD 11.
- #[cfg(any(target_os = "dragonfly", target_os = "netbsd", target_os = "openbsd"))]
- MAP_RENAME;
- /// Region may contain semaphores.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
- MAP_HASSEMAPHORE;
- /// Region grows down, like a stack.
- #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
- MAP_STACK;
- /// Pages in this mapping are not retained in the kernel's memory cache.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- MAP_NOCACHE;
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- MAP_JIT;
- }
-}
-
-#[cfg(target_os = "linux")]
-libc_bitflags!{
- /// Options for `mremap()`.
- pub struct MRemapFlags: c_int {
- /// Permit the kernel to relocate the mapping to a new virtual address, if necessary.
- MREMAP_MAYMOVE;
- /// Place the mapping at exactly the address specified in `new_address`.
- MREMAP_FIXED;
- }
-}
-
-libc_enum!{
- /// Usage information for a range of memory to allow for performance optimizations by the kernel.
- ///
- /// Used by [`madvise`](./fn.madvise.html).
- #[repr(i32)]
- pub enum MmapAdvise {
- /// No further special treatment. This is the default.
- MADV_NORMAL,
- /// Expect random page references.
- MADV_RANDOM,
- /// Expect sequential page references.
- MADV_SEQUENTIAL,
- /// Expect access in the near future.
- MADV_WILLNEED,
- /// Do not expect access in the near future.
- MADV_DONTNEED,
- /// Free up a given range of pages and its associated backing store.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MADV_REMOVE,
- /// Do not make pages in this range available to the child after a `fork(2)`.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MADV_DONTFORK,
- /// Undo the effect of `MADV_DONTFORK`.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MADV_DOFORK,
- /// Poison the given pages.
- ///
- /// Subsequent references to those pages are treated like hardware memory corruption.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MADV_HWPOISON,
- /// Enable Kernel Samepage Merging (KSM) for the given pages.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MADV_MERGEABLE,
- /// Undo the effect of `MADV_MERGEABLE`
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MADV_UNMERGEABLE,
- /// Preserve the memory of each page but offline the original page.
- #[cfg(any(target_os = "android",
- all(target_os = "linux", any(
- target_arch = "aarch64",
- target_arch = "arm",
- target_arch = "ppc",
- target_arch = "s390x",
- target_arch = "x86",
- target_arch = "x86_64",
- target_arch = "sparc64"))))]
- MADV_SOFT_OFFLINE,
- /// Enable Transparent Huge Pages (THP) for pages in the given range.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MADV_HUGEPAGE,
- /// Undo the effect of `MADV_HUGEPAGE`.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MADV_NOHUGEPAGE,
- /// Exclude the given range from a core dump.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MADV_DONTDUMP,
- /// Undo the effect of an earlier `MADV_DONTDUMP`.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MADV_DODUMP,
- /// Specify that the application no longer needs the pages in the given range.
- MADV_FREE,
- /// Request that the system not flush the current range to disk unless it needs to.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- MADV_NOSYNC,
- /// Undoes the effects of `MADV_NOSYNC` for any future pages dirtied within the given range.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- MADV_AUTOSYNC,
- /// Region is not included in a core file.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- MADV_NOCORE,
- /// Include region in a core file
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- MADV_CORE,
- #[cfg(any(target_os = "freebsd"))]
- MADV_PROTECT,
- /// Invalidate the hardware page table for the given region.
- #[cfg(target_os = "dragonfly")]
- MADV_INVAL,
- /// Set the offset of the page directory page to `value` for the virtual page table.
- #[cfg(target_os = "dragonfly")]
- MADV_SETMAP,
- /// Indicates that the application will not need the data in the given range.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- MADV_ZERO_WIRED_PAGES,
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- MADV_FREE_REUSABLE,
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- MADV_FREE_REUSE,
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- MADV_CAN_REUSE,
- }
-}
-
-libc_bitflags!{
- /// Configuration flags for `msync`.
- pub struct MsFlags: c_int {
- /// Schedule an update but return immediately.
- MS_ASYNC;
- /// Invalidate all cached data.
- MS_INVALIDATE;
- /// Invalidate pages, but leave them mapped.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- MS_KILLPAGES;
- /// Deactivate pages, but leave them mapped.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- MS_DEACTIVATE;
- /// Perform an update and wait for it to complete.
- MS_SYNC;
- }
-}
-
-libc_bitflags!{
- /// Flags for `mlockall`.
- pub struct MlockAllFlags: c_int {
- /// Lock pages that are currently mapped into the address space of the process.
- MCL_CURRENT;
- /// Lock pages which will become mapped into the address space of the process in the future.
- MCL_FUTURE;
- }
-}
-
-/// Locks all memory pages that contain part of the address range with `length`
-/// bytes starting at `addr`.
-///
-/// Locked pages never move to the swap area.
-///
-/// # Safety
-///
-/// `addr` must meet all the requirements described in the `mlock(2)` man page.
-pub unsafe fn mlock(addr: *const c_void, length: size_t) -> Result<()> {
- Errno::result(libc::mlock(addr, length)).map(drop)
-}
-
-/// Unlocks all memory pages that contain part of the address range with
-/// `length` bytes starting at `addr`.
-///
-/// # Safety
-///
-/// `addr` must meet all the requirements described in the `munlock(2)` man
-/// page.
-pub unsafe fn munlock(addr: *const c_void, length: size_t) -> Result<()> {
- Errno::result(libc::munlock(addr, length)).map(drop)
-}
-
-/// Locks all memory pages mapped into this process' address space.
-///
-/// Locked pages never move to the swap area.
-///
-/// # Safety
-///
-/// `addr` must meet all the requirements described in the `mlockall(2)` man
-/// page.
-pub fn mlockall(flags: MlockAllFlags) -> Result<()> {
- unsafe { Errno::result(libc::mlockall(flags.bits())) }.map(drop)
-}
-
-/// Unlocks all memory pages mapped into this process' address space.
-pub fn munlockall() -> Result<()> {
- unsafe { Errno::result(libc::munlockall()) }.map(drop)
-}
-
-/// allocate memory, or map files or devices into memory
-///
-/// # Safety
-///
-/// See the `mmap(2)` man page for detailed requirements.
-pub unsafe fn mmap(addr: *mut c_void, length: size_t, prot: ProtFlags, flags: MapFlags, fd: RawFd, offset: off_t) -> Result<*mut c_void> {
- let ret = libc::mmap(addr, length, prot.bits(), flags.bits(), fd, offset);
-
- if ret == libc::MAP_FAILED {
- Err(Error::Sys(Errno::last()))
- } else {
- Ok(ret)
- }
-}
-
-/// Expands (or shrinks) an existing memory mapping, potentially moving it at
-/// the same time.
-///
-/// # Safety
-///
-/// See the `mremap(2)` [man page](https://man7.org/linux/man-pages/man2/mremap.2.html) for
-/// detailed requirements.
-#[cfg(target_os = "linux")]
-pub unsafe fn mremap(
- addr: *mut c_void,
- old_size: size_t,
- new_size: size_t,
- flags: MRemapFlags,
- new_address: Option<* mut c_void>,
-) -> Result<*mut c_void> {
- let ret = libc::mremap(addr, old_size, new_size, flags.bits(), new_address.unwrap_or(std::ptr::null_mut()));
-
- if ret == libc::MAP_FAILED {
- Err(Error::Sys(Errno::last()))
- } else {
- Ok(ret)
- }
-}
-
-/// remove a mapping
-///
-/// # Safety
-///
-/// `addr` must meet all the requirements described in the `munmap(2)` man
-/// page.
-pub unsafe fn munmap(addr: *mut c_void, len: size_t) -> Result<()> {
- Errno::result(libc::munmap(addr, len)).map(drop)
-}
-
-/// give advice about use of memory
-///
-/// # Safety
-///
-/// See the `madvise(2)` man page. Take special care when using
-/// `MmapAdvise::MADV_FREE`.
-pub unsafe fn madvise(addr: *mut c_void, length: size_t, advise: MmapAdvise) -> Result<()> {
- Errno::result(libc::madvise(addr, length, advise as i32)).map(drop)
-}
-
-/// Set protection of memory mapping.
-///
-/// See [`mprotect(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mprotect.html) for
-/// details.
-///
-/// # Safety
-///
-/// Calls to `mprotect` are inherently unsafe, as changes to memory protections can lead to
-/// SIGSEGVs.
-///
-/// ```
-/// # use nix::libc::size_t;
-/// # use nix::sys::mman::{mmap, mprotect, MapFlags, ProtFlags};
-/// # use std::ptr;
-/// const ONE_K: size_t = 1024;
-/// let mut slice: &mut [u8] = unsafe {
-/// let mem = mmap(ptr::null_mut(), ONE_K, ProtFlags::PROT_NONE,
-/// MapFlags::MAP_ANON | MapFlags::MAP_PRIVATE, -1, 0).unwrap();
-/// mprotect(mem, ONE_K, ProtFlags::PROT_READ | ProtFlags::PROT_WRITE).unwrap();
-/// std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
-/// };
-/// assert_eq!(slice[0], 0x00);
-/// slice[0] = 0xFF;
-/// assert_eq!(slice[0], 0xFF);
-/// ```
-pub unsafe fn mprotect(addr: *mut c_void, length: size_t, prot: ProtFlags) -> Result<()> {
- Errno::result(libc::mprotect(addr, length, prot.bits())).map(drop)
-}
-
-/// synchronize a mapped region
-///
-/// # Safety
-///
-/// `addr` must meet all the requirements described in the `msync(2)` man
-/// page.
-pub unsafe fn msync(addr: *mut c_void, length: size_t, flags: MsFlags) -> Result<()> {
- Errno::result(libc::msync(addr, length, flags.bits())).map(drop)
-}
-
-#[cfg(not(target_os = "android"))]
-pub fn shm_open<P: ?Sized + NixPath>(name: &P, flag: OFlag, mode: Mode) -> Result<RawFd> {
- let ret = name.with_nix_path(|cstr| {
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- unsafe {
- libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::c_uint)
- }
- #[cfg(not(any(target_os = "macos", target_os = "ios")))]
- unsafe {
- libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::mode_t)
- }
- })?;
-
- Errno::result(ret)
-}
-
-#[cfg(not(target_os = "android"))]
-pub fn shm_unlink<P: ?Sized + NixPath>(name: &P) -> Result<()> {
- let ret = name.with_nix_path(|cstr| {
- unsafe { libc::shm_unlink(cstr.as_ptr()) }
- })?;
-
- Errno::result(ret).map(drop)
-}
diff --git a/vendor/nix-0.20.0/src/sys/mod.rs b/vendor/nix-0.20.0/src/sys/mod.rs
deleted file mode 100644
index 438fb4f..0000000
--- a/vendor/nix-0.20.0/src/sys/mod.rs
+++ /dev/null
@@ -1,110 +0,0 @@
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd"))]
-pub mod aio;
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub mod epoll;
-
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
-pub mod event;
-
-#[cfg(target_os = "linux")]
-pub mod eventfd;
-
-#[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "redox",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
-#[macro_use]
-pub mod ioctl;
-
-#[cfg(target_os = "linux")]
-pub mod memfd;
-
-#[cfg(not(target_os = "redox"))]
-pub mod mman;
-
-#[cfg(target_os = "linux")]
-pub mod personality;
-
-pub mod pthread;
-
-#[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
-pub mod ptrace;
-
-#[cfg(target_os = "linux")]
-pub mod quota;
-
-#[cfg(any(target_os = "linux"))]
-pub mod reboot;
-
-#[cfg(not(target_os = "redox"))]
-pub mod select;
-
-#[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
-pub mod sendfile;
-
-pub mod signal;
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub mod signalfd;
-
-#[cfg(not(target_os = "redox"))]
-pub mod socket;
-
-pub mod stat;
-
-#[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "openbsd"
-))]
-pub mod statfs;
-
-pub mod statvfs;
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub mod sysinfo;
-
-pub mod termios;
-
-pub mod time;
-
-pub mod uio;
-
-pub mod utsname;
-
-pub mod wait;
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub mod inotify;
-
-#[cfg(target_os = "linux")]
-pub mod timerfd;
diff --git a/vendor/nix-0.20.0/src/sys/personality.rs b/vendor/nix-0.20.0/src/sys/personality.rs
deleted file mode 100644
index 6548b65..0000000
--- a/vendor/nix-0.20.0/src/sys/personality.rs
+++ /dev/null
@@ -1,70 +0,0 @@
-use crate::Result;
-use crate::errno::Errno;
-
-use libc::{self, c_int, c_ulong};
-
-libc_bitflags! {
- /// Flags used and returned by [`get()`](fn.get.html) and
- /// [`set()`](fn.set.html).
- pub struct Persona: c_int {
- ADDR_COMPAT_LAYOUT;
- ADDR_NO_RANDOMIZE;
- ADDR_LIMIT_32BIT;
- ADDR_LIMIT_3GB;
- #[cfg(not(target_env = "musl"))]
- FDPIC_FUNCPTRS;
- MMAP_PAGE_ZERO;
- READ_IMPLIES_EXEC;
- SHORT_INODE;
- STICKY_TIMEOUTS;
- #[cfg(not(target_env = "musl"))]
- UNAME26;
- WHOLE_SECONDS;
- }
-}
-
-/// Retrieve the current process personality.
-///
-/// Returns a Result containing a Persona instance.
-///
-/// Example:
-///
-/// ```
-/// # use nix::sys::personality::{self, Persona};
-/// let pers = personality::get().unwrap();
-/// assert!(!pers.contains(Persona::WHOLE_SECONDS));
-/// ```
-pub fn get() -> Result<Persona> {
- let res = unsafe {
- libc::personality(0xFFFFFFFF)
- };
-
- Errno::result(res).map(|r| Persona::from_bits_truncate(r))
-}
-
-/// Set the current process personality.
-///
-/// Returns a Result containing the *previous* personality for the
-/// process, as a Persona.
-///
-/// For more information, see [personality(2)](https://man7.org/linux/man-pages/man2/personality.2.html)
-///
-/// **NOTE**: This call **replaces** the current personality entirely.
-/// To **update** the personality, first call `get()` and then `set()`
-/// with the modified persona.
-///
-/// Example:
-///
-/// ```
-/// # use nix::sys::personality::{self, Persona};
-/// let mut pers = personality::get().unwrap();
-/// assert!(!pers.contains(Persona::ADDR_NO_RANDOMIZE));
-/// personality::set(pers | Persona::ADDR_NO_RANDOMIZE);
-/// ```
-pub fn set(persona: Persona) -> Result<Persona> {
- let res = unsafe {
- libc::personality(persona.bits() as c_ulong)
- };
-
- Errno::result(res).map(|r| Persona::from_bits_truncate(r))
-}
diff --git a/vendor/nix-0.20.0/src/sys/pthread.rs b/vendor/nix-0.20.0/src/sys/pthread.rs
deleted file mode 100644
index a4d9825..0000000
--- a/vendor/nix-0.20.0/src/sys/pthread.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-use libc::{self, pthread_t};
-
-pub type Pthread = pthread_t;
-
-/// Obtain ID of the calling thread (see
-/// [`pthread_self(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_self.html)
-///
-/// The thread ID returned by `pthread_self()` is not the same thing as
-/// the kernel thread ID returned by a call to `gettid(2)`.
-#[inline]
-pub fn pthread_self() -> Pthread {
- unsafe { libc::pthread_self() }
-}
diff --git a/vendor/nix-0.20.0/src/sys/ptrace/bsd.rs b/vendor/nix-0.20.0/src/sys/ptrace/bsd.rs
deleted file mode 100644
index e85afc7..0000000
--- a/vendor/nix-0.20.0/src/sys/ptrace/bsd.rs
+++ /dev/null
@@ -1,177 +0,0 @@
-use cfg_if::cfg_if;
-use crate::errno::Errno;
-use libc::{self, c_int};
-use std::ptr;
-use crate::sys::signal::Signal;
-use crate::unistd::Pid;
-use crate::Result;
-
-pub type RequestType = c_int;
-
-cfg_if! {
- if #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "openbsd"))] {
- #[doc(hidden)]
- pub type AddressType = *mut ::libc::c_char;
- } else {
- #[doc(hidden)]
- pub type AddressType = *mut ::libc::c_void;
- }
-}
-
-libc_enum! {
- #[repr(i32)]
- /// Ptrace Request enum defining the action to be taken.
- pub enum Request {
- PT_TRACE_ME,
- PT_READ_I,
- PT_READ_D,
- #[cfg(target_os = "macos")]
- PT_READ_U,
- PT_WRITE_I,
- PT_WRITE_D,
- #[cfg(target_os = "macos")]
- PT_WRITE_U,
- PT_CONTINUE,
- PT_KILL,
- #[cfg(any(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos"),
- all(target_os = "openbsd", target_arch = "x86_64"),
- all(target_os = "netbsd", any(target_arch = "x86_64",
- target_arch = "powerpc"))))]
- PT_STEP,
- PT_ATTACH,
- PT_DETACH,
- #[cfg(target_os = "macos")]
- PT_SIGEXC,
- #[cfg(target_os = "macos")]
- PT_THUPDATE,
- #[cfg(target_os = "macos")]
- PT_ATTACHEXC
- }
-}
-
-unsafe fn ptrace_other(
- request: Request,
- pid: Pid,
- addr: AddressType,
- data: c_int,
-) -> Result<c_int> {
- Errno::result(libc::ptrace(
- request as RequestType,
- libc::pid_t::from(pid),
- addr,
- data,
- )).map(|_| 0)
-}
-
-/// Sets the process as traceable, as with `ptrace(PT_TRACEME, ...)`
-///
-/// Indicates that this process is to be traced by its parent.
-/// This is the only ptrace request to be issued by the tracee.
-pub fn traceme() -> Result<()> {
- unsafe { ptrace_other(Request::PT_TRACE_ME, Pid::from_raw(0), ptr::null_mut(), 0).map(drop) }
-}
-
-/// Attach to a running process, as with `ptrace(PT_ATTACH, ...)`
-///
-/// Attaches to the process specified by `pid`, making it a tracee of the calling process.
-pub fn attach(pid: Pid) -> Result<()> {
- unsafe { ptrace_other(Request::PT_ATTACH, pid, ptr::null_mut(), 0).map(drop) }
-}
-
-/// Detaches the current running process, as with `ptrace(PT_DETACH, ...)`
-///
-/// Detaches from the process specified by `pid` allowing it to run freely, optionally delivering a
-/// signal specified by `sig`.
-pub fn detach<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as c_int,
- None => 0,
- };
- unsafe {
- ptrace_other(Request::PT_DETACH, pid, ptr::null_mut(), data).map(drop)
- }
-}
-
-/// Restart the stopped tracee process, as with `ptrace(PTRACE_CONT, ...)`
-///
-/// Continues the execution of the process with PID `pid`, optionally
-/// delivering a signal specified by `sig`.
-pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as c_int,
- None => 0,
- };
- unsafe {
- // Ignore the useless return value
- ptrace_other(Request::PT_CONTINUE, pid, 1 as AddressType, data).map(drop)
- }
-}
-
-/// Issues a kill request as with `ptrace(PT_KILL, ...)`
-///
-/// This request is equivalent to `ptrace(PT_CONTINUE, ..., SIGKILL);`
-pub fn kill(pid: Pid) -> Result<()> {
- unsafe {
- ptrace_other(Request::PT_KILL, pid, 0 as AddressType, 0).map(drop)
- }
-}
-
-/// Move the stopped tracee process forward by a single step as with
-/// `ptrace(PT_STEP, ...)`
-///
-/// Advances the execution of the process with PID `pid` by a single step optionally delivering a
-/// signal specified by `sig`.
-///
-/// # Example
-/// ```rust
-/// use nix::sys::ptrace::step;
-/// use nix::unistd::Pid;
-/// use nix::sys::signal::Signal;
-/// use nix::sys::wait::*;
-/// fn main() {
-/// // If a process changes state to the stopped state because of a SIGUSR1
-/// // signal, this will step the process forward and forward the user
-/// // signal to the stopped process
-/// match waitpid(Pid::from_raw(-1), None) {
-/// Ok(WaitStatus::Stopped(pid, Signal::SIGUSR1)) => {
-/// let _ = step(pid, Signal::SIGUSR1);
-/// }
-/// _ => {},
-/// }
-/// }
-/// ```
-#[cfg(
- any(
- any(target_os = "dragonfly", target_os = "freebsd", target_os = "macos"),
- all(target_os = "openbsd", target_arch = "x86_64"),
- all(target_os = "netbsd",
- any(target_arch = "x86_64", target_arch = "powerpc")
- )
- )
-)]
-pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as c_int,
- None => 0,
- };
- unsafe { ptrace_other(Request::PT_STEP, pid, ptr::null_mut(), data).map(drop) }
-}
-
-/// Reads a word from a processes memory at the given address
-pub fn read(pid: Pid, addr: AddressType) -> Result<c_int> {
- unsafe {
- // Traditionally there was a difference between reading data or
- // instruction memory but not in modern systems.
- ptrace_other(Request::PT_READ_D, pid, addr, 0)
- }
-}
-
-/// Writes a word into the processes memory at the given address
-pub fn write(pid: Pid, addr: AddressType, data: c_int) -> Result<()> {
- unsafe { ptrace_other(Request::PT_WRITE_D, pid, addr, data).map(drop) }
-}
diff --git a/vendor/nix-0.20.0/src/sys/ptrace/linux.rs b/vendor/nix-0.20.0/src/sys/ptrace/linux.rs
deleted file mode 100644
index 8d1dd16..0000000
--- a/vendor/nix-0.20.0/src/sys/ptrace/linux.rs
+++ /dev/null
@@ -1,468 +0,0 @@
-//! For detailed description of the ptrace requests, consult `man ptrace`.
-
-use cfg_if::cfg_if;
-use std::{mem, ptr};
-use crate::{Error, Result};
-use crate::errno::Errno;
-use libc::{self, c_void, c_long, siginfo_t};
-use crate::unistd::Pid;
-use crate::sys::signal::Signal;
-
-pub type AddressType = *mut ::libc::c_void;
-
-#[cfg(all(
- target_os = "linux",
- any(all(target_arch = "x86_64",
- any(target_env = "gnu", target_env = "musl")),
- all(target_arch = "x86", target_env = "gnu"))
-))]
-use libc::user_regs_struct;
-
-cfg_if! {
- if #[cfg(any(all(target_os = "linux", target_arch = "s390x"),
- all(target_os = "linux", target_env = "gnu")))] {
- #[doc(hidden)]
- pub type RequestType = ::libc::c_uint;
- } else {
- #[doc(hidden)]
- pub type RequestType = ::libc::c_int;
- }
-}
-
-libc_enum!{
- #[cfg_attr(not(any(target_env = "musl", target_os = "android")), repr(u32))]
- #[cfg_attr(any(target_env = "musl", target_os = "android"), repr(i32))]
- /// Ptrace Request enum defining the action to be taken.
- pub enum Request {
- PTRACE_TRACEME,
- PTRACE_PEEKTEXT,
- PTRACE_PEEKDATA,
- PTRACE_PEEKUSER,
- PTRACE_POKETEXT,
- PTRACE_POKEDATA,
- PTRACE_POKEUSER,
- PTRACE_CONT,
- PTRACE_KILL,
- PTRACE_SINGLESTEP,
- #[cfg(any(all(target_os = "android", target_pointer_width = "32"),
- all(target_os = "linux", any(target_env = "musl",
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "x86_64",
- target_pointer_width = "32"))))]
- PTRACE_GETREGS,
- #[cfg(any(all(target_os = "android", target_pointer_width = "32"),
- all(target_os = "linux", any(target_env = "musl",
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "x86_64",
- target_pointer_width = "32"))))]
- PTRACE_SETREGS,
- #[cfg(any(all(target_os = "android", target_pointer_width = "32"),
- all(target_os = "linux", any(target_env = "musl",
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "x86_64",
- target_pointer_width = "32"))))]
- PTRACE_GETFPREGS,
- #[cfg(any(all(target_os = "android", target_pointer_width = "32"),
- all(target_os = "linux", any(target_env = "musl",
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "x86_64",
- target_pointer_width = "32"))))]
- PTRACE_SETFPREGS,
- PTRACE_ATTACH,
- PTRACE_DETACH,
- #[cfg(all(target_os = "linux", any(target_env = "musl",
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "x86",
- target_arch = "x86_64")))]
- PTRACE_GETFPXREGS,
- #[cfg(all(target_os = "linux", any(target_env = "musl",
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "x86",
- target_arch = "x86_64")))]
- PTRACE_SETFPXREGS,
- PTRACE_SYSCALL,
- PTRACE_SETOPTIONS,
- PTRACE_GETEVENTMSG,
- PTRACE_GETSIGINFO,
- PTRACE_SETSIGINFO,
- #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
- target_arch = "mips64"))))]
- PTRACE_GETREGSET,
- #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
- target_arch = "mips64"))))]
- PTRACE_SETREGSET,
- #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
- target_arch = "mips64"))))]
- PTRACE_SEIZE,
- #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
- target_arch = "mips64"))))]
- PTRACE_INTERRUPT,
- #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
- target_arch = "mips64"))))]
- PTRACE_LISTEN,
- #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
- target_arch = "mips64"))))]
- PTRACE_PEEKSIGINFO,
- #[cfg(all(target_os = "linux", target_env = "gnu",
- any(target_arch = "x86", target_arch = "x86_64")))]
- PTRACE_SYSEMU,
- #[cfg(all(target_os = "linux", target_env = "gnu",
- any(target_arch = "x86", target_arch = "x86_64")))]
- PTRACE_SYSEMU_SINGLESTEP,
- }
-}
-
-libc_enum!{
- #[repr(i32)]
- /// Using the ptrace options the tracer can configure the tracee to stop
- /// at certain events. This enum is used to define those events as defined
- /// in `man ptrace`.
- pub enum Event {
- /// Event that stops before a return from fork or clone.
- PTRACE_EVENT_FORK,
- /// Event that stops before a return from vfork or clone.
- PTRACE_EVENT_VFORK,
- /// Event that stops before a return from clone.
- PTRACE_EVENT_CLONE,
- /// Event that stops before a return from execve.
- PTRACE_EVENT_EXEC,
- /// Event for a return from vfork.
- PTRACE_EVENT_VFORK_DONE,
- /// Event for a stop before an exit. Unlike the waitpid Exit status program.
- /// registers can still be examined
- PTRACE_EVENT_EXIT,
- /// STop triggered by a seccomp rule on a tracee.
- PTRACE_EVENT_SECCOMP,
- // PTRACE_EVENT_STOP not provided by libc because it's defined in glibc 2.26
- }
-}
-
-libc_bitflags! {
- /// Ptrace options used in conjunction with the PTRACE_SETOPTIONS request.
- /// See `man ptrace` for more details.
- pub struct Options: libc::c_int {
- /// When delivering system call traps set a bit to allow tracer to
- /// distinguish between normal stops or syscall stops. May not work on
- /// all systems.
- PTRACE_O_TRACESYSGOOD;
- /// Stop tracee at next fork and start tracing the forked process.
- PTRACE_O_TRACEFORK;
- /// Stop tracee at next vfork call and trace the vforked process.
- PTRACE_O_TRACEVFORK;
- /// Stop tracee at next clone call and trace the cloned process.
- PTRACE_O_TRACECLONE;
- /// Stop tracee at next execve call.
- PTRACE_O_TRACEEXEC;
- /// Stop tracee at vfork completion.
- PTRACE_O_TRACEVFORKDONE;
- /// Stop tracee at next exit call. Stops before exit commences allowing
- /// tracer to see location of exit and register states.
- PTRACE_O_TRACEEXIT;
- /// Stop tracee when a SECCOMP_RET_TRACE rule is triggered. See `man seccomp` for more
- /// details.
- PTRACE_O_TRACESECCOMP;
- /// Send a SIGKILL to the tracee if the tracer exits. This is useful
- /// for ptrace jailers to prevent tracees from escaping their control.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- PTRACE_O_EXITKILL;
- }
-}
-
-fn ptrace_peek(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result<c_long> {
- let ret = unsafe {
- Errno::clear();
- libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)
- };
- match Errno::result(ret) {
- Ok(..) | Err(Error::Sys(Errno::UnknownErrno)) => Ok(ret),
- err @ Err(..) => err,
- }
-}
-
-/// Get user registers, as with `ptrace(PTRACE_GETREGS, ...)`
-#[cfg(all(
- target_os = "linux",
- any(all(target_arch = "x86_64",
- any(target_env = "gnu", target_env = "musl")),
- all(target_arch = "x86", target_env = "gnu"))
-))]
-pub fn getregs(pid: Pid) -> Result<user_regs_struct> {
- ptrace_get_data::<user_regs_struct>(Request::PTRACE_GETREGS, pid)
-}
-
-/// Set user registers, as with `ptrace(PTRACE_SETREGS, ...)`
-#[cfg(all(
- target_os = "linux",
- any(all(target_arch = "x86_64",
- any(target_env = "gnu", target_env = "musl")),
- all(target_arch = "x86", target_env = "gnu"))
-))]
-pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> {
- let res = unsafe {
- libc::ptrace(Request::PTRACE_SETREGS as RequestType,
- libc::pid_t::from(pid),
- ptr::null_mut::<c_void>(),
- ®s as *const _ as *const c_void)
- };
- Errno::result(res).map(drop)
-}
-
-/// Function for ptrace requests that return values from the data field.
-/// Some ptrace get requests populate structs or larger elements than `c_long`
-/// and therefore use the data field to return values. This function handles these
-/// requests.
-fn ptrace_get_data<T>(request: Request, pid: Pid) -> Result<T> {
- let mut data = mem::MaybeUninit::uninit();
- let res = unsafe {
- libc::ptrace(request as RequestType,
- libc::pid_t::from(pid),
- ptr::null_mut::<T>(),
- data.as_mut_ptr() as *const _ as *const c_void)
- };
- Errno::result(res)?;
- Ok(unsafe{ data.assume_init() })
-}
-
-unsafe fn ptrace_other(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result<c_long> {
- Errno::result(libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)).map(|_| 0)
-}
-
-/// Set options, as with `ptrace(PTRACE_SETOPTIONS,...)`.
-pub fn setoptions(pid: Pid, options: Options) -> Result<()> {
- let res = unsafe {
- libc::ptrace(Request::PTRACE_SETOPTIONS as RequestType,
- libc::pid_t::from(pid),
- ptr::null_mut::<c_void>(),
- options.bits() as *mut c_void)
- };
- Errno::result(res).map(drop)
-}
-
-/// Gets a ptrace event as described by `ptrace(PTRACE_GETEVENTMSG,...)`
-pub fn getevent(pid: Pid) -> Result<c_long> {
- ptrace_get_data::<c_long>(Request::PTRACE_GETEVENTMSG, pid)
-}
-
-/// Get siginfo as with `ptrace(PTRACE_GETSIGINFO,...)`
-pub fn getsiginfo(pid: Pid) -> Result<siginfo_t> {
- ptrace_get_data::<siginfo_t>(Request::PTRACE_GETSIGINFO, pid)
-}
-
-/// Set siginfo as with `ptrace(PTRACE_SETSIGINFO,...)`
-pub fn setsiginfo(pid: Pid, sig: &siginfo_t) -> Result<()> {
- let ret = unsafe{
- Errno::clear();
- libc::ptrace(Request::PTRACE_SETSIGINFO as RequestType,
- libc::pid_t::from(pid),
- ptr::null_mut::<c_void>(),
- sig as *const _ as *const c_void)
- };
- match Errno::result(ret) {
- Ok(_) => Ok(()),
- Err(e) => Err(e),
- }
-}
-
-/// Sets the process as traceable, as with `ptrace(PTRACE_TRACEME, ...)`
-///
-/// Indicates that this process is to be traced by its parent.
-/// This is the only ptrace request to be issued by the tracee.
-pub fn traceme() -> Result<()> {
- unsafe {
- ptrace_other(
- Request::PTRACE_TRACEME,
- Pid::from_raw(0),
- ptr::null_mut(),
- ptr::null_mut(),
- ).map(drop) // ignore the useless return value
- }
-}
-
-/// Continue execution until the next syscall, as with `ptrace(PTRACE_SYSCALL, ...)`
-///
-/// Arranges for the tracee to be stopped at the next entry to or exit from a system call,
-/// optionally delivering a signal specified by `sig`.
-pub fn syscall<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as i32 as *mut c_void,
- None => ptr::null_mut(),
- };
- unsafe {
- ptrace_other(
- Request::PTRACE_SYSCALL,
- pid,
- ptr::null_mut(),
- data,
- ).map(drop) // ignore the useless return value
- }
-}
-
-/// Continue execution until the next syscall, as with `ptrace(PTRACE_SYSEMU, ...)`
-///
-/// In contrast to the `syscall` function, the syscall stopped at will not be executed.
-/// Thus the the tracee will only be stopped once per syscall,
-/// optionally delivering a signal specified by `sig`.
-#[cfg(all(target_os = "linux", target_env = "gnu", any(target_arch = "x86", target_arch = "x86_64")))]
-pub fn sysemu<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as i32 as *mut c_void,
- None => ptr::null_mut(),
- };
- unsafe {
- ptrace_other(Request::PTRACE_SYSEMU, pid, ptr::null_mut(), data).map(drop)
- // ignore the useless return value
- }
-}
-
-/// Attach to a running process, as with `ptrace(PTRACE_ATTACH, ...)`
-///
-/// Attaches to the process specified by `pid`, making it a tracee of the calling process.
-pub fn attach(pid: Pid) -> Result<()> {
- unsafe {
- ptrace_other(
- Request::PTRACE_ATTACH,
- pid,
- ptr::null_mut(),
- ptr::null_mut(),
- ).map(drop) // ignore the useless return value
- }
-}
-
-/// Attach to a running process, as with `ptrace(PTRACE_SEIZE, ...)`
-///
-/// Attaches to the process specified in pid, making it a tracee of the calling process.
-#[cfg(all(target_os = "linux", not(any(target_arch = "mips", target_arch = "mips64"))))]
-pub fn seize(pid: Pid, options: Options) -> Result<()> {
- unsafe {
- ptrace_other(
- Request::PTRACE_SEIZE,
- pid,
- ptr::null_mut(),
- options.bits() as *mut c_void,
- ).map(drop) // ignore the useless return value
- }
-}
-
-/// Detaches the current running process, as with `ptrace(PTRACE_DETACH, ...)`
-///
-/// Detaches from the process specified by `pid` allowing it to run freely, optionally delivering a
-/// signal specified by `sig`.
-pub fn detach<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as i32 as *mut c_void,
- None => ptr::null_mut(),
- };
- unsafe {
- ptrace_other(
- Request::PTRACE_DETACH,
- pid,
- ptr::null_mut(),
- data
- ).map(drop)
- }
-}
-
-/// Restart the stopped tracee process, as with `ptrace(PTRACE_CONT, ...)`
-///
-/// Continues the execution of the process with PID `pid`, optionally
-/// delivering a signal specified by `sig`.
-pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as i32 as *mut c_void,
- None => ptr::null_mut(),
- };
- unsafe {
- ptrace_other(Request::PTRACE_CONT, pid, ptr::null_mut(), data).map(drop) // ignore the useless return value
- }
-}
-
-/// Issues a kill request as with `ptrace(PTRACE_KILL, ...)`
-///
-/// This request is equivalent to `ptrace(PTRACE_CONT, ..., SIGKILL);`
-pub fn kill(pid: Pid) -> Result<()> {
- unsafe {
- ptrace_other(Request::PTRACE_KILL, pid, ptr::null_mut(), ptr::null_mut()).map(drop)
- }
-}
-
-/// Move the stopped tracee process forward by a single step as with
-/// `ptrace(PTRACE_SINGLESTEP, ...)`
-///
-/// Advances the execution of the process with PID `pid` by a single step optionally delivering a
-/// signal specified by `sig`.
-///
-/// # Example
-/// ```rust
-/// use nix::sys::ptrace::step;
-/// use nix::unistd::Pid;
-/// use nix::sys::signal::Signal;
-/// use nix::sys::wait::*;
-/// fn main() {
-/// // If a process changes state to the stopped state because of a SIGUSR1
-/// // signal, this will step the process forward and forward the user
-/// // signal to the stopped process
-/// match waitpid(Pid::from_raw(-1), None) {
-/// Ok(WaitStatus::Stopped(pid, Signal::SIGUSR1)) => {
-/// let _ = step(pid, Signal::SIGUSR1);
-/// }
-/// _ => {},
-/// }
-/// }
-/// ```
-pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as i32 as *mut c_void,
- None => ptr::null_mut(),
- };
- unsafe {
- ptrace_other(Request::PTRACE_SINGLESTEP, pid, ptr::null_mut(), data).map(drop)
- }
-}
-
-/// Move the stopped tracee process forward by a single step or stop at the next syscall
-/// as with `ptrace(PTRACE_SYSEMU_SINGLESTEP, ...)`
-///
-/// Advances the execution by a single step or until the next syscall.
-/// In case the tracee is stopped at a syscall, the syscall will not be executed.
-/// Optionally, the signal specified by `sig` is delivered to the tracee upon continuation.
-#[cfg(all(target_os = "linux", target_env = "gnu", any(target_arch = "x86", target_arch = "x86_64")))]
-pub fn sysemu_step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as i32 as *mut c_void,
- None => ptr::null_mut(),
- };
- unsafe {
- ptrace_other(
- Request::PTRACE_SYSEMU_SINGLESTEP,
- pid,
- ptr::null_mut(),
- data,
- )
- .map(drop) // ignore the useless return value
- }
-}
-
-/// Reads a word from a processes memory at the given address
-pub fn read(pid: Pid, addr: AddressType) -> Result<c_long> {
- ptrace_peek(Request::PTRACE_PEEKDATA, pid, addr, ptr::null_mut())
-}
-
-/// Writes a word into the processes memory at the given address
-///
-/// # Safety
-///
-/// The `data` argument is passed directly to `ptrace(2)`. Read that man page
-/// for guidance.
-pub unsafe fn write(
- pid: Pid,
- addr: AddressType,
- data: *mut c_void) -> Result<()>
-{
- ptrace_other(Request::PTRACE_POKEDATA, pid, addr, data).map(drop)
-}
diff --git a/vendor/nix-0.20.0/src/sys/ptrace/mod.rs b/vendor/nix-0.20.0/src/sys/ptrace/mod.rs
deleted file mode 100644
index 782c304..0000000
--- a/vendor/nix-0.20.0/src/sys/ptrace/mod.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-///! Provides helpers for making ptrace system calls
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-mod linux;
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use self::linux::*;
-
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
-mod bsd;
-
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
-pub use self::bsd::*;
diff --git a/vendor/nix-0.20.0/src/sys/quota.rs b/vendor/nix-0.20.0/src/sys/quota.rs
deleted file mode 100644
index 1933013..0000000
--- a/vendor/nix-0.20.0/src/sys/quota.rs
+++ /dev/null
@@ -1,275 +0,0 @@
-//! Set and configure disk quotas for users, groups, or projects.
-//!
-//! # Examples
-//!
-//! Enabling and setting a quota:
-//!
-//! ```rust,no_run
-//! # use nix::sys::quota::{Dqblk, quotactl_on, quotactl_set, QuotaFmt, QuotaType, QuotaValidFlags};
-//! quotactl_on(QuotaType::USRQUOTA, "/dev/sda1", QuotaFmt::QFMT_VFS_V1, "aquota.user");
-//! let mut dqblk: Dqblk = Default::default();
-//! dqblk.set_blocks_hard_limit(10000);
-//! dqblk.set_blocks_soft_limit(8000);
-//! quotactl_set(QuotaType::USRQUOTA, "/dev/sda1", 50, &dqblk, QuotaValidFlags::QIF_BLIMITS);
-//! ```
-use std::default::Default;
-use std::{mem, ptr};
-use libc::{self, c_int, c_char};
-use crate::{Result, NixPath};
-use crate::errno::Errno;
-
-struct QuotaCmd(QuotaSubCmd, QuotaType);
-
-impl QuotaCmd {
- #[allow(unused_unsafe)]
- fn as_int(&self) -> c_int {
- unsafe { libc::QCMD(self.0 as i32, self.1 as i32) }
- }
-}
-
-// linux quota version >= 2
-libc_enum!{
- #[repr(i32)]
- enum QuotaSubCmd {
- Q_SYNC,
- Q_QUOTAON,
- Q_QUOTAOFF,
- Q_GETQUOTA,
- Q_SETQUOTA,
- }
-}
-
-libc_enum!{
- /// The scope of the quota.
- #[repr(i32)]
- pub enum QuotaType {
- /// Specify a user quota
- USRQUOTA,
- /// Specify a group quota
- GRPQUOTA,
- }
-}
-
-libc_enum!{
- /// The type of quota format to use.
- #[repr(i32)]
- pub enum QuotaFmt {
- /// Use the original quota format.
- QFMT_VFS_OLD,
- /// Use the standard VFS v0 quota format.
- ///
- /// Handles 32-bit UIDs/GIDs and quota limits up to 2<sup>32</sup> bytes/2<sup>32</sup> inodes.
- QFMT_VFS_V0,
- /// Use the VFS v1 quota format.
- ///
- /// Handles 32-bit UIDs/GIDs and quota limits of 2<sup>64</sup> bytes/2<sup>64</sup> inodes.
- QFMT_VFS_V1,
- }
-}
-
-libc_bitflags!(
- /// Indicates the quota fields that are valid to read from.
- #[derive(Default)]
- pub struct QuotaValidFlags: u32 {
- /// The block hard & soft limit fields.
- QIF_BLIMITS;
- /// The current space field.
- QIF_SPACE;
- /// The inode hard & soft limit fields.
- QIF_ILIMITS;
- /// The current inodes field.
- QIF_INODES;
- /// The disk use time limit field.
- QIF_BTIME;
- /// The file quote time limit field.
- QIF_ITIME;
- /// All block & inode limits.
- QIF_LIMITS;
- /// The space & inodes usage fields.
- QIF_USAGE;
- /// The time limit fields.
- QIF_TIMES;
- /// All fields.
- QIF_ALL;
- }
-);
-
-/// Wrapper type for `if_dqblk`
-#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct Dqblk(libc::dqblk);
-
-impl Default for Dqblk {
- fn default() -> Dqblk {
- Dqblk(libc::dqblk {
- dqb_bhardlimit: 0,
- dqb_bsoftlimit: 0,
- dqb_curspace: 0,
- dqb_ihardlimit: 0,
- dqb_isoftlimit: 0,
- dqb_curinodes: 0,
- dqb_btime: 0,
- dqb_itime: 0,
- dqb_valid: 0,
- })
- }
-}
-
-impl Dqblk {
- /// The absolute limit on disk quota blocks allocated.
- pub fn blocks_hard_limit(&self) -> Option<u64> {
- let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
- if valid_fields.contains(QuotaValidFlags::QIF_BLIMITS) {
- Some(self.0.dqb_bhardlimit)
- } else {
- None
- }
- }
-
- /// Set the absolute limit on disk quota blocks allocated.
- pub fn set_blocks_hard_limit(&mut self, limit: u64) {
- self.0.dqb_bhardlimit = limit;
- }
-
- /// Preferred limit on disk quota blocks
- pub fn blocks_soft_limit(&self) -> Option<u64> {
- let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
- if valid_fields.contains(QuotaValidFlags::QIF_BLIMITS) {
- Some(self.0.dqb_bsoftlimit)
- } else {
- None
- }
- }
-
- /// Set the preferred limit on disk quota blocks allocated.
- pub fn set_blocks_soft_limit(&mut self, limit: u64) {
- self.0.dqb_bsoftlimit = limit;
- }
-
- /// Current occupied space (bytes).
- pub fn occupied_space(&self) -> Option<u64> {
- let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
- if valid_fields.contains(QuotaValidFlags::QIF_SPACE) {
- Some(self.0.dqb_curspace)
- } else {
- None
- }
- }
-
- /// Maximum number of allocated inodes.
- pub fn inodes_hard_limit(&self) -> Option<u64> {
- let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
- if valid_fields.contains(QuotaValidFlags::QIF_ILIMITS) {
- Some(self.0.dqb_ihardlimit)
- } else {
- None
- }
- }
-
- /// Set the maximum number of allocated inodes.
- pub fn set_inodes_hard_limit(&mut self, limit: u64) {
- self.0.dqb_ihardlimit = limit;
- }
-
- /// Preferred inode limit
- pub fn inodes_soft_limit(&self) -> Option<u64> {
- let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
- if valid_fields.contains(QuotaValidFlags::QIF_ILIMITS) {
- Some(self.0.dqb_isoftlimit)
- } else {
- None
- }
- }
-
- /// Set the preferred limit of allocated inodes.
- pub fn set_inodes_soft_limit(&mut self, limit: u64) {
- self.0.dqb_isoftlimit = limit;
- }
-
- /// Current number of allocated inodes.
- pub fn allocated_inodes(&self) -> Option<u64> {
- let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
- if valid_fields.contains(QuotaValidFlags::QIF_INODES) {
- Some(self.0.dqb_curinodes)
- } else {
- None
- }
- }
-
- /// Time limit for excessive disk use.
- pub fn block_time_limit(&self) -> Option<u64> {
- let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
- if valid_fields.contains(QuotaValidFlags::QIF_BTIME) {
- Some(self.0.dqb_btime)
- } else {
- None
- }
- }
-
- /// Set the time limit for excessive disk use.
- pub fn set_block_time_limit(&mut self, limit: u64) {
- self.0.dqb_btime = limit;
- }
-
- /// Time limit for excessive files.
- pub fn inode_time_limit(&self) -> Option<u64> {
- let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
- if valid_fields.contains(QuotaValidFlags::QIF_ITIME) {
- Some(self.0.dqb_itime)
- } else {
- None
- }
- }
-
- /// Set the time limit for excessive files.
- pub fn set_inode_time_limit(&mut self, limit: u64) {
- self.0.dqb_itime = limit;
- }
-}
-
-fn quotactl<P: ?Sized + NixPath>(cmd: QuotaCmd, special: Option<&P>, id: c_int, addr: *mut c_char) -> Result<()> {
- unsafe {
- Errno::clear();
- let res = match special {
- Some(dev) => dev.with_nix_path(|path| libc::quotactl(cmd.as_int(), path.as_ptr(), id, addr)),
- None => Ok(libc::quotactl(cmd.as_int(), ptr::null(), id, addr)),
- }?;
-
- Errno::result(res).map(drop)
- }
-}
-
-/// Turn on disk quotas for a block device.
-pub fn quotactl_on<P: ?Sized + NixPath>(which: QuotaType, special: &P, format: QuotaFmt, quota_file: &P) -> Result<()> {
- quota_file.with_nix_path(|path| {
- let mut path_copy = path.to_bytes_with_nul().to_owned();
- let p: *mut c_char = path_copy.as_mut_ptr() as *mut c_char;
- quotactl(QuotaCmd(QuotaSubCmd::Q_QUOTAON, which), Some(special), format as c_int, p)
- })?
-}
-
-/// Disable disk quotas for a block device.
-pub fn quotactl_off<P: ?Sized + NixPath>(which: QuotaType, special: &P) -> Result<()> {
- quotactl(QuotaCmd(QuotaSubCmd::Q_QUOTAOFF, which), Some(special), 0, ptr::null_mut())
-}
-
-/// Update the on-disk copy of quota usages for a filesystem.
-///
-/// If `special` is `None`, then all file systems with active quotas are sync'd.
-pub fn quotactl_sync<P: ?Sized + NixPath>(which: QuotaType, special: Option<&P>) -> Result<()> {
- quotactl(QuotaCmd(QuotaSubCmd::Q_SYNC, which), special, 0, ptr::null_mut())
-}
-
-/// Get disk quota limits and current usage for the given user/group id.
-pub fn quotactl_get<P: ?Sized + NixPath>(which: QuotaType, special: &P, id: c_int) -> Result<Dqblk> {
- let mut dqblk = mem::MaybeUninit::uninit();
- quotactl(QuotaCmd(QuotaSubCmd::Q_GETQUOTA, which), Some(special), id, dqblk.as_mut_ptr() as *mut c_char)?;
- Ok(unsafe{ Dqblk(dqblk.assume_init())})
-}
-
-/// Configure quota values for the specified fields for a given user/group id.
-pub fn quotactl_set<P: ?Sized + NixPath>(which: QuotaType, special: &P, id: c_int, dqblk: &Dqblk, fields: QuotaValidFlags) -> Result<()> {
- let mut dqblk_copy = *dqblk;
- dqblk_copy.0.dqb_valid = fields.bits();
- quotactl(QuotaCmd(QuotaSubCmd::Q_SETQUOTA, which), Some(special), id, &mut dqblk_copy as *mut _ as *mut c_char)
-}
diff --git a/vendor/nix-0.20.0/src/sys/reboot.rs b/vendor/nix-0.20.0/src/sys/reboot.rs
deleted file mode 100644
index e319130..0000000
--- a/vendor/nix-0.20.0/src/sys/reboot.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-//! Reboot/shutdown or enable/disable Ctrl-Alt-Delete.
-
-use crate::{Error, Result};
-use crate::errno::Errno;
-use libc;
-use std::convert::Infallible;
-use std::mem::drop;
-
-libc_enum! {
- /// How exactly should the system be rebooted.
- ///
- /// See [`set_cad_enabled()`](fn.set_cad_enabled.html) for
- /// enabling/disabling Ctrl-Alt-Delete.
- #[repr(i32)]
- pub enum RebootMode {
- RB_HALT_SYSTEM,
- RB_KEXEC,
- RB_POWER_OFF,
- RB_AUTOBOOT,
- // we do not support Restart2,
- RB_SW_SUSPEND,
- }
-}
-
-pub fn reboot(how: RebootMode) -> Result<Infallible> {
- unsafe {
- libc::reboot(how as libc::c_int)
- };
- Err(Error::Sys(Errno::last()))
-}
-
-/// Enable or disable the reboot keystroke (Ctrl-Alt-Delete).
-///
-/// Corresponds to calling `reboot(RB_ENABLE_CAD)` or `reboot(RB_DISABLE_CAD)` in C.
-pub fn set_cad_enabled(enable: bool) -> Result<()> {
- let cmd = if enable {
- libc::RB_ENABLE_CAD
- } else {
- libc::RB_DISABLE_CAD
- };
- let res = unsafe {
- libc::reboot(cmd)
- };
- Errno::result(res).map(drop)
-}
diff --git a/vendor/nix-0.20.0/src/sys/select.rs b/vendor/nix-0.20.0/src/sys/select.rs
deleted file mode 100644
index a576c7e..0000000
--- a/vendor/nix-0.20.0/src/sys/select.rs
+++ /dev/null
@@ -1,414 +0,0 @@
-use std::iter::FusedIterator;
-use std::mem;
-use std::ops::Range;
-use std::os::unix::io::RawFd;
-use std::ptr::{null, null_mut};
-use libc::{self, c_int};
-use crate::Result;
-use crate::errno::Errno;
-use crate::sys::signal::SigSet;
-use crate::sys::time::{TimeSpec, TimeVal};
-
-pub use libc::FD_SETSIZE;
-
-#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct FdSet(libc::fd_set);
-
-impl FdSet {
- pub fn new() -> FdSet {
- let mut fdset = mem::MaybeUninit::uninit();
- unsafe {
- libc::FD_ZERO(fdset.as_mut_ptr());
- FdSet(fdset.assume_init())
- }
- }
-
- pub fn insert(&mut self, fd: RawFd) {
- unsafe { libc::FD_SET(fd, &mut self.0) };
- }
-
- pub fn remove(&mut self, fd: RawFd) {
- unsafe { libc::FD_CLR(fd, &mut self.0) };
- }
-
- pub fn contains(&mut self, fd: RawFd) -> bool {
- unsafe { libc::FD_ISSET(fd, &mut self.0) }
- }
-
- pub fn clear(&mut self) {
- unsafe { libc::FD_ZERO(&mut self.0) };
- }
-
- /// Finds the highest file descriptor in the set.
- ///
- /// Returns `None` if the set is empty.
- ///
- /// This can be used to calculate the `nfds` parameter of the [`select`] function.
- ///
- /// # Example
- ///
- /// ```
- /// # use nix::sys::select::FdSet;
- /// # fn main() {
- /// let mut set = FdSet::new();
- /// set.insert(4);
- /// set.insert(9);
- /// assert_eq!(set.highest(), Some(9));
- /// # }
- /// ```
- ///
- /// [`select`]: fn.select.html
- pub fn highest(&mut self) -> Option<RawFd> {
- self.fds(None).next_back()
- }
-
- /// Returns an iterator over the file descriptors in the set.
- ///
- /// For performance, it takes an optional higher bound: the iterator will
- /// not return any elements of the set greater than the given file
- /// descriptor.
- ///
- /// # Examples
- ///
- /// ```
- /// # use nix::sys::select::FdSet;
- /// # use std::os::unix::io::RawFd;
- /// let mut set = FdSet::new();
- /// set.insert(4);
- /// set.insert(9);
- /// let fds: Vec<RawFd> = set.fds(None).collect();
- /// assert_eq!(fds, vec![4, 9]);
- /// ```
- #[inline]
- pub fn fds(&mut self, highest: Option<RawFd>) -> Fds {
- Fds {
- set: self,
- range: 0..highest.map(|h| h as usize + 1).unwrap_or(FD_SETSIZE),
- }
- }
-}
-
-impl Default for FdSet {
- fn default() -> Self {
- Self::new()
- }
-}
-
-/// Iterator over `FdSet`.
-#[derive(Debug)]
-pub struct Fds<'a> {
- set: &'a mut FdSet,
- range: Range<usize>,
-}
-
-impl<'a> Iterator for Fds<'a> {
- type Item = RawFd;
-
- fn next(&mut self) -> Option<RawFd> {
- while let Some(i) = self.range.next() {
- if self.set.contains(i as RawFd) {
- return Some(i as RawFd);
- }
- }
- None
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- let (_, upper) = self.range.size_hint();
- (0, upper)
- }
-}
-
-impl<'a> DoubleEndedIterator for Fds<'a> {
- #[inline]
- fn next_back(&mut self) -> Option<RawFd> {
- while let Some(i) = self.range.next_back() {
- if self.set.contains(i as RawFd) {
- return Some(i as RawFd);
- }
- }
- None
- }
-}
-
-impl<'a> FusedIterator for Fds<'a> {}
-
-/// Monitors file descriptors for readiness
-///
-/// Returns the total number of ready file descriptors in all sets. The sets are changed so that all
-/// file descriptors that are ready for the given operation are set.
-///
-/// When this function returns, `timeout` has an implementation-defined value.
-///
-/// # Parameters
-///
-/// * `nfds`: The highest file descriptor set in any of the passed `FdSet`s, plus 1. If `None`, this
-/// is calculated automatically by calling [`FdSet::highest`] on all descriptor sets and adding 1
-/// to the maximum of that.
-/// * `readfds`: File descriptors to check for being ready to read.
-/// * `writefds`: File descriptors to check for being ready to write.
-/// * `errorfds`: File descriptors to check for pending error conditions.
-/// * `timeout`: Maximum time to wait for descriptors to become ready (`None` to block
-/// indefinitely).
-///
-/// # References
-///
-/// [select(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html)
-///
-/// [`FdSet::highest`]: struct.FdSet.html#method.highest
-pub fn select<'a, N, R, W, E, T>(nfds: N,
- readfds: R,
- writefds: W,
- errorfds: E,
- timeout: T) -> Result<c_int>
-where
- N: Into<Option<c_int>>,
- R: Into<Option<&'a mut FdSet>>,
- W: Into<Option<&'a mut FdSet>>,
- E: Into<Option<&'a mut FdSet>>,
- T: Into<Option<&'a mut TimeVal>>,
-{
- let mut readfds = readfds.into();
- let mut writefds = writefds.into();
- let mut errorfds = errorfds.into();
- let timeout = timeout.into();
-
- let nfds = nfds.into().unwrap_or_else(|| {
- readfds.iter_mut()
- .chain(writefds.iter_mut())
- .chain(errorfds.iter_mut())
- .map(|set| set.highest().unwrap_or(-1))
- .max()
- .unwrap_or(-1) + 1
- });
-
- let readfds = readfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
- let writefds = writefds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
- let errorfds = errorfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
- let timeout = timeout.map(|tv| tv as *mut _ as *mut libc::timeval)
- .unwrap_or(null_mut());
-
- let res = unsafe {
- libc::select(nfds, readfds, writefds, errorfds, timeout)
- };
-
- Errno::result(res)
-}
-
-/// Monitors file descriptors for readiness with an altered signal mask.
-///
-/// Returns the total number of ready file descriptors in all sets. The sets are changed so that all
-/// file descriptors that are ready for the given operation are set.
-///
-/// When this function returns, the original signal mask is restored.
-///
-/// Unlike [`select`](#fn.select), `pselect` does not mutate the `timeout` value.
-///
-/// # Parameters
-///
-/// * `nfds`: The highest file descriptor set in any of the passed `FdSet`s, plus 1. If `None`, this
-/// is calculated automatically by calling [`FdSet::highest`] on all descriptor sets and adding 1
-/// to the maximum of that.
-/// * `readfds`: File descriptors to check for read readiness
-/// * `writefds`: File descriptors to check for write readiness
-/// * `errorfds`: File descriptors to check for pending error conditions.
-/// * `timeout`: Maximum time to wait for descriptors to become ready (`None` to block
-/// indefinitely).
-/// * `sigmask`: Signal mask to activate while waiting for file descriptors to turn
-/// ready (`None` to set no alternative signal mask).
-///
-/// # References
-///
-/// [pselect(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html)
-///
-/// [The new pselect() system call](https://lwn.net/Articles/176911/)
-///
-/// [`FdSet::highest`]: struct.FdSet.html#method.highest
-pub fn pselect<'a, N, R, W, E, T, S>(nfds: N,
- readfds: R,
- writefds: W,
- errorfds: E,
- timeout: T,
- sigmask: S) -> Result<c_int>
-where
- N: Into<Option<c_int>>,
- R: Into<Option<&'a mut FdSet>>,
- W: Into<Option<&'a mut FdSet>>,
- E: Into<Option<&'a mut FdSet>>,
- T: Into<Option<&'a TimeSpec>>,
- S: Into<Option<&'a SigSet>>,
-{
- let mut readfds = readfds.into();
- let mut writefds = writefds.into();
- let mut errorfds = errorfds.into();
- let sigmask = sigmask.into();
- let timeout = timeout.into();
-
- let nfds = nfds.into().unwrap_or_else(|| {
- readfds.iter_mut()
- .chain(writefds.iter_mut())
- .chain(errorfds.iter_mut())
- .map(|set| set.highest().unwrap_or(-1))
- .max()
- .unwrap_or(-1) + 1
- });
-
- let readfds = readfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
- let writefds = writefds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
- let errorfds = errorfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
- let timeout = timeout.map(|ts| ts.as_ref() as *const libc::timespec).unwrap_or(null());
- let sigmask = sigmask.map(|sm| sm.as_ref() as *const libc::sigset_t).unwrap_or(null());
-
- let res = unsafe {
- libc::pselect(nfds, readfds, writefds, errorfds, timeout, sigmask)
- };
-
- Errno::result(res)
-}
-
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use std::os::unix::io::RawFd;
- use crate::sys::time::{TimeVal, TimeValLike};
- use crate::unistd::{write, pipe};
-
- #[test]
- fn fdset_insert() {
- let mut fd_set = FdSet::new();
-
- for i in 0..FD_SETSIZE {
- assert!(!fd_set.contains(i as RawFd));
- }
-
- fd_set.insert(7);
-
- assert!(fd_set.contains(7));
- }
-
- #[test]
- fn fdset_remove() {
- let mut fd_set = FdSet::new();
-
- for i in 0..FD_SETSIZE {
- assert!(!fd_set.contains(i as RawFd));
- }
-
- fd_set.insert(7);
- fd_set.remove(7);
-
- for i in 0..FD_SETSIZE {
- assert!(!fd_set.contains(i as RawFd));
- }
- }
-
- #[test]
- fn fdset_clear() {
- let mut fd_set = FdSet::new();
- fd_set.insert(1);
- fd_set.insert((FD_SETSIZE / 2) as RawFd);
- fd_set.insert((FD_SETSIZE - 1) as RawFd);
-
- fd_set.clear();
-
- for i in 0..FD_SETSIZE {
- assert!(!fd_set.contains(i as RawFd));
- }
- }
-
- #[test]
- fn fdset_highest() {
- let mut set = FdSet::new();
- assert_eq!(set.highest(), None);
- set.insert(0);
- assert_eq!(set.highest(), Some(0));
- set.insert(90);
- assert_eq!(set.highest(), Some(90));
- set.remove(0);
- assert_eq!(set.highest(), Some(90));
- set.remove(90);
- assert_eq!(set.highest(), None);
-
- set.insert(4);
- set.insert(5);
- set.insert(7);
- assert_eq!(set.highest(), Some(7));
- }
-
- #[test]
- fn fdset_fds() {
- let mut set = FdSet::new();
- assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![]);
- set.insert(0);
- assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![0]);
- set.insert(90);
- assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![0, 90]);
-
- // highest limit
- assert_eq!(set.fds(Some(89)).collect::<Vec<_>>(), vec![0]);
- assert_eq!(set.fds(Some(90)).collect::<Vec<_>>(), vec![0, 90]);
- }
-
- #[test]
- fn test_select() {
- let (r1, w1) = pipe().unwrap();
- write(w1, b"hi!").unwrap();
- let (r2, _w2) = pipe().unwrap();
-
- let mut fd_set = FdSet::new();
- fd_set.insert(r1);
- fd_set.insert(r2);
-
- let mut timeout = TimeVal::seconds(10);
- assert_eq!(1, select(None,
- &mut fd_set,
- None,
- None,
- &mut timeout).unwrap());
- assert!(fd_set.contains(r1));
- assert!(!fd_set.contains(r2));
- }
-
- #[test]
- fn test_select_nfds() {
- let (r1, w1) = pipe().unwrap();
- write(w1, b"hi!").unwrap();
- let (r2, _w2) = pipe().unwrap();
-
- let mut fd_set = FdSet::new();
- fd_set.insert(r1);
- fd_set.insert(r2);
-
- let mut timeout = TimeVal::seconds(10);
- assert_eq!(1, select(Some(fd_set.highest().unwrap() + 1),
- &mut fd_set,
- None,
- None,
- &mut timeout).unwrap());
- assert!(fd_set.contains(r1));
- assert!(!fd_set.contains(r2));
- }
-
- #[test]
- fn test_select_nfds2() {
- let (r1, w1) = pipe().unwrap();
- write(w1, b"hi!").unwrap();
- let (r2, _w2) = pipe().unwrap();
-
- let mut fd_set = FdSet::new();
- fd_set.insert(r1);
- fd_set.insert(r2);
-
- let mut timeout = TimeVal::seconds(10);
- assert_eq!(1, select(::std::cmp::max(r1, r2) + 1,
- &mut fd_set,
- None,
- None,
- &mut timeout).unwrap());
- assert!(fd_set.contains(r1));
- assert!(!fd_set.contains(r2));
- }
-}
diff --git a/vendor/nix-0.20.0/src/sys/sendfile.rs b/vendor/nix-0.20.0/src/sys/sendfile.rs
deleted file mode 100644
index 84fe2a9..0000000
--- a/vendor/nix-0.20.0/src/sys/sendfile.rs
+++ /dev/null
@@ -1,203 +0,0 @@
-use cfg_if::cfg_if;
-use std::os::unix::io::RawFd;
-use std::ptr;
-
-use libc::{self, off_t};
-
-use crate::Result;
-use crate::errno::Errno;
-
-/// Copy up to `count` bytes to `out_fd` from `in_fd` starting at `offset`.
-///
-/// Returns a `Result` with the number of bytes written.
-///
-/// If `offset` is `None`, `sendfile` will begin reading at the current offset of `in_fd`and will
-/// update the offset of `in_fd`. If `offset` is `Some`, `sendfile` will begin at the specified
-/// offset and will not update the offset of `in_fd`. Instead, it will mutate `offset` to point to
-/// the byte after the last byte copied.
-///
-/// `in_fd` must support `mmap`-like operations and therefore cannot be a socket.
-///
-/// For more information, see [the sendfile(2) man page.](http://man7.org/linux/man-pages/man2/sendfile.2.html)
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub fn sendfile(
- out_fd: RawFd,
- in_fd: RawFd,
- offset: Option<&mut off_t>,
- count: usize,
-) -> Result<usize> {
- let offset = offset
- .map(|offset| offset as *mut _)
- .unwrap_or(ptr::null_mut());
- let ret = unsafe { libc::sendfile(out_fd, in_fd, offset, count) };
- Errno::result(ret).map(|r| r as usize)
-}
-
-cfg_if! {
- if #[cfg(any(target_os = "freebsd",
- target_os = "ios",
- target_os = "macos"))] {
- use crate::sys::uio::IoVec;
-
- #[derive(Clone, Debug, Eq, Hash, PartialEq)]
- struct SendfileHeaderTrailer<'a>(
- libc::sf_hdtr,
- Option<Vec<IoVec<&'a [u8]>>>,
- Option<Vec<IoVec<&'a [u8]>>>,
- );
-
- impl<'a> SendfileHeaderTrailer<'a> {
- fn new(
- headers: Option<&'a [&'a [u8]]>,
- trailers: Option<&'a [&'a [u8]]>
- ) -> SendfileHeaderTrailer<'a> {
- let header_iovecs: Option<Vec<IoVec<&[u8]>>> =
- headers.map(|s| s.iter().map(|b| IoVec::from_slice(b)).collect());
- let trailer_iovecs: Option<Vec<IoVec<&[u8]>>> =
- trailers.map(|s| s.iter().map(|b| IoVec::from_slice(b)).collect());
- SendfileHeaderTrailer(
- libc::sf_hdtr {
- headers: {
- header_iovecs
- .as_ref()
- .map_or(ptr::null(), |v| v.as_ptr()) as *mut libc::iovec
- },
- hdr_cnt: header_iovecs.as_ref().map(|v| v.len()).unwrap_or(0) as i32,
- trailers: {
- trailer_iovecs
- .as_ref()
- .map_or(ptr::null(), |v| v.as_ptr()) as *mut libc::iovec
- },
- trl_cnt: trailer_iovecs.as_ref().map(|v| v.len()).unwrap_or(0) as i32
- },
- header_iovecs,
- trailer_iovecs,
- )
- }
- }
- }
-}
-
-cfg_if! {
- if #[cfg(target_os = "freebsd")] {
- use libc::c_int;
-
- libc_bitflags!{
- /// Configuration options for [`sendfile`.](fn.sendfile.html)
- pub struct SfFlags: c_int {
- /// Causes `sendfile` to return EBUSY instead of blocking when attempting to read a
- /// busy page.
- SF_NODISKIO;
- /// Causes `sendfile` to sleep until the network stack releases its reference to the
- /// VM pages read. When `sendfile` returns, the data is not guaranteed to have been
- /// sent, but it is safe to modify the file.
- SF_SYNC;
- /// Causes `sendfile` to cache exactly the number of pages specified in the
- /// `readahead` parameter, disabling caching heuristics.
- SF_USER_READAHEAD;
- /// Causes `sendfile` not to cache the data read.
- SF_NOCACHE;
- }
- }
-
- /// Read up to `count` bytes from `in_fd` starting at `offset` and write to `out_sock`.
- ///
- /// Returns a `Result` and a count of bytes written. Bytes written may be non-zero even if
- /// an error occurs.
- ///
- /// `in_fd` must describe a regular file or shared memory object. `out_sock` must describe a
- /// stream socket.
- ///
- /// If `offset` falls past the end of the file, the function returns success and zero bytes
- /// written.
- ///
- /// If `count` is `None` or 0, bytes will be read from `in_fd` until reaching the end of
- /// file (EOF).
- ///
- /// `headers` and `trailers` specify optional slices of byte slices to be sent before and
- /// after the data read from `in_fd`, respectively. The length of headers and trailers sent
- /// is included in the returned count of bytes written. The values of `offset` and `count`
- /// do not apply to headers or trailers.
- ///
- /// `readahead` specifies the minimum number of pages to cache in memory ahead of the page
- /// currently being sent.
- ///
- /// For more information, see
- /// [the sendfile(2) man page.](https://www.freebsd.org/cgi/man.cgi?query=sendfile&sektion=2)
- #[allow(clippy::too_many_arguments)]
- pub fn sendfile(
- in_fd: RawFd,
- out_sock: RawFd,
- offset: off_t,
- count: Option<usize>,
- headers: Option<&[&[u8]]>,
- trailers: Option<&[&[u8]]>,
- flags: SfFlags,
- readahead: u16
- ) -> (Result<()>, off_t) {
- // Readahead goes in upper 16 bits
- // Flags goes in lower 16 bits
- // see `man 2 sendfile`
- let ra32 = u32::from(readahead);
- let flags: u32 = (ra32 << 16) | (flags.bits() as u32);
- let mut bytes_sent: off_t = 0;
- let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
- let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
- let return_code = unsafe {
- libc::sendfile(in_fd,
- out_sock,
- offset,
- count.unwrap_or(0),
- hdtr_ptr as *mut libc::sf_hdtr,
- &mut bytes_sent as *mut off_t,
- flags as c_int)
- };
- (Errno::result(return_code).and(Ok(())), bytes_sent)
- }
- } else if #[cfg(any(target_os = "ios", target_os = "macos"))] {
- /// Read bytes from `in_fd` starting at `offset` and write up to `count` bytes to
- /// `out_sock`.
- ///
- /// Returns a `Result` and a count of bytes written. Bytes written may be non-zero even if
- /// an error occurs.
- ///
- /// `in_fd` must describe a regular file. `out_sock` must describe a stream socket.
- ///
- /// If `offset` falls past the end of the file, the function returns success and zero bytes
- /// written.
- ///
- /// If `count` is `None` or 0, bytes will be read from `in_fd` until reaching the end of
- /// file (EOF).
- ///
- /// `hdtr` specifies an optional list of headers and trailers to be sent before and after
- /// the data read from `in_fd`, respectively. The length of headers and trailers sent is
- /// included in the returned count of bytes written. If any headers are specified and
- /// `count` is non-zero, the length of the headers will be counted in the limit of total
- /// bytes sent. Trailers do not count toward the limit of bytes sent and will always be sent
- /// regardless. The value of `offset` does not affect headers or trailers.
- ///
- /// For more information, see
- /// [the sendfile(2) man page.](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man2/sendfile.2.html)
- pub fn sendfile(
- in_fd: RawFd,
- out_sock: RawFd,
- offset: off_t,
- count: Option<off_t>,
- headers: Option<&[&[u8]]>,
- trailers: Option<&[&[u8]]>
- ) -> (Result<()>, off_t) {
- let mut len = count.unwrap_or(0);
- let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
- let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
- let return_code = unsafe {
- libc::sendfile(in_fd,
- out_sock,
- offset,
- &mut len as *mut off_t,
- hdtr_ptr as *mut libc::sf_hdtr,
- 0)
- };
- (Errno::result(return_code).and(Ok(())), len)
- }
- }
-}
diff --git a/vendor/nix-0.20.0/src/sys/signal.rs b/vendor/nix-0.20.0/src/sys/signal.rs
deleted file mode 100644
index 2f8b5fa..0000000
--- a/vendor/nix-0.20.0/src/sys/signal.rs
+++ /dev/null
@@ -1,1092 +0,0 @@
-// Portions of this file are Copyright 2014 The Rust Project Developers.
-// See http://rust-lang.org/COPYRIGHT.
-
-///! Operating system signals.
-
-use crate::{Error, Result};
-use crate::errno::Errno;
-use crate::unistd::Pid;
-use std::convert::TryFrom;
-use std::mem;
-use std::fmt;
-use std::str::FromStr;
-#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-use std::os::unix::io::RawFd;
-use std::ptr;
-
-#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
-pub use self::sigevent::*;
-
-libc_enum!{
- // Currently there is only one definition of c_int in libc, as well as only one
- // type for signal constants.
- // We would prefer to use the libc::c_int alias in the repr attribute. Unfortunately
- // this is not (yet) possible.
- #[repr(i32)]
- pub enum Signal {
- SIGHUP,
- SIGINT,
- SIGQUIT,
- SIGILL,
- SIGTRAP,
- SIGABRT,
- SIGBUS,
- SIGFPE,
- SIGKILL,
- SIGUSR1,
- SIGSEGV,
- SIGUSR2,
- SIGPIPE,
- SIGALRM,
- SIGTERM,
- #[cfg(all(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux"),
- not(any(target_arch = "mips", target_arch = "mips64",
- target_arch = "sparc64"))))]
- SIGSTKFLT,
- SIGCHLD,
- SIGCONT,
- SIGSTOP,
- SIGTSTP,
- SIGTTIN,
- SIGTTOU,
- SIGURG,
- SIGXCPU,
- SIGXFSZ,
- SIGVTALRM,
- SIGPROF,
- SIGWINCH,
- SIGIO,
- #[cfg(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux"))]
- SIGPWR,
- SIGSYS,
- #[cfg(not(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux",
- target_os = "redox")))]
- SIGEMT,
- #[cfg(not(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux",
- target_os = "redox")))]
- SIGINFO,
- }
-}
-
-impl FromStr for Signal {
- type Err = Error;
- fn from_str(s: &str) -> Result<Signal> {
- Ok(match s {
- "SIGHUP" => Signal::SIGHUP,
- "SIGINT" => Signal::SIGINT,
- "SIGQUIT" => Signal::SIGQUIT,
- "SIGILL" => Signal::SIGILL,
- "SIGTRAP" => Signal::SIGTRAP,
- "SIGABRT" => Signal::SIGABRT,
- "SIGBUS" => Signal::SIGBUS,
- "SIGFPE" => Signal::SIGFPE,
- "SIGKILL" => Signal::SIGKILL,
- "SIGUSR1" => Signal::SIGUSR1,
- "SIGSEGV" => Signal::SIGSEGV,
- "SIGUSR2" => Signal::SIGUSR2,
- "SIGPIPE" => Signal::SIGPIPE,
- "SIGALRM" => Signal::SIGALRM,
- "SIGTERM" => Signal::SIGTERM,
- #[cfg(all(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux"),
- not(any(target_arch = "mips", target_arch = "mips64",
- target_arch = "sparc64"))))]
- "SIGSTKFLT" => Signal::SIGSTKFLT,
- "SIGCHLD" => Signal::SIGCHLD,
- "SIGCONT" => Signal::SIGCONT,
- "SIGSTOP" => Signal::SIGSTOP,
- "SIGTSTP" => Signal::SIGTSTP,
- "SIGTTIN" => Signal::SIGTTIN,
- "SIGTTOU" => Signal::SIGTTOU,
- "SIGURG" => Signal::SIGURG,
- "SIGXCPU" => Signal::SIGXCPU,
- "SIGXFSZ" => Signal::SIGXFSZ,
- "SIGVTALRM" => Signal::SIGVTALRM,
- "SIGPROF" => Signal::SIGPROF,
- "SIGWINCH" => Signal::SIGWINCH,
- "SIGIO" => Signal::SIGIO,
- #[cfg(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux"))]
- "SIGPWR" => Signal::SIGPWR,
- "SIGSYS" => Signal::SIGSYS,
- #[cfg(not(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux",
- target_os = "redox")))]
- "SIGEMT" => Signal::SIGEMT,
- #[cfg(not(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux",
- target_os = "redox")))]
- "SIGINFO" => Signal::SIGINFO,
- _ => return Err(Error::invalid_argument()),
- })
- }
-}
-
-impl Signal {
- /// Returns name of signal.
- ///
- /// This function is equivalent to `<Signal as AsRef<str>>::as_ref()`,
- /// with difference that returned string is `'static`
- /// and not bound to `self`'s lifetime.
- pub fn as_str(self) -> &'static str {
- match self {
- Signal::SIGHUP => "SIGHUP",
- Signal::SIGINT => "SIGINT",
- Signal::SIGQUIT => "SIGQUIT",
- Signal::SIGILL => "SIGILL",
- Signal::SIGTRAP => "SIGTRAP",
- Signal::SIGABRT => "SIGABRT",
- Signal::SIGBUS => "SIGBUS",
- Signal::SIGFPE => "SIGFPE",
- Signal::SIGKILL => "SIGKILL",
- Signal::SIGUSR1 => "SIGUSR1",
- Signal::SIGSEGV => "SIGSEGV",
- Signal::SIGUSR2 => "SIGUSR2",
- Signal::SIGPIPE => "SIGPIPE",
- Signal::SIGALRM => "SIGALRM",
- Signal::SIGTERM => "SIGTERM",
- #[cfg(all(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux"),
- not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
- Signal::SIGSTKFLT => "SIGSTKFLT",
- Signal::SIGCHLD => "SIGCHLD",
- Signal::SIGCONT => "SIGCONT",
- Signal::SIGSTOP => "SIGSTOP",
- Signal::SIGTSTP => "SIGTSTP",
- Signal::SIGTTIN => "SIGTTIN",
- Signal::SIGTTOU => "SIGTTOU",
- Signal::SIGURG => "SIGURG",
- Signal::SIGXCPU => "SIGXCPU",
- Signal::SIGXFSZ => "SIGXFSZ",
- Signal::SIGVTALRM => "SIGVTALRM",
- Signal::SIGPROF => "SIGPROF",
- Signal::SIGWINCH => "SIGWINCH",
- Signal::SIGIO => "SIGIO",
- #[cfg(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux"))]
- Signal::SIGPWR => "SIGPWR",
- Signal::SIGSYS => "SIGSYS",
- #[cfg(not(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux",
- target_os = "redox")))]
- Signal::SIGEMT => "SIGEMT",
- #[cfg(not(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux",
- target_os = "redox")))]
- Signal::SIGINFO => "SIGINFO",
- }
- }
-}
-
-impl AsRef<str> for Signal {
- fn as_ref(&self) -> &str {
- self.as_str()
- }
-}
-
-impl fmt::Display for Signal {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.write_str(self.as_ref())
- }
-}
-
-pub use self::Signal::*;
-
-#[cfg(target_os = "redox")]
-const SIGNALS: [Signal; 29] = [
- SIGHUP,
- SIGINT,
- SIGQUIT,
- SIGILL,
- SIGTRAP,
- SIGABRT,
- SIGBUS,
- SIGFPE,
- SIGKILL,
- SIGUSR1,
- SIGSEGV,
- SIGUSR2,
- SIGPIPE,
- SIGALRM,
- SIGTERM,
- SIGCHLD,
- SIGCONT,
- SIGSTOP,
- SIGTSTP,
- SIGTTIN,
- SIGTTOU,
- SIGURG,
- SIGXCPU,
- SIGXFSZ,
- SIGVTALRM,
- SIGPROF,
- SIGWINCH,
- SIGIO,
- SIGSYS];
-#[cfg(all(any(target_os = "linux", target_os = "android",
- target_os = "emscripten", target_os = "fuchsia"),
- not(any(target_arch = "mips", target_arch = "mips64",
- target_arch = "sparc64"))))]
-const SIGNALS: [Signal; 31] = [
- SIGHUP,
- SIGINT,
- SIGQUIT,
- SIGILL,
- SIGTRAP,
- SIGABRT,
- SIGBUS,
- SIGFPE,
- SIGKILL,
- SIGUSR1,
- SIGSEGV,
- SIGUSR2,
- SIGPIPE,
- SIGALRM,
- SIGTERM,
- SIGSTKFLT,
- SIGCHLD,
- SIGCONT,
- SIGSTOP,
- SIGTSTP,
- SIGTTIN,
- SIGTTOU,
- SIGURG,
- SIGXCPU,
- SIGXFSZ,
- SIGVTALRM,
- SIGPROF,
- SIGWINCH,
- SIGIO,
- SIGPWR,
- SIGSYS];
-#[cfg(all(any(target_os = "linux", target_os = "android",
- target_os = "emscripten", target_os = "fuchsia"),
- any(target_arch = "mips", target_arch = "mips64",
- target_arch = "sparc64")))]
-const SIGNALS: [Signal; 30] = [
- SIGHUP,
- SIGINT,
- SIGQUIT,
- SIGILL,
- SIGTRAP,
- SIGABRT,
- SIGBUS,
- SIGFPE,
- SIGKILL,
- SIGUSR1,
- SIGSEGV,
- SIGUSR2,
- SIGPIPE,
- SIGALRM,
- SIGTERM,
- SIGCHLD,
- SIGCONT,
- SIGSTOP,
- SIGTSTP,
- SIGTTIN,
- SIGTTOU,
- SIGURG,
- SIGXCPU,
- SIGXFSZ,
- SIGVTALRM,
- SIGPROF,
- SIGWINCH,
- SIGIO,
- SIGPWR,
- SIGSYS];
-#[cfg(not(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia", target_os = "emscripten",
- target_os = "redox")))]
-const SIGNALS: [Signal; 31] = [
- SIGHUP,
- SIGINT,
- SIGQUIT,
- SIGILL,
- SIGTRAP,
- SIGABRT,
- SIGBUS,
- SIGFPE,
- SIGKILL,
- SIGUSR1,
- SIGSEGV,
- SIGUSR2,
- SIGPIPE,
- SIGALRM,
- SIGTERM,
- SIGCHLD,
- SIGCONT,
- SIGSTOP,
- SIGTSTP,
- SIGTTIN,
- SIGTTOU,
- SIGURG,
- SIGXCPU,
- SIGXFSZ,
- SIGVTALRM,
- SIGPROF,
- SIGWINCH,
- SIGIO,
- SIGSYS,
- SIGEMT,
- SIGINFO];
-
-pub const NSIG: libc::c_int = 32;
-
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct SignalIterator {
- next: usize,
-}
-
-impl Iterator for SignalIterator {
- type Item = Signal;
-
- fn next(&mut self) -> Option<Signal> {
- if self.next < SIGNALS.len() {
- let next_signal = SIGNALS[self.next];
- self.next += 1;
- Some(next_signal)
- } else {
- None
- }
- }
-}
-
-impl Signal {
- pub fn iterator() -> SignalIterator {
- SignalIterator{next: 0}
- }
-}
-
-impl TryFrom<libc::c_int> for Signal {
- type Error = Error;
-
- fn try_from(signum: libc::c_int) -> Result<Signal> {
- if 0 < signum && signum < NSIG {
- Ok(unsafe { mem::transmute(signum) })
- } else {
- Err(Error::invalid_argument())
- }
- }
-}
-
-pub const SIGIOT : Signal = SIGABRT;
-pub const SIGPOLL : Signal = SIGIO;
-pub const SIGUNUSED : Signal = SIGSYS;
-
-#[cfg(not(target_os = "redox"))]
-type SaFlags_t = libc::c_int;
-#[cfg(target_os = "redox")]
-type SaFlags_t = libc::c_ulong;
-
-libc_bitflags!{
- pub struct SaFlags: SaFlags_t {
- SA_NOCLDSTOP;
- SA_NOCLDWAIT;
- SA_NODEFER;
- SA_ONSTACK;
- SA_RESETHAND;
- SA_RESTART;
- SA_SIGINFO;
- }
-}
-
-libc_enum! {
- #[repr(i32)]
- pub enum SigmaskHow {
- SIG_BLOCK,
- SIG_UNBLOCK,
- SIG_SETMASK,
- }
-}
-
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct SigSet {
- sigset: libc::sigset_t
-}
-
-
-impl SigSet {
- pub fn all() -> SigSet {
- let mut sigset = mem::MaybeUninit::uninit();
- let _ = unsafe { libc::sigfillset(sigset.as_mut_ptr()) };
-
- unsafe{ SigSet { sigset: sigset.assume_init() } }
- }
-
- pub fn empty() -> SigSet {
- let mut sigset = mem::MaybeUninit::uninit();
- let _ = unsafe { libc::sigemptyset(sigset.as_mut_ptr()) };
-
- unsafe{ SigSet { sigset: sigset.assume_init() } }
- }
-
- pub fn add(&mut self, signal: Signal) {
- unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
- }
-
- pub fn clear(&mut self) {
- unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
- }
-
- pub fn remove(&mut self, signal: Signal) {
- unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
- }
-
- pub fn contains(&self, signal: Signal) -> bool {
- let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signal as libc::c_int) };
-
- match res {
- 1 => true,
- 0 => false,
- _ => unreachable!("unexpected value from sigismember"),
- }
- }
-
- pub fn extend(&mut self, other: &SigSet) {
- for signal in Signal::iterator() {
- if other.contains(signal) {
- self.add(signal);
- }
- }
- }
-
- /// Gets the currently blocked (masked) set of signals for the calling thread.
- pub fn thread_get_mask() -> Result<SigSet> {
- let mut oldmask = mem::MaybeUninit::uninit();
- do_pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(oldmask.as_mut_ptr()))?;
- Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}})
- }
-
- /// Sets the set of signals as the signal mask for the calling thread.
- pub fn thread_set_mask(&self) -> Result<()> {
- pthread_sigmask(SigmaskHow::SIG_SETMASK, Some(self), None)
- }
-
- /// Adds the set of signals to the signal mask for the calling thread.
- pub fn thread_block(&self) -> Result<()> {
- pthread_sigmask(SigmaskHow::SIG_BLOCK, Some(self), None)
- }
-
- /// Removes the set of signals from the signal mask for the calling thread.
- pub fn thread_unblock(&self) -> Result<()> {
- pthread_sigmask(SigmaskHow::SIG_UNBLOCK, Some(self), None)
- }
-
- /// Sets the set of signals as the signal mask, and returns the old mask.
- pub fn thread_swap_mask(&self, how: SigmaskHow) -> Result<SigSet> {
- let mut oldmask = mem::MaybeUninit::uninit();
- do_pthread_sigmask(how, Some(self), Some(oldmask.as_mut_ptr()))?;
- Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}})
- }
-
- /// Suspends execution of the calling thread until one of the signals in the
- /// signal mask becomes pending, and returns the accepted signal.
- #[cfg(not(target_os = "redox"))] // RedoxFS does not yet support sigwait
- pub fn wait(&self) -> Result<Signal> {
- let mut signum = mem::MaybeUninit::uninit();
- let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, signum.as_mut_ptr()) };
-
- Errno::result(res).map(|_| unsafe {
- Signal::try_from(signum.assume_init()).unwrap()
- })
- }
-}
-
-impl AsRef<libc::sigset_t> for SigSet {
- fn as_ref(&self) -> &libc::sigset_t {
- &self.sigset
- }
-}
-
-/// A signal handler.
-#[allow(unknown_lints)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum SigHandler {
- /// Default signal handling.
- SigDfl,
- /// Request that the signal be ignored.
- SigIgn,
- /// Use the given signal-catching function, which takes in the signal.
- Handler(extern fn(libc::c_int)),
- /// Use the given signal-catching function, which takes in the signal, information about how
- /// the signal was generated, and a pointer to the threads `ucontext_t`.
- #[cfg(not(target_os = "redox"))]
- SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
-}
-
-/// Action to take on receipt of a signal. Corresponds to `sigaction`.
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct SigAction {
- sigaction: libc::sigaction
-}
-
-impl SigAction {
- /// Creates a new action.
- ///
- /// The `SA_SIGINFO` bit in the `flags` argument is ignored (it will be set only if `handler`
- /// is the `SigAction` variant). `mask` specifies other signals to block during execution of
- /// the signal-catching function.
- pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction {
- #[cfg(target_os = "redox")]
- unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
- (*p).sa_handler = match handler {
- SigHandler::SigDfl => libc::SIG_DFL,
- SigHandler::SigIgn => libc::SIG_IGN,
- SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
- };
- }
-
- #[cfg(not(target_os = "redox"))]
- unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
- (*p).sa_sigaction = match handler {
- SigHandler::SigDfl => libc::SIG_DFL,
- SigHandler::SigIgn => libc::SIG_IGN,
- SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
- SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
- };
- }
-
- let mut s = mem::MaybeUninit::<libc::sigaction>::uninit();
- unsafe {
- let p = s.as_mut_ptr();
- install_sig(p, handler);
- (*p).sa_flags = match handler {
- #[cfg(not(target_os = "redox"))]
- SigHandler::SigAction(_) => (flags | SaFlags::SA_SIGINFO).bits(),
- _ => (flags - SaFlags::SA_SIGINFO).bits(),
- };
- (*p).sa_mask = mask.sigset;
-
- SigAction { sigaction: s.assume_init() }
- }
- }
-
- /// Returns the flags set on the action.
- pub fn flags(&self) -> SaFlags {
- SaFlags::from_bits_truncate(self.sigaction.sa_flags)
- }
-
- /// Returns the set of signals that are blocked during execution of the action's
- /// signal-catching function.
- pub fn mask(&self) -> SigSet {
- SigSet { sigset: self.sigaction.sa_mask }
- }
-
- /// Returns the action's handler.
- #[cfg(not(target_os = "redox"))]
- pub fn handler(&self) -> SigHandler {
- match self.sigaction.sa_sigaction {
- libc::SIG_DFL => SigHandler::SigDfl,
- libc::SIG_IGN => SigHandler::SigIgn,
- f if self.flags().contains(SaFlags::SA_SIGINFO) =>
- SigHandler::SigAction( unsafe { mem::transmute(f) } ),
- f => SigHandler::Handler( unsafe { mem::transmute(f) } ),
- }
- }
-
- /// Returns the action's handler.
- #[cfg(target_os = "redox")]
- pub fn handler(&self) -> SigHandler {
- match self.sigaction.sa_handler {
- libc::SIG_DFL => SigHandler::SigDfl,
- libc::SIG_IGN => SigHandler::SigIgn,
- f => SigHandler::Handler( unsafe { mem::transmute(f) } ),
- }
- }
-}
-
-/// Changes the action taken by a process on receipt of a specific signal.
-///
-/// `signal` can be any signal except `SIGKILL` or `SIGSTOP`. On success, it returns the previous
-/// action for the given signal. If `sigaction` fails, no new signal handler is installed.
-///
-/// # Safety
-///
-/// Signal handlers may be called at any point during execution, which limits what is safe to do in
-/// the body of the signal-catching function. Be certain to only make syscalls that are explicitly
-/// marked safe for signal handlers and only share global data using atomics.
-pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
- let mut oldact = mem::MaybeUninit::<libc::sigaction>::uninit();
-
- let res = libc::sigaction(signal as libc::c_int,
- &sigaction.sigaction as *const libc::sigaction,
- oldact.as_mut_ptr());
-
- Errno::result(res).map(|_| SigAction { sigaction: oldact.assume_init() })
-}
-
-/// Signal management (see [signal(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html))
-///
-/// Installs `handler` for the given `signal`, returning the previous signal
-/// handler. `signal` should only be used following another call to `signal` or
-/// if the current handler is the default. The return value of `signal` is
-/// undefined after setting the handler with [`sigaction`][SigActionFn].
-///
-/// # Safety
-///
-/// If the pointer to the previous signal handler is invalid, undefined
-/// behavior could be invoked when casting it back to a [`SigAction`][SigActionStruct].
-///
-/// # Examples
-///
-/// Ignore `SIGINT`:
-///
-/// ```no_run
-/// # use nix::sys::signal::{self, Signal, SigHandler};
-/// unsafe { signal::signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap();
-/// ```
-///
-/// Use a signal handler to set a flag variable:
-///
-/// ```no_run
-/// # #[macro_use] extern crate lazy_static;
-/// # use std::convert::TryFrom;
-/// # use std::sync::atomic::{AtomicBool, Ordering};
-/// # use nix::sys::signal::{self, Signal, SigHandler};
-/// lazy_static! {
-/// static ref SIGNALED: AtomicBool = AtomicBool::new(false);
-/// }
-///
-/// extern fn handle_sigint(signal: libc::c_int) {
-/// let signal = Signal::try_from(signal).unwrap();
-/// SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed);
-/// }
-///
-/// fn main() {
-/// let handler = SigHandler::Handler(handle_sigint);
-/// unsafe { signal::signal(Signal::SIGINT, handler) }.unwrap();
-/// }
-/// ```
-///
-/// # Errors
-///
-/// Returns [`Error::UnsupportedOperation`] if `handler` is
-/// [`SigAction`][SigActionStruct]. Use [`sigaction`][SigActionFn] instead.
-///
-/// `signal` also returns any error from `libc::signal`, such as when an attempt
-/// is made to catch a signal that cannot be caught or to ignore a signal that
-/// cannot be ignored.
-///
-/// [`Error::UnsupportedOperation`]: ../../enum.Error.html#variant.UnsupportedOperation
-/// [SigActionStruct]: struct.SigAction.html
-/// [sigactionFn]: fn.sigaction.html
-pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler> {
- let signal = signal as libc::c_int;
- let res = match handler {
- SigHandler::SigDfl => libc::signal(signal, libc::SIG_DFL),
- SigHandler::SigIgn => libc::signal(signal, libc::SIG_IGN),
- SigHandler::Handler(handler) => libc::signal(signal, handler as libc::sighandler_t),
- #[cfg(not(target_os = "redox"))]
- SigHandler::SigAction(_) => return Err(Error::UnsupportedOperation),
- };
- Errno::result(res).map(|oldhandler| {
- match oldhandler {
- libc::SIG_DFL => SigHandler::SigDfl,
- libc::SIG_IGN => SigHandler::SigIgn,
- f => SigHandler::Handler(mem::transmute(f)),
- }
- })
-}
-
-fn do_pthread_sigmask(how: SigmaskHow,
- set: Option<&SigSet>,
- oldset: Option<*mut libc::sigset_t>) -> Result<()> {
- if set.is_none() && oldset.is_none() {
- return Ok(())
- }
-
- let res = unsafe {
- // if set or oldset is None, pass in null pointers instead
- libc::pthread_sigmask(how as libc::c_int,
- set.map_or_else(ptr::null::<libc::sigset_t>,
- |s| &s.sigset as *const libc::sigset_t),
- oldset.unwrap_or(ptr::null_mut())
- )
- };
-
- Errno::result(res).map(drop)
-}
-
-/// Manages the signal mask (set of blocked signals) for the calling thread.
-///
-/// If the `set` parameter is `Some(..)`, then the signal mask will be updated with the signal set.
-/// The `how` flag decides the type of update. If `set` is `None`, `how` will be ignored,
-/// and no modification will take place.
-///
-/// If the 'oldset' parameter is `Some(..)` then the current signal mask will be written into it.
-///
-/// If both `set` and `oldset` is `Some(..)`, the current signal mask will be written into oldset,
-/// and then it will be updated with `set`.
-///
-/// If both `set` and `oldset` is None, this function is a no-op.
-///
-/// For more information, visit the [`pthread_sigmask`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html),
-/// or [`sigprocmask`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html) man pages.
-pub fn pthread_sigmask(how: SigmaskHow,
- set: Option<&SigSet>,
- oldset: Option<&mut SigSet>) -> Result<()>
-{
- do_pthread_sigmask(how, set, oldset.map(|os| &mut os.sigset as *mut _ ))
-}
-
-/// Examine and change blocked signals.
-///
-/// For more informations see the [`sigprocmask` man
-/// pages](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html).
-pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut SigSet>) -> Result<()> {
- if set.is_none() && oldset.is_none() {
- return Ok(())
- }
-
- let res = unsafe {
- // if set or oldset is None, pass in null pointers instead
- libc::sigprocmask(how as libc::c_int,
- set.map_or_else(ptr::null::<libc::sigset_t>,
- |s| &s.sigset as *const libc::sigset_t),
- oldset.map_or_else(ptr::null_mut::<libc::sigset_t>,
- |os| &mut os.sigset as *mut libc::sigset_t))
- };
-
- Errno::result(res).map(drop)
-}
-
-pub fn kill<T: Into<Option<Signal>>>(pid: Pid, signal: T) -> Result<()> {
- let res = unsafe { libc::kill(pid.into(),
- match signal.into() {
- Some(s) => s as libc::c_int,
- None => 0,
- }) };
-
- Errno::result(res).map(drop)
-}
-
-/// Send a signal to a process group [(see
-/// killpg(3))](http://pubs.opengroup.org/onlinepubs/9699919799/functions/killpg.html).
-///
-/// If `pgrp` less then or equal 1, the behavior is platform-specific.
-/// If `signal` is `None`, `killpg` will only preform error checking and won't
-/// send any signal.
-#[cfg(not(target_os = "fuchsia"))]
-pub fn killpg<T: Into<Option<Signal>>>(pgrp: Pid, signal: T) -> Result<()> {
- let res = unsafe { libc::killpg(pgrp.into(),
- match signal.into() {
- Some(s) => s as libc::c_int,
- None => 0,
- }) };
-
- Errno::result(res).map(drop)
-}
-
-pub fn raise(signal: Signal) -> Result<()> {
- let res = unsafe { libc::raise(signal as libc::c_int) };
-
- Errno::result(res).map(drop)
-}
-
-
-#[cfg(target_os = "freebsd")]
-pub type type_of_thread_id = libc::lwpid_t;
-#[cfg(target_os = "linux")]
-pub type type_of_thread_id = libc::pid_t;
-
-/// Used to request asynchronous notification of certain events, for example,
-/// with POSIX AIO, POSIX message queues, and POSIX timers.
-// sigval is actually a union of a int and a void*. But it's never really used
-// as a pointer, because neither libc nor the kernel ever dereference it. nix
-// therefore presents it as an intptr_t, which is how kevent uses it.
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum SigevNotify {
- /// No notification will be delivered
- SigevNone,
- /// The signal given by `signal` will be delivered to the process. The
- /// value in `si_value` will be present in the `si_value` field of the
- /// `siginfo_t` structure of the queued signal.
- SigevSignal { signal: Signal, si_value: libc::intptr_t },
- // Note: SIGEV_THREAD is not implemented because libc::sigevent does not
- // expose a way to set the union members needed by SIGEV_THREAD.
- /// A new `kevent` is posted to the kqueue `kq`. The `kevent`'s `udata`
- /// field will contain the value in `udata`.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- SigevKevent { kq: RawFd, udata: libc::intptr_t },
- /// The signal `signal` is queued to the thread whose LWP ID is given in
- /// `thread_id`. The value stored in `si_value` will be present in the
- /// `si_value` of the `siginfo_t` structure of the queued signal.
- #[cfg(any(target_os = "freebsd", target_os = "linux"))]
- SigevThreadId { signal: Signal, thread_id: type_of_thread_id,
- si_value: libc::intptr_t },
-}
-
-#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
-mod sigevent {
- use std::mem;
- use std::ptr;
- use super::SigevNotify;
- #[cfg(any(target_os = "freebsd", target_os = "linux"))]
- use super::type_of_thread_id;
-
- /// Used to request asynchronous notification of the completion of certain
- /// events, such as POSIX AIO and timers.
- #[repr(C)]
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct SigEvent {
- sigevent: libc::sigevent
- }
-
- impl SigEvent {
- /// **Note:** this constructor does not allow the user to set the
- /// `sigev_notify_kevent_flags` field. That's considered ok because on FreeBSD
- /// at least those flags don't do anything useful. That field is part of a
- /// union that shares space with the more genuinely useful fields.
- ///
- /// **Note:** This constructor also doesn't allow the caller to set the
- /// `sigev_notify_function` or `sigev_notify_attributes` fields, which are
- /// required for `SIGEV_THREAD`. That's considered ok because on no operating
- /// system is `SIGEV_THREAD` the most efficient way to deliver AIO
- /// notification. FreeBSD and DragonFly BSD programs should prefer `SIGEV_KEVENT`.
- /// Linux, Solaris, and portable programs should prefer `SIGEV_THREAD_ID` or
- /// `SIGEV_SIGNAL`. That field is part of a union that shares space with the
- /// more genuinely useful `sigev_notify_thread_id`
- pub fn new(sigev_notify: SigevNotify) -> SigEvent {
- // NB: This uses MaybeUninit rather than mem::zeroed because libc::sigevent contains a
- // function pointer on Fuchsia as of https://github.com/rust-lang/libc/commit/2f59370,
- // and function pointers must not be null.
- let mut sev = unsafe { mem::MaybeUninit::<libc::sigevent>::zeroed().assume_init() };
- sev.sigev_notify = match sigev_notify {
- SigevNotify::SigevNone => libc::SIGEV_NONE,
- SigevNotify::SigevSignal{..} => libc::SIGEV_SIGNAL,
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- SigevNotify::SigevKevent{..} => libc::SIGEV_KEVENT,
- #[cfg(target_os = "freebsd")]
- SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
- #[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))]
- SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
- #[cfg(any(all(target_os = "linux", target_env = "musl"), target_arch = "mips"))]
- SigevNotify::SigevThreadId{..} => 4 // No SIGEV_THREAD_ID defined
- };
- sev.sigev_signo = match sigev_notify {
- SigevNotify::SigevSignal{ signal, .. } => signal as libc::c_int,
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- SigevNotify::SigevKevent{ kq, ..} => kq,
- #[cfg(any(target_os = "linux", target_os = "freebsd"))]
- SigevNotify::SigevThreadId{ signal, .. } => signal as libc::c_int,
- _ => 0
- };
- sev.sigev_value.sival_ptr = match sigev_notify {
- SigevNotify::SigevNone => ptr::null_mut::<libc::c_void>(),
- SigevNotify::SigevSignal{ si_value, .. } => si_value as *mut libc::c_void,
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- SigevNotify::SigevKevent{ udata, .. } => udata as *mut libc::c_void,
- #[cfg(any(target_os = "freebsd", target_os = "linux"))]
- SigevNotify::SigevThreadId{ si_value, .. } => si_value as *mut libc::c_void,
- };
- SigEvent::set_tid(&mut sev, &sigev_notify);
- SigEvent{sigevent: sev}
- }
-
- #[cfg(any(target_os = "freebsd", target_os = "linux"))]
- fn set_tid(sev: &mut libc::sigevent, sigev_notify: &SigevNotify) {
- sev.sigev_notify_thread_id = match *sigev_notify {
- SigevNotify::SigevThreadId { thread_id, .. } => thread_id,
- _ => 0 as type_of_thread_id
- };
- }
-
- #[cfg(not(any(target_os = "freebsd", target_os = "linux")))]
- fn set_tid(_sev: &mut libc::sigevent, _sigev_notify: &SigevNotify) {
- }
-
- pub fn sigevent(&self) -> libc::sigevent {
- self.sigevent
- }
- }
-
- impl<'a> From<&'a libc::sigevent> for SigEvent {
- fn from(sigevent: &libc::sigevent) -> Self {
- SigEvent{ sigevent: *sigevent }
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- #[cfg(not(target_os = "redox"))]
- use std::thread;
- use super::*;
-
- #[test]
- fn test_contains() {
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
-
- assert!(mask.contains(SIGUSR1));
- assert!(!mask.contains(SIGUSR2));
-
- let all = SigSet::all();
- assert!(all.contains(SIGUSR1));
- assert!(all.contains(SIGUSR2));
- }
-
- #[test]
- fn test_clear() {
- let mut set = SigSet::all();
- set.clear();
- for signal in Signal::iterator() {
- assert!(!set.contains(signal));
- }
- }
-
- #[test]
- fn test_from_str_round_trips() {
- for signal in Signal::iterator() {
- assert_eq!(signal.as_ref().parse::<Signal>().unwrap(), signal);
- assert_eq!(signal.to_string().parse::<Signal>().unwrap(), signal);
- }
- }
-
- #[test]
- fn test_from_str_invalid_value() {
- let errval = Err(Error::Sys(Errno::EINVAL));
- assert_eq!("NOSIGNAL".parse::<Signal>(), errval);
- assert_eq!("kill".parse::<Signal>(), errval);
- assert_eq!("9".parse::<Signal>(), errval);
- }
-
- #[test]
- fn test_extend() {
- let mut one_signal = SigSet::empty();
- one_signal.add(SIGUSR1);
-
- let mut two_signals = SigSet::empty();
- two_signals.add(SIGUSR2);
- two_signals.extend(&one_signal);
-
- assert!(two_signals.contains(SIGUSR1));
- assert!(two_signals.contains(SIGUSR2));
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_thread_signal_set_mask() {
- thread::spawn(|| {
- let prev_mask = SigSet::thread_get_mask()
- .expect("Failed to get existing signal mask!");
-
- let mut test_mask = prev_mask;
- test_mask.add(SIGUSR1);
-
- assert!(test_mask.thread_set_mask().is_ok());
- let new_mask = SigSet::thread_get_mask()
- .expect("Failed to get new mask!");
-
- assert!(new_mask.contains(SIGUSR1));
- assert!(!new_mask.contains(SIGUSR2));
-
- prev_mask.thread_set_mask().expect("Failed to revert signal mask!");
- }).join().unwrap();
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_thread_signal_block() {
- thread::spawn(|| {
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
-
- assert!(mask.thread_block().is_ok());
-
- assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
- }).join().unwrap();
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_thread_signal_unblock() {
- thread::spawn(|| {
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
-
- assert!(mask.thread_unblock().is_ok());
-
- assert!(!SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
- }).join().unwrap();
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_thread_signal_swap() {
- thread::spawn(|| {
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
- mask.thread_block().unwrap();
-
- assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
-
- let mut mask2 = SigSet::empty();
- mask2.add(SIGUSR2);
-
- let oldmask = mask2.thread_swap_mask(SigmaskHow::SIG_SETMASK)
- .unwrap();
-
- assert!(oldmask.contains(SIGUSR1));
- assert!(!oldmask.contains(SIGUSR2));
-
- assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR2));
- }).join().unwrap();
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_sigaction() {
- thread::spawn(|| {
- extern fn test_sigaction_handler(_: libc::c_int) {}
- extern fn test_sigaction_action(_: libc::c_int,
- _: *mut libc::siginfo_t, _: *mut libc::c_void) {}
-
- let handler_sig = SigHandler::Handler(test_sigaction_handler);
-
- let flags = SaFlags::SA_ONSTACK | SaFlags::SA_RESTART |
- SaFlags::SA_SIGINFO;
-
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
-
- let action_sig = SigAction::new(handler_sig, flags, mask);
-
- assert_eq!(action_sig.flags(),
- SaFlags::SA_ONSTACK | SaFlags::SA_RESTART);
- assert_eq!(action_sig.handler(), handler_sig);
-
- mask = action_sig.mask();
- assert!(mask.contains(SIGUSR1));
- assert!(!mask.contains(SIGUSR2));
-
- let handler_act = SigHandler::SigAction(test_sigaction_action);
- let action_act = SigAction::new(handler_act, flags, mask);
- assert_eq!(action_act.handler(), handler_act);
-
- let action_dfl = SigAction::new(SigHandler::SigDfl, flags, mask);
- assert_eq!(action_dfl.handler(), SigHandler::SigDfl);
-
- let action_ign = SigAction::new(SigHandler::SigIgn, flags, mask);
- assert_eq!(action_ign.handler(), SigHandler::SigIgn);
- }).join().unwrap();
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_sigwait() {
- thread::spawn(|| {
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
- mask.add(SIGUSR2);
- mask.thread_block().unwrap();
-
- raise(SIGUSR1).unwrap();
- assert_eq!(mask.wait().unwrap(), SIGUSR1);
- }).join().unwrap();
- }
-}
diff --git a/vendor/nix-0.20.0/src/sys/signalfd.rs b/vendor/nix-0.20.0/src/sys/signalfd.rs
deleted file mode 100644
index c43b450..0000000
--- a/vendor/nix-0.20.0/src/sys/signalfd.rs
+++ /dev/null
@@ -1,178 +0,0 @@
-//! Interface for the `signalfd` syscall.
-//!
-//! # Signal discarding
-//! When a signal can't be delivered to a process (or thread), it will become a pending signal.
-//! Failure to deliver could happen if the signal is blocked by every thread in the process or if
-//! the signal handler is still handling a previous signal.
-//!
-//! If a signal is sent to a process (or thread) that already has a pending signal of the same
-//! type, it will be discarded. This means that if signals of the same type are received faster than
-//! they are processed, some of those signals will be dropped. Because of this limitation,
-//! `signalfd` in itself cannot be used for reliable communication between processes or threads.
-//!
-//! Once the signal is unblocked, or the signal handler is finished, and a signal is still pending
-//! (ie. not consumed from a signalfd) it will be delivered to the signal handler.
-//!
-//! Please note that signal discarding is not specific to `signalfd`, but also happens with regular
-//! signal handlers.
-use libc;
-use crate::unistd;
-use crate::{Error, Result};
-use crate::errno::Errno;
-pub use crate::sys::signal::{self, SigSet};
-pub use libc::signalfd_siginfo as siginfo;
-
-use std::os::unix::io::{RawFd, AsRawFd};
-use std::mem;
-
-
-libc_bitflags!{
- pub struct SfdFlags: libc::c_int {
- SFD_NONBLOCK;
- SFD_CLOEXEC;
- }
-}
-
-pub const SIGNALFD_NEW: RawFd = -1;
-pub const SIGNALFD_SIGINFO_SIZE: usize = 128;
-
-/// Creates a new file descriptor for reading signals.
-///
-/// **Important:** please read the module level documentation about signal discarding before using
-/// this function!
-///
-/// The `mask` parameter specifies the set of signals that can be accepted via this file descriptor.
-///
-/// A signal must be blocked on every thread in a process, otherwise it won't be visible from
-/// signalfd (the default handler will be invoked instead).
-///
-/// See [the signalfd man page for more information](http://man7.org/linux/man-pages/man2/signalfd.2.html)
-pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result<RawFd> {
- unsafe {
- Errno::result(libc::signalfd(fd as libc::c_int, mask.as_ref(), flags.bits()))
- }
-}
-
-/// A helper struct for creating, reading and closing a `signalfd` instance.
-///
-/// **Important:** please read the module level documentation about signal discarding before using
-/// this struct!
-///
-/// # Examples
-///
-/// ```
-/// # use nix::sys::signalfd::*;
-/// // Set the thread to block the SIGUSR1 signal, otherwise the default handler will be used
-/// let mut mask = SigSet::empty();
-/// mask.add(signal::SIGUSR1);
-/// mask.thread_block().unwrap();
-///
-/// // Signals are queued up on the file descriptor
-/// let mut sfd = SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap();
-///
-/// match sfd.read_signal() {
-/// // we caught a signal
-/// Ok(Some(sig)) => (),
-/// // there were no signals waiting (only happens when the SFD_NONBLOCK flag is set,
-/// // otherwise the read_signal call blocks)
-/// Ok(None) => (),
-/// Err(err) => (), // some error happend
-/// }
-/// ```
-#[derive(Debug, Eq, Hash, PartialEq)]
-pub struct SignalFd(RawFd);
-
-impl SignalFd {
- pub fn new(mask: &SigSet) -> Result<SignalFd> {
- Self::with_flags(mask, SfdFlags::empty())
- }
-
- pub fn with_flags(mask: &SigSet, flags: SfdFlags) -> Result<SignalFd> {
- let fd = signalfd(SIGNALFD_NEW, mask, flags)?;
-
- Ok(SignalFd(fd))
- }
-
- pub fn set_mask(&mut self, mask: &SigSet) -> Result<()> {
- signalfd(self.0, mask, SfdFlags::empty()).map(drop)
- }
-
- pub fn read_signal(&mut self) -> Result<Option<siginfo>> {
- let mut buffer = mem::MaybeUninit::<[u8; SIGNALFD_SIGINFO_SIZE]>::uninit();
-
- let res = Errno::result(unsafe {
- libc::read(self.0,
- buffer.as_mut_ptr() as *mut libc::c_void,
- SIGNALFD_SIGINFO_SIZE as libc::size_t)
- }).map(|r| r as usize);
- match res {
- Ok(SIGNALFD_SIGINFO_SIZE) => Ok(Some(unsafe { mem::transmute(buffer.assume_init()) })),
- Ok(_) => unreachable!("partial read on signalfd"),
- Err(Error::Sys(Errno::EAGAIN)) => Ok(None),
- Err(error) => Err(error)
- }
- }
-}
-
-impl Drop for SignalFd {
- fn drop(&mut self) {
- let e = unistd::close(self.0);
- if !std::thread::panicking() && e == Err(Error::Sys(Errno::EBADF)) {
- panic!("Closing an invalid file descriptor!");
- };
- }
-}
-
-impl AsRawFd for SignalFd {
- fn as_raw_fd(&self) -> RawFd {
- self.0
- }
-}
-
-impl Iterator for SignalFd {
- type Item = siginfo;
-
- fn next(&mut self) -> Option<Self::Item> {
- match self.read_signal() {
- Ok(Some(sig)) => Some(sig),
- Ok(None) | Err(_) => None,
- }
- }
-}
-
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use std::mem;
- use libc;
-
-
- #[test]
- fn check_siginfo_size() {
- assert_eq!(mem::size_of::<libc::signalfd_siginfo>(), SIGNALFD_SIGINFO_SIZE);
- }
-
- #[test]
- fn create_signalfd() {
- let mask = SigSet::empty();
- let fd = SignalFd::new(&mask);
- assert!(fd.is_ok());
- }
-
- #[test]
- fn create_signalfd_with_opts() {
- let mask = SigSet::empty();
- let fd = SignalFd::with_flags(&mask, SfdFlags::SFD_CLOEXEC | SfdFlags::SFD_NONBLOCK);
- assert!(fd.is_ok());
- }
-
- #[test]
- fn read_empty_signalfd() {
- let mask = SigSet::empty();
- let mut fd = SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap();
-
- let res = fd.read_signal();
- assert!(res.unwrap().is_none());
- }
-}
diff --git a/vendor/nix-0.20.0/src/sys/socket/addr.rs b/vendor/nix-0.20.0/src/sys/socket/addr.rs
deleted file mode 100644
index 2299c57..0000000
--- a/vendor/nix-0.20.0/src/sys/socket/addr.rs
+++ /dev/null
@@ -1,1340 +0,0 @@
-use super::sa_family_t;
-use crate::{Error, Result, NixPath};
-use crate::errno::Errno;
-use std::{fmt, mem, net, ptr, slice};
-use std::ffi::OsStr;
-use std::hash::{Hash, Hasher};
-use std::path::Path;
-use std::os::unix::ffi::OsStrExt;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-use crate::sys::socket::addr::netlink::NetlinkAddr;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-use crate::sys::socket::addr::alg::AlgAddr;
-#[cfg(any(target_os = "ios", target_os = "macos"))]
-use std::os::unix::io::RawFd;
-#[cfg(any(target_os = "ios", target_os = "macos"))]
-use crate::sys::socket::addr::sys_control::SysControlAddr;
-#[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "fuchsia"))]
-pub use self::datalink::LinkAddr;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use self::vsock::VsockAddr;
-
-/// These constants specify the protocol family to be used
-/// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
-#[repr(i32)]
-#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
-pub enum AddressFamily {
- /// Local communication (see [`unix(7)`](http://man7.org/linux/man-pages/man7/unix.7.html))
- Unix = libc::AF_UNIX,
- /// IPv4 Internet protocols (see [`ip(7)`](http://man7.org/linux/man-pages/man7/ip.7.html))
- Inet = libc::AF_INET,
- /// IPv6 Internet protocols (see [`ipv6(7)`](http://man7.org/linux/man-pages/man7/ipv6.7.html))
- Inet6 = libc::AF_INET6,
- /// Kernel user interface device (see [`netlink(7)`](http://man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Netlink = libc::AF_NETLINK,
- /// Low level packet interface (see [`packet(7)`](http://man7.org/linux/man-pages/man7/packet.7.html))
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))]
- Packet = libc::AF_PACKET,
- /// KEXT Controls and Notifications
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- System = libc::AF_SYSTEM,
- /// Amateur radio AX.25 protocol
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Ax25 = libc::AF_AX25,
- /// IPX - Novell protocols
- Ipx = libc::AF_IPX,
- /// AppleTalk
- AppleTalk = libc::AF_APPLETALK,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- NetRom = libc::AF_NETROM,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Bridge = libc::AF_BRIDGE,
- /// Access to raw ATM PVCs
- #[cfg(any(target_os = "android", target_os = "linux"))]
- AtmPvc = libc::AF_ATMPVC,
- /// ITU-T X.25 / ISO-8208 protocol (see [`x25(7)`](http://man7.org/linux/man-pages/man7/x25.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- X25 = libc::AF_X25,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Rose = libc::AF_ROSE,
- Decnet = libc::AF_DECnet,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- NetBeui = libc::AF_NETBEUI,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Security = libc::AF_SECURITY,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Key = libc::AF_KEY,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Ash = libc::AF_ASH,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Econet = libc::AF_ECONET,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- AtmSvc = libc::AF_ATMSVC,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Rds = libc::AF_RDS,
- Sna = libc::AF_SNA,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Irda = libc::AF_IRDA,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Pppox = libc::AF_PPPOX,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Wanpipe = libc::AF_WANPIPE,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Llc = libc::AF_LLC,
- #[cfg(target_os = "linux")]
- Ib = libc::AF_IB,
- #[cfg(target_os = "linux")]
- Mpls = libc::AF_MPLS,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Can = libc::AF_CAN,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Tipc = libc::AF_TIPC,
- #[cfg(not(any(target_os = "ios", target_os = "macos")))]
- Bluetooth = libc::AF_BLUETOOTH,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Iucv = libc::AF_IUCV,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- RxRpc = libc::AF_RXRPC,
- Isdn = libc::AF_ISDN,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Phonet = libc::AF_PHONET,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Ieee802154 = libc::AF_IEEE802154,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Caif = libc::AF_CAIF,
- /// Interface to kernel crypto API
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Alg = libc::AF_ALG,
- #[cfg(target_os = "linux")]
- Nfc = libc::AF_NFC,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Vsock = libc::AF_VSOCK,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- ImpLink = libc::AF_IMPLINK,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- Pup = libc::AF_PUP,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- Chaos = libc::AF_CHAOS,
- #[cfg(any(target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- Ns = libc::AF_NS,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- Iso = libc::AF_ISO,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- Datakit = libc::AF_DATAKIT,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- Ccitt = libc::AF_CCITT,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- Dli = libc::AF_DLI,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- Lat = libc::AF_LAT,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- Hylink = libc::AF_HYLINK,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- Link = libc::AF_LINK,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- Coip = libc::AF_COIP,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- Cnt = libc::AF_CNT,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- Natm = libc::AF_NATM,
- /// Unspecified address family, (see [`getaddrinfo(3)`](http://man7.org/linux/man-pages/man3/getaddrinfo.3.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Unspec = libc::AF_UNSPEC,
-}
-
-impl AddressFamily {
- /// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from
- /// the `sa_family` field of a `sockaddr`.
- ///
- /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link/Packet
- /// and System. Returns None for unsupported or unknown address families.
- pub fn from_i32(family: i32) -> Option<AddressFamily> {
- match family {
- libc::AF_UNIX => Some(AddressFamily::Unix),
- libc::AF_INET => Some(AddressFamily::Inet),
- libc::AF_INET6 => Some(AddressFamily::Inet6),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_NETLINK => Some(AddressFamily::Netlink),
- #[cfg(any(target_os = "macos", target_os = "macos"))]
- libc::AF_SYSTEM => Some(AddressFamily::System),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_PACKET => Some(AddressFamily::Packet),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- libc::AF_LINK => Some(AddressFamily::Link),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_VSOCK => Some(AddressFamily::Vsock),
- _ => None
- }
- }
-}
-
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum InetAddr {
- V4(libc::sockaddr_in),
- V6(libc::sockaddr_in6),
-}
-
-impl InetAddr {
- pub fn from_std(std: &net::SocketAddr) -> InetAddr {
- match *std {
- net::SocketAddr::V4(ref addr) => {
- InetAddr::V4(libc::sockaddr_in {
- sin_family: AddressFamily::Inet as sa_family_t,
- sin_port: addr.port().to_be(), // network byte order
- sin_addr: Ipv4Addr::from_std(addr.ip()).0,
- .. unsafe { mem::zeroed() }
- })
- }
- net::SocketAddr::V6(ref addr) => {
- InetAddr::V6(libc::sockaddr_in6 {
- sin6_family: AddressFamily::Inet6 as sa_family_t,
- sin6_port: addr.port().to_be(), // network byte order
- sin6_addr: Ipv6Addr::from_std(addr.ip()).0,
- sin6_flowinfo: addr.flowinfo(), // host byte order
- sin6_scope_id: addr.scope_id(), // host byte order
- .. unsafe { mem::zeroed() }
- })
- }
- }
- }
-
- pub fn new(ip: IpAddr, port: u16) -> InetAddr {
- match ip {
- IpAddr::V4(ref ip) => {
- InetAddr::V4(libc::sockaddr_in {
- sin_family: AddressFamily::Inet as sa_family_t,
- sin_port: port.to_be(),
- sin_addr: ip.0,
- .. unsafe { mem::zeroed() }
- })
- }
- IpAddr::V6(ref ip) => {
- InetAddr::V6(libc::sockaddr_in6 {
- sin6_family: AddressFamily::Inet6 as sa_family_t,
- sin6_port: port.to_be(),
- sin6_addr: ip.0,
- .. unsafe { mem::zeroed() }
- })
- }
- }
- }
- /// Gets the IP address associated with this socket address.
- pub fn ip(&self) -> IpAddr {
- match *self {
- InetAddr::V4(ref sa) => IpAddr::V4(Ipv4Addr(sa.sin_addr)),
- InetAddr::V6(ref sa) => IpAddr::V6(Ipv6Addr(sa.sin6_addr)),
- }
- }
-
- /// Gets the port number associated with this socket address
- pub fn port(&self) -> u16 {
- match *self {
- InetAddr::V6(ref sa) => u16::from_be(sa.sin6_port),
- InetAddr::V4(ref sa) => u16::from_be(sa.sin_port),
- }
- }
-
- pub fn to_std(&self) -> net::SocketAddr {
- match *self {
- InetAddr::V4(ref sa) => net::SocketAddr::V4(
- net::SocketAddrV4::new(
- Ipv4Addr(sa.sin_addr).to_std(),
- self.port())),
- InetAddr::V6(ref sa) => net::SocketAddr::V6(
- net::SocketAddrV6::new(
- Ipv6Addr(sa.sin6_addr).to_std(),
- self.port(),
- sa.sin6_flowinfo,
- sa.sin6_scope_id)),
- }
- }
-
- pub fn to_str(&self) -> String {
- format!("{}", self)
- }
-}
-
-impl fmt::Display for InetAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- InetAddr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()),
- InetAddr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()),
- }
- }
-}
-
-/*
- *
- * ===== IpAddr =====
- *
- */
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum IpAddr {
- V4(Ipv4Addr),
- V6(Ipv6Addr),
-}
-
-impl IpAddr {
- /// Create a new IpAddr that contains an IPv4 address.
- ///
- /// The result will represent the IP address a.b.c.d
- pub fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr {
- IpAddr::V4(Ipv4Addr::new(a, b, c, d))
- }
-
- /// Create a new IpAddr that contains an IPv6 address.
- ///
- /// The result will represent the IP address a:b:c:d:e:f
- #[allow(clippy::many_single_char_names)]
- #[allow(clippy::too_many_arguments)]
- pub fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr {
- IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h))
- }
-
- pub fn from_std(std: &net::IpAddr) -> IpAddr {
- match *std {
- net::IpAddr::V4(ref std) => IpAddr::V4(Ipv4Addr::from_std(std)),
- net::IpAddr::V6(ref std) => IpAddr::V6(Ipv6Addr::from_std(std)),
- }
- }
-
- pub fn to_std(&self) -> net::IpAddr {
- match *self {
- IpAddr::V4(ref ip) => net::IpAddr::V4(ip.to_std()),
- IpAddr::V6(ref ip) => net::IpAddr::V6(ip.to_std()),
- }
- }
-}
-
-impl fmt::Display for IpAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- IpAddr::V4(ref v4) => v4.fmt(f),
- IpAddr::V6(ref v6) => v6.fmt(f)
- }
- }
-}
-
-/*
- *
- * ===== Ipv4Addr =====
- *
- */
-
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct Ipv4Addr(pub libc::in_addr);
-
-impl Ipv4Addr {
- #[allow(clippy::identity_op)] // More readable this way
- pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
- let ip = ((u32::from(a) << 24) |
- (u32::from(b) << 16) |
- (u32::from(c) << 8) |
- (u32::from(d) << 0)).to_be();
-
- Ipv4Addr(libc::in_addr { s_addr: ip })
- }
-
- // Use pass by reference for symmetry with Ipv6Addr::from_std
- #[allow(clippy::trivially_copy_pass_by_ref)]
- pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr {
- let bits = std.octets();
- Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
- }
-
- pub fn any() -> Ipv4Addr {
- Ipv4Addr(libc::in_addr { s_addr: libc::INADDR_ANY })
- }
-
- pub fn octets(self) -> [u8; 4] {
- let bits = u32::from_be(self.0.s_addr);
- [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
- }
-
- pub fn to_std(self) -> net::Ipv4Addr {
- let bits = self.octets();
- net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
- }
-}
-
-impl fmt::Display for Ipv4Addr {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- let octets = self.octets();
- write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
- }
-}
-
-/*
- *
- * ===== Ipv6Addr =====
- *
- */
-
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct Ipv6Addr(pub libc::in6_addr);
-
-// Note that IPv6 addresses are stored in big endian order on all architectures.
-// See https://tools.ietf.org/html/rfc1700 or consult your favorite search
-// engine.
-
-macro_rules! to_u8_array {
- ($($num:ident),*) => {
- [ $(($num>>8) as u8, ($num&0xff) as u8,)* ]
- }
-}
-
-macro_rules! to_u16_array {
- ($slf:ident, $($first:expr, $second:expr),*) => {
- [$( (($slf.0.s6_addr[$first] as u16) << 8) + $slf.0.s6_addr[$second] as u16,)*]
- }
-}
-
-impl Ipv6Addr {
- #[allow(clippy::many_single_char_names)]
- #[allow(clippy::too_many_arguments)]
- pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
- Ipv6Addr(libc::in6_addr{s6_addr: to_u8_array!(a,b,c,d,e,f,g,h)})
- }
-
- pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr {
- let s = std.segments();
- Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
- }
-
- /// Return the eight 16-bit segments that make up this address
- pub fn segments(&self) -> [u16; 8] {
- to_u16_array!(self, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
- }
-
- pub fn to_std(&self) -> net::Ipv6Addr {
- let s = self.segments();
- net::Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
- }
-}
-
-impl fmt::Display for Ipv6Addr {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- self.to_std().fmt(fmt)
- }
-}
-
-/// A wrapper around `sockaddr_un`.
-///
-/// This also tracks the length of `sun_path` address (excluding
-/// a terminating null), because it may not be null-terminated. For example,
-/// unconnected and Linux abstract sockets are never null-terminated, and POSIX
-/// does not require that `sun_len` include the terminating null even for normal
-/// sockets. Note that the actual sockaddr length is greater by
-/// `offset_of!(libc::sockaddr_un, sun_path)`
-#[derive(Clone, Copy, Debug)]
-pub struct UnixAddr(pub libc::sockaddr_un, pub usize);
-
-impl UnixAddr {
- /// Create a new sockaddr_un representing a filesystem path.
- pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> {
- path.with_nix_path(|cstr| {
- unsafe {
- let mut ret = libc::sockaddr_un {
- sun_family: AddressFamily::Unix as sa_family_t,
- .. mem::zeroed()
- };
-
- let bytes = cstr.to_bytes();
-
- if bytes.len() > ret.sun_path.len() {
- return Err(Error::Sys(Errno::ENAMETOOLONG));
- }
-
- ptr::copy_nonoverlapping(bytes.as_ptr(),
- ret.sun_path.as_mut_ptr() as *mut u8,
- bytes.len());
-
- Ok(UnixAddr(ret, bytes.len()))
- }
- })?
- }
-
- /// Create a new `sockaddr_un` representing an address in the "abstract namespace".
- ///
- /// The leading null byte for the abstract namespace is automatically added;
- /// thus the input `path` is expected to be the bare name, not null-prefixed.
- /// This is a Linux-specific extension, primarily used to allow chrooted
- /// processes to communicate with processes having a different filesystem view.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> {
- unsafe {
- let mut ret = libc::sockaddr_un {
- sun_family: AddressFamily::Unix as sa_family_t,
- .. mem::zeroed()
- };
-
- if path.len() + 1 > ret.sun_path.len() {
- return Err(Error::Sys(Errno::ENAMETOOLONG));
- }
-
- // Abstract addresses are represented by sun_path[0] ==
- // b'\0', so copy starting one byte in.
- ptr::copy_nonoverlapping(path.as_ptr(),
- ret.sun_path.as_mut_ptr().offset(1) as *mut u8,
- path.len());
-
- Ok(UnixAddr(ret, path.len() + 1))
- }
- }
-
- fn sun_path(&self) -> &[u8] {
- unsafe { slice::from_raw_parts(self.0.sun_path.as_ptr() as *const u8, self.1) }
- }
-
- /// If this address represents a filesystem path, return that path.
- pub fn path(&self) -> Option<&Path> {
- if self.1 == 0 || self.0.sun_path[0] == 0 {
- // unnamed or abstract
- None
- } else {
- let p = self.sun_path();
- // POSIX only requires that `sun_len` be at least long enough to
- // contain the pathname, and it need not be null-terminated. So we
- // need to create a string that is the shorter of the
- // null-terminated length or the full length.
- let ptr = &self.0.sun_path as *const libc::c_char;
- let reallen = unsafe { libc::strnlen(ptr, p.len()) };
- Some(Path::new(<OsStr as OsStrExt>::from_bytes(&p[..reallen])))
- }
- }
-
- /// If this address represents an abstract socket, return its name.
- ///
- /// For abstract sockets only the bare name is returned, without the
- /// leading null byte. `None` is returned for unnamed or path-backed sockets.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- pub fn as_abstract(&self) -> Option<&[u8]> {
- if self.1 >= 1 && self.0.sun_path[0] == 0 {
- Some(&self.sun_path()[1..])
- } else {
- // unnamed or filesystem path
- None
- }
- }
-}
-
-impl fmt::Display for UnixAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- if self.1 == 0 {
- f.write_str("<unbound UNIX socket>")
- } else if let Some(path) = self.path() {
- path.display().fmt(f)
- } else {
- let display = String::from_utf8_lossy(&self.sun_path()[1..]);
- write!(f, "@{}", display)
- }
- }
-}
-
-impl PartialEq for UnixAddr {
- fn eq(&self, other: &UnixAddr) -> bool {
- self.sun_path() == other.sun_path()
- }
-}
-
-impl Eq for UnixAddr {}
-
-impl Hash for UnixAddr {
- fn hash<H: Hasher>(&self, s: &mut H) {
- ( self.0.sun_family, self.sun_path() ).hash(s)
- }
-}
-
-/// Represents a socket address
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum SockAddr {
- Inet(InetAddr),
- Unix(UnixAddr),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Netlink(NetlinkAddr),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Alg(AlgAddr),
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- SysControl(SysControlAddr),
- /// Datalink address (MAC)
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- Link(LinkAddr),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Vsock(VsockAddr),
-}
-
-impl SockAddr {
- pub fn new_inet(addr: InetAddr) -> SockAddr {
- SockAddr::Inet(addr)
- }
-
- pub fn new_unix<P: ?Sized + NixPath>(path: &P) -> Result<SockAddr> {
- Ok(SockAddr::Unix(UnixAddr::new(path)?))
- }
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- pub fn new_netlink(pid: u32, groups: u32) -> SockAddr {
- SockAddr::Netlink(NetlinkAddr::new(pid, groups))
- }
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- pub fn new_alg(alg_type: &str, alg_name: &str) -> SockAddr {
- SockAddr::Alg(AlgAddr::new(alg_type, alg_name))
- }
-
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr> {
- SysControlAddr::from_name(sockfd, name, unit).map(|a| SockAddr::SysControl(a))
- }
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- pub fn new_vsock(cid: u32, port: u32) -> SockAddr {
- SockAddr::Vsock(VsockAddr::new(cid, port))
- }
-
- pub fn family(&self) -> AddressFamily {
- match *self {
- SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet,
- SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6,
- SockAddr::Unix(..) => AddressFamily::Unix,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Netlink(..) => AddressFamily::Netlink,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Alg(..) => AddressFamily::Alg,
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- SockAddr::SysControl(..) => AddressFamily::System,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Link(..) => AddressFamily::Packet,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- SockAddr::Link(..) => AddressFamily::Link,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Vsock(..) => AddressFamily::Vsock,
- }
- }
-
- pub fn to_str(&self) -> String {
- format!("{}", self)
- }
-
- /// Creates a `SockAddr` struct from libc's sockaddr.
- ///
- /// Supports only the following address families: Unix, Inet (v4 & v6), Netlink and System.
- /// Returns None for unsupported families.
- ///
- /// # Safety
- ///
- /// unsafe because it takes a raw pointer as argument. The caller must
- /// ensure that the pointer is valid.
- #[cfg(not(target_os = "fuchsia"))]
- pub(crate) unsafe fn from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr> {
- if addr.is_null() {
- None
- } else {
- match AddressFamily::from_i32(i32::from((*addr).sa_family)) {
- Some(AddressFamily::Unix) => None,
- Some(AddressFamily::Inet) => Some(SockAddr::Inet(
- InetAddr::V4(*(addr as *const libc::sockaddr_in)))),
- Some(AddressFamily::Inet6) => Some(SockAddr::Inet(
- InetAddr::V6(*(addr as *const libc::sockaddr_in6)))),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Some(AddressFamily::Netlink) => Some(SockAddr::Netlink(
- NetlinkAddr(*(addr as *const libc::sockaddr_nl)))),
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- Some(AddressFamily::System) => Some(SockAddr::SysControl(
- SysControlAddr(*(addr as *const libc::sockaddr_ctl)))),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Some(AddressFamily::Packet) => Some(SockAddr::Link(
- LinkAddr(*(addr as *const libc::sockaddr_ll)))),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- Some(AddressFamily::Link) => {
- let ether_addr = LinkAddr(*(addr as *const libc::sockaddr_dl));
- if ether_addr.is_empty() {
- None
- } else {
- Some(SockAddr::Link(ether_addr))
- }
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(
- VsockAddr(*(addr as *const libc::sockaddr_vm)))),
- // Other address families are currently not supported and simply yield a None
- // entry instead of a proper conversion to a `SockAddr`.
- Some(_) | None => None,
- }
- }
- }
-
- /// Conversion from nix's SockAddr type to the underlying libc sockaddr type.
- ///
- /// This is useful for interfacing with other libc functions that don't yet have nix wrappers.
- /// Returns a reference to the underlying data type (as a sockaddr reference) along
- /// with the size of the actual data type. sockaddr is commonly used as a proxy for
- /// a superclass as C doesn't support inheritance, so many functions that take
- /// a sockaddr * need to take the size of the underlying type as well and then internally cast it back.
- pub fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
- match *self {
- SockAddr::Inet(InetAddr::V4(ref addr)) => (
- // This cast is always allowed in C
- unsafe {
- &*(addr as *const libc::sockaddr_in as *const libc::sockaddr)
- },
- mem::size_of_val(addr) as libc::socklen_t
- ),
- SockAddr::Inet(InetAddr::V6(ref addr)) => (
- // This cast is always allowed in C
- unsafe {
- &*(addr as *const libc::sockaddr_in6 as *const libc::sockaddr)
- },
- mem::size_of_val(addr) as libc::socklen_t
- ),
- SockAddr::Unix(UnixAddr(ref addr, len)) => (
- // This cast is always allowed in C
- unsafe {
- &*(addr as *const libc::sockaddr_un as *const libc::sockaddr)
- },
- (len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t
- ),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Netlink(NetlinkAddr(ref sa)) => (
- // This cast is always allowed in C
- unsafe {
- &*(sa as *const libc::sockaddr_nl as *const libc::sockaddr)
- },
- mem::size_of_val(sa) as libc::socklen_t
- ),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Alg(AlgAddr(ref sa)) => (
- // This cast is always allowed in C
- unsafe {
- &*(sa as *const libc::sockaddr_alg as *const libc::sockaddr)
- },
- mem::size_of_val(sa) as libc::socklen_t
- ),
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- SockAddr::SysControl(SysControlAddr(ref sa)) => (
- // This cast is always allowed in C
- unsafe {
- &*(sa as *const libc::sockaddr_ctl as *const libc::sockaddr)
- },
- mem::size_of_val(sa) as libc::socklen_t
-
- ),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Link(LinkAddr(ref addr)) => (
- // This cast is always allowed in C
- unsafe {
- &*(addr as *const libc::sockaddr_ll as *const libc::sockaddr)
- },
- mem::size_of_val(addr) as libc::socklen_t
- ),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- SockAddr::Link(LinkAddr(ref addr)) => (
- // This cast is always allowed in C
- unsafe {
- &*(addr as *const libc::sockaddr_dl as *const libc::sockaddr)
- },
- mem::size_of_val(addr) as libc::socklen_t
- ),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Vsock(VsockAddr(ref sa)) => (
- // This cast is always allowed in C
- unsafe {
- &*(sa as *const libc::sockaddr_vm as *const libc::sockaddr)
- },
- mem::size_of_val(sa) as libc::socklen_t
- ),
- }
- }
-}
-
-impl fmt::Display for SockAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- SockAddr::Inet(ref inet) => inet.fmt(f),
- SockAddr::Unix(ref unix) => unix.fmt(f),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Netlink(ref nl) => nl.fmt(f),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Alg(ref nl) => nl.fmt(f),
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- SockAddr::SysControl(ref sc) => sc.fmt(f),
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- SockAddr::Link(ref ether_addr) => ether_addr.fmt(f),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Vsock(ref svm) => svm.fmt(f),
- }
- }
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub mod netlink {
- use crate::sys::socket::addr::AddressFamily;
- use libc::{sa_family_t, sockaddr_nl};
- use std::{fmt, mem};
-
- #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
- pub struct NetlinkAddr(pub sockaddr_nl);
-
- impl NetlinkAddr {
- pub fn new(pid: u32, groups: u32) -> NetlinkAddr {
- let mut addr: sockaddr_nl = unsafe { mem::zeroed() };
- addr.nl_family = AddressFamily::Netlink as sa_family_t;
- addr.nl_pid = pid;
- addr.nl_groups = groups;
-
- NetlinkAddr(addr)
- }
-
- pub fn pid(&self) -> u32 {
- self.0.nl_pid
- }
-
- pub fn groups(&self) -> u32 {
- self.0.nl_groups
- }
- }
-
- impl fmt::Display for NetlinkAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "pid: {} groups: {}", self.pid(), self.groups())
- }
- }
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub mod alg {
- use libc::{AF_ALG, sockaddr_alg, c_char};
- use std::{fmt, mem, str};
- use std::hash::{Hash, Hasher};
- use std::ffi::CStr;
-
- #[derive(Copy, Clone)]
- pub struct AlgAddr(pub sockaddr_alg);
-
- // , PartialEq, Eq, Debug, Hash
- impl PartialEq for AlgAddr {
- fn eq(&self, other: &Self) -> bool {
- let (inner, other) = (self.0, other.0);
- (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]) ==
- (other.salg_family, &other.salg_type[..], other.salg_feat, other.salg_mask, &other.salg_name[..])
- }
- }
-
- impl Eq for AlgAddr {}
-
- impl Hash for AlgAddr {
- fn hash<H: Hasher>(&self, s: &mut H) {
- let inner = self.0;
- (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]).hash(s);
- }
- }
-
- impl AlgAddr {
- pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr {
- let mut addr: sockaddr_alg = unsafe { mem::zeroed() };
- addr.salg_family = AF_ALG as u16;
- addr.salg_type[..alg_type.len()].copy_from_slice(alg_type.to_string().as_bytes());
- addr.salg_name[..alg_name.len()].copy_from_slice(alg_name.to_string().as_bytes());
-
- AlgAddr(addr)
- }
-
-
- pub fn alg_type(&self) -> &CStr {
- unsafe { CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char) }
- }
-
- pub fn alg_name(&self) -> &CStr {
- unsafe { CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char) }
- }
- }
-
- impl fmt::Display for AlgAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "type: {} alg: {}",
- self.alg_name().to_string_lossy(),
- self.alg_type().to_string_lossy())
- }
- }
-
- impl fmt::Debug for AlgAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Display::fmt(self, f)
- }
- }
-}
-
-#[cfg(any(target_os = "ios", target_os = "macos"))]
-pub mod sys_control {
- use crate::sys::socket::addr::AddressFamily;
- use libc::{self, c_uchar};
- use std::{fmt, mem};
- use std::os::unix::io::RawFd;
- use crate::{Errno, Error, Result};
-
- // FIXME: Move type into `libc`
- #[repr(C)]
- #[derive(Clone, Copy)]
- #[allow(missing_debug_implementations)]
- pub struct ctl_ioc_info {
- pub ctl_id: u32,
- pub ctl_name: [c_uchar; MAX_KCTL_NAME],
- }
-
- const CTL_IOC_MAGIC: u8 = 'N' as u8;
- const CTL_IOC_INFO: u8 = 3;
- const MAX_KCTL_NAME: usize = 96;
-
- ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info);
-
- #[repr(C)]
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct SysControlAddr(pub libc::sockaddr_ctl);
-
- impl SysControlAddr {
- pub fn new(id: u32, unit: u32) -> SysControlAddr {
- let addr = libc::sockaddr_ctl {
- sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar,
- sc_family: AddressFamily::System as c_uchar,
- ss_sysaddr: libc::AF_SYS_CONTROL as u16,
- sc_id: id,
- sc_unit: unit,
- sc_reserved: [0; 5]
- };
-
- SysControlAddr(addr)
- }
-
- pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> {
- if name.len() > MAX_KCTL_NAME {
- return Err(Error::Sys(Errno::ENAMETOOLONG));
- }
-
- let mut ctl_name = [0; MAX_KCTL_NAME];
- ctl_name[..name.len()].clone_from_slice(name.as_bytes());
- let mut info = ctl_ioc_info { ctl_id: 0, ctl_name };
-
- unsafe { ctl_info(sockfd, &mut info)?; }
-
- Ok(SysControlAddr::new(info.ctl_id, unit))
- }
-
- pub fn id(&self) -> u32 {
- self.0.sc_id
- }
-
- pub fn unit(&self) -> u32 {
- self.0.sc_unit
- }
- }
-
- impl fmt::Display for SysControlAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Debug::fmt(self, f)
- }
- }
-}
-
-
-#[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))]
-mod datalink {
- use super::{fmt, AddressFamily};
-
- /// Hardware Address
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct LinkAddr(pub libc::sockaddr_ll);
-
- impl LinkAddr {
- /// Always AF_PACKET
- pub fn family(&self) -> AddressFamily {
- assert_eq!(self.0.sll_family as i32, libc::AF_PACKET);
- AddressFamily::Packet
- }
-
- /// Physical-layer protocol
- pub fn protocol(&self) -> u16 {
- self.0.sll_protocol
- }
-
- /// Interface number
- pub fn ifindex(&self) -> usize {
- self.0.sll_ifindex as usize
- }
-
- /// ARP hardware type
- pub fn hatype(&self) -> u16 {
- self.0.sll_hatype
- }
-
- /// Packet type
- pub fn pkttype(&self) -> u8 {
- self.0.sll_pkttype
- }
-
- /// Length of MAC address
- pub fn halen(&self) -> usize {
- self.0.sll_halen as usize
- }
-
- /// Physical-layer address (MAC)
- pub fn addr(&self) -> [u8; 6] {
- [
- self.0.sll_addr[0] as u8,
- self.0.sll_addr[1] as u8,
- self.0.sll_addr[2] as u8,
- self.0.sll_addr[3] as u8,
- self.0.sll_addr[4] as u8,
- self.0.sll_addr[5] as u8,
- ]
- }
- }
-
- impl fmt::Display for LinkAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let addr = self.addr();
- write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
- addr[0],
- addr[1],
- addr[2],
- addr[3],
- addr[4],
- addr[5])
- }
- }
-}
-
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
-mod datalink {
- use super::{fmt, AddressFamily};
-
- /// Hardware Address
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct LinkAddr(pub libc::sockaddr_dl);
-
- impl LinkAddr {
- /// Total length of sockaddr
- pub fn len(&self) -> usize {
- self.0.sdl_len as usize
- }
-
- /// always == AF_LINK
- pub fn family(&self) -> AddressFamily {
- assert_eq!(i32::from(self.0.sdl_family), libc::AF_LINK);
- AddressFamily::Link
- }
-
- /// interface index, if != 0, system given index for interface
- pub fn ifindex(&self) -> usize {
- self.0.sdl_index as usize
- }
-
- /// Datalink type
- pub fn datalink_type(&self) -> u8 {
- self.0.sdl_type
- }
-
- // MAC address start position
- pub fn nlen(&self) -> usize {
- self.0.sdl_nlen as usize
- }
-
- /// link level address length
- pub fn alen(&self) -> usize {
- self.0.sdl_alen as usize
- }
-
- /// link layer selector length
- pub fn slen(&self) -> usize {
- self.0.sdl_slen as usize
- }
-
- /// if link level address length == 0,
- /// or `sdl_data` not be larger.
- pub fn is_empty(&self) -> bool {
- let nlen = self.nlen();
- let alen = self.alen();
- let data_len = self.0.sdl_data.len();
-
- alen == 0 || nlen + alen >= data_len
- }
-
- /// Physical-layer address (MAC)
- pub fn addr(&self) -> [u8; 6] {
- let nlen = self.nlen();
- let data = self.0.sdl_data;
-
- assert!(!self.is_empty());
-
- [
- data[nlen] as u8,
- data[nlen + 1] as u8,
- data[nlen + 2] as u8,
- data[nlen + 3] as u8,
- data[nlen + 4] as u8,
- data[nlen + 5] as u8,
- ]
- }
- }
-
- impl fmt::Display for LinkAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let addr = self.addr();
- write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
- addr[0],
- addr[1],
- addr[2],
- addr[3],
- addr[4],
- addr[5])
- }
- }
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub mod vsock {
- use crate::sys::socket::addr::AddressFamily;
- use libc::{sa_family_t, sockaddr_vm};
- use std::{fmt, mem};
- use std::hash::{Hash, Hasher};
-
- #[derive(Copy, Clone)]
- pub struct VsockAddr(pub sockaddr_vm);
-
- impl PartialEq for VsockAddr {
- fn eq(&self, other: &Self) -> bool {
- let (inner, other) = (self.0, other.0);
- (inner.svm_family, inner.svm_cid, inner.svm_port) ==
- (other.svm_family, other.svm_cid, other.svm_port)
- }
- }
-
- impl Eq for VsockAddr {}
-
- impl Hash for VsockAddr {
- fn hash<H: Hasher>(&self, s: &mut H) {
- let inner = self.0;
- (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s);
- }
- }
-
- /// VSOCK Address
- ///
- /// The address for AF_VSOCK socket is defined as a combination of a
- /// 32-bit Context Identifier (CID) and a 32-bit port number.
- impl VsockAddr {
- pub fn new(cid: u32, port: u32) -> VsockAddr {
- let mut addr: sockaddr_vm = unsafe { mem::zeroed() };
- addr.svm_family = AddressFamily::Vsock as sa_family_t;
- addr.svm_cid = cid;
- addr.svm_port = port;
-
- VsockAddr(addr)
- }
-
- /// Context Identifier (CID)
- pub fn cid(&self) -> u32 {
- self.0.svm_cid
- }
-
- /// Port number
- pub fn port(&self) -> u32 {
- self.0.svm_port
- }
- }
-
- impl fmt::Display for VsockAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "cid: {} port: {}", self.cid(), self.port())
- }
- }
-
- impl fmt::Debug for VsockAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Display::fmt(self, f)
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- use super::*;
-
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[test]
- fn test_macos_loopback_datalink_addr() {
- let bytes = [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
- let sa = bytes.as_ptr() as *const libc::sockaddr;
- let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
- assert!(_sock_addr.is_none());
- }
-
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[test]
- fn test_macos_tap_datalink_addr() {
- let bytes = [20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35, 76, -80];
- let ptr = bytes.as_ptr();
- let sa = ptr as *const libc::sockaddr;
- let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
-
- assert!(_sock_addr.is_some());
-
- let sock_addr = _sock_addr.unwrap();
-
- assert_eq!(sock_addr.family(), AddressFamily::Link);
-
- match sock_addr {
- SockAddr::Link(ether_addr) => {
- assert_eq!(ether_addr.addr(), [24u8, 101, 144, 221, 76, 176]);
- },
- _ => { unreachable!() }
- };
- }
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[test]
- fn test_abstract_sun_path() {
- let name = String::from("nix\0abstract\0test");
- let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
-
- let sun_path1 = addr.sun_path();
- let sun_path2 = [0u8, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116];
- assert_eq!(sun_path1.len(), sun_path2.len());
- for i in 0..sun_path1.len() {
- assert_eq!(sun_path1[i], sun_path2[i]);
- }
- }
-}
diff --git a/vendor/nix-0.20.0/src/sys/socket/mod.rs b/vendor/nix-0.20.0/src/sys/socket/mod.rs
deleted file mode 100644
index 11ed329..0000000
--- a/vendor/nix-0.20.0/src/sys/socket/mod.rs
+++ /dev/null
@@ -1,1767 +0,0 @@
-//! Socket interface functions
-//!
-//! [Further reading](http://man7.org/linux/man-pages/man7/socket.7.html)
-use cfg_if::cfg_if;
-use crate::{Error, Result, errno::Errno};
-use libc::{self, c_void, c_int, iovec, socklen_t, size_t,
- CMSG_FIRSTHDR, CMSG_NXTHDR, CMSG_DATA, CMSG_LEN};
-use std::{mem, ptr, slice};
-use std::os::unix::io::RawFd;
-use crate::sys::time::TimeVal;
-use crate::sys::uio::IoVec;
-
-mod addr;
-pub mod sockopt;
-
-/*
- *
- * ===== Re-exports =====
- *
- */
-
-pub use self::addr::{
- AddressFamily,
- SockAddr,
- InetAddr,
- UnixAddr,
- IpAddr,
- Ipv4Addr,
- Ipv6Addr,
- LinkAddr,
-};
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use crate::sys::socket::addr::netlink::NetlinkAddr;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use crate::sys::socket::addr::alg::AlgAddr;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use crate::sys::socket::addr::vsock::VsockAddr;
-
-pub use libc::{
- cmsghdr,
- msghdr,
- sa_family_t,
- sockaddr,
- sockaddr_in,
- sockaddr_in6,
- sockaddr_storage,
- sockaddr_un,
-};
-
-// Needed by the cmsg_space macro
-#[doc(hidden)]
-pub use libc::{c_uint, CMSG_SPACE};
-
-/// These constants are used to specify the communication semantics
-/// when creating a socket with [`socket()`](fn.socket.html)
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
-#[repr(i32)]
-pub enum SockType {
- /// Provides sequenced, reliable, two-way, connection-
- /// based byte streams. An out-of-band data transmission
- /// mechanism may be supported.
- Stream = libc::SOCK_STREAM,
- /// Supports datagrams (connectionless, unreliable
- /// messages of a fixed maximum length).
- Datagram = libc::SOCK_DGRAM,
- /// Provides a sequenced, reliable, two-way connection-
- /// based data transmission path for datagrams of fixed
- /// maximum length; a consumer is required to read an
- /// entire packet with each input system call.
- SeqPacket = libc::SOCK_SEQPACKET,
- /// Provides raw network protocol access.
- Raw = libc::SOCK_RAW,
- /// Provides a reliable datagram layer that does not
- /// guarantee ordering.
- Rdm = libc::SOCK_RDM,
-}
-
-/// Constants used in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
-/// to specify the protocol to use.
-#[repr(i32)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum SockProtocol {
- /// TCP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html))
- Tcp = libc::IPPROTO_TCP,
- /// UDP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html))
- Udp = libc::IPPROTO_UDP,
- /// Allows applications and other KEXTs to be notified when certain kernel events occur
- /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- KextEvent = libc::SYSPROTO_EVENT,
- /// Allows applications to configure and control a KEXT
- /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- KextControl = libc::SYSPROTO_CONTROL,
- /// Receives routing and link updates and may be used to modify the routing tables (both IPv4 and IPv6), IP addresses, link
- // parameters, neighbor setups, queueing disciplines, traffic classes and packet classifiers
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- NetlinkRoute = libc::NETLINK_ROUTE,
- /// Reserved for user-mode socket protocols
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- NetlinkUserSock = libc::NETLINK_USERSOCK,
- /// Query information about sockets of various protocol families from the kernel
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- NetlinkSockDiag = libc::NETLINK_SOCK_DIAG,
- /// SELinux event notifications.
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- NetlinkSELinux = libc::NETLINK_SELINUX,
- /// Open-iSCSI
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- NetlinkISCSI = libc::NETLINK_ISCSI,
- /// Auditing
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- NetlinkAudit = libc::NETLINK_AUDIT,
- /// Access to FIB lookup from user space
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- NetlinkFIBLookup = libc::NETLINK_FIB_LOOKUP,
- /// Netfilter subsystem
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- NetlinkNetFilter = libc::NETLINK_NETFILTER,
- /// SCSI Transports
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- NetlinkSCSITransport = libc::NETLINK_SCSITRANSPORT,
- /// Infiniband RDMA
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- NetlinkRDMA = libc::NETLINK_RDMA,
- /// Transport IPv6 packets from netfilter to user space. Used by ip6_queue kernel module.
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- NetlinkIPv6Firewall = libc::NETLINK_IP6_FW,
- /// DECnet routing messages
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- NetlinkDECNetRoutingMessage = libc::NETLINK_DNRTMSG,
- /// Kernel messages to user space
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- NetlinkKObjectUEvent = libc::NETLINK_KOBJECT_UEVENT,
- /// Netlink interface to request information about ciphers registered with the kernel crypto API as well as allow
- /// configuration of the kernel crypto API.
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- NetlinkCrypto = libc::NETLINK_CRYPTO,
-}
-
-libc_bitflags!{
- /// Additional socket options
- pub struct SockFlag: c_int {
- /// Set non-blocking mode on the new socket
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
- SOCK_NONBLOCK;
- /// Set close-on-exec on the new descriptor
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
- SOCK_CLOEXEC;
- /// Return `EPIPE` instead of raising `SIGPIPE`
- #[cfg(target_os = "netbsd")]
- SOCK_NOSIGPIPE;
- /// For domains `AF_INET(6)`, only allow `connect(2)`, `sendto(2)`, or `sendmsg(2)`
- /// to the DNS port (typically 53)
- #[cfg(target_os = "openbsd")]
- SOCK_DNS;
- }
-}
-
-libc_bitflags!{
- /// Flags for send/recv and their relatives
- pub struct MsgFlags: c_int {
- /// Sends or requests out-of-band data on sockets that support this notion
- /// (e.g., of type [`Stream`](enum.SockType.html)); the underlying protocol must also
- /// support out-of-band data.
- MSG_OOB;
- /// Peeks at an incoming message. The data is treated as unread and the next
- /// [`recv()`](fn.recv.html)
- /// or similar function shall still return this data.
- MSG_PEEK;
- /// Receive operation blocks until the full amount of data can be
- /// returned. The function may return smaller amount of data if a signal
- /// is caught, an error or disconnect occurs.
- MSG_WAITALL;
- /// Enables nonblocking operation; if the operation would block,
- /// `EAGAIN` or `EWOULDBLOCK` is returned. This provides similar
- /// behavior to setting the `O_NONBLOCK` flag
- /// (via the [`fcntl`](../../fcntl/fn.fcntl.html)
- /// `F_SETFL` operation), but differs in that `MSG_DONTWAIT` is a per-
- /// call option, whereas `O_NONBLOCK` is a setting on the open file
- /// description (see [open(2)](http://man7.org/linux/man-pages/man2/open.2.html)),
- /// which will affect all threads in
- /// the calling process and as well as other processes that hold
- /// file descriptors referring to the same open file description.
- MSG_DONTWAIT;
- /// Receive flags: Control Data was discarded (buffer too small)
- MSG_CTRUNC;
- /// For raw ([`Packet`](addr/enum.AddressFamily.html)), Internet datagram
- /// (since Linux 2.4.27/2.6.8),
- /// netlink (since Linux 2.6.22) and UNIX datagram (since Linux 3.4)
- /// sockets: return the real length of the packet or datagram, even
- /// when it was longer than the passed buffer. Not implemented for UNIX
- /// domain ([unix(7)](https://linux.die.net/man/7/unix)) sockets.
- ///
- /// For use with Internet stream sockets, see [tcp(7)](https://linux.die.net/man/7/tcp).
- MSG_TRUNC;
- /// Terminates a record (when this notion is supported, as for
- /// sockets of type [`SeqPacket`](enum.SockType.html)).
- MSG_EOR;
- /// This flag specifies that queued errors should be received from
- /// the socket error queue. (For more details, see
- /// [recvfrom(2)](https://linux.die.net/man/2/recvfrom))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- MSG_ERRQUEUE;
- /// Set the `close-on-exec` flag for the file descriptor received via a UNIX domain
- /// file descriptor using the `SCM_RIGHTS` operation (described in
- /// [unix(7)](https://linux.die.net/man/7/unix)).
- /// This flag is useful for the same reasons as the `O_CLOEXEC` flag of
- /// [open(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html).
- ///
- /// Only used in [`recvmsg`](fn.recvmsg.html) function.
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
- MSG_CMSG_CLOEXEC;
- }
-}
-
-cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
- /// Unix credentials of the sending process.
- ///
- /// This struct is used with the `SO_PEERCRED` ancillary message
- /// and the `SCM_CREDENTIALS` control message for UNIX sockets.
- #[repr(transparent)]
- #[derive(Clone, Copy, Debug, Eq, PartialEq)]
- pub struct UnixCredentials(libc::ucred);
-
- impl UnixCredentials {
- /// Creates a new instance with the credentials of the current process
- pub fn new() -> Self {
- UnixCredentials(libc::ucred {
- pid: crate::unistd::getpid().as_raw(),
- uid: crate::unistd::getuid().as_raw(),
- gid: crate::unistd::getgid().as_raw(),
- })
- }
-
- /// Returns the process identifier
- pub fn pid(&self) -> libc::pid_t {
- self.0.pid
- }
-
- /// Returns the user identifier
- pub fn uid(&self) -> libc::uid_t {
- self.0.uid
- }
-
- /// Returns the group identifier
- pub fn gid(&self) -> libc::gid_t {
- self.0.gid
- }
- }
-
- impl Default for UnixCredentials {
- fn default() -> Self {
- Self::new()
- }
- }
-
- impl From<libc::ucred> for UnixCredentials {
- fn from(cred: libc::ucred) -> Self {
- UnixCredentials(cred)
- }
- }
-
- impl Into<libc::ucred> for UnixCredentials {
- fn into(self) -> libc::ucred {
- self.0
- }
- }
- } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] {
- /// Unix credentials of the sending process.
- ///
- /// This struct is used with the `SCM_CREDS` ancillary message for UNIX sockets.
- #[repr(transparent)]
- #[derive(Clone, Copy, Debug, Eq, PartialEq)]
- pub struct UnixCredentials(libc::cmsgcred);
-
- impl UnixCredentials {
- /// Returns the process identifier
- pub fn pid(&self) -> libc::pid_t {
- self.0.cmcred_pid
- }
-
- /// Returns the real user identifier
- pub fn uid(&self) -> libc::uid_t {
- self.0.cmcred_uid
- }
-
- /// Returns the effective user identifier
- pub fn euid(&self) -> libc::uid_t {
- self.0.cmcred_euid
- }
-
- /// Returns the real group identifier
- pub fn gid(&self) -> libc::gid_t {
- self.0.cmcred_gid
- }
-
- /// Returns a list group identifiers (the first one being the effective GID)
- pub fn groups(&self) -> &[libc::gid_t] {
- unsafe { slice::from_raw_parts(self.0.cmcred_groups.as_ptr() as *const libc::gid_t, self.0.cmcred_ngroups as _) }
- }
- }
-
- impl From<libc::cmsgcred> for UnixCredentials {
- fn from(cred: libc::cmsgcred) -> Self {
- UnixCredentials(cred)
- }
- }
- }
-}
-
-/// Request for multicast socket operations
-///
-/// This is a wrapper type around `ip_mreq`.
-#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub struct IpMembershipRequest(libc::ip_mreq);
-
-impl IpMembershipRequest {
- /// Instantiate a new `IpMembershipRequest`
- ///
- /// If `interface` is `None`, then `Ipv4Addr::any()` will be used for the interface.
- pub fn new(group: Ipv4Addr, interface: Option<Ipv4Addr>) -> Self {
- IpMembershipRequest(libc::ip_mreq {
- imr_multiaddr: group.0,
- imr_interface: interface.unwrap_or_else(Ipv4Addr::any).0,
- })
- }
-}
-
-/// Request for ipv6 multicast socket operations
-///
-/// This is a wrapper type around `ipv6_mreq`.
-#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub struct Ipv6MembershipRequest(libc::ipv6_mreq);
-
-impl Ipv6MembershipRequest {
- /// Instantiate a new `Ipv6MembershipRequest`
- pub fn new(group: Ipv6Addr) -> Self {
- Ipv6MembershipRequest(libc::ipv6_mreq {
- ipv6mr_multiaddr: group.0,
- ipv6mr_interface: 0,
- })
- }
-}
-
-/// Create a buffer large enough for storing some control messages as returned
-/// by [`recvmsg`](fn.recvmsg.html).
-///
-/// # Examples
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// # use nix::sys::time::TimeVal;
-/// # use std::os::unix::io::RawFd;
-/// # fn main() {
-/// // Create a buffer for a `ControlMessageOwned::ScmTimestamp` message
-/// let _ = cmsg_space!(TimeVal);
-/// // Create a buffer big enough for a `ControlMessageOwned::ScmRights` message
-/// // with two file descriptors
-/// let _ = cmsg_space!([RawFd; 2]);
-/// // Create a buffer big enough for a `ControlMessageOwned::ScmRights` message
-/// // and a `ControlMessageOwned::ScmTimestamp` message
-/// let _ = cmsg_space!(RawFd, TimeVal);
-/// # }
-/// ```
-// Unfortunately, CMSG_SPACE isn't a const_fn, or else we could return a
-// stack-allocated array.
-#[macro_export]
-macro_rules! cmsg_space {
- ( $( $x:ty ),* ) => {
- {
- use nix::sys::socket::{c_uint, CMSG_SPACE};
- use std::mem;
- let mut space = 0;
- $(
- // CMSG_SPACE is always safe
- space += unsafe {
- CMSG_SPACE(mem::size_of::<$x>() as c_uint)
- } as usize;
- )*
- Vec::<u8>::with_capacity(space)
- }
- }
-}
-
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub struct RecvMsg<'a> {
- pub bytes: usize,
- cmsghdr: Option<&'a cmsghdr>,
- pub address: Option<SockAddr>,
- pub flags: MsgFlags,
- mhdr: msghdr,
-}
-
-impl<'a> RecvMsg<'a> {
- /// Iterate over the valid control messages pointed to by this
- /// msghdr.
- pub fn cmsgs(&self) -> CmsgIterator {
- CmsgIterator {
- cmsghdr: self.cmsghdr,
- mhdr: &self.mhdr
- }
- }
-}
-
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub struct CmsgIterator<'a> {
- /// Control message buffer to decode from. Must adhere to cmsg alignment.
- cmsghdr: Option<&'a cmsghdr>,
- mhdr: &'a msghdr
-}
-
-impl<'a> Iterator for CmsgIterator<'a> {
- type Item = ControlMessageOwned;
-
- fn next(&mut self) -> Option<ControlMessageOwned> {
- match self.cmsghdr {
- None => None, // No more messages
- Some(hdr) => {
- // Get the data.
- // Safe if cmsghdr points to valid data returned by recvmsg(2)
- let cm = unsafe { Some(ControlMessageOwned::decode_from(hdr))};
- // Advance the internal pointer. Safe if mhdr and cmsghdr point
- // to valid data returned by recvmsg(2)
- self.cmsghdr = unsafe {
- let p = CMSG_NXTHDR(self.mhdr as *const _, hdr as *const _);
- p.as_ref()
- };
- cm
- }
- }
- }
-}
-
-/// A type-safe wrapper around a single control message, as used with
-/// [`recvmsg`](#fn.recvmsg).
-///
-/// [Further reading](http://man7.org/linux/man-pages/man3/cmsg.3.html)
-// Nix version 0.13.0 and earlier used ControlMessage for both recvmsg and
-// sendmsg. However, on some platforms the messages returned by recvmsg may be
-// unaligned. ControlMessageOwned takes those messages by copy, obviating any
-// alignment issues.
-//
-// See https://github.com/nix-rust/nix/issues/999
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub enum ControlMessageOwned {
- /// Received version of
- /// [`ControlMessage::ScmRights`][#enum.ControlMessage.html#variant.ScmRights]
- ScmRights(Vec<RawFd>),
- /// Received version of
- /// [`ControlMessage::ScmCredentials`][#enum.ControlMessage.html#variant.ScmCredentials]
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ScmCredentials(UnixCredentials),
- /// Received version of
- /// [`ControlMessage::ScmCreds`][#enum.ControlMessage.html#variant.ScmCreds]
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- ScmCreds(UnixCredentials),
- /// A message of type `SCM_TIMESTAMP`, containing the time the
- /// packet was received by the kernel.
- ///
- /// See the kernel's explanation in "SO_TIMESTAMP" of
- /// [networking/timestamping](https://www.kernel.org/doc/Documentation/networking/timestamping.txt).
- ///
- /// # Examples
- ///
- /// # #[macro_use] extern crate nix;
- /// # use nix::sys::socket::*;
- /// # use nix::sys::uio::IoVec;
- /// # use nix::sys::time::*;
- /// # use std::time::*;
- /// # fn main() {
- /// // Set up
- /// let message = "Ohayō!".as_bytes();
- /// let in_socket = socket(
- /// AddressFamily::Inet,
- /// SockType::Datagram,
- /// SockFlag::empty(),
- /// None).unwrap();
- /// setsockopt(in_socket, sockopt::ReceiveTimestamp, &true).unwrap();
- /// let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0);
- /// bind(in_socket, &SockAddr::new_inet(localhost)).unwrap();
- /// let address = getsockname(in_socket).unwrap();
- /// // Get initial time
- /// let time0 = SystemTime::now();
- /// // Send the message
- /// let iov = [IoVec::from_slice(message)];
- /// let flags = MsgFlags::empty();
- /// let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap();
- /// assert_eq!(message.len(), l);
- /// // Receive the message
- /// let mut buffer = vec![0u8; message.len()];
- /// let mut cmsgspace = cmsg_space!(TimeVal);
- /// let iov = [IoVec::from_mut_slice(&mut buffer)];
- /// let r = recvmsg(in_socket, &iov, Some(&mut cmsgspace), flags).unwrap();
- /// let rtime = match r.cmsgs().next() {
- /// Some(ControlMessageOwned::ScmTimestamp(rtime)) => rtime,
- /// Some(_) => panic!("Unexpected control message"),
- /// None => panic!("No control message")
- /// };
- /// // Check the final time
- /// let time1 = SystemTime::now();
- /// // the packet's received timestamp should lie in-between the two system
- /// // times, unless the system clock was adjusted in the meantime.
- /// let rduration = Duration::new(rtime.tv_sec() as u64,
- /// rtime.tv_usec() as u32 * 1000);
- /// assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration);
- /// assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap());
- /// // Close socket
- /// nix::unistd::close(in_socket).unwrap();
- /// # }
- /// ```
- ScmTimestamp(TimeVal),
- #[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- ))]
- Ipv4PacketInfo(libc::in_pktinfo),
- #[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "openbsd",
- target_os = "netbsd",
- ))]
- Ipv6PacketInfo(libc::in6_pktinfo),
- #[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- ))]
- Ipv4RecvIf(libc::sockaddr_dl),
- #[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- ))]
- Ipv4RecvDstAddr(libc::in_addr),
-
- /// UDP Generic Receive Offload (GRO) allows receiving multiple UDP
- /// packets from a single sender.
- /// Fixed-size payloads are following one by one in a receive buffer.
- /// This Control Message indicates the size of all smaller packets,
- /// except, maybe, the last one.
- ///
- /// `UdpGroSegment` socket option should be enabled on a socket
- /// to allow receiving GRO packets.
- #[cfg(target_os = "linux")]
- UdpGroSegments(u16),
-
- /// Catch-all variant for unimplemented cmsg types.
- #[doc(hidden)]
- Unknown(UnknownCmsg),
-}
-
-impl ControlMessageOwned {
- /// Decodes a `ControlMessageOwned` from raw bytes.
- ///
- /// This is only safe to call if the data is correct for the message type
- /// specified in the header. Normally, the kernel ensures that this is the
- /// case. "Correct" in this case includes correct length, alignment and
- /// actual content.
- // Clippy complains about the pointer alignment of `p`, not understanding
- // that it's being fed to a function that can handle that.
- #[allow(clippy::cast_ptr_alignment)]
- unsafe fn decode_from(header: &cmsghdr) -> ControlMessageOwned
- {
- let p = CMSG_DATA(header);
- let len = header as *const _ as usize + header.cmsg_len as usize
- - p as usize;
- match (header.cmsg_level, header.cmsg_type) {
- (libc::SOL_SOCKET, libc::SCM_RIGHTS) => {
- let n = len / mem::size_of::<RawFd>();
- let mut fds = Vec::with_capacity(n);
- for i in 0..n {
- let fdp = (p as *const RawFd).add(i);
- fds.push(ptr::read_unaligned(fdp));
- }
- ControlMessageOwned::ScmRights(fds)
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- (libc::SOL_SOCKET, libc::SCM_CREDENTIALS) => {
- let cred: libc::ucred = ptr::read_unaligned(p as *const _);
- ControlMessageOwned::ScmCredentials(cred.into())
- }
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- (libc::SOL_SOCKET, libc::SCM_CREDS) => {
- let cred: libc::cmsgcred = ptr::read_unaligned(p as *const _);
- ControlMessageOwned::ScmCreds(cred.into())
- }
- (libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => {
- let tv: libc::timeval = ptr::read_unaligned(p as *const _);
- ControlMessageOwned::ScmTimestamp(TimeVal::from(tv))
- },
- #[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"
- ))]
- (libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => {
- let info = ptr::read_unaligned(p as *const libc::in6_pktinfo);
- ControlMessageOwned::Ipv6PacketInfo(info)
- }
- #[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- ))]
- (libc::IPPROTO_IP, libc::IP_PKTINFO) => {
- let info = ptr::read_unaligned(p as *const libc::in_pktinfo);
- ControlMessageOwned::Ipv4PacketInfo(info)
- }
- #[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- ))]
- (libc::IPPROTO_IP, libc::IP_RECVIF) => {
- let dl = ptr::read_unaligned(p as *const libc::sockaddr_dl);
- ControlMessageOwned::Ipv4RecvIf(dl)
- },
- #[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- ))]
- (libc::IPPROTO_IP, libc::IP_RECVDSTADDR) => {
- let dl = ptr::read_unaligned(p as *const libc::in_addr);
- ControlMessageOwned::Ipv4RecvDstAddr(dl)
- },
- #[cfg(target_os = "linux")]
- (libc::SOL_UDP, libc::UDP_GRO) => {
- let gso_size: u16 = ptr::read_unaligned(p as *const _);
- ControlMessageOwned::UdpGroSegments(gso_size)
- },
- (_, _) => {
- let sl = slice::from_raw_parts(p, len);
- let ucmsg = UnknownCmsg(*header, Vec::<u8>::from(&sl[..]));
- ControlMessageOwned::Unknown(ucmsg)
- }
- }
- }
-}
-
-/// A type-safe zero-copy wrapper around a single control message, as used wih
-/// [`sendmsg`](#fn.sendmsg). More types may be added to this enum; do not
-/// exhaustively pattern-match it.
-///
-/// [Further reading](http://man7.org/linux/man-pages/man3/cmsg.3.html)
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub enum ControlMessage<'a> {
- /// A message of type `SCM_RIGHTS`, containing an array of file
- /// descriptors passed between processes.
- ///
- /// See the description in the "Ancillary messages" section of the
- /// [unix(7) man page](http://man7.org/linux/man-pages/man7/unix.7.html).
- ///
- /// Using multiple `ScmRights` messages for a single `sendmsg` call isn't
- /// recommended since it causes platform-dependent behaviour: It might
- /// swallow all but the first `ScmRights` message or fail with `EINVAL`.
- /// Instead, you can put all fds to be passed into a single `ScmRights`
- /// message.
- ScmRights(&'a [RawFd]),
- /// A message of type `SCM_CREDENTIALS`, containing the pid, uid and gid of
- /// a process connected to the socket.
- ///
- /// This is similar to the socket option `SO_PEERCRED`, but requires a
- /// process to explicitly send its credentials. A process running as root is
- /// allowed to specify any credentials, while credentials sent by other
- /// processes are verified by the kernel.
- ///
- /// For further information, please refer to the
- /// [`unix(7)`](http://man7.org/linux/man-pages/man7/unix.7.html) man page.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ScmCredentials(&'a UnixCredentials),
- /// A message of type `SCM_CREDS`, containing the pid, uid, euid, gid and groups of
- /// a process connected to the socket.
- ///
- /// This is similar to the socket options `LOCAL_CREDS` and `LOCAL_PEERCRED`, but
- /// requires a process to explicitly send its credentials.
- ///
- /// Credentials are always overwritten by the kernel, so this variant does have
- /// any data, unlike the receive-side
- /// [`ControlMessageOwned::ScmCreds`][#enum.ControlMessageOwned.html#variant.ScmCreds].
- ///
- /// For further information, please refer to the
- /// [`unix(4)`](https://www.freebsd.org/cgi/man.cgi?query=unix) man page.
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- ScmCreds,
-
- /// Set IV for `AF_ALG` crypto API.
- ///
- /// For further information, please refer to the
- /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
- #[cfg(any(
- target_os = "android",
- target_os = "linux",
- ))]
- AlgSetIv(&'a [u8]),
- /// Set crypto operation for `AF_ALG` crypto API. It may be one of
- /// `ALG_OP_ENCRYPT` or `ALG_OP_DECRYPT`
- ///
- /// For further information, please refer to the
- /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
- #[cfg(any(
- target_os = "android",
- target_os = "linux",
- ))]
- AlgSetOp(&'a libc::c_int),
- /// Set the length of associated authentication data (AAD) (applicable only to AEAD algorithms)
- /// for `AF_ALG` crypto API.
- ///
- /// For further information, please refer to the
- /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
- #[cfg(any(
- target_os = "android",
- target_os = "linux",
- ))]
- AlgSetAeadAssoclen(&'a u32),
-
- /// UDP GSO makes it possible for applications to generate network packets
- /// for a virtual MTU much greater than the real one.
- /// The length of the send data no longer matches the expected length on
- /// the wire.
- /// The size of the datagram payload as it should appear on the wire may be
- /// passed through this control message.
- /// Send buffer should consist of multiple fixed-size wire payloads
- /// following one by one, and the last, possibly smaller one.
- #[cfg(target_os = "linux")]
- UdpGsoSegments(&'a u16),
-
- /// Configure the sending addressing and interface for v4
- ///
- /// For further information, please refer to the
- /// [`ip(7)`](http://man7.org/linux/man-pages/man7/ip.7.html) man page.
- #[cfg(any(target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "android",
- target_os = "ios",))]
- Ipv4PacketInfo(&'a libc::in_pktinfo),
-
- /// Configure the sending addressing and interface for v6
- ///
- /// For further information, please refer to the
- /// [`ipv6(7)`](http://man7.org/linux/man-pages/man7/ipv6.7.html) man page.
- #[cfg(any(target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "freebsd",
- target_os = "android",
- target_os = "ios",))]
- Ipv6PacketInfo(&'a libc::in6_pktinfo),
-}
-
-// An opaque structure used to prevent cmsghdr from being a public type
-#[doc(hidden)]
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct UnknownCmsg(cmsghdr, Vec<u8>);
-
-impl<'a> ControlMessage<'a> {
- /// The value of CMSG_SPACE on this message.
- /// Safe because CMSG_SPACE is always safe
- fn space(&self) -> usize {
- unsafe{CMSG_SPACE(self.len() as libc::c_uint) as usize}
- }
-
- /// The value of CMSG_LEN on this message.
- /// Safe because CMSG_LEN is always safe
- #[cfg(any(target_os = "android",
- all(target_os = "linux", not(target_env = "musl"))))]
- fn cmsg_len(&self) -> usize {
- unsafe{CMSG_LEN(self.len() as libc::c_uint) as usize}
- }
-
- #[cfg(not(any(target_os = "android",
- all(target_os = "linux", not(target_env = "musl")))))]
- fn cmsg_len(&self) -> libc::c_uint {
- unsafe{CMSG_LEN(self.len() as libc::c_uint)}
- }
-
- /// Return a reference to the payload data as a byte pointer
- fn copy_to_cmsg_data(&self, cmsg_data: *mut u8) {
- let data_ptr = match *self {
- ControlMessage::ScmRights(fds) => {
- fds as *const _ as *const u8
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::ScmCredentials(creds) => {
- &creds.0 as *const libc::ucred as *const u8
- }
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- ControlMessage::ScmCreds => {
- // The kernel overwrites the data, we just zero it
- // to make sure it's not uninitialized memory
- unsafe { ptr::write_bytes(cmsg_data, 0, self.len()) };
- return
- }
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetIv(iv) => {
- #[allow(deprecated)] // https://github.com/rust-lang/libc/issues/1501
- let af_alg_iv = libc::af_alg_iv {
- ivlen: iv.len() as u32,
- iv: [0u8; 0],
- };
-
- let size = mem::size_of_val(&af_alg_iv);
-
- unsafe {
- ptr::copy_nonoverlapping(
- &af_alg_iv as *const _ as *const u8,
- cmsg_data,
- size,
- );
- ptr::copy_nonoverlapping(
- iv.as_ptr(),
- cmsg_data.add(size),
- iv.len()
- );
- };
-
- return
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetOp(op) => {
- op as *const _ as *const u8
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetAeadAssoclen(len) => {
- len as *const _ as *const u8
- },
- #[cfg(target_os = "linux")]
- ControlMessage::UdpGsoSegments(gso_size) => {
- gso_size as *const _ as *const u8
- },
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "android",
- target_os = "ios",))]
- ControlMessage::Ipv4PacketInfo(info) => info as *const _ as *const u8,
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "freebsd",
- target_os = "android", target_os = "ios",))]
- ControlMessage::Ipv6PacketInfo(info) => info as *const _ as *const u8,
- };
- unsafe {
- ptr::copy_nonoverlapping(
- data_ptr,
- cmsg_data,
- self.len()
- )
- };
- }
-
- /// The size of the payload, excluding its cmsghdr
- fn len(&self) -> usize {
- match *self {
- ControlMessage::ScmRights(fds) => {
- mem::size_of_val(fds)
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::ScmCredentials(creds) => {
- mem::size_of_val(creds)
- }
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- ControlMessage::ScmCreds => {
- mem::size_of::<libc::cmsgcred>()
- }
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetIv(iv) => {
- mem::size_of_val(&iv) + iv.len()
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetOp(op) => {
- mem::size_of_val(op)
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetAeadAssoclen(len) => {
- mem::size_of_val(len)
- },
- #[cfg(target_os = "linux")]
- ControlMessage::UdpGsoSegments(gso_size) => {
- mem::size_of_val(gso_size)
- },
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "android",
- target_os = "ios",))]
- ControlMessage::Ipv4PacketInfo(info) => mem::size_of_val(info),
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "freebsd",
- target_os = "android", target_os = "ios",))]
- ControlMessage::Ipv6PacketInfo(info) => mem::size_of_val(info),
- }
- }
-
- /// Returns the value to put into the `cmsg_level` field of the header.
- fn cmsg_level(&self) -> libc::c_int {
- match *self {
- ControlMessage::ScmRights(_) => libc::SOL_SOCKET,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET,
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- ControlMessage::ScmCreds => libc::SOL_SOCKET,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetIv(_) | ControlMessage::AlgSetOp(_) |
- ControlMessage::AlgSetAeadAssoclen(_) => libc::SOL_ALG,
- #[cfg(target_os = "linux")]
- ControlMessage::UdpGsoSegments(_) => libc::SOL_UDP,
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "android",
- target_os = "ios",))]
- ControlMessage::Ipv4PacketInfo(_) => libc::IPPROTO_IP,
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "freebsd",
- target_os = "android", target_os = "ios",))]
- ControlMessage::Ipv6PacketInfo(_) => libc::IPPROTO_IPV6,
- }
- }
-
- /// Returns the value to put into the `cmsg_type` field of the header.
- fn cmsg_type(&self) -> libc::c_int {
- match *self {
- ControlMessage::ScmRights(_) => libc::SCM_RIGHTS,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS,
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- ControlMessage::ScmCreds => libc::SCM_CREDS,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetIv(_) => {
- libc::ALG_SET_IV
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetOp(_) => {
- libc::ALG_SET_OP
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetAeadAssoclen(_) => {
- libc::ALG_SET_AEAD_ASSOCLEN
- },
- #[cfg(target_os = "linux")]
- ControlMessage::UdpGsoSegments(_) => {
- libc::UDP_SEGMENT
- },
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "android",
- target_os = "ios",))]
- ControlMessage::Ipv4PacketInfo(_) => libc::IP_PKTINFO,
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "freebsd",
- target_os = "android", target_os = "ios",))]
- ControlMessage::Ipv6PacketInfo(_) => libc::IPV6_PKTINFO,
- }
- }
-
- // Unsafe: cmsg must point to a valid cmsghdr with enough space to
- // encode self.
- unsafe fn encode_into(&self, cmsg: *mut cmsghdr) {
- (*cmsg).cmsg_level = self.cmsg_level();
- (*cmsg).cmsg_type = self.cmsg_type();
- (*cmsg).cmsg_len = self.cmsg_len();
- self.copy_to_cmsg_data(CMSG_DATA(cmsg));
- }
-}
-
-
-/// Send data in scatter-gather vectors to a socket, possibly accompanied
-/// by ancillary data. Optionally direct the message at the given address,
-/// as with sendto.
-///
-/// Allocates if cmsgs is nonempty.
-pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage],
- flags: MsgFlags, addr: Option<&SockAddr>) -> Result<usize>
-{
- let capacity = cmsgs.iter().map(|c| c.space()).sum();
-
- // First size the buffer needed to hold the cmsgs. It must be zeroed,
- // because subsequent code will not clear the padding bytes.
- let mut cmsg_buffer = vec![0u8; capacity];
-
- let mhdr = pack_mhdr_to_send(&mut cmsg_buffer[..], &iov, &cmsgs, addr);
-
- let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };
-
- Errno::result(ret).map(|r| r as usize)
-}
-
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
-#[derive(Debug)]
-pub struct SendMmsgData<'a, I, C>
- where
- I: AsRef<[IoVec<&'a [u8]>]>,
- C: AsRef<[ControlMessage<'a>]>
-{
- pub iov: I,
- pub cmsgs: C,
- pub addr: Option<SockAddr>,
- pub _lt: std::marker::PhantomData<&'a I>,
-}
-
-/// An extension of `sendmsg` that allows the caller to transmit multiple
-/// messages on a socket using a single system call. This has performance
-/// benefits for some applications.
-///
-/// Allocations are performed for cmsgs and to build `msghdr` buffer
-///
-/// # Arguments
-///
-/// * `fd`: Socket file descriptor
-/// * `data`: Struct that implements `IntoIterator` with `SendMmsgData` items
-/// * `flags`: Optional flags passed directly to the operating system.
-///
-/// # Returns
-/// `Vec` with numbers of sent bytes on each sent message.
-///
-/// # References
-/// [`sendmsg`](fn.sendmsg.html)
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
-pub fn sendmmsg<'a, I, C>(
- fd: RawFd,
- data: impl std::iter::IntoIterator<Item=&'a SendMmsgData<'a, I, C>>,
- flags: MsgFlags
-) -> Result<Vec<usize>>
- where
- I: AsRef<[IoVec<&'a [u8]>]> + 'a,
- C: AsRef<[ControlMessage<'a>]> + 'a,
-{
- let iter = data.into_iter();
-
- let size_hint = iter.size_hint();
- let reserve_items = size_hint.1.unwrap_or(size_hint.0);
-
- let mut output = Vec::<libc::mmsghdr>::with_capacity(reserve_items);
-
- let mut cmsgs_buffer = vec![0u8; 0];
-
- for d in iter {
- let cmsgs_start = cmsgs_buffer.len();
- let cmsgs_required_capacity: usize = d.cmsgs.as_ref().iter().map(|c| c.space()).sum();
- let cmsgs_buffer_need_capacity = cmsgs_start + cmsgs_required_capacity;
- cmsgs_buffer.resize(cmsgs_buffer_need_capacity, 0);
-
- output.push(libc::mmsghdr {
- msg_hdr: pack_mhdr_to_send(
- &mut cmsgs_buffer[cmsgs_start..],
- &d.iov,
- &d.cmsgs,
- d.addr.as_ref()
- ),
- msg_len: 0,
- });
- };
-
- let ret = unsafe { libc::sendmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _) };
-
- let sent_messages = Errno::result(ret)? as usize;
- let mut sent_bytes = Vec::with_capacity(sent_messages);
-
- for item in &output {
- sent_bytes.push(item.msg_len as usize);
- }
-
- Ok(sent_bytes)
-}
-
-
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
-#[derive(Debug)]
-pub struct RecvMmsgData<'a, I>
- where
- I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,
-{
- pub iov: I,
- pub cmsg_buffer: Option<&'a mut Vec<u8>>,
-}
-
-/// An extension of `recvmsg` that allows the caller to receive multiple
-/// messages from a socket using a single system call. This has
-/// performance benefits for some applications.
-///
-/// `iov` and `cmsg_buffer` should be constructed similarly to `recvmsg`
-///
-/// Multiple allocations are performed
-///
-/// # Arguments
-///
-/// * `fd`: Socket file descriptor
-/// * `data`: Struct that implements `IntoIterator` with `RecvMmsgData` items
-/// * `flags`: Optional flags passed directly to the operating system.
-///
-/// # RecvMmsgData
-///
-/// * `iov`: Scatter-gather list of buffers to receive the message
-/// * `cmsg_buffer`: Space to receive ancillary data. Should be created by
-/// [`cmsg_space!`](macro.cmsg_space.html)
-///
-/// # Returns
-/// A `Vec` with multiple `RecvMsg`, one per received message
-///
-/// # References
-/// - [`recvmsg`](fn.recvmsg.html)
-/// - [`RecvMsg`](struct.RecvMsg.html)
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
-pub fn recvmmsg<'a, I>(
- fd: RawFd,
- data: impl std::iter::IntoIterator<Item=&'a mut RecvMmsgData<'a, I>,
- IntoIter=impl ExactSizeIterator + Iterator<Item=&'a mut RecvMmsgData<'a, I>>>,
- flags: MsgFlags,
- timeout: Option<crate::sys::time::TimeSpec>
-) -> Result<Vec<RecvMsg<'a>>>
- where
- I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,
-{
- let iter = data.into_iter();
-
- let num_messages = iter.len();
-
- let mut output: Vec<libc::mmsghdr> = Vec::with_capacity(num_messages);
-
- // Addresses should be pre-allocated. pack_mhdr_to_receive will store them
- // as raw pointers, so we may not move them. Turn the vec into a boxed
- // slice so we won't inadvertently reallocate the vec.
- let mut addresses = vec![mem::MaybeUninit::uninit(); num_messages]
- .into_boxed_slice();
-
- let results: Vec<_> = iter.enumerate().map(|(i, d)| {
- let (msg_controllen, mhdr) = unsafe {
- pack_mhdr_to_receive(
- d.iov.as_ref(),
- &mut d.cmsg_buffer,
- addresses[i].as_mut_ptr(),
- )
- };
-
- output.push(
- libc::mmsghdr {
- msg_hdr: mhdr,
- msg_len: 0,
- }
- );
-
- (msg_controllen as usize, &mut d.cmsg_buffer)
- }).collect();
-
- let timeout = if let Some(mut t) = timeout {
- t.as_mut() as *mut libc::timespec
- } else {
- ptr::null_mut()
- };
-
- let ret = unsafe { libc::recvmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _, timeout) };
-
- let _ = Errno::result(ret)?;
-
- Ok(output
- .into_iter()
- .take(ret as usize)
- .zip(addresses.iter().map(|addr| unsafe{addr.assume_init()}))
- .zip(results.into_iter())
- .map(|((mmsghdr, address), (msg_controllen, cmsg_buffer))| {
- unsafe {
- read_mhdr(
- mmsghdr.msg_hdr,
- mmsghdr.msg_len as isize,
- msg_controllen,
- address,
- cmsg_buffer
- )
- }
- })
- .collect())
-}
-
-unsafe fn read_mhdr<'a, 'b>(
- mhdr: msghdr,
- r: isize,
- msg_controllen: usize,
- address: sockaddr_storage,
- cmsg_buffer: &'a mut Option<&'b mut Vec<u8>>
-) -> RecvMsg<'b> {
- let cmsghdr = {
- if mhdr.msg_controllen > 0 {
- // got control message(s)
- cmsg_buffer
- .as_mut()
- .unwrap()
- .set_len(mhdr.msg_controllen as usize);
- debug_assert!(!mhdr.msg_control.is_null());
- debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
- CMSG_FIRSTHDR(&mhdr as *const msghdr)
- } else {
- ptr::null()
- }.as_ref()
- };
-
- let address = sockaddr_storage_to_addr(
- &address ,
- mhdr.msg_namelen as usize
- ).ok();
-
- RecvMsg {
- bytes: r as usize,
- cmsghdr,
- address,
- flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
- mhdr,
- }
-}
-
-unsafe fn pack_mhdr_to_receive<'a, I>(
- iov: I,
- cmsg_buffer: &mut Option<&mut Vec<u8>>,
- address: *mut sockaddr_storage,
-) -> (usize, msghdr)
- where
- I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,
-{
- let (msg_control, msg_controllen) = cmsg_buffer.as_mut()
- .map(|v| (v.as_mut_ptr(), v.capacity()))
- .unwrap_or((ptr::null_mut(), 0));
-
- let mhdr = {
- // Musl's msghdr has private fields, so this is the only way to
- // initialize it.
- let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
- let p = mhdr.as_mut_ptr();
- (*p).msg_name = address as *mut c_void;
- (*p).msg_namelen = mem::size_of::<sockaddr_storage>() as socklen_t;
- (*p).msg_iov = iov.as_ref().as_ptr() as *mut iovec;
- (*p).msg_iovlen = iov.as_ref().len() as _;
- (*p).msg_control = msg_control as *mut c_void;
- (*p).msg_controllen = msg_controllen as _;
- (*p).msg_flags = 0;
- mhdr.assume_init()
- };
-
- (msg_controllen, mhdr)
-}
-
-fn pack_mhdr_to_send<'a, I, C>(
- cmsg_buffer: &mut [u8],
- iov: I,
- cmsgs: C,
- addr: Option<&SockAddr>
-) -> msghdr
- where
- I: AsRef<[IoVec<&'a [u8]>]>,
- C: AsRef<[ControlMessage<'a>]>
-{
- let capacity = cmsg_buffer.len();
-
- // Next encode the sending address, if provided
- let (name, namelen) = match addr {
- Some(addr) => {
- let (x, y) = addr.as_ffi_pair();
- (x as *const _, y)
- },
- None => (ptr::null(), 0),
- };
-
- // The message header must be initialized before the individual cmsgs.
- let cmsg_ptr = if capacity > 0 {
- cmsg_buffer.as_ptr() as *mut c_void
- } else {
- ptr::null_mut()
- };
-
- let mhdr = unsafe {
- // Musl's msghdr has private fields, so this is the only way to
- // initialize it.
- let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
- let p = mhdr.as_mut_ptr();
- (*p).msg_name = name as *mut _;
- (*p).msg_namelen = namelen;
- // transmute iov into a mutable pointer. sendmsg doesn't really mutate
- // the buffer, but the standard says that it takes a mutable pointer
- (*p).msg_iov = iov.as_ref().as_ptr() as *mut _;
- (*p).msg_iovlen = iov.as_ref().len() as _;
- (*p).msg_control = cmsg_ptr;
- (*p).msg_controllen = capacity as _;
- (*p).msg_flags = 0;
- mhdr.assume_init()
- };
-
- // Encode each cmsg. This must happen after initializing the header because
- // CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields.
- // CMSG_FIRSTHDR is always safe
- let mut pmhdr: *mut cmsghdr = unsafe { CMSG_FIRSTHDR(&mhdr as *const msghdr) };
- for cmsg in cmsgs.as_ref() {
- assert_ne!(pmhdr, ptr::null_mut());
- // Safe because we know that pmhdr is valid, and we initialized it with
- // sufficient space
- unsafe { cmsg.encode_into(pmhdr) };
- // Safe because mhdr is valid
- pmhdr = unsafe { CMSG_NXTHDR(&mhdr as *const msghdr, pmhdr) };
- }
-
- mhdr
-}
-
-/// Receive message in scatter-gather vectors from a socket, and
-/// optionally receive ancillary data into the provided buffer.
-/// If no ancillary data is desired, use () as the type parameter.
-///
-/// # Arguments
-///
-/// * `fd`: Socket file descriptor
-/// * `iov`: Scatter-gather list of buffers to receive the message
-/// * `cmsg_buffer`: Space to receive ancillary data. Should be created by
-/// [`cmsg_space!`](macro.cmsg_space.html)
-/// * `flags`: Optional flags passed directly to the operating system.
-///
-/// # References
-/// [recvmsg(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
-pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
- mut cmsg_buffer: Option<&'a mut Vec<u8>>,
- flags: MsgFlags) -> Result<RecvMsg<'a>>
-{
- let mut address = mem::MaybeUninit::uninit();
-
- let (msg_controllen, mut mhdr) = unsafe {
- pack_mhdr_to_receive(&iov, &mut cmsg_buffer, address.as_mut_ptr())
- };
-
- let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
-
- let r = Errno::result(ret)?;
-
- Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, address.assume_init(), &mut cmsg_buffer) })
-}
-
-
-/// Create an endpoint for communication
-///
-/// The `protocol` specifies a particular protocol to be used with the
-/// socket. Normally only a single protocol exists to support a
-/// particular socket type within a given protocol family, in which case
-/// protocol can be specified as `None`. However, it is possible that many
-/// protocols may exist, in which case a particular protocol must be
-/// specified in this manner.
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html)
-pub fn socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: T) -> Result<RawFd> {
- let protocol = match protocol.into() {
- None => 0,
- Some(p) => p as c_int,
- };
-
- // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
- // little easier to understand by separating it out. So we have to merge these bitfields
- // here.
- let mut ty = ty as c_int;
- ty |= flags.bits();
-
- let res = unsafe { libc::socket(domain as c_int, ty, protocol) };
-
- Errno::result(res)
-}
-
-/// Create a pair of connected sockets
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html)
-pub fn socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, protocol: T,
- flags: SockFlag) -> Result<(RawFd, RawFd)> {
- let protocol = match protocol.into() {
- None => 0,
- Some(p) => p as c_int,
- };
-
- // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
- // little easier to understand by separating it out. So we have to merge these bitfields
- // here.
- let mut ty = ty as c_int;
- ty |= flags.bits();
-
- let mut fds = [-1, -1];
-
- let res = unsafe { libc::socketpair(domain as c_int, ty, protocol, fds.as_mut_ptr()) };
- Errno::result(res)?;
-
- Ok((fds[0], fds[1]))
-}
-
-/// Listen for connections on a socket
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
-pub fn listen(sockfd: RawFd, backlog: usize) -> Result<()> {
- let res = unsafe { libc::listen(sockfd, backlog as c_int) };
-
- Errno::result(res).map(drop)
-}
-
-/// Bind a name to a socket
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html)
-pub fn bind(fd: RawFd, addr: &SockAddr) -> Result<()> {
- let res = unsafe {
- let (ptr, len) = addr.as_ffi_pair();
- libc::bind(fd, ptr, len)
- };
-
- Errno::result(res).map(drop)
-}
-
-/// Accept a connection on a socket
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html)
-pub fn accept(sockfd: RawFd) -> Result<RawFd> {
- let res = unsafe { libc::accept(sockfd, ptr::null_mut(), ptr::null_mut()) };
-
- Errno::result(res)
-}
-
-/// Accept a connection on a socket
-///
-/// [Further reading](http://man7.org/linux/man-pages/man2/accept.2.html)
-#[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "openbsd"))]
-pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
- let res = unsafe { libc::accept4(sockfd, ptr::null_mut(), ptr::null_mut(), flags.bits()) };
-
- Errno::result(res)
-}
-
-/// Initiate a connection on a socket
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)
-pub fn connect(fd: RawFd, addr: &SockAddr) -> Result<()> {
- let res = unsafe {
- let (ptr, len) = addr.as_ffi_pair();
- libc::connect(fd, ptr, len)
- };
-
- Errno::result(res).map(drop)
-}
-
-/// Receive data from a connection-oriented socket. Returns the number of
-/// bytes read
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
-pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
- unsafe {
- let ret = libc::recv(
- sockfd,
- buf.as_ptr() as *mut c_void,
- buf.len() as size_t,
- flags.bits());
-
- Errno::result(ret).map(|r| r as usize)
- }
-}
-
-/// Receive data from a connectionless or connection-oriented socket. Returns
-/// the number of bytes read and, for connectionless sockets, the socket
-/// address of the sender.
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
-pub fn recvfrom(sockfd: RawFd, buf: &mut [u8])
- -> Result<(usize, Option<SockAddr>)>
-{
- unsafe {
- let mut addr: sockaddr_storage = mem::zeroed();
- let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
-
- let ret = Errno::result(libc::recvfrom(
- sockfd,
- buf.as_ptr() as *mut c_void,
- buf.len() as size_t,
- 0,
- &mut addr as *mut libc::sockaddr_storage as *mut libc::sockaddr,
- &mut len as *mut socklen_t))? as usize;
-
- match sockaddr_storage_to_addr(&addr, len as usize) {
- Err(Error::Sys(Errno::ENOTCONN)) => Ok((ret, None)),
- Ok(addr) => Ok((ret, Some(addr))),
- Err(e) => Err(e)
- }
- }
-}
-
-/// Send a message to a socket
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html)
-pub fn sendto(fd: RawFd, buf: &[u8], addr: &SockAddr, flags: MsgFlags) -> Result<usize> {
- let ret = unsafe {
- let (ptr, len) = addr.as_ffi_pair();
- libc::sendto(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits(), ptr, len)
- };
-
- Errno::result(ret).map(|r| r as usize)
-}
-
-/// Send data to a connection-oriented socket. Returns the number of bytes read
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
-pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
- let ret = unsafe {
- libc::send(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits())
- };
-
- Errno::result(ret).map(|r| r as usize)
-}
-
-/*
- *
- * ===== Socket Options =====
- *
- */
-
-/// Represents a socket option that can be accessed or set. Used as an argument
-/// to `getsockopt`
-pub trait GetSockOpt : Copy {
- type Val;
-
- #[doc(hidden)]
- fn get(&self, fd: RawFd) -> Result<Self::Val>;
-}
-
-/// Represents a socket option that can be accessed or set. Used as an argument
-/// to `setsockopt`
-pub trait SetSockOpt : Clone {
- type Val;
-
- #[doc(hidden)]
- fn set(&self, fd: RawFd, val: &Self::Val) -> Result<()>;
-}
-
-/// Get the current value for the requested socket option
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html)
-pub fn getsockopt<O: GetSockOpt>(fd: RawFd, opt: O) -> Result<O::Val> {
- opt.get(fd)
-}
-
-/// Sets the value for the requested socket option
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
-///
-/// # Examples
-///
-/// ```
-/// use nix::sys::socket::setsockopt;
-/// use nix::sys::socket::sockopt::KeepAlive;
-/// use std::net::TcpListener;
-/// use std::os::unix::io::AsRawFd;
-///
-/// let listener = TcpListener::bind("0.0.0.0:0").unwrap();
-/// let fd = listener.as_raw_fd();
-/// let res = setsockopt(fd, KeepAlive, &true);
-/// assert!(res.is_ok());
-/// ```
-pub fn setsockopt<O: SetSockOpt>(fd: RawFd, opt: O, val: &O::Val) -> Result<()> {
- opt.set(fd, val)
-}
-
-/// Get the address of the peer connected to the socket `fd`.
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
-pub fn getpeername(fd: RawFd) -> Result<SockAddr> {
- unsafe {
- let mut addr = mem::MaybeUninit::uninit();
- let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
-
- let ret = libc::getpeername(
- fd,
- addr.as_mut_ptr() as *mut libc::sockaddr,
- &mut len
- );
-
- Errno::result(ret)?;
-
- sockaddr_storage_to_addr(&addr.assume_init(), len as usize)
- }
-}
-
-/// Get the current address to which the socket `fd` is bound.
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
-pub fn getsockname(fd: RawFd) -> Result<SockAddr> {
- unsafe {
- let mut addr = mem::MaybeUninit::uninit();
- let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
-
- let ret = libc::getsockname(
- fd,
- addr.as_mut_ptr() as *mut libc::sockaddr,
- &mut len
- );
-
- Errno::result(ret)?;
-
- sockaddr_storage_to_addr(&addr.assume_init(), len as usize)
- }
-}
-
-/// Return the appropriate `SockAddr` type from a `sockaddr_storage` of a
-/// certain size.
-///
-/// In C this would usually be done by casting. The `len` argument
-/// should be the number of bytes in the `sockaddr_storage` that are actually
-/// allocated and valid. It must be at least as large as all the useful parts
-/// of the structure. Note that in the case of a `sockaddr_un`, `len` need not
-/// include the terminating null.
-pub fn sockaddr_storage_to_addr(
- addr: &sockaddr_storage,
- len: usize) -> Result<SockAddr> {
-
- assert!(len <= mem::size_of::<sockaddr_un>());
- if len < mem::size_of_val(&addr.ss_family) {
- return Err(Error::Sys(Errno::ENOTCONN));
- }
-
- match c_int::from(addr.ss_family) {
- libc::AF_INET => {
- assert_eq!(len as usize, mem::size_of::<sockaddr_in>());
- let sin = unsafe {
- *(addr as *const sockaddr_storage as *const sockaddr_in)
- };
- Ok(SockAddr::Inet(InetAddr::V4(sin)))
- }
- libc::AF_INET6 => {
- assert_eq!(len as usize, mem::size_of::<sockaddr_in6>());
- let sin6 = unsafe {
- *(addr as *const _ as *const sockaddr_in6)
- };
- Ok(SockAddr::Inet(InetAddr::V6(sin6)))
- }
- libc::AF_UNIX => {
- let pathlen = len - offset_of!(sockaddr_un, sun_path);
- let sun = unsafe {
- *(addr as *const _ as *const sockaddr_un)
- };
- Ok(SockAddr::Unix(UnixAddr(sun, pathlen)))
- }
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_PACKET => {
- use libc::sockaddr_ll;
- assert_eq!(len as usize, mem::size_of::<sockaddr_ll>());
- let sll = unsafe {
- *(addr as *const _ as *const sockaddr_ll)
- };
- Ok(SockAddr::Link(LinkAddr(sll)))
- }
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_NETLINK => {
- use libc::sockaddr_nl;
- let snl = unsafe {
- *(addr as *const _ as *const sockaddr_nl)
- };
- Ok(SockAddr::Netlink(NetlinkAddr(snl)))
- }
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_ALG => {
- use libc::sockaddr_alg;
- let salg = unsafe {
- *(addr as *const _ as *const sockaddr_alg)
- };
- Ok(SockAddr::Alg(AlgAddr(salg)))
- }
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_VSOCK => {
- use libc::sockaddr_vm;
- let svm = unsafe {
- *(addr as *const _ as *const sockaddr_vm)
- };
- Ok(SockAddr::Vsock(VsockAddr(svm)))
- }
- af => panic!("unexpected address family {}", af),
- }
-}
-
-
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum Shutdown {
- /// Further receptions will be disallowed.
- Read,
- /// Further transmissions will be disallowed.
- Write,
- /// Further receptions and transmissions will be disallowed.
- Both,
-}
-
-/// Shut down part of a full-duplex connection.
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html)
-pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
- unsafe {
- use libc::shutdown;
-
- let how = match how {
- Shutdown::Read => libc::SHUT_RD,
- Shutdown::Write => libc::SHUT_WR,
- Shutdown::Both => libc::SHUT_RDWR,
- };
-
- Errno::result(shutdown(df, how)).map(drop)
- }
-}
diff --git a/vendor/nix-0.20.0/src/sys/socket/sockopt.rs b/vendor/nix-0.20.0/src/sys/socket/sockopt.rs
deleted file mode 100644
index 5b7b4fe..0000000
--- a/vendor/nix-0.20.0/src/sys/socket/sockopt.rs
+++ /dev/null
@@ -1,695 +0,0 @@
-use cfg_if::cfg_if;
-use super::{GetSockOpt, SetSockOpt};
-use crate::Result;
-use crate::errno::Errno;
-use crate::sys::time::TimeVal;
-use libc::{self, c_int, c_void, socklen_t};
-use std::mem::{
- self,
- MaybeUninit
-};
-use std::os::unix::io::RawFd;
-use std::ffi::{OsStr, OsString};
-#[cfg(target_family = "unix")]
-use std::os::unix::ffi::OsStrExt;
-
-// Constants
-// TCP_CA_NAME_MAX isn't defined in user space include files
-#[cfg(any(target_os = "freebsd", target_os = "linux"))]
-const TCP_CA_NAME_MAX: usize = 16;
-
-/// Helper for implementing `SetSockOpt` for a given socket option. See
-/// [`::sys::socket::SetSockOpt`](sys/socket/trait.SetSockOpt.html).
-///
-/// This macro aims to help implementing `SetSockOpt` for different socket options that accept
-/// different kinds of data to be used with `setsockopt`.
-///
-/// Instead of using this macro directly consider using `sockopt_impl!`, especially if the option
-/// you are implementing represents a simple type.
-///
-/// # Arguments
-///
-/// * `$name:ident`: name of the type you want to implement `SetSockOpt` for.
-/// * `$level:path` : socket layer, or a `protocol level`: could be *raw sockets*
-/// (`libc::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),
-/// and more. Please refer to your system manual for more options. Will be passed as the second
-/// argument (`level`) to the `setsockopt` call.
-/// * `$flag:path`: a flag name to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`,
-/// `libc::IP_ADD_MEMBERSHIP` and others. Will be passed as the third argument (`option_name`)
-/// to the `setsockopt` call.
-/// * Type of the value that you are going to set.
-/// * Type that implements the `Set` trait for the type from the previous item (like `SetBool` for
-/// `bool`, `SetUsize` for `usize`, etc.).
-macro_rules! setsockopt_impl {
- ($name:ident, $level:path, $flag:path, $ty:ty, $setter:ty) => {
- impl SetSockOpt for $name {
- type Val = $ty;
-
- fn set(&self, fd: RawFd, val: &$ty) -> Result<()> {
- unsafe {
- let setter: $setter = Set::new(val);
-
- let res = libc::setsockopt(fd, $level, $flag,
- setter.ffi_ptr(),
- setter.ffi_len());
- Errno::result(res).map(drop)
- }
- }
- }
- }
-}
-
-/// Helper for implementing `GetSockOpt` for a given socket option. See
-/// [`::sys::socket::GetSockOpt`](sys/socket/trait.GetSockOpt.html).
-///
-/// This macro aims to help implementing `GetSockOpt` for different socket options that accept
-/// different kinds of data to be use with `getsockopt`.
-///
-/// Instead of using this macro directly consider using `sockopt_impl!`, especially if the option
-/// you are implementing represents a simple type.
-///
-/// # Arguments
-///
-/// * Name of the type you want to implement `GetSockOpt` for.
-/// * Socket layer, or a `protocol level`: could be *raw sockets* (`lic::SOL_SOCKET`), *ip
-/// protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`), and more. Please refer
-/// to your system manual for more options. Will be passed as the second argument (`level`) to
-/// the `getsockopt` call.
-/// * A flag to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`,
-/// `libc::SO_ORIGINAL_DST` and others. Will be passed as the third argument (`option_name`) to
-/// the `getsockopt` call.
-/// * Type of the value that you are going to get.
-/// * Type that implements the `Get` trait for the type from the previous item (`GetBool` for
-/// `bool`, `GetUsize` for `usize`, etc.).
-macro_rules! getsockopt_impl {
- ($name:ident, $level:path, $flag:path, $ty:ty, $getter:ty) => {
- impl GetSockOpt for $name {
- type Val = $ty;
-
- fn get(&self, fd: RawFd) -> Result<$ty> {
- unsafe {
- let mut getter: $getter = Get::uninit();
-
- let res = libc::getsockopt(fd, $level, $flag,
- getter.ffi_ptr(),
- getter.ffi_len());
- Errno::result(res)?;
-
- Ok(getter.assume_init())
- }
- }
- }
- }
-}
-
-/// Helper to generate the sockopt accessors. See
-/// [`::sys::socket::GetSockOpt`](sys/socket/trait.GetSockOpt.html) and
-/// [`::sys::socket::SetSockOpt`](sys/socket/trait.SetSockOpt.html).
-///
-/// This macro aims to help implementing `GetSockOpt` and `SetSockOpt` for different socket options
-/// that accept different kinds of data to be use with `getsockopt` and `setsockopt` respectively.
-///
-/// Basically this macro wraps up the [`getsockopt_impl!`](macro.getsockopt_impl.html) and
-/// [`setsockopt_impl!`](macro.setsockopt_impl.html) macros.
-///
-/// # Arguments
-///
-/// * `GetOnly`, `SetOnly` or `Both`: whether you want to implement only getter, only setter or
-/// both of them.
-/// * `$name:ident`: name of type `GetSockOpt`/`SetSockOpt` will be implemented for.
-/// * `$level:path` : socket layer, or a `protocol level`: could be *raw sockets*
-/// (`lic::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),
-/// and more. Please refer to your system manual for more options. Will be passed as the second
-/// argument (`level`) to the `getsockopt`/`setsockopt` call.
-/// * `$flag:path`: a flag name to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`,
-/// `libc::IP_ADD_MEMBERSHIP` and others. Will be passed as the third argument (`option_name`)
-/// to the `setsockopt`/`getsockopt` call.
-/// * `$ty:ty`: type of the value that will be get/set.
-/// * `$getter:ty`: `Get` implementation; optional; only for `GetOnly` and `Both`.
-/// * `$setter:ty`: `Set` implementation; optional; only for `SetOnly` and `Both`.
-macro_rules! sockopt_impl {
- (GetOnly, $name:ident, $level:path, $flag:path, bool) => {
- sockopt_impl!(GetOnly, $name, $level, $flag, bool, GetBool);
- };
-
- (GetOnly, $name:ident, $level:path, $flag:path, u8) => {
- sockopt_impl!(GetOnly, $name, $level, $flag, u8, GetU8);
- };
-
- (GetOnly, $name:ident, $level:path, $flag:path, usize) => {
- sockopt_impl!(GetOnly, $name, $level, $flag, usize, GetUsize);
- };
-
- (SetOnly, $name:ident, $level:path, $flag:path, bool) => {
- sockopt_impl!(SetOnly, $name, $level, $flag, bool, SetBool);
- };
-
- (SetOnly, $name:ident, $level:path, $flag:path, u8) => {
- sockopt_impl!(SetOnly, $name, $level, $flag, u8, SetU8);
- };
-
- (SetOnly, $name:ident, $level:path, $flag:path, usize) => {
- sockopt_impl!(SetOnly, $name, $level, $flag, usize, SetUsize);
- };
-
- (Both, $name:ident, $level:path, $flag:path, bool) => {
- sockopt_impl!(Both, $name, $level, $flag, bool, GetBool, SetBool);
- };
-
- (Both, $name:ident, $level:path, $flag:path, u8) => {
- sockopt_impl!(Both, $name, $level, $flag, u8, GetU8, SetU8);
- };
-
- (Both, $name:ident, $level:path, $flag:path, usize) => {
- sockopt_impl!(Both, $name, $level, $flag, usize, GetUsize, SetUsize);
- };
-
- (Both, $name:ident, $level:path, $flag:path, OsString<$array:ty>) => {
- sockopt_impl!(Both, $name, $level, $flag, OsString, GetOsString<$array>, SetOsString);
- };
-
- /*
- * Matchers with generic getter types must be placed at the end, so
- * they'll only match _after_ specialized matchers fail
- */
- (GetOnly, $name:ident, $level:path, $flag:path, $ty:ty) => {
- sockopt_impl!(GetOnly, $name, $level, $flag, $ty, GetStruct<$ty>);
- };
-
- (GetOnly, $name:ident, $level:path, $flag:path, $ty:ty, $getter:ty) => {
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct $name;
-
- getsockopt_impl!($name, $level, $flag, $ty, $getter);
- };
-
- (SetOnly, $name:ident, $level:path, $flag:path, $ty:ty) => {
- sockopt_impl!(SetOnly, $name, $level, $flag, $ty, SetStruct<$ty>);
- };
-
- (SetOnly, $name:ident, $level:path, $flag:path, $ty:ty, $setter:ty) => {
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct $name;
-
- setsockopt_impl!($name, $level, $flag, $ty, $setter);
- };
-
- (Both, $name:ident, $level:path, $flag:path, $ty:ty, $getter:ty, $setter:ty) => {
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct $name;
-
- setsockopt_impl!($name, $level, $flag, $ty, $setter);
- getsockopt_impl!($name, $level, $flag, $ty, $getter);
- };
-
- (Both, $name:ident, $level:path, $flag:path, $ty:ty) => {
- sockopt_impl!(Both, $name, $level, $flag, $ty, GetStruct<$ty>, SetStruct<$ty>);
- };
-}
-
-/*
- *
- * ===== Define sockopts =====
- *
- */
-
-sockopt_impl!(Both, ReuseAddr, libc::SOL_SOCKET, libc::SO_REUSEADDR, bool);
-sockopt_impl!(Both, ReusePort, libc::SOL_SOCKET, libc::SO_REUSEPORT, bool);
-sockopt_impl!(Both, TcpNoDelay, libc::IPPROTO_TCP, libc::TCP_NODELAY, bool);
-sockopt_impl!(Both, Linger, libc::SOL_SOCKET, libc::SO_LINGER, libc::linger);
-sockopt_impl!(SetOnly, IpAddMembership, libc::IPPROTO_IP, libc::IP_ADD_MEMBERSHIP, super::IpMembershipRequest);
-sockopt_impl!(SetOnly, IpDropMembership, libc::IPPROTO_IP, libc::IP_DROP_MEMBERSHIP, super::IpMembershipRequest);
-cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
- sockopt_impl!(SetOnly, Ipv6AddMembership, libc::IPPROTO_IPV6, libc::IPV6_ADD_MEMBERSHIP, super::Ipv6MembershipRequest);
- sockopt_impl!(SetOnly, Ipv6DropMembership, libc::IPPROTO_IPV6, libc::IPV6_DROP_MEMBERSHIP, super::Ipv6MembershipRequest);
- } else if #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))] {
- sockopt_impl!(SetOnly, Ipv6AddMembership, libc::IPPROTO_IPV6, libc::IPV6_JOIN_GROUP, super::Ipv6MembershipRequest);
- sockopt_impl!(SetOnly, Ipv6DropMembership, libc::IPPROTO_IPV6, libc::IPV6_LEAVE_GROUP, super::Ipv6MembershipRequest);
- }
-}
-sockopt_impl!(Both, IpMulticastTtl, libc::IPPROTO_IP, libc::IP_MULTICAST_TTL, u8);
-sockopt_impl!(Both, IpMulticastLoop, libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP, bool);
-sockopt_impl!(Both, ReceiveTimeout, libc::SOL_SOCKET, libc::SO_RCVTIMEO, TimeVal);
-sockopt_impl!(Both, SendTimeout, libc::SOL_SOCKET, libc::SO_SNDTIMEO, TimeVal);
-sockopt_impl!(Both, Broadcast, libc::SOL_SOCKET, libc::SO_BROADCAST, bool);
-sockopt_impl!(Both, OobInline, libc::SOL_SOCKET, libc::SO_OOBINLINE, bool);
-sockopt_impl!(GetOnly, SocketError, libc::SOL_SOCKET, libc::SO_ERROR, i32);
-sockopt_impl!(Both, KeepAlive, libc::SOL_SOCKET, libc::SO_KEEPALIVE, bool);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(GetOnly, PeerCredentials, libc::SOL_SOCKET, libc::SO_PEERCRED, super::UnixCredentials);
-#[cfg(any(target_os = "ios",
- target_os = "macos"))]
-sockopt_impl!(Both, TcpKeepAlive, libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, u32);
-#[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "nacl"))]
-sockopt_impl!(Both, TcpKeepIdle, libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, u32);
-#[cfg(not(target_os = "openbsd"))]
-sockopt_impl!(Both, TcpKeepCount, libc::IPPROTO_TCP, libc::TCP_KEEPCNT, u32);
-#[cfg(not(target_os = "openbsd"))]
-sockopt_impl!(Both, TcpKeepInterval, libc::IPPROTO_TCP, libc::TCP_KEEPINTVL, u32);
-sockopt_impl!(Both, RcvBuf, libc::SOL_SOCKET, libc::SO_RCVBUF, usize);
-sockopt_impl!(Both, SndBuf, libc::SOL_SOCKET, libc::SO_SNDBUF, usize);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(SetOnly, RcvBufForce, libc::SOL_SOCKET, libc::SO_RCVBUFFORCE, usize);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(SetOnly, SndBufForce, libc::SOL_SOCKET, libc::SO_SNDBUFFORCE, usize);
-sockopt_impl!(GetOnly, SockType, libc::SOL_SOCKET, libc::SO_TYPE, super::SockType);
-sockopt_impl!(GetOnly, AcceptConn, libc::SOL_SOCKET, libc::SO_ACCEPTCONN, bool);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(Both, BindToDevice, libc::SOL_SOCKET, libc::SO_BINDTODEVICE, OsString<[u8; libc::IFNAMSIZ]>);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(GetOnly, OriginalDst, libc::SOL_IP, libc::SO_ORIGINAL_DST, libc::sockaddr_in);
-sockopt_impl!(Both, ReceiveTimestamp, libc::SOL_SOCKET, libc::SO_TIMESTAMP, bool);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(Both, IpTransparent, libc::SOL_IP, libc::IP_TRANSPARENT, bool);
-#[cfg(target_os = "openbsd")]
-sockopt_impl!(Both, BindAny, libc::SOL_SOCKET, libc::SO_BINDANY, bool);
-#[cfg(target_os = "freebsd")]
-sockopt_impl!(Both, BindAny, libc::IPPROTO_IP, libc::IP_BINDANY, bool);
-#[cfg(target_os = "linux")]
-sockopt_impl!(Both, Mark, libc::SOL_SOCKET, libc::SO_MARK, u32);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(Both, PassCred, libc::SOL_SOCKET, libc::SO_PASSCRED, bool);
-#[cfg(any(target_os = "freebsd", target_os = "linux"))]
-sockopt_impl!(Both, TcpCongestion, libc::IPPROTO_TCP, libc::TCP_CONGESTION, OsString<[u8; TCP_CA_NAME_MAX]>);
-#[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
-))]
-sockopt_impl!(Both, Ipv4PacketInfo, libc::IPPROTO_IP, libc::IP_PKTINFO, bool);
-#[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
-))]
-sockopt_impl!(Both, Ipv6RecvPacketInfo, libc::IPPROTO_IPV6, libc::IPV6_RECVPKTINFO, bool);
-#[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
-))]
-sockopt_impl!(Both, Ipv4RecvIf, libc::IPPROTO_IP, libc::IP_RECVIF, bool);
-#[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
-))]
-sockopt_impl!(Both, Ipv4RecvDstAddr, libc::IPPROTO_IP, libc::IP_RECVDSTADDR, bool);
-#[cfg(target_os = "linux")]
-sockopt_impl!(Both, UdpGsoSegment, libc::SOL_UDP, libc::UDP_SEGMENT, libc::c_int);
-#[cfg(target_os = "linux")]
-sockopt_impl!(Both, UdpGroSegment, libc::IPPROTO_UDP, libc::UDP_GRO, bool);
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[derive(Copy, Clone, Debug)]
-pub struct AlgSetAeadAuthSize;
-
-// ALG_SET_AEAD_AUTH_SIZE read the length from passed `option_len`
-// See https://elixir.bootlin.com/linux/v4.4/source/crypto/af_alg.c#L222
-#[cfg(any(target_os = "android", target_os = "linux"))]
-impl SetSockOpt for AlgSetAeadAuthSize {
- type Val = usize;
-
- fn set(&self, fd: RawFd, val: &usize) -> Result<()> {
- unsafe {
- let res = libc::setsockopt(fd,
- libc::SOL_ALG,
- libc::ALG_SET_AEAD_AUTHSIZE,
- ::std::ptr::null(),
- *val as libc::socklen_t);
- Errno::result(res).map(drop)
- }
- }
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[derive(Clone, Debug)]
-pub struct AlgSetKey<T>(::std::marker::PhantomData<T>);
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-impl<T> Default for AlgSetKey<T> {
- fn default() -> Self {
- AlgSetKey(Default::default())
- }
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-impl<T> SetSockOpt for AlgSetKey<T> where T: AsRef<[u8]> + Clone {
- type Val = T;
-
- fn set(&self, fd: RawFd, val: &T) -> Result<()> {
- unsafe {
- let res = libc::setsockopt(fd,
- libc::SOL_ALG,
- libc::ALG_SET_KEY,
- val.as_ref().as_ptr() as *const _,
- val.as_ref().len() as libc::socklen_t);
- Errno::result(res).map(drop)
- }
- }
-}
-
-/*
- *
- * ===== Accessor helpers =====
- *
- */
-
-/// Helper trait that describes what is expected from a `GetSockOpt` getter.
-unsafe trait Get<T> {
- /// Returns an uninitialized value.
- unsafe fn uninit() -> Self;
- /// Returns a pointer to the stored value. This pointer will be passed to the system's
- /// `getsockopt` call (`man 3p getsockopt`, argument `option_value`).
- fn ffi_ptr(&mut self) -> *mut c_void;
- /// Returns length of the stored value. This pointer will be passed to the system's
- /// `getsockopt` call (`man 3p getsockopt`, argument `option_len`).
- fn ffi_len(&mut self) -> *mut socklen_t;
- /// Returns the hopefully initialized inner value.
- unsafe fn assume_init(self) -> T;
-}
-
-/// Helper trait that describes what is expected from a `SetSockOpt` setter.
-unsafe trait Set<'a, T> {
- /// Initialize the setter with a given value.
- fn new(val: &'a T) -> Self;
- /// Returns a pointer to the stored value. This pointer will be passed to the system's
- /// `setsockopt` call (`man 3p setsockopt`, argument `option_value`).
- fn ffi_ptr(&self) -> *const c_void;
- /// Returns length of the stored value. This pointer will be passed to the system's
- /// `setsockopt` call (`man 3p setsockopt`, argument `option_len`).
- fn ffi_len(&self) -> socklen_t;
-}
-
-/// Getter for an arbitrary `struct`.
-struct GetStruct<T> {
- len: socklen_t,
- val: MaybeUninit<T>,
-}
-
-unsafe impl<T> Get<T> for GetStruct<T> {
- unsafe fn uninit() -> Self {
- GetStruct {
- len: mem::size_of::<T>() as socklen_t,
- val: MaybeUninit::uninit(),
- }
- }
-
- fn ffi_ptr(&mut self) -> *mut c_void {
- self.val.as_mut_ptr() as *mut c_void
- }
-
- fn ffi_len(&mut self) -> *mut socklen_t {
- &mut self.len
- }
-
- unsafe fn assume_init(self) -> T {
- assert_eq!(self.len as usize, mem::size_of::<T>(), "invalid getsockopt implementation");
- self.val.assume_init()
- }
-}
-
-/// Setter for an arbitrary `struct`.
-struct SetStruct<'a, T: 'static> {
- ptr: &'a T,
-}
-
-unsafe impl<'a, T> Set<'a, T> for SetStruct<'a, T> {
- fn new(ptr: &'a T) -> SetStruct<'a, T> {
- SetStruct { ptr }
- }
-
- fn ffi_ptr(&self) -> *const c_void {
- self.ptr as *const T as *const c_void
- }
-
- fn ffi_len(&self) -> socklen_t {
- mem::size_of::<T>() as socklen_t
- }
-}
-
-/// Getter for a boolean value.
-struct GetBool {
- len: socklen_t,
- val: MaybeUninit<c_int>,
-}
-
-unsafe impl Get<bool> for GetBool {
- unsafe fn uninit() -> Self {
- GetBool {
- len: mem::size_of::<c_int>() as socklen_t,
- val: MaybeUninit::uninit(),
- }
- }
-
- fn ffi_ptr(&mut self) -> *mut c_void {
- self.val.as_mut_ptr() as *mut c_void
- }
-
- fn ffi_len(&mut self) -> *mut socklen_t {
- &mut self.len
- }
-
- unsafe fn assume_init(self) -> bool {
- assert_eq!(self.len as usize, mem::size_of::<c_int>(), "invalid getsockopt implementation");
- self.val.assume_init() != 0
- }
-}
-
-/// Setter for a boolean value.
-struct SetBool {
- val: c_int,
-}
-
-unsafe impl<'a> Set<'a, bool> for SetBool {
- fn new(val: &'a bool) -> SetBool {
- SetBool { val: if *val { 1 } else { 0 } }
- }
-
- fn ffi_ptr(&self) -> *const c_void {
- &self.val as *const c_int as *const c_void
- }
-
- fn ffi_len(&self) -> socklen_t {
- mem::size_of::<c_int>() as socklen_t
- }
-}
-
-/// Getter for an `u8` value.
-struct GetU8 {
- len: socklen_t,
- val: MaybeUninit<u8>,
-}
-
-unsafe impl Get<u8> for GetU8 {
- unsafe fn uninit() -> Self {
- GetU8 {
- len: mem::size_of::<u8>() as socklen_t,
- val: MaybeUninit::uninit(),
- }
- }
-
- fn ffi_ptr(&mut self) -> *mut c_void {
- self.val.as_mut_ptr() as *mut c_void
- }
-
- fn ffi_len(&mut self) -> *mut socklen_t {
- &mut self.len
- }
-
- unsafe fn assume_init(self) -> u8 {
- assert_eq!(self.len as usize, mem::size_of::<u8>(), "invalid getsockopt implementation");
- self.val.assume_init()
- }
-}
-
-/// Setter for an `u8` value.
-struct SetU8 {
- val: u8,
-}
-
-unsafe impl<'a> Set<'a, u8> for SetU8 {
- fn new(val: &'a u8) -> SetU8 {
- SetU8 { val: *val as u8 }
- }
-
- fn ffi_ptr(&self) -> *const c_void {
- &self.val as *const u8 as *const c_void
- }
-
- fn ffi_len(&self) -> socklen_t {
- mem::size_of::<c_int>() as socklen_t
- }
-}
-
-/// Getter for an `usize` value.
-struct GetUsize {
- len: socklen_t,
- val: MaybeUninit<c_int>,
-}
-
-unsafe impl Get<usize> for GetUsize {
- unsafe fn uninit() -> Self {
- GetUsize {
- len: mem::size_of::<c_int>() as socklen_t,
- val: MaybeUninit::uninit(),
- }
- }
-
- fn ffi_ptr(&mut self) -> *mut c_void {
- self.val.as_mut_ptr() as *mut c_void
- }
-
- fn ffi_len(&mut self) -> *mut socklen_t {
- &mut self.len
- }
-
- unsafe fn assume_init(self) -> usize {
- assert_eq!(self.len as usize, mem::size_of::<c_int>(), "invalid getsockopt implementation");
- self.val.assume_init() as usize
- }
-}
-
-/// Setter for an `usize` value.
-struct SetUsize {
- val: c_int,
-}
-
-unsafe impl<'a> Set<'a, usize> for SetUsize {
- fn new(val: &'a usize) -> SetUsize {
- SetUsize { val: *val as c_int }
- }
-
- fn ffi_ptr(&self) -> *const c_void {
- &self.val as *const c_int as *const c_void
- }
-
- fn ffi_len(&self) -> socklen_t {
- mem::size_of::<c_int>() as socklen_t
- }
-}
-
-/// Getter for a `OsString` value.
-struct GetOsString<T: AsMut<[u8]>> {
- len: socklen_t,
- val: MaybeUninit<T>,
-}
-
-unsafe impl<T: AsMut<[u8]>> Get<OsString> for GetOsString<T> {
- unsafe fn uninit() -> Self {
- GetOsString {
- len: mem::size_of::<T>() as socklen_t,
- val: MaybeUninit::uninit(),
- }
- }
-
- fn ffi_ptr(&mut self) -> *mut c_void {
- self.val.as_mut_ptr() as *mut c_void
- }
-
- fn ffi_len(&mut self) -> *mut socklen_t {
- &mut self.len
- }
-
- unsafe fn assume_init(self) -> OsString {
- let len = self.len as usize;
- let mut v = self.val.assume_init();
- OsStr::from_bytes(&v.as_mut()[0..len]).to_owned()
- }
-}
-
-/// Setter for a `OsString` value.
-struct SetOsString<'a> {
- val: &'a OsStr,
-}
-
-unsafe impl<'a> Set<'a, OsString> for SetOsString<'a> {
- fn new(val: &'a OsString) -> SetOsString {
- SetOsString { val: val.as_os_str() }
- }
-
- fn ffi_ptr(&self) -> *const c_void {
- self.val.as_bytes().as_ptr() as *const c_void
- }
-
- fn ffi_len(&self) -> socklen_t {
- self.val.len() as socklen_t
- }
-}
-
-
-#[cfg(test)]
-mod test {
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[test]
- fn can_get_peercred_on_unix_socket() {
- use super::super::*;
-
- let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap();
- let a_cred = getsockopt(a, super::PeerCredentials).unwrap();
- let b_cred = getsockopt(b, super::PeerCredentials).unwrap();
- assert_eq!(a_cred, b_cred);
- assert!(a_cred.pid() != 0);
- }
-
- #[test]
- fn is_socket_type_unix() {
- use super::super::*;
- use crate::unistd::close;
-
- let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap();
- let a_type = getsockopt(a, super::SockType).unwrap();
- assert_eq!(a_type, SockType::Stream);
- close(a).unwrap();
- close(b).unwrap();
- }
-
- #[test]
- fn is_socket_type_dgram() {
- use super::super::*;
- use crate::unistd::close;
-
- let s = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None).unwrap();
- let s_type = getsockopt(s, super::SockType).unwrap();
- assert_eq!(s_type, SockType::Datagram);
- close(s).unwrap();
- }
-
- #[cfg(any(target_os = "freebsd",
- target_os = "linux",
- target_os = "nacl"))]
- #[test]
- fn can_get_listen_on_tcp_socket() {
- use super::super::*;
- use crate::unistd::close;
-
- let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
- let s_listening = getsockopt(s, super::AcceptConn).unwrap();
- assert!(!s_listening);
- listen(s, 10).unwrap();
- let s_listening2 = getsockopt(s, super::AcceptConn).unwrap();
- assert!(s_listening2);
- close(s).unwrap();
- }
-
-}
diff --git a/vendor/nix-0.20.0/src/sys/stat.rs b/vendor/nix-0.20.0/src/sys/stat.rs
deleted file mode 100644
index df81a2c..0000000
--- a/vendor/nix-0.20.0/src/sys/stat.rs
+++ /dev/null
@@ -1,297 +0,0 @@
-pub use libc::{dev_t, mode_t};
-pub use libc::stat as FileStat;
-
-use crate::{Result, NixPath, errno::Errno};
-#[cfg(not(target_os = "redox"))]
-use crate::fcntl::{AtFlags, at_rawfd};
-use std::mem;
-use std::os::unix::io::RawFd;
-use crate::sys::time::{TimeSpec, TimeVal};
-
-libc_bitflags!(
- pub struct SFlag: mode_t {
- S_IFIFO;
- S_IFCHR;
- S_IFDIR;
- S_IFBLK;
- S_IFREG;
- S_IFLNK;
- S_IFSOCK;
- S_IFMT;
- }
-);
-
-libc_bitflags! {
- pub struct Mode: mode_t {
- S_IRWXU;
- S_IRUSR;
- S_IWUSR;
- S_IXUSR;
- S_IRWXG;
- S_IRGRP;
- S_IWGRP;
- S_IXGRP;
- S_IRWXO;
- S_IROTH;
- S_IWOTH;
- S_IXOTH;
- S_ISUID as mode_t;
- S_ISGID as mode_t;
- S_ISVTX as mode_t;
- }
-}
-
-pub fn mknod<P: ?Sized + NixPath>(path: &P, kind: SFlag, perm: Mode, dev: dev_t) -> Result<()> {
- let res = path.with_nix_path(|cstr| {
- unsafe {
- libc::mknod(cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev)
- }
- })?;
-
- Errno::result(res).map(drop)
-}
-
-#[cfg(target_os = "linux")]
-pub fn major(dev: dev_t) -> u64 {
- ((dev >> 32) & 0xffff_f000) |
- ((dev >> 8) & 0x0000_0fff)
-}
-
-#[cfg(target_os = "linux")]
-pub fn minor(dev: dev_t) -> u64 {
- ((dev >> 12) & 0xffff_ff00) |
- ((dev ) & 0x0000_00ff)
-}
-
-#[cfg(target_os = "linux")]
-pub fn makedev(major: u64, minor: u64) -> dev_t {
- ((major & 0xffff_f000) << 32) |
- ((major & 0x0000_0fff) << 8) |
- ((minor & 0xffff_ff00) << 12) |
- (minor & 0x0000_00ff)
-}
-
-pub fn umask(mode: Mode) -> Mode {
- let prev = unsafe { libc::umask(mode.bits() as mode_t) };
- Mode::from_bits(prev).expect("[BUG] umask returned invalid Mode")
-}
-
-pub fn stat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
- let mut dst = mem::MaybeUninit::uninit();
- let res = path.with_nix_path(|cstr| {
- unsafe {
- libc::stat(cstr.as_ptr(), dst.as_mut_ptr())
- }
- })?;
-
- Errno::result(res)?;
-
- Ok(unsafe{dst.assume_init()})
-}
-
-pub fn lstat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
- let mut dst = mem::MaybeUninit::uninit();
- let res = path.with_nix_path(|cstr| {
- unsafe {
- libc::lstat(cstr.as_ptr(), dst.as_mut_ptr())
- }
- })?;
-
- Errno::result(res)?;
-
- Ok(unsafe{dst.assume_init()})
-}
-
-pub fn fstat(fd: RawFd) -> Result<FileStat> {
- let mut dst = mem::MaybeUninit::uninit();
- let res = unsafe { libc::fstat(fd, dst.as_mut_ptr()) };
-
- Errno::result(res)?;
-
- Ok(unsafe{dst.assume_init()})
-}
-
-#[cfg(not(target_os = "redox"))]
-pub fn fstatat<P: ?Sized + NixPath>(dirfd: RawFd, pathname: &P, f: AtFlags) -> Result<FileStat> {
- let mut dst = mem::MaybeUninit::uninit();
- let res = pathname.with_nix_path(|cstr| {
- unsafe { libc::fstatat(dirfd, cstr.as_ptr(), dst.as_mut_ptr(), f.bits() as libc::c_int) }
- })?;
-
- Errno::result(res)?;
-
- Ok(unsafe{dst.assume_init()})
-}
-
-/// Change the file permission bits of the file specified by a file descriptor.
-///
-/// # References
-///
-/// [fchmod(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html).
-pub fn fchmod(fd: RawFd, mode: Mode) -> Result<()> {
- let res = unsafe { libc::fchmod(fd, mode.bits() as mode_t) };
-
- Errno::result(res).map(drop)
-}
-
-/// Flags for `fchmodat` function.
-#[derive(Clone, Copy, Debug)]
-pub enum FchmodatFlags {
- FollowSymlink,
- NoFollowSymlink,
-}
-
-/// Change the file permission bits.
-///
-/// The file to be changed is determined relative to the directory associated
-/// with the file descriptor `dirfd` or the current working directory
-/// if `dirfd` is `None`.
-///
-/// If `flag` is `FchmodatFlags::NoFollowSymlink` and `path` names a symbolic link,
-/// then the mode of the symbolic link is changed.
-///
-/// `fchmodat(None, path, mode, FchmodatFlags::FollowSymlink)` is identical to
-/// a call `libc::chmod(path, mode)`. That's why `chmod` is unimplemented
-/// in the `nix` crate.
-///
-/// # References
-///
-/// [fchmodat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html).
-#[cfg(not(target_os = "redox"))]
-pub fn fchmodat<P: ?Sized + NixPath>(
- dirfd: Option<RawFd>,
- path: &P,
- mode: Mode,
- flag: FchmodatFlags,
-) -> Result<()> {
- let atflag =
- match flag {
- FchmodatFlags::FollowSymlink => AtFlags::empty(),
- FchmodatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
- };
- let res = path.with_nix_path(|cstr| unsafe {
- libc::fchmodat(
- at_rawfd(dirfd),
- cstr.as_ptr(),
- mode.bits() as mode_t,
- atflag.bits() as libc::c_int,
- )
- })?;
-
- Errno::result(res).map(drop)
-}
-
-/// Change the access and modification times of a file.
-///
-/// `utimes(path, times)` is identical to
-/// `utimensat(None, path, times, UtimensatFlags::FollowSymlink)`. The former
-/// is a deprecated API so prefer using the latter if the platforms you care
-/// about support it.
-///
-/// # References
-///
-/// [utimes(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/utimes.html).
-pub fn utimes<P: ?Sized + NixPath>(path: &P, atime: &TimeVal, mtime: &TimeVal) -> Result<()> {
- let times: [libc::timeval; 2] = [*atime.as_ref(), *mtime.as_ref()];
- let res = path.with_nix_path(|cstr| unsafe {
- libc::utimes(cstr.as_ptr(), ×[0])
- })?;
-
- Errno::result(res).map(drop)
-}
-
-/// Change the access and modification times of a file without following symlinks.
-///
-/// `lutimes(path, times)` is identical to
-/// `utimensat(None, path, times, UtimensatFlags::NoFollowSymlink)`. The former
-/// is a deprecated API so prefer using the latter if the platforms you care
-/// about support it.
-///
-/// # References
-///
-/// [lutimes(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lutimes.html).
-#[cfg(any(target_os = "linux",
- target_os = "haiku",
- target_os = "ios",
- target_os = "macos",
- target_os = "freebsd",
- target_os = "netbsd"))]
-pub fn lutimes<P: ?Sized + NixPath>(path: &P, atime: &TimeVal, mtime: &TimeVal) -> Result<()> {
- let times: [libc::timeval; 2] = [*atime.as_ref(), *mtime.as_ref()];
- let res = path.with_nix_path(|cstr| unsafe {
- libc::lutimes(cstr.as_ptr(), ×[0])
- })?;
-
- Errno::result(res).map(drop)
-}
-
-/// Change the access and modification times of the file specified by a file descriptor.
-///
-/// # References
-///
-/// [futimens(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html).
-#[inline]
-pub fn futimens(fd: RawFd, atime: &TimeSpec, mtime: &TimeSpec) -> Result<()> {
- let times: [libc::timespec; 2] = [*atime.as_ref(), *mtime.as_ref()];
- let res = unsafe { libc::futimens(fd, ×[0]) };
-
- Errno::result(res).map(drop)
-}
-
-/// Flags for `utimensat` function.
-#[derive(Clone, Copy, Debug)]
-pub enum UtimensatFlags {
- FollowSymlink,
- NoFollowSymlink,
-}
-
-/// Change the access and modification times of a file.
-///
-/// The file to be changed is determined relative to the directory associated
-/// with the file descriptor `dirfd` or the current working directory
-/// if `dirfd` is `None`.
-///
-/// If `flag` is `UtimensatFlags::NoFollowSymlink` and `path` names a symbolic link,
-/// then the mode of the symbolic link is changed.
-///
-/// `utimensat(None, path, times, UtimensatFlags::FollowSymlink)` is identical to
-/// `utimes(path, times)`. The latter is a deprecated API so prefer using the
-/// former if the platforms you care about support it.
-///
-/// # References
-///
-/// [utimensat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/utimens.html).
-#[cfg(not(target_os = "redox"))]
-pub fn utimensat<P: ?Sized + NixPath>(
- dirfd: Option<RawFd>,
- path: &P,
- atime: &TimeSpec,
- mtime: &TimeSpec,
- flag: UtimensatFlags
-) -> Result<()> {
- let atflag =
- match flag {
- UtimensatFlags::FollowSymlink => AtFlags::empty(),
- UtimensatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
- };
- let times: [libc::timespec; 2] = [*atime.as_ref(), *mtime.as_ref()];
- let res = path.with_nix_path(|cstr| unsafe {
- libc::utimensat(
- at_rawfd(dirfd),
- cstr.as_ptr(),
- ×[0],
- atflag.bits() as libc::c_int,
- )
- })?;
-
- Errno::result(res).map(drop)
-}
-
-#[cfg(not(target_os = "redox"))]
-pub fn mkdirat<P: ?Sized + NixPath>(fd: RawFd, path: &P, mode: Mode) -> Result<()> {
- let res = path.with_nix_path(|cstr| {
- unsafe { libc::mkdirat(fd, cstr.as_ptr(), mode.bits() as mode_t) }
- })?;
-
- Errno::result(res).map(drop)
-}
diff --git a/vendor/nix-0.20.0/src/sys/statfs.rs b/vendor/nix-0.20.0/src/sys/statfs.rs
deleted file mode 100644
index 27b7259..0000000
--- a/vendor/nix-0.20.0/src/sys/statfs.rs
+++ /dev/null
@@ -1,568 +0,0 @@
-use std::fmt::{self, Debug};
-use std::mem;
-use std::os::unix::io::AsRawFd;
-#[cfg(not(any(target_os = "linux", target_os = "android")))]
-use std::ffi::CStr;
-
-use crate::{NixPath, Result, errno::Errno};
-
-#[cfg(target_os = "android")]
-pub type fsid_t = libc::__fsid_t;
-#[cfg(not(target_os = "android"))]
-pub type fsid_t = libc::fsid_t;
-
-#[derive(Clone, Copy)]
-#[repr(transparent)]
-pub struct Statfs(libc::statfs);
-
-#[cfg(target_os = "freebsd")]
-type fs_type_t = u32;
-#[cfg(target_os = "android")]
-type fs_type_t = libc::c_ulong;
-#[cfg(all(target_os = "linux", target_arch = "s390x"))]
-type fs_type_t = libc::c_uint;
-#[cfg(all(target_os = "linux", target_env = "musl"))]
-type fs_type_t = libc::c_ulong;
-#[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
-type fs_type_t = libc::__fsword_t;
-
-#[cfg(any(
- target_os = "freebsd",
- target_os = "android",
- all(target_os = "linux", target_arch = "s390x"),
- all(target_os = "linux", target_env = "musl"),
- all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))),
-))]
-#[derive(Eq, Copy, Clone, PartialEq, Debug)]
-pub struct FsType(pub fs_type_t);
-
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const ADFS_SUPER_MAGIC: FsType = FsType(libc::ADFS_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const AFFS_SUPER_MAGIC: FsType = FsType(libc::AFFS_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const CODA_SUPER_MAGIC: FsType = FsType(libc::CODA_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const EXT2_SUPER_MAGIC: FsType = FsType(libc::EXT2_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const HPFS_SUPER_MAGIC: FsType = FsType(libc::HPFS_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const ISOFS_SUPER_MAGIC: FsType = FsType(libc::ISOFS_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const JFFS2_SUPER_MAGIC: FsType = FsType(libc::JFFS2_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const MINIX_SUPER_MAGIC: FsType = FsType(libc::MINIX_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const MINIX_SUPER_MAGIC2: FsType = FsType(libc::MINIX_SUPER_MAGIC2 as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const MINIX2_SUPER_MAGIC: FsType = FsType(libc::MINIX2_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const MINIX2_SUPER_MAGIC2: FsType = FsType(libc::MINIX2_SUPER_MAGIC2 as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const MSDOS_SUPER_MAGIC: FsType = FsType(libc::MSDOS_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const OPENPROM_SUPER_MAGIC: FsType = FsType(libc::OPENPROM_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const OVERLAYFS_SUPER_MAGIC: FsType = FsType(libc::OVERLAYFS_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const PROC_SUPER_MAGIC: FsType = FsType(libc::PROC_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const QNX4_SUPER_MAGIC: FsType = FsType(libc::QNX4_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const REISERFS_SUPER_MAGIC: FsType = FsType(libc::REISERFS_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const USBDEVICE_SUPER_MAGIC: FsType = FsType(libc::USBDEVICE_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const CGROUP_SUPER_MAGIC: FsType = FsType(libc::CGROUP_SUPER_MAGIC as fs_type_t);
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-pub const CGROUP2_SUPER_MAGIC: FsType = FsType(libc::CGROUP2_SUPER_MAGIC as fs_type_t);
-
-
-impl Statfs {
- /// Magic code defining system type
- #[cfg(not(any(
- target_os = "openbsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos"
- )))]
- pub fn filesystem_type(&self) -> FsType {
- FsType(self.0.f_type)
- }
-
- /// Magic code defining system type
- #[cfg(not(any(target_os = "linux", target_os = "android")))]
- pub fn filesystem_type_name(&self) -> &str {
- let c_str = unsafe { CStr::from_ptr(self.0.f_fstypename.as_ptr()) };
- c_str.to_str().unwrap()
- }
-
- /// Optimal transfer block size
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- pub fn optimal_transfer_size(&self) -> i32 {
- self.0.f_iosize
- }
-
- /// Optimal transfer block size
- #[cfg(target_os = "openbsd")]
- pub fn optimal_transfer_size(&self) -> u32 {
- self.0.f_iosize
- }
-
- /// Optimal transfer block size
- #[cfg(all(target_os = "linux", target_arch = "s390x"))]
- pub fn optimal_transfer_size(&self) -> u32 {
- self.0.f_bsize
- }
-
- /// Optimal transfer block size
- #[cfg(any(
- target_os = "android",
- all(target_os = "linux", target_env = "musl")
- ))]
- pub fn optimal_transfer_size(&self) -> libc::c_ulong {
- self.0.f_bsize
- }
-
- /// Optimal transfer block size
- #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
- pub fn optimal_transfer_size(&self) -> libc::__fsword_t {
- self.0.f_bsize
- }
-
- /// Optimal transfer block size
- #[cfg(target_os = "dragonfly")]
- pub fn optimal_transfer_size(&self) -> libc::c_long {
- self.0.f_iosize
- }
-
- /// Optimal transfer block size
- #[cfg(target_os = "freebsd")]
- pub fn optimal_transfer_size(&self) -> u64 {
- self.0.f_iosize
- }
-
- /// Size of a block
- #[cfg(any(target_os = "ios", target_os = "macos", target_os = "openbsd"))]
- pub fn block_size(&self) -> u32 {
- self.0.f_bsize
- }
-
- /// Size of a block
- // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
- #[cfg(all(target_os = "linux", target_arch = "s390x"))]
- pub fn block_size(&self) -> u32 {
- self.0.f_bsize
- }
-
- /// Size of a block
- // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
- #[cfg(all(target_os = "linux", target_env = "musl"))]
- pub fn block_size(&self) -> libc::c_ulong {
- self.0.f_bsize
- }
-
- /// Size of a block
- // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
- #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
- pub fn block_size(&self) -> libc::__fsword_t {
- self.0.f_bsize
- }
-
- /// Size of a block
- #[cfg(target_os = "freebsd")]
- pub fn block_size(&self) -> u64 {
- self.0.f_bsize
- }
-
- /// Size of a block
- #[cfg(target_os = "android")]
- pub fn block_size(&self) -> libc::c_ulong {
- self.0.f_bsize
- }
-
- /// Size of a block
- #[cfg(target_os = "dragonfly")]
- pub fn block_size(&self) -> libc::c_long {
- self.0.f_bsize
- }
-
- /// Maximum length of filenames
- #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
- pub fn maximum_name_length(&self) -> u32 {
- self.0.f_namemax
- }
-
- /// Maximum length of filenames
- #[cfg(all(target_os = "linux", target_arch = "s390x"))]
- pub fn maximum_name_length(&self) -> u32 {
- self.0.f_namelen
- }
-
- /// Maximum length of filenames
- #[cfg(all(target_os = "linux", target_env = "musl"))]
- pub fn maximum_name_length(&self) -> libc::c_ulong {
- self.0.f_namelen
- }
-
- /// Maximum length of filenames
- #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
- pub fn maximum_name_length(&self) -> libc::__fsword_t {
- self.0.f_namelen
- }
-
- /// Maximum length of filenames
- #[cfg(target_os = "android")]
- pub fn maximum_name_length(&self) -> libc::c_ulong {
- self.0.f_namelen
- }
-
- /// Total data blocks in filesystem
- #[cfg(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
- target_os = "freebsd",
- target_os = "openbsd",
- ))]
- pub fn blocks(&self) -> u64 {
- self.0.f_blocks
- }
-
- /// Total data blocks in filesystem
- #[cfg(target_os = "dragonfly")]
- pub fn blocks(&self) -> libc::c_long {
- self.0.f_blocks
- }
-
- /// Total data blocks in filesystem
- #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))]
- pub fn blocks(&self) -> u64 {
- self.0.f_blocks
- }
-
- /// Total data blocks in filesystem
- #[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "dragonfly",
- all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32")))
- )))]
- pub fn blocks(&self) -> libc::c_ulong {
- self.0.f_blocks
- }
-
- /// Free blocks in filesystem
- #[cfg(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
- target_os = "freebsd",
- target_os = "openbsd",
- ))]
- pub fn blocks_free(&self) -> u64 {
- self.0.f_bfree
- }
-
- /// Free blocks in filesystem
- #[cfg(target_os = "dragonfly")]
- pub fn blocks_free(&self) -> libc::c_long {
- self.0.f_bfree
- }
-
- /// Free blocks in filesystem
- #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))]
- pub fn blocks_free(&self) -> u64 {
- self.0.f_bfree
- }
-
- /// Free blocks in filesystem
- #[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "dragonfly",
- all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32")))
- )))]
- pub fn blocks_free(&self) -> libc::c_ulong {
- self.0.f_bfree
- }
-
- /// Free blocks available to unprivileged user
- #[cfg(any(target_os = "ios", target_os = "macos", target_os = "android"))]
- pub fn blocks_available(&self) -> u64 {
- self.0.f_bavail
- }
-
- /// Free blocks available to unprivileged user
- #[cfg(target_os = "dragonfly")]
- pub fn blocks_available(&self) -> libc::c_long {
- self.0.f_bavail
- }
-
- /// Free blocks available to unprivileged user
- #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
- pub fn blocks_available(&self) -> i64 {
- self.0.f_bavail
- }
-
- /// Free blocks available to unprivileged user
- #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))]
- pub fn blocks_available(&self) -> u64 {
- self.0.f_bavail
- }
-
- /// Free blocks available to unprivileged user
- #[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "dragonfly",
- all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32")))
- )))]
- pub fn blocks_available(&self) -> libc::c_ulong {
- self.0.f_bavail
- }
-
- /// Total file nodes in filesystem
- #[cfg(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
- target_os = "freebsd",
- target_os = "openbsd",
- ))]
- pub fn files(&self) -> u64 {
- self.0.f_files
- }
-
- /// Total file nodes in filesystem
- #[cfg(target_os = "dragonfly")]
- pub fn files(&self) -> libc::c_long {
- self.0.f_files
- }
-
- /// Total file nodes in filesystem
- #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))]
- pub fn files(&self) -> libc::fsfilcnt_t {
- self.0.f_files
- }
-
- /// Total file nodes in filesystem
- #[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "dragonfly",
- all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32")))
- )))]
- pub fn files(&self) -> libc::c_ulong {
- self.0.f_files
- }
-
- /// Free file nodes in filesystem
- #[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "macos",
- target_os = "openbsd"
- ))]
- pub fn files_free(&self) -> u64 {
- self.0.f_ffree
- }
-
- /// Free file nodes in filesystem
- #[cfg(target_os = "dragonfly")]
- pub fn files_free(&self) -> libc::c_long {
- self.0.f_ffree
- }
-
- /// Free file nodes in filesystem
- #[cfg(target_os = "freebsd")]
- pub fn files_free(&self) -> i64 {
- self.0.f_ffree
- }
-
- /// Free file nodes in filesystem
- #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))]
- pub fn files_free(&self) -> libc::fsfilcnt_t {
- self.0.f_ffree
- }
-
- /// Free file nodes in filesystem
- #[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "dragonfly",
- all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32")))
- )))]
- pub fn files_free(&self) -> libc::c_ulong {
- self.0.f_ffree
- }
-
- /// Filesystem ID
- pub fn filesystem_id(&self) -> fsid_t {
- self.0.f_fsid
- }
-}
-
-impl Debug for Statfs {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_struct("Statfs")
- .field("optimal_transfer_size", &self.optimal_transfer_size())
- .field("block_size", &self.block_size())
- .field("blocks", &self.blocks())
- .field("blocks_free", &self.blocks_free())
- .field("blocks_available", &self.blocks_available())
- .field("files", &self.files())
- .field("files_free", &self.files_free())
- .field("filesystem_id", &self.filesystem_id())
- .finish()
- }
-}
-
-pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> {
- unsafe {
- let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
- let res = path.with_nix_path(|path| libc::statfs(path.as_ptr(), stat.as_mut_ptr()))?;
- Errno::result(res).map(|_| Statfs(stat.assume_init()))
- }
-}
-
-pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> {
- unsafe {
- let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
- Errno::result(libc::fstatfs(fd.as_raw_fd(), stat.as_mut_ptr()))
- .map(|_| Statfs(stat.assume_init()))
- }
-}
-
-#[cfg(test)]
-mod test {
- use std::fs::File;
-
- use crate::sys::statfs::*;
- use crate::sys::statvfs::*;
- use std::path::Path;
-
- #[test]
- fn statfs_call() {
- check_statfs("/tmp");
- check_statfs("/dev");
- check_statfs("/run");
- check_statfs("/");
- }
-
- #[test]
- fn fstatfs_call() {
- check_fstatfs("/tmp");
- check_fstatfs("/dev");
- check_fstatfs("/run");
- check_fstatfs("/");
- }
-
- fn check_fstatfs(path: &str) {
- if !Path::new(path).exists() {
- return;
- }
- let vfs = statvfs(path.as_bytes()).unwrap();
- let file = File::open(path).unwrap();
- let fs = fstatfs(&file).unwrap();
- assert_fs_equals(fs, vfs);
- }
-
- fn check_statfs(path: &str) {
- if !Path::new(path).exists() {
- return;
- }
- let vfs = statvfs(path.as_bytes()).unwrap();
- let fs = statfs(path.as_bytes()).unwrap();
- assert_fs_equals(fs, vfs);
- }
-
- fn assert_fs_equals(fs: Statfs, vfs: Statvfs) {
- assert_eq!(fs.files() as u64, vfs.files() as u64);
- assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
- assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
- }
-
- // This test is ignored because files_free/blocks_free can change after statvfs call and before
- // statfs call.
- #[test]
- #[ignore]
- fn statfs_call_strict() {
- check_statfs_strict("/tmp");
- check_statfs_strict("/dev");
- check_statfs_strict("/run");
- check_statfs_strict("/");
- }
-
- // This test is ignored because files_free/blocks_free can change after statvfs call and before
- // fstatfs call.
- #[test]
- #[ignore]
- fn fstatfs_call_strict() {
- check_fstatfs_strict("/tmp");
- check_fstatfs_strict("/dev");
- check_fstatfs_strict("/run");
- check_fstatfs_strict("/");
- }
-
- fn check_fstatfs_strict(path: &str) {
- if !Path::new(path).exists() {
- return;
- }
- let vfs = statvfs(path.as_bytes());
- let file = File::open(path).unwrap();
- let fs = fstatfs(&file);
- assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
- }
-
- fn check_statfs_strict(path: &str) {
- if !Path::new(path).exists() {
- return;
- }
- let vfs = statvfs(path.as_bytes());
- let fs = statfs(path.as_bytes());
- assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
- }
-
- fn assert_fs_equals_strict(fs: Statfs, vfs: Statvfs) {
- assert_eq!(fs.files_free() as u64, vfs.files_free() as u64);
- assert_eq!(fs.blocks_free() as u64, vfs.blocks_free() as u64);
- assert_eq!(fs.blocks_available() as u64, vfs.blocks_available() as u64);
- assert_eq!(fs.files() as u64, vfs.files() as u64);
- assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
- assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
- }
-}
diff --git a/vendor/nix-0.20.0/src/sys/statvfs.rs b/vendor/nix-0.20.0/src/sys/statvfs.rs
deleted file mode 100644
index 9bea973..0000000
--- a/vendor/nix-0.20.0/src/sys/statvfs.rs
+++ /dev/null
@@ -1,161 +0,0 @@
-//! Get filesystem statistics
-//!
-//! See [the man pages](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html)
-//! for more details.
-use std::mem;
-use std::os::unix::io::AsRawFd;
-
-use libc::{self, c_ulong};
-
-use crate::{Result, NixPath, errno::Errno};
-
-#[cfg(not(target_os = "redox"))]
-libc_bitflags!(
- /// File system mount Flags
- #[repr(C)]
- #[derive(Default)]
- pub struct FsFlags: c_ulong {
- /// Read Only
- ST_RDONLY;
- /// Do not allow the set-uid bits to have an effect
- ST_NOSUID;
- /// Do not interpret character or block-special devices
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ST_NODEV;
- /// Do not allow execution of binaries on the filesystem
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ST_NOEXEC;
- /// All IO should be done synchronously
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ST_SYNCHRONOUS;
- /// Allow mandatory locks on the filesystem
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ST_MANDLOCK;
- /// Write on file/directory/symlink
- #[cfg(target_os = "linux")]
- ST_WRITE;
- /// Append-only file
- #[cfg(target_os = "linux")]
- ST_APPEND;
- /// Immutable file
- #[cfg(target_os = "linux")]
- ST_IMMUTABLE;
- /// Do not update access times on files
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ST_NOATIME;
- /// Do not update access times on files
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ST_NODIRATIME;
- /// Update access time relative to modify/change time
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_env = "musl"))))]
- ST_RELATIME;
- }
-);
-
-/// Wrapper around the POSIX `statvfs` struct
-///
-/// For more information see the [`statvfs(3)` man pages](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_statvfs.h.html).
-#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct Statvfs(libc::statvfs);
-
-impl Statvfs {
- /// get the file system block size
- pub fn block_size(&self) -> c_ulong {
- self.0.f_bsize
- }
-
- /// Get the fundamental file system block size
- pub fn fragment_size(&self) -> c_ulong {
- self.0.f_frsize
- }
-
- /// Get the number of blocks.
- ///
- /// Units are in units of `fragment_size()`
- pub fn blocks(&self) -> libc::fsblkcnt_t {
- self.0.f_blocks
- }
-
- /// Get the number of free blocks in the file system
- pub fn blocks_free(&self) -> libc::fsblkcnt_t {
- self.0.f_bfree
- }
-
- /// Get the number of free blocks for unprivileged users
- pub fn blocks_available(&self) -> libc::fsblkcnt_t {
- self.0.f_bavail
- }
-
- /// Get the total number of file inodes
- pub fn files(&self) -> libc::fsfilcnt_t {
- self.0.f_files
- }
-
- /// Get the number of free file inodes
- pub fn files_free(&self) -> libc::fsfilcnt_t {
- self.0.f_ffree
- }
-
- /// Get the number of free file inodes for unprivileged users
- pub fn files_available(&self) -> libc::fsfilcnt_t {
- self.0.f_favail
- }
-
- /// Get the file system id
- pub fn filesystem_id(&self) -> c_ulong {
- self.0.f_fsid
- }
-
- /// Get the mount flags
- #[cfg(not(target_os = "redox"))]
- pub fn flags(&self) -> FsFlags {
- FsFlags::from_bits_truncate(self.0.f_flag)
- }
-
- /// Get the maximum filename length
- pub fn name_max(&self) -> c_ulong {
- self.0.f_namemax
- }
-
-}
-
-/// Return a `Statvfs` object with information about the `path`
-pub fn statvfs<P: ?Sized + NixPath>(path: &P) -> Result<Statvfs> {
- unsafe {
- Errno::clear();
- let mut stat = mem::MaybeUninit::<libc::statvfs>::uninit();
- let res = path.with_nix_path(|path|
- libc::statvfs(path.as_ptr(), stat.as_mut_ptr())
- )?;
-
- Errno::result(res).map(|_| Statvfs(stat.assume_init()))
- }
-}
-
-/// Return a `Statvfs` object with information about `fd`
-pub fn fstatvfs<T: AsRawFd>(fd: &T) -> Result<Statvfs> {
- unsafe {
- Errno::clear();
- let mut stat = mem::MaybeUninit::<libc::statvfs>::uninit();
- Errno::result(libc::fstatvfs(fd.as_raw_fd(), stat.as_mut_ptr()))
- .map(|_| Statvfs(stat.assume_init()))
- }
-}
-
-#[cfg(test)]
-mod test {
- use std::fs::File;
- use crate::sys::statvfs::*;
-
- #[test]
- fn statvfs_call() {
- statvfs("/".as_bytes()).unwrap();
- }
-
- #[test]
- fn fstatvfs_call() {
- let root = File::open("/").unwrap();
- fstatvfs(&root).unwrap();
- }
-}
diff --git a/vendor/nix-0.20.0/src/sys/sysinfo.rs b/vendor/nix-0.20.0/src/sys/sysinfo.rs
deleted file mode 100644
index 222a2fc..0000000
--- a/vendor/nix-0.20.0/src/sys/sysinfo.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-use libc::{self, SI_LOAD_SHIFT};
-use std::{cmp, mem};
-use std::time::Duration;
-
-use crate::Result;
-use crate::errno::Errno;
-
-/// System info structure returned by `sysinfo`.
-#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
-#[repr(transparent)]
-pub struct SysInfo(libc::sysinfo);
-
-// The fields are c_ulong on 32-bit linux, u64 on 64-bit linux; x32's ulong is u32
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
-type mem_blocks_t = u64;
-#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
-type mem_blocks_t = libc::c_ulong;
-
-impl SysInfo {
- /// Returns the load average tuple.
- ///
- /// The returned values represent the load average over time intervals of
- /// 1, 5, and 15 minutes, respectively.
- pub fn load_average(&self) -> (f64, f64, f64) {
- (
- self.0.loads[0] as f64 / (1 << SI_LOAD_SHIFT) as f64,
- self.0.loads[1] as f64 / (1 << SI_LOAD_SHIFT) as f64,
- self.0.loads[2] as f64 / (1 << SI_LOAD_SHIFT) as f64,
- )
- }
-
- /// Returns the time since system boot.
- pub fn uptime(&self) -> Duration {
- // Truncate negative values to 0
- Duration::from_secs(cmp::max(self.0.uptime, 0) as u64)
- }
-
- /// Current number of processes.
- pub fn process_count(&self) -> u16 {
- self.0.procs
- }
-
- /// Returns the amount of swap memory in Bytes.
- pub fn swap_total(&self) -> u64 {
- self.scale_mem(self.0.totalswap)
- }
-
- /// Returns the amount of unused swap memory in Bytes.
- pub fn swap_free(&self) -> u64 {
- self.scale_mem(self.0.freeswap)
- }
-
- /// Returns the total amount of installed RAM in Bytes.
- pub fn ram_total(&self) -> u64 {
- self.scale_mem(self.0.totalram)
- }
-
- /// Returns the amount of completely unused RAM in Bytes.
- ///
- /// "Unused" in this context means that the RAM in neither actively used by
- /// programs, nor by the operating system as disk cache or buffer. It is
- /// "wasted" RAM since it currently serves no purpose.
- pub fn ram_unused(&self) -> u64 {
- self.scale_mem(self.0.freeram)
- }
-
- fn scale_mem(&self, units: mem_blocks_t) -> u64 {
- units as u64 * self.0.mem_unit as u64
- }
-}
-
-/// Returns system information.
-///
-/// [See `sysinfo(2)`](http://man7.org/linux/man-pages/man2/sysinfo.2.html).
-pub fn sysinfo() -> Result<SysInfo> {
- let mut info = mem::MaybeUninit::uninit();
- let res = unsafe { libc::sysinfo(info.as_mut_ptr()) };
- Errno::result(res).map(|_| unsafe{ SysInfo(info.assume_init()) })
-}
diff --git a/vendor/nix-0.20.0/src/sys/termios.rs b/vendor/nix-0.20.0/src/sys/termios.rs
deleted file mode 100644
index c30de80..0000000
--- a/vendor/nix-0.20.0/src/sys/termios.rs
+++ /dev/null
@@ -1,1090 +0,0 @@
-//! An interface for controlling asynchronous communication ports
-//!
-//! This interface provides a safe wrapper around the termios subsystem defined by POSIX. The
-//! underlying types are all implemented in libc for most platforms and either wrapped in safer
-//! types here or exported directly.
-//!
-//! If you are unfamiliar with the `termios` API, you should first read the
-//! [API documentation](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/termios.h.html) and
-//! then come back to understand how `nix` safely wraps it.
-//!
-//! It should be noted that this API incurs some runtime overhead above the base `libc` definitions.
-//! As this interface is not used with high-bandwidth information, this should be fine in most
-//! cases. The primary cost when using this API is that the `Termios` datatype here duplicates the
-//! standard fields of the underlying `termios` struct and uses safe type wrappers for those fields.
-//! This means that when crossing the FFI interface to the underlying C library, data is first
-//! copied into the underlying `termios` struct, then the operation is done, and the data is copied
-//! back (with additional sanity checking) into the safe wrapper types. The `termios` struct is
-//! relatively small across all platforms (on the order of 32-64 bytes).
-//!
-//! The following examples highlight some of the API use cases such that users coming from using C
-//! or reading the standard documentation will understand how to use the safe API exposed here.
-//!
-//! Example disabling processing of the end-of-file control character:
-//!
-//! ```
-//! # use self::nix::sys::termios::SpecialCharacterIndices::VEOF;
-//! # use self::nix::sys::termios::{_POSIX_VDISABLE, Termios};
-//! # let mut termios: Termios = unsafe { std::mem::zeroed() };
-//! termios.control_chars[VEOF as usize] = _POSIX_VDISABLE;
-//! ```
-//!
-//! The flags within `Termios` are defined as bitfields using the `bitflags` crate. This provides
-//! an interface for working with bitfields that is similar to working with the raw unsigned
-//! integer types but offers type safety because of the internal checking that values will always
-//! be a valid combination of the defined flags.
-//!
-//! An example showing some of the basic operations for interacting with the control flags:
-//!
-//! ```
-//! # use self::nix::sys::termios::{ControlFlags, Termios};
-//! # let mut termios: Termios = unsafe { std::mem::zeroed() };
-//! termios.control_flags & ControlFlags::CSIZE == ControlFlags::CS5;
-//! termios.control_flags |= ControlFlags::CS5;
-//! ```
-//!
-//! # Baud rates
-//!
-//! This API is not consistent across platforms when it comes to `BaudRate`: Android and Linux both
-//! only support the rates specified by the `BaudRate` enum through their termios API while the BSDs
-//! support arbitrary baud rates as the values of the `BaudRate` enum constants are the same integer
-//! value of the constant (`B9600` == `9600`). Therefore the `nix::termios` API uses the following
-//! conventions:
-//!
-//! * `cfgetispeed()` - Returns `u32` on BSDs, `BaudRate` on Android/Linux
-//! * `cfgetospeed()` - Returns `u32` on BSDs, `BaudRate` on Android/Linux
-//! * `cfsetispeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux
-//! * `cfsetospeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux
-//! * `cfsetspeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux
-//!
-//! The most common use case of specifying a baud rate using the enum will work the same across
-//! platforms:
-//!
-//! ```rust
-//! # use nix::sys::termios::{BaudRate, cfsetispeed, cfsetospeed, cfsetspeed, Termios};
-//! # fn main() {
-//! # let mut t: Termios = unsafe { std::mem::zeroed() };
-//! cfsetispeed(&mut t, BaudRate::B9600);
-//! cfsetospeed(&mut t, BaudRate::B9600);
-//! cfsetspeed(&mut t, BaudRate::B9600);
-//! # }
-//! ```
-//!
-//! Additionally round-tripping baud rates is consistent across platforms:
-//!
-//! ```rust
-//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetispeed, cfsetspeed, Termios};
-//! # fn main() {
-//! # let mut t: Termios = unsafe { std::mem::zeroed() };
-//! # cfsetspeed(&mut t, BaudRate::B9600);
-//! let speed = cfgetispeed(&t);
-//! assert_eq!(speed, cfgetospeed(&t));
-//! cfsetispeed(&mut t, speed);
-//! # }
-//! ```
-//!
-//! On non-BSDs, `cfgetispeed()` and `cfgetospeed()` both return a `BaudRate`:
-//!
-#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
- target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
- doc = " ```rust,ignore")]
-#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
- target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
- doc = " ```rust")]
-//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
-//! # fn main() {
-//! # let mut t: Termios = unsafe { std::mem::zeroed() };
-//! # cfsetspeed(&mut t, BaudRate::B9600);
-//! assert_eq!(cfgetispeed(&t), BaudRate::B9600);
-//! assert_eq!(cfgetospeed(&t), BaudRate::B9600);
-//! # }
-//! ```
-//!
-//! But on the BSDs, `cfgetispeed()` and `cfgetospeed()` both return `u32`s:
-//!
-#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
- target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
- doc = " ```rust")]
-#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
- target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
- doc = " ```rust,ignore")]
-//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
-//! # fn main() {
-//! # let mut t: Termios = unsafe { std::mem::zeroed() };
-//! # cfsetspeed(&mut t, 9600u32);
-//! assert_eq!(cfgetispeed(&t), 9600u32);
-//! assert_eq!(cfgetospeed(&t), 9600u32);
-//! # }
-//! ```
-//!
-//! It's trivial to convert from a `BaudRate` to a `u32` on BSDs:
-//!
-#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
- target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
- doc = " ```rust")]
-#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
- target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
- doc = " ```rust,ignore")]
-//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfsetspeed, Termios};
-//! # fn main() {
-//! # let mut t: Termios = unsafe { std::mem::zeroed() };
-//! # cfsetspeed(&mut t, 9600u32);
-//! assert_eq!(cfgetispeed(&t), BaudRate::B9600.into());
-//! assert_eq!(u32::from(BaudRate::B9600), 9600u32);
-//! # }
-//! ```
-//!
-//! And on BSDs you can specify arbitrary baud rates (**note** this depends on hardware support)
-//! by specifying baud rates directly using `u32`s:
-//!
-#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
- target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
- doc = " ```rust")]
-#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
- target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
- doc = " ```rust,ignore")]
-//! # use nix::sys::termios::{cfsetispeed, cfsetospeed, cfsetspeed, Termios};
-//! # fn main() {
-//! # let mut t: Termios = unsafe { std::mem::zeroed() };
-//! cfsetispeed(&mut t, 9600u32);
-//! cfsetospeed(&mut t, 9600u32);
-//! cfsetspeed(&mut t, 9600u32);
-//! # }
-//! ```
-use cfg_if::cfg_if;
-use crate::{Error, Result};
-use crate::errno::Errno;
-use libc::{self, c_int, tcflag_t};
-use std::cell::{Ref, RefCell};
-use std::convert::{From, TryFrom};
-use std::mem;
-use std::os::unix::io::RawFd;
-
-use crate::unistd::Pid;
-
-/// Stores settings for the termios API
-///
-/// This is a wrapper around the `libc::termios` struct that provides a safe interface for the
-/// standard fields. The only safe way to obtain an instance of this struct is to extract it from
-/// an open port using `tcgetattr()`.
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct Termios {
- inner: RefCell<libc::termios>,
- /// Input mode flags (see `termios.c_iflag` documentation)
- pub input_flags: InputFlags,
- /// Output mode flags (see `termios.c_oflag` documentation)
- pub output_flags: OutputFlags,
- /// Control mode flags (see `termios.c_cflag` documentation)
- pub control_flags: ControlFlags,
- /// Local mode flags (see `termios.c_lflag` documentation)
- pub local_flags: LocalFlags,
- /// Control characters (see `termios.c_cc` documentation)
- pub control_chars: [libc::cc_t; NCCS],
-}
-
-impl Termios {
- /// Exposes an immutable reference to the underlying `libc::termios` data structure.
- ///
- /// This is not part of `nix`'s public API because it requires additional work to maintain type
- /// safety.
- pub(crate) fn get_libc_termios(&self) -> Ref<libc::termios> {
- {
- let mut termios = self.inner.borrow_mut();
- termios.c_iflag = self.input_flags.bits();
- termios.c_oflag = self.output_flags.bits();
- termios.c_cflag = self.control_flags.bits();
- termios.c_lflag = self.local_flags.bits();
- termios.c_cc = self.control_chars;
- }
- self.inner.borrow()
- }
-
- /// Exposes the inner `libc::termios` datastore within `Termios`.
- ///
- /// This is unsafe because if this is used to modify the inner `libc::termios` struct, it will
- /// not automatically update the safe wrapper type around it. In this case it should also be
- /// paired with a call to `update_wrapper()` so that the wrapper-type and internal
- /// representation stay consistent.
- pub(crate) unsafe fn get_libc_termios_mut(&mut self) -> *mut libc::termios {
- {
- let mut termios = self.inner.borrow_mut();
- termios.c_iflag = self.input_flags.bits();
- termios.c_oflag = self.output_flags.bits();
- termios.c_cflag = self.control_flags.bits();
- termios.c_lflag = self.local_flags.bits();
- termios.c_cc = self.control_chars;
- }
- self.inner.as_ptr()
- }
-
- /// Updates the wrapper values from the internal `libc::termios` data structure.
- pub(crate) fn update_wrapper(&mut self) {
- let termios = *self.inner.borrow_mut();
- self.input_flags = InputFlags::from_bits_truncate(termios.c_iflag);
- self.output_flags = OutputFlags::from_bits_truncate(termios.c_oflag);
- self.control_flags = ControlFlags::from_bits_truncate(termios.c_cflag);
- self.local_flags = LocalFlags::from_bits_truncate(termios.c_lflag);
- self.control_chars = termios.c_cc;
- }
-}
-
-impl From<libc::termios> for Termios {
- fn from(termios: libc::termios) -> Self {
- Termios {
- inner: RefCell::new(termios),
- input_flags: InputFlags::from_bits_truncate(termios.c_iflag),
- output_flags: OutputFlags::from_bits_truncate(termios.c_oflag),
- control_flags: ControlFlags::from_bits_truncate(termios.c_cflag),
- local_flags: LocalFlags::from_bits_truncate(termios.c_lflag),
- control_chars: termios.c_cc,
- }
- }
-}
-
-impl From<Termios> for libc::termios {
- fn from(termios: Termios) -> Self {
- termios.inner.into_inner()
- }
-}
-
-libc_enum!{
- /// Baud rates supported by the system.
- ///
- /// For the BSDs, arbitrary baud rates can be specified by using `u32`s directly instead of this
- /// enum.
- ///
- /// B0 is special and will disable the port.
- #[cfg_attr(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64"), repr(u64))]
- #[cfg_attr(not(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64")), repr(u32))]
- pub enum BaudRate {
- B0,
- B50,
- B75,
- B110,
- B134,
- B150,
- B200,
- B300,
- B600,
- B1200,
- B1800,
- B2400,
- B4800,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- B7200,
- B9600,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- B14400,
- B19200,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- B28800,
- B38400,
- B57600,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- B76800,
- B115200,
- B230400,
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd"))]
- B460800,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B500000,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B576000,
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd"))]
- B921600,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B1000000,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B1152000,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B1500000,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B2000000,
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- B2500000,
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- B3000000,
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- B3500000,
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- B4000000,
- }
-}
-
-impl TryFrom<libc::speed_t> for BaudRate {
- type Error = Error;
-
- fn try_from(s: libc::speed_t) -> Result<BaudRate> {
- use libc::{B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, B4800,
- B9600, B19200, B38400, B57600, B115200, B230400};
- #[cfg(any(target_os = "android", target_os = "linux"))]
- use libc::{B500000, B576000, B1000000, B1152000, B1500000, B2000000};
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- use libc::{B2500000, B3000000, B3500000, B4000000};
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- use libc::{B7200, B14400, B28800, B76800};
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd"))]
- use libc::{B460800, B921600};
-
- match s {
- B0 => Ok(BaudRate::B0),
- B50 => Ok(BaudRate::B50),
- B75 => Ok(BaudRate::B75),
- B110 => Ok(BaudRate::B110),
- B134 => Ok(BaudRate::B134),
- B150 => Ok(BaudRate::B150),
- B200 => Ok(BaudRate::B200),
- B300 => Ok(BaudRate::B300),
- B600 => Ok(BaudRate::B600),
- B1200 => Ok(BaudRate::B1200),
- B1800 => Ok(BaudRate::B1800),
- B2400 => Ok(BaudRate::B2400),
- B4800 => Ok(BaudRate::B4800),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- B7200 => Ok(BaudRate::B7200),
- B9600 => Ok(BaudRate::B9600),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- B14400 => Ok(BaudRate::B14400),
- B19200 => Ok(BaudRate::B19200),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- B28800 => Ok(BaudRate::B28800),
- B38400 => Ok(BaudRate::B38400),
- B57600 => Ok(BaudRate::B57600),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- B76800 => Ok(BaudRate::B76800),
- B115200 => Ok(BaudRate::B115200),
- B230400 => Ok(BaudRate::B230400),
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd"))]
- B460800 => Ok(BaudRate::B460800),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B500000 => Ok(BaudRate::B500000),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B576000 => Ok(BaudRate::B576000),
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd"))]
- B921600 => Ok(BaudRate::B921600),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B1000000 => Ok(BaudRate::B1000000),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B1152000 => Ok(BaudRate::B1152000),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B1500000 => Ok(BaudRate::B1500000),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B2000000 => Ok(BaudRate::B2000000),
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- B2500000 => Ok(BaudRate::B2500000),
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- B3000000 => Ok(BaudRate::B3000000),
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- B3500000 => Ok(BaudRate::B3500000),
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- B4000000 => Ok(BaudRate::B4000000),
- _ => Err(Error::invalid_argument())
- }
- }
-}
-
-#[cfg(any(target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
-impl From<BaudRate> for u32 {
- fn from(b: BaudRate) -> u32 {
- b as u32
- }
-}
-
-// TODO: Add TCSASOFT, which will require treating this as a bitfield.
-libc_enum! {
- /// Specify when a port configuration change should occur.
- ///
- /// Used as an argument to `tcsetattr()`
- #[repr(i32)]
- pub enum SetArg {
- /// The change will occur immediately
- TCSANOW,
- /// The change occurs after all output has been written
- TCSADRAIN,
- /// Same as `TCSADRAIN`, but will also flush the input buffer
- TCSAFLUSH,
- }
-}
-
-libc_enum! {
- /// Specify a combination of the input and output buffers to flush
- ///
- /// Used as an argument to `tcflush()`.
- #[repr(i32)]
- pub enum FlushArg {
- /// Flush data that was received but not read
- TCIFLUSH,
- /// Flush data written but not transmitted
- TCOFLUSH,
- /// Flush both received data not read and written data not transmitted
- TCIOFLUSH,
- }
-}
-
-libc_enum! {
- /// Specify how transmission flow should be altered
- ///
- /// Used as an argument to `tcflow()`.
- #[repr(i32)]
- pub enum FlowArg {
- /// Suspend transmission
- TCOOFF,
- /// Resume transmission
- TCOON,
- /// Transmit a STOP character, which should disable a connected terminal device
- TCIOFF,
- /// Transmit a START character, which should re-enable a connected terminal device
- TCION,
- }
-}
-
-// TODO: Make this usable directly as a slice index.
-libc_enum! {
- /// Indices into the `termios.c_cc` array for special characters.
- #[repr(usize)]
- pub enum SpecialCharacterIndices {
- VDISCARD,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- VDSUSP,
- VEOF,
- VEOL,
- VEOL2,
- VERASE,
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- VERASE2,
- VINTR,
- VKILL,
- VLNEXT,
- #[cfg(not(all(target_os = "linux", target_arch = "sparc64")))]
- VMIN,
- VQUIT,
- VREPRINT,
- VSTART,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- VSTATUS,
- VSTOP,
- VSUSP,
- #[cfg(target_os = "linux")]
- VSWTC,
- #[cfg(target_os = "haiku")]
- VSWTCH,
- #[cfg(not(all(target_os = "linux", target_arch = "sparc64")))]
- VTIME,
- VWERASE,
- #[cfg(target_os = "dragonfly")]
- VCHECKPT,
- }
-}
-
-#[cfg(all(target_os = "linux", target_arch = "sparc64"))]
-impl SpecialCharacterIndices {
- pub const VMIN: SpecialCharacterIndices = SpecialCharacterIndices::VEOF;
- pub const VTIME: SpecialCharacterIndices = SpecialCharacterIndices::VEOL;
-}
-
-pub use libc::NCCS;
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
-pub use libc::_POSIX_VDISABLE;
-
-libc_bitflags! {
- /// Flags for configuring the input mode of a terminal
- pub struct InputFlags: tcflag_t {
- IGNBRK;
- BRKINT;
- IGNPAR;
- PARMRK;
- INPCK;
- ISTRIP;
- INLCR;
- IGNCR;
- ICRNL;
- IXON;
- IXOFF;
- IXANY;
- IMAXBEL;
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
- IUTF8;
- }
-}
-
-libc_bitflags! {
- /// Flags for configuring the output mode of a terminal
- pub struct OutputFlags: tcflag_t {
- OPOST;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "linux",
- target_os = "openbsd"))]
- OLCUC;
- ONLCR;
- OCRNL as tcflag_t;
- ONOCR as tcflag_t;
- ONLRET as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- OFILL as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- OFDEL as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- NL0 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- NL1 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- CR0 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- CR1 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- CR2 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- CR3 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- TAB0 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- TAB1 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- TAB2 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- TAB3 as tcflag_t;
- #[cfg(any(target_os = "android", target_os = "linux"))]
- XTABS;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- BS0 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- BS1 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- VT0 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- VT1 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- FF0 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- FF1 as tcflag_t;
- #[cfg(any(target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- OXTABS;
- #[cfg(any(target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- ONOEOT as tcflag_t;
-
- // Bitmasks for use with OutputFlags to select specific settings
- // These should be moved to be a mask once https://github.com/rust-lang-nursery/bitflags/issues/110
- // is resolved.
-
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- NLDLY as tcflag_t; // FIXME: Datatype needs to be corrected in libc for mac
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- CRDLY as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- TABDLY as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- BSDLY as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- VTDLY as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- FFDLY as tcflag_t;
- }
-}
-
-libc_bitflags! {
- /// Flags for setting the control mode of a terminal
- pub struct ControlFlags: tcflag_t {
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- CIGNORE;
- CS5;
- CS6;
- CS7;
- CS8;
- CSTOPB;
- CREAD;
- PARENB;
- PARODD;
- HUPCL;
- CLOCAL;
- #[cfg(not(target_os = "redox"))]
- CRTSCTS;
- #[cfg(any(target_os = "android", target_os = "linux"))]
- CBAUD;
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "mips"))))]
- CMSPAR;
- #[cfg(any(target_os = "android",
- all(target_os = "linux",
- not(any(target_arch = "powerpc", target_arch = "powerpc64")))))]
- CIBAUD;
- #[cfg(any(target_os = "android", target_os = "linux"))]
- CBAUDEX;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- MDMBUF;
- #[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
- CHWFLOW;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "netbsd",
- target_os = "openbsd"))]
- CCTS_OFLOW;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "netbsd",
- target_os = "openbsd"))]
- CRTS_IFLOW;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd"))]
- CDTR_IFLOW;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd"))]
- CDSR_OFLOW;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd"))]
- CCAR_OFLOW;
-
- // Bitmasks for use with ControlFlags to select specific settings
- // These should be moved to be a mask once https://github.com/rust-lang-nursery/bitflags/issues/110
- // is resolved.
-
- CSIZE;
- }
-}
-
-libc_bitflags! {
- /// Flags for setting any local modes
- pub struct LocalFlags: tcflag_t {
- #[cfg(not(target_os = "redox"))]
- ECHOKE;
- ECHOE;
- ECHOK;
- ECHO;
- ECHONL;
- #[cfg(not(target_os = "redox"))]
- ECHOPRT;
- #[cfg(not(target_os = "redox"))]
- ECHOCTL;
- ISIG;
- ICANON;
- #[cfg(any(target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- ALTWERASE;
- IEXTEN;
- #[cfg(not(target_os = "redox"))]
- EXTPROC;
- TOSTOP;
- #[cfg(not(target_os = "redox"))]
- FLUSHO;
- #[cfg(any(target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- NOKERNINFO;
- #[cfg(not(target_os = "redox"))]
- PENDIN;
- NOFLSH;
- }
-}
-
-cfg_if!{
- if #[cfg(any(target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))] {
- /// Get input baud rate (see
- /// [cfgetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
- ///
- /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure.
- pub fn cfgetispeed(termios: &Termios) -> u32 {
- let inner_termios = termios.get_libc_termios();
- unsafe { libc::cfgetispeed(&*inner_termios) as u32 }
- }
-
- /// Get output baud rate (see
- /// [cfgetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
- ///
- /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure.
- pub fn cfgetospeed(termios: &Termios) -> u32 {
- let inner_termios = termios.get_libc_termios();
- unsafe { libc::cfgetospeed(&*inner_termios) as u32 }
- }
-
- /// Set input baud rate (see
- /// [cfsetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
- ///
- /// `cfsetispeed()` sets the intput baud rate in the given `Termios` structure.
- pub fn cfsetispeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> {
- let inner_termios = unsafe { termios.get_libc_termios_mut() };
- let res = unsafe { libc::cfsetispeed(inner_termios, baud.into() as libc::speed_t) };
- termios.update_wrapper();
- Errno::result(res).map(drop)
- }
-
- /// Set output baud rate (see
- /// [cfsetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
- ///
- /// `cfsetospeed()` sets the output baud rate in the given termios structure.
- pub fn cfsetospeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> {
- let inner_termios = unsafe { termios.get_libc_termios_mut() };
- let res = unsafe { libc::cfsetospeed(inner_termios, baud.into() as libc::speed_t) };
- termios.update_wrapper();
- Errno::result(res).map(drop)
- }
-
- /// Set both the input and output baud rates (see
- /// [termios(3)](https://www.freebsd.org/cgi/man.cgi?query=cfsetspeed)).
- ///
- /// `cfsetspeed()` sets the input and output baud rate in the given termios structure. Note that
- /// this is part of the 4.4BSD standard and not part of POSIX.
- pub fn cfsetspeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> {
- let inner_termios = unsafe { termios.get_libc_termios_mut() };
- let res = unsafe { libc::cfsetspeed(inner_termios, baud.into() as libc::speed_t) };
- termios.update_wrapper();
- Errno::result(res).map(drop)
- }
- } else {
- use std::convert::TryInto;
-
- /// Get input baud rate (see
- /// [cfgetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
- ///
- /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure.
- pub fn cfgetispeed(termios: &Termios) -> BaudRate {
- let inner_termios = termios.get_libc_termios();
- unsafe { libc::cfgetispeed(&*inner_termios) }.try_into().unwrap()
- }
-
- /// Get output baud rate (see
- /// [cfgetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
- ///
- /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure.
- pub fn cfgetospeed(termios: &Termios) -> BaudRate {
- let inner_termios = termios.get_libc_termios();
- unsafe { libc::cfgetospeed(&*inner_termios) }.try_into().unwrap()
- }
-
- /// Set input baud rate (see
- /// [cfsetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
- ///
- /// `cfsetispeed()` sets the intput baud rate in the given `Termios` structure.
- pub fn cfsetispeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
- let inner_termios = unsafe { termios.get_libc_termios_mut() };
- let res = unsafe { libc::cfsetispeed(inner_termios, baud as libc::speed_t) };
- termios.update_wrapper();
- Errno::result(res).map(drop)
- }
-
- /// Set output baud rate (see
- /// [cfsetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
- ///
- /// `cfsetospeed()` sets the output baud rate in the given `Termios` structure.
- pub fn cfsetospeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
- let inner_termios = unsafe { termios.get_libc_termios_mut() };
- let res = unsafe { libc::cfsetospeed(inner_termios, baud as libc::speed_t) };
- termios.update_wrapper();
- Errno::result(res).map(drop)
- }
-
- /// Set both the input and output baud rates (see
- /// [termios(3)](https://www.freebsd.org/cgi/man.cgi?query=cfsetspeed)).
- ///
- /// `cfsetspeed()` sets the input and output baud rate in the given `Termios` structure. Note that
- /// this is part of the 4.4BSD standard and not part of POSIX.
- pub fn cfsetspeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
- let inner_termios = unsafe { termios.get_libc_termios_mut() };
- let res = unsafe { libc::cfsetspeed(inner_termios, baud as libc::speed_t) };
- termios.update_wrapper();
- Errno::result(res).map(drop)
- }
- }
-}
-
-/// Configures the port to something like the "raw" mode of the old Version 7 terminal driver (see
-/// [termios(3)](http://man7.org/linux/man-pages/man3/termios.3.html)).
-///
-/// `cfmakeraw()` configures the termios structure such that input is available character-by-
-/// character, echoing is disabled, and all special input and output processing is disabled. Note
-/// that this is a non-standard function, but is available on Linux and BSDs.
-pub fn cfmakeraw(termios: &mut Termios) {
- let inner_termios = unsafe { termios.get_libc_termios_mut() };
- unsafe {
- libc::cfmakeraw(inner_termios);
- }
- termios.update_wrapper();
-}
-
-/// Configures the port to "sane" mode (like the configuration of a newly created terminal) (see
-/// [tcsetattr(3)](https://www.freebsd.org/cgi/man.cgi?query=tcsetattr)).
-///
-/// Note that this is a non-standard function, available on FreeBSD.
-#[cfg(target_os = "freebsd")]
-pub fn cfmakesane(termios: &mut Termios) {
- let inner_termios = unsafe { termios.get_libc_termios_mut() };
- unsafe {
- libc::cfmakesane(inner_termios);
- }
- termios.update_wrapper();
-}
-
-/// Return the configuration of a port
-/// [tcgetattr(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetattr.html)).
-///
-/// `tcgetattr()` returns a `Termios` structure with the current configuration for a port. Modifying
-/// this structure *will not* reconfigure the port, instead the modifications should be done to
-/// the `Termios` structure and then the port should be reconfigured using `tcsetattr()`.
-pub fn tcgetattr(fd: RawFd) -> Result<Termios> {
- let mut termios = mem::MaybeUninit::uninit();
-
- let res = unsafe { libc::tcgetattr(fd, termios.as_mut_ptr()) };
-
- Errno::result(res)?;
-
- unsafe { Ok(termios.assume_init().into()) }
-}
-
-/// Set the configuration for a terminal (see
-/// [tcsetattr(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetattr.html)).
-///
-/// `tcsetattr()` reconfigures the given port based on a given `Termios` structure. This change
-/// takes affect at a time specified by `actions`. Note that this function may return success if
-/// *any* of the parameters were successfully set, not only if all were set successfully.
-pub fn tcsetattr(fd: RawFd, actions: SetArg, termios: &Termios) -> Result<()> {
- let inner_termios = termios.get_libc_termios();
- Errno::result(unsafe { libc::tcsetattr(fd, actions as c_int, &*inner_termios) }).map(drop)
-}
-
-/// Block until all output data is written (see
-/// [tcdrain(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcdrain.html)).
-pub fn tcdrain(fd: RawFd) -> Result<()> {
- Errno::result(unsafe { libc::tcdrain(fd) }).map(drop)
-}
-
-/// Suspend or resume the transmission or reception of data (see
-/// [tcflow(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflow.html)).
-///
-/// `tcflow()` suspends of resumes the transmission or reception of data for the given port
-/// depending on the value of `action`.
-pub fn tcflow(fd: RawFd, action: FlowArg) -> Result<()> {
- Errno::result(unsafe { libc::tcflow(fd, action as c_int) }).map(drop)
-}
-
-/// Discard data in the output or input queue (see
-/// [tcflush(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflush.html)).
-///
-/// `tcflush()` will discard data for a terminal port in the input queue, output queue, or both
-/// depending on the value of `action`.
-pub fn tcflush(fd: RawFd, action: FlushArg) -> Result<()> {
- Errno::result(unsafe { libc::tcflush(fd, action as c_int) }).map(drop)
-}
-
-/// Send a break for a specific duration (see
-/// [tcsendbreak(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsendbreak.html)).
-///
-/// When using asynchronous data transmission `tcsendbreak()` will transmit a continuous stream
-/// of zero-valued bits for an implementation-defined duration.
-pub fn tcsendbreak(fd: RawFd, duration: c_int) -> Result<()> {
- Errno::result(unsafe { libc::tcsendbreak(fd, duration) }).map(drop)
-}
-
-/// Get the session controlled by the given terminal (see
-/// [tcgetsid(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetsid.html)).
-pub fn tcgetsid(fd: RawFd) -> Result<Pid> {
- let res = unsafe { libc::tcgetsid(fd) };
-
- Errno::result(res).map(Pid::from_raw)
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
-
- #[test]
- fn try_from() {
- assert_eq!(Ok(BaudRate::B0), BaudRate::try_from(libc::B0));
- assert!(BaudRate::try_from(999999999).is_err());
- }
-}
diff --git a/vendor/nix-0.20.0/src/sys/time.rs b/vendor/nix-0.20.0/src/sys/time.rs
deleted file mode 100644
index 7546d1b..0000000
--- a/vendor/nix-0.20.0/src/sys/time.rs
+++ /dev/null
@@ -1,601 +0,0 @@
-use std::{cmp, fmt, ops};
-use std::time::Duration;
-use std::convert::From;
-use libc::{timespec, timeval};
-#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
-pub use libc::{time_t, suseconds_t};
-
-pub trait TimeValLike: Sized {
- #[inline]
- fn zero() -> Self {
- Self::seconds(0)
- }
-
- #[inline]
- fn hours(hours: i64) -> Self {
- let secs = hours.checked_mul(SECS_PER_HOUR)
- .expect("TimeValLike::hours ouf of bounds");
- Self::seconds(secs)
- }
-
- #[inline]
- fn minutes(minutes: i64) -> Self {
- let secs = minutes.checked_mul(SECS_PER_MINUTE)
- .expect("TimeValLike::minutes out of bounds");
- Self::seconds(secs)
- }
-
- fn seconds(seconds: i64) -> Self;
- fn milliseconds(milliseconds: i64) -> Self;
- fn microseconds(microseconds: i64) -> Self;
- fn nanoseconds(nanoseconds: i64) -> Self;
-
- #[inline]
- fn num_hours(&self) -> i64 {
- self.num_seconds() / 3600
- }
-
- #[inline]
- fn num_minutes(&self) -> i64 {
- self.num_seconds() / 60
- }
-
- fn num_seconds(&self) -> i64;
- fn num_milliseconds(&self) -> i64;
- fn num_microseconds(&self) -> i64;
- fn num_nanoseconds(&self) -> i64;
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct TimeSpec(timespec);
-
-const NANOS_PER_SEC: i64 = 1_000_000_000;
-const SECS_PER_MINUTE: i64 = 60;
-const SECS_PER_HOUR: i64 = 3600;
-
-#[cfg(target_pointer_width = "64")]
-const TS_MAX_SECONDS: i64 = (::std::i64::MAX / NANOS_PER_SEC) - 1;
-
-#[cfg(target_pointer_width = "32")]
-const TS_MAX_SECONDS: i64 = ::std::isize::MAX as i64;
-
-const TS_MIN_SECONDS: i64 = -TS_MAX_SECONDS;
-
-// x32 compatibility
-// See https://sourceware.org/bugzilla/show_bug.cgi?id=16437
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
-type timespec_tv_nsec_t = i64;
-#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
-type timespec_tv_nsec_t = libc::c_long;
-
-impl From<timespec> for TimeSpec {
- fn from(ts: timespec) -> Self {
- Self(ts)
- }
-}
-
-impl From<Duration> for TimeSpec {
- fn from(duration: Duration) -> Self {
- #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
- TimeSpec(timespec {
- tv_sec: duration.as_secs() as time_t,
- tv_nsec: duration.subsec_nanos() as timespec_tv_nsec_t
- })
- }
-}
-
-impl From<TimeSpec> for Duration {
- fn from(timespec: TimeSpec) -> Self {
- Duration::new(timespec.0.tv_sec as u64, timespec.0.tv_nsec as u32)
- }
-}
-
-impl AsRef<timespec> for TimeSpec {
- fn as_ref(&self) -> ×pec {
- &self.0
- }
-}
-
-impl AsMut<timespec> for TimeSpec {
- fn as_mut(&mut self) -> &mut timespec {
- &mut self.0
- }
-}
-
-impl Ord for TimeSpec {
- // The implementation of cmp is simplified by assuming that the struct is
- // normalized. That is, tv_nsec must always be within [0, 1_000_000_000)
- fn cmp(&self, other: &TimeSpec) -> cmp::Ordering {
- if self.tv_sec() == other.tv_sec() {
- self.tv_nsec().cmp(&other.tv_nsec())
- } else {
- self.tv_sec().cmp(&other.tv_sec())
- }
- }
-}
-
-impl PartialOrd for TimeSpec {
- fn partial_cmp(&self, other: &TimeSpec) -> Option<cmp::Ordering> {
- Some(self.cmp(other))
- }
-}
-
-impl TimeValLike for TimeSpec {
- #[inline]
- fn seconds(seconds: i64) -> TimeSpec {
- assert!(seconds >= TS_MIN_SECONDS && seconds <= TS_MAX_SECONDS,
- "TimeSpec out of bounds; seconds={}", seconds);
- #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
- TimeSpec(timespec {tv_sec: seconds as time_t, tv_nsec: 0 })
- }
-
- #[inline]
- fn milliseconds(milliseconds: i64) -> TimeSpec {
- let nanoseconds = milliseconds.checked_mul(1_000_000)
- .expect("TimeSpec::milliseconds out of bounds");
-
- TimeSpec::nanoseconds(nanoseconds)
- }
-
- /// Makes a new `TimeSpec` with given number of microseconds.
- #[inline]
- fn microseconds(microseconds: i64) -> TimeSpec {
- let nanoseconds = microseconds.checked_mul(1_000)
- .expect("TimeSpec::milliseconds out of bounds");
-
- TimeSpec::nanoseconds(nanoseconds)
- }
-
- /// Makes a new `TimeSpec` with given number of nanoseconds.
- #[inline]
- fn nanoseconds(nanoseconds: i64) -> TimeSpec {
- let (secs, nanos) = div_mod_floor_64(nanoseconds, NANOS_PER_SEC);
- assert!(secs >= TS_MIN_SECONDS && secs <= TS_MAX_SECONDS,
- "TimeSpec out of bounds");
- #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
- TimeSpec(timespec {tv_sec: secs as time_t,
- tv_nsec: nanos as timespec_tv_nsec_t })
- }
-
- fn num_seconds(&self) -> i64 {
- if self.tv_sec() < 0 && self.tv_nsec() > 0 {
- (self.tv_sec() + 1) as i64
- } else {
- self.tv_sec() as i64
- }
- }
-
- fn num_milliseconds(&self) -> i64 {
- self.num_nanoseconds() / 1_000_000
- }
-
- fn num_microseconds(&self) -> i64 {
- self.num_nanoseconds() / 1_000_000_000
- }
-
- fn num_nanoseconds(&self) -> i64 {
- let secs = self.num_seconds() * 1_000_000_000;
- let nsec = self.nanos_mod_sec();
- secs + nsec as i64
- }
-}
-
-impl TimeSpec {
- fn nanos_mod_sec(&self) -> timespec_tv_nsec_t {
- if self.tv_sec() < 0 && self.tv_nsec() > 0 {
- self.tv_nsec() - NANOS_PER_SEC as timespec_tv_nsec_t
- } else {
- self.tv_nsec()
- }
- }
-
- #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
- pub fn tv_sec(&self) -> time_t {
- self.0.tv_sec
- }
-
- pub fn tv_nsec(&self) -> timespec_tv_nsec_t {
- self.0.tv_nsec
- }
-}
-
-impl ops::Neg for TimeSpec {
- type Output = TimeSpec;
-
- fn neg(self) -> TimeSpec {
- TimeSpec::nanoseconds(-self.num_nanoseconds())
- }
-}
-
-impl ops::Add for TimeSpec {
- type Output = TimeSpec;
-
- fn add(self, rhs: TimeSpec) -> TimeSpec {
- TimeSpec::nanoseconds(
- self.num_nanoseconds() + rhs.num_nanoseconds())
- }
-}
-
-impl ops::Sub for TimeSpec {
- type Output = TimeSpec;
-
- fn sub(self, rhs: TimeSpec) -> TimeSpec {
- TimeSpec::nanoseconds(
- self.num_nanoseconds() - rhs.num_nanoseconds())
- }
-}
-
-impl ops::Mul<i32> for TimeSpec {
- type Output = TimeSpec;
-
- fn mul(self, rhs: i32) -> TimeSpec {
- let usec = self.num_nanoseconds().checked_mul(i64::from(rhs))
- .expect("TimeSpec multiply out of bounds");
-
- TimeSpec::nanoseconds(usec)
- }
-}
-
-impl ops::Div<i32> for TimeSpec {
- type Output = TimeSpec;
-
- fn div(self, rhs: i32) -> TimeSpec {
- let usec = self.num_nanoseconds() / i64::from(rhs);
- TimeSpec::nanoseconds(usec)
- }
-}
-
-impl fmt::Display for TimeSpec {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let (abs, sign) = if self.tv_sec() < 0 {
- (-*self, "-")
- } else {
- (*self, "")
- };
-
- let sec = abs.tv_sec();
-
- write!(f, "{}", sign)?;
-
- if abs.tv_nsec() == 0 {
- if abs.tv_sec() == 1 {
- write!(f, "{} second", sec)?;
- } else {
- write!(f, "{} seconds", sec)?;
- }
- } else if abs.tv_nsec() % 1_000_000 == 0 {
- write!(f, "{}.{:03} seconds", sec, abs.tv_nsec() / 1_000_000)?;
- } else if abs.tv_nsec() % 1_000 == 0 {
- write!(f, "{}.{:06} seconds", sec, abs.tv_nsec() / 1_000)?;
- } else {
- write!(f, "{}.{:09} seconds", sec, abs.tv_nsec())?;
- }
-
- Ok(())
- }
-}
-
-
-
-#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct TimeVal(timeval);
-
-const MICROS_PER_SEC: i64 = 1_000_000;
-
-#[cfg(target_pointer_width = "64")]
-const TV_MAX_SECONDS: i64 = (::std::i64::MAX / MICROS_PER_SEC) - 1;
-
-#[cfg(target_pointer_width = "32")]
-const TV_MAX_SECONDS: i64 = ::std::isize::MAX as i64;
-
-const TV_MIN_SECONDS: i64 = -TV_MAX_SECONDS;
-
-impl AsRef<timeval> for TimeVal {
- fn as_ref(&self) -> &timeval {
- &self.0
- }
-}
-
-impl AsMut<timeval> for TimeVal {
- fn as_mut(&mut self) -> &mut timeval {
- &mut self.0
- }
-}
-
-impl Ord for TimeVal {
- // The implementation of cmp is simplified by assuming that the struct is
- // normalized. That is, tv_usec must always be within [0, 1_000_000)
- fn cmp(&self, other: &TimeVal) -> cmp::Ordering {
- if self.tv_sec() == other.tv_sec() {
- self.tv_usec().cmp(&other.tv_usec())
- } else {
- self.tv_sec().cmp(&other.tv_sec())
- }
- }
-}
-
-impl PartialOrd for TimeVal {
- fn partial_cmp(&self, other: &TimeVal) -> Option<cmp::Ordering> {
- Some(self.cmp(other))
- }
-}
-
-impl TimeValLike for TimeVal {
- #[inline]
- fn seconds(seconds: i64) -> TimeVal {
- assert!(seconds >= TV_MIN_SECONDS && seconds <= TV_MAX_SECONDS,
- "TimeVal out of bounds; seconds={}", seconds);
- #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
- TimeVal(timeval {tv_sec: seconds as time_t, tv_usec: 0 })
- }
-
- #[inline]
- fn milliseconds(milliseconds: i64) -> TimeVal {
- let microseconds = milliseconds.checked_mul(1_000)
- .expect("TimeVal::milliseconds out of bounds");
-
- TimeVal::microseconds(microseconds)
- }
-
- /// Makes a new `TimeVal` with given number of microseconds.
- #[inline]
- fn microseconds(microseconds: i64) -> TimeVal {
- let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
- assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS,
- "TimeVal out of bounds");
- #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
- TimeVal(timeval {tv_sec: secs as time_t,
- tv_usec: micros as suseconds_t })
- }
-
- /// Makes a new `TimeVal` with given number of nanoseconds. Some precision
- /// will be lost
- #[inline]
- fn nanoseconds(nanoseconds: i64) -> TimeVal {
- let microseconds = nanoseconds / 1000;
- let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
- assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS,
- "TimeVal out of bounds");
- #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
- TimeVal(timeval {tv_sec: secs as time_t,
- tv_usec: micros as suseconds_t })
- }
-
- fn num_seconds(&self) -> i64 {
- if self.tv_sec() < 0 && self.tv_usec() > 0 {
- (self.tv_sec() + 1) as i64
- } else {
- self.tv_sec() as i64
- }
- }
-
- fn num_milliseconds(&self) -> i64 {
- self.num_microseconds() / 1_000
- }
-
- fn num_microseconds(&self) -> i64 {
- let secs = self.num_seconds() * 1_000_000;
- let usec = self.micros_mod_sec();
- secs + usec as i64
- }
-
- fn num_nanoseconds(&self) -> i64 {
- self.num_microseconds() * 1_000
- }
-}
-
-impl TimeVal {
- fn micros_mod_sec(&self) -> suseconds_t {
- if self.tv_sec() < 0 && self.tv_usec() > 0 {
- self.tv_usec() - MICROS_PER_SEC as suseconds_t
- } else {
- self.tv_usec()
- }
- }
-
- #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
- pub fn tv_sec(&self) -> time_t {
- self.0.tv_sec
- }
-
- pub fn tv_usec(&self) -> suseconds_t {
- self.0.tv_usec
- }
-}
-
-impl ops::Neg for TimeVal {
- type Output = TimeVal;
-
- fn neg(self) -> TimeVal {
- TimeVal::microseconds(-self.num_microseconds())
- }
-}
-
-impl ops::Add for TimeVal {
- type Output = TimeVal;
-
- fn add(self, rhs: TimeVal) -> TimeVal {
- TimeVal::microseconds(
- self.num_microseconds() + rhs.num_microseconds())
- }
-}
-
-impl ops::Sub for TimeVal {
- type Output = TimeVal;
-
- fn sub(self, rhs: TimeVal) -> TimeVal {
- TimeVal::microseconds(
- self.num_microseconds() - rhs.num_microseconds())
- }
-}
-
-impl ops::Mul<i32> for TimeVal {
- type Output = TimeVal;
-
- fn mul(self, rhs: i32) -> TimeVal {
- let usec = self.num_microseconds().checked_mul(i64::from(rhs))
- .expect("TimeVal multiply out of bounds");
-
- TimeVal::microseconds(usec)
- }
-}
-
-impl ops::Div<i32> for TimeVal {
- type Output = TimeVal;
-
- fn div(self, rhs: i32) -> TimeVal {
- let usec = self.num_microseconds() / i64::from(rhs);
- TimeVal::microseconds(usec)
- }
-}
-
-impl fmt::Display for TimeVal {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let (abs, sign) = if self.tv_sec() < 0 {
- (-*self, "-")
- } else {
- (*self, "")
- };
-
- let sec = abs.tv_sec();
-
- write!(f, "{}", sign)?;
-
- if abs.tv_usec() == 0 {
- if abs.tv_sec() == 1 {
- write!(f, "{} second", sec)?;
- } else {
- write!(f, "{} seconds", sec)?;
- }
- } else if abs.tv_usec() % 1000 == 0 {
- write!(f, "{}.{:03} seconds", sec, abs.tv_usec() / 1000)?;
- } else {
- write!(f, "{}.{:06} seconds", sec, abs.tv_usec())?;
- }
-
- Ok(())
- }
-}
-
-impl From<timeval> for TimeVal {
- fn from(tv: timeval) -> Self {
- TimeVal(tv)
- }
-}
-
-#[inline]
-fn div_mod_floor_64(this: i64, other: i64) -> (i64, i64) {
- (div_floor_64(this, other), mod_floor_64(this, other))
-}
-
-#[inline]
-fn div_floor_64(this: i64, other: i64) -> i64 {
- match div_rem_64(this, other) {
- (d, r) if (r > 0 && other < 0)
- || (r < 0 && other > 0) => d - 1,
- (d, _) => d,
- }
-}
-
-#[inline]
-fn mod_floor_64(this: i64, other: i64) -> i64 {
- match this % other {
- r if (r > 0 && other < 0)
- || (r < 0 && other > 0) => r + other,
- r => r,
- }
-}
-
-#[inline]
-fn div_rem_64(this: i64, other: i64) -> (i64, i64) {
- (this / other, this % other)
-}
-
-#[cfg(test)]
-mod test {
- use super::{TimeSpec, TimeVal, TimeValLike};
- use std::time::Duration;
-
- #[test]
- pub fn test_timespec() {
- assert!(TimeSpec::seconds(1) != TimeSpec::zero());
- assert_eq!(TimeSpec::seconds(1) + TimeSpec::seconds(2),
- TimeSpec::seconds(3));
- assert_eq!(TimeSpec::minutes(3) + TimeSpec::seconds(2),
- TimeSpec::seconds(182));
- }
-
- #[test]
- pub fn test_timespec_from() {
- let duration = Duration::new(123, 123_456_789);
- let timespec = TimeSpec::nanoseconds(123_123_456_789);
-
- assert_eq!(TimeSpec::from(duration), timespec);
- assert_eq!(Duration::from(timespec), duration);
- }
-
- #[test]
- pub fn test_timespec_neg() {
- let a = TimeSpec::seconds(1) + TimeSpec::nanoseconds(123);
- let b = TimeSpec::seconds(-1) + TimeSpec::nanoseconds(-123);
-
- assert_eq!(a, -b);
- }
-
- #[test]
- pub fn test_timespec_ord() {
- assert!(TimeSpec::seconds(1) == TimeSpec::nanoseconds(1_000_000_000));
- assert!(TimeSpec::seconds(1) < TimeSpec::nanoseconds(1_000_000_001));
- assert!(TimeSpec::seconds(1) > TimeSpec::nanoseconds(999_999_999));
- assert!(TimeSpec::seconds(-1) < TimeSpec::nanoseconds(-999_999_999));
- assert!(TimeSpec::seconds(-1) > TimeSpec::nanoseconds(-1_000_000_001));
- }
-
- #[test]
- pub fn test_timespec_fmt() {
- assert_eq!(TimeSpec::zero().to_string(), "0 seconds");
- assert_eq!(TimeSpec::seconds(42).to_string(), "42 seconds");
- assert_eq!(TimeSpec::milliseconds(42).to_string(), "0.042 seconds");
- assert_eq!(TimeSpec::microseconds(42).to_string(), "0.000042 seconds");
- assert_eq!(TimeSpec::nanoseconds(42).to_string(), "0.000000042 seconds");
- assert_eq!(TimeSpec::seconds(-86401).to_string(), "-86401 seconds");
- }
-
- #[test]
- pub fn test_timeval() {
- assert!(TimeVal::seconds(1) != TimeVal::zero());
- assert_eq!(TimeVal::seconds(1) + TimeVal::seconds(2),
- TimeVal::seconds(3));
- assert_eq!(TimeVal::minutes(3) + TimeVal::seconds(2),
- TimeVal::seconds(182));
- }
-
- #[test]
- pub fn test_timeval_ord() {
- assert!(TimeVal::seconds(1) == TimeVal::microseconds(1_000_000));
- assert!(TimeVal::seconds(1) < TimeVal::microseconds(1_000_001));
- assert!(TimeVal::seconds(1) > TimeVal::microseconds(999_999));
- assert!(TimeVal::seconds(-1) < TimeVal::microseconds(-999_999));
- assert!(TimeVal::seconds(-1) > TimeVal::microseconds(-1_000_001));
- }
-
- #[test]
- pub fn test_timeval_neg() {
- let a = TimeVal::seconds(1) + TimeVal::microseconds(123);
- let b = TimeVal::seconds(-1) + TimeVal::microseconds(-123);
-
- assert_eq!(a, -b);
- }
-
- #[test]
- pub fn test_timeval_fmt() {
- assert_eq!(TimeVal::zero().to_string(), "0 seconds");
- assert_eq!(TimeVal::seconds(42).to_string(), "42 seconds");
- assert_eq!(TimeVal::milliseconds(42).to_string(), "0.042 seconds");
- assert_eq!(TimeVal::microseconds(42).to_string(), "0.000042 seconds");
- assert_eq!(TimeVal::nanoseconds(1402).to_string(), "0.000001 seconds");
- assert_eq!(TimeVal::seconds(-86401).to_string(), "-86401 seconds");
- }
-}
diff --git a/vendor/nix-0.20.0/src/sys/timerfd.rs b/vendor/nix-0.20.0/src/sys/timerfd.rs
deleted file mode 100644
index 4a24719..0000000
--- a/vendor/nix-0.20.0/src/sys/timerfd.rs
+++ /dev/null
@@ -1,285 +0,0 @@
-//! Timer API via file descriptors.
-//!
-//! Timer FD is a Linux-only API to create timers and get expiration
-//! notifications through file descriptors.
-//!
-//! For more documentation, please read [timerfd_create(2)](http://man7.org/linux/man-pages/man2/timerfd_create.2.html).
-//!
-//! # Examples
-//!
-//! Create a new one-shot timer that expires after 1 second.
-//! ```
-//! # use std::os::unix::io::AsRawFd;
-//! # use nix::sys::timerfd::{TimerFd, ClockId, TimerFlags, TimerSetTimeFlags,
-//! # Expiration};
-//! # use nix::sys::time::{TimeSpec, TimeValLike};
-//! # use nix::unistd::read;
-//! #
-//! // We create a new monotonic timer.
-//! let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty())
-//! .unwrap();
-//!
-//! // We set a new one-shot timer in 1 seconds.
-//! timer.set(
-//! Expiration::OneShot(TimeSpec::seconds(1)),
-//! TimerSetTimeFlags::empty()
-//! ).unwrap();
-//!
-//! // We wait for the timer to expire.
-//! timer.wait().unwrap();
-//! ```
-use crate::sys::time::TimeSpec;
-use crate::unistd::read;
-use crate::{errno::Errno, Error, Result};
-use bitflags::bitflags;
-use libc::c_int;
-use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
-
-/// A timerfd instance. This is also a file descriptor, you can feed it to
-/// other interfaces consuming file descriptors, epoll for example.
-#[derive(Debug)]
-pub struct TimerFd {
- fd: RawFd,
-}
-
-impl AsRawFd for TimerFd {
- fn as_raw_fd(&self) -> RawFd {
- self.fd
- }
-}
-
-impl FromRawFd for TimerFd {
- unsafe fn from_raw_fd(fd: RawFd) -> Self {
- TimerFd { fd }
- }
-}
-
-libc_enum! {
- /// The type of the clock used to mark the progress of the timer. For more
- /// details on each kind of clock, please refer to [timerfd_create(2)](http://man7.org/linux/man-pages/man2/timerfd_create.2.html).
- #[repr(i32)]
- pub enum ClockId {
- CLOCK_REALTIME,
- CLOCK_MONOTONIC,
- CLOCK_BOOTTIME,
- CLOCK_REALTIME_ALARM,
- CLOCK_BOOTTIME_ALARM,
- }
-}
-
-libc_bitflags! {
- /// Additional flags to change the behaviour of the file descriptor at the
- /// time of creation.
- pub struct TimerFlags: c_int {
- TFD_NONBLOCK;
- TFD_CLOEXEC;
- }
-}
-
-bitflags! {
- /// Flags that are used for arming the timer.
- pub struct TimerSetTimeFlags: libc::c_int {
- const TFD_TIMER_ABSTIME = libc::TFD_TIMER_ABSTIME;
- }
-}
-
-#[derive(Debug, Clone, Copy)]
-struct TimerSpec(libc::itimerspec);
-
-impl TimerSpec {
- pub fn none() -> Self {
- Self(libc::itimerspec {
- it_interval: libc::timespec {
- tv_sec: 0,
- tv_nsec: 0,
- },
- it_value: libc::timespec {
- tv_sec: 0,
- tv_nsec: 0,
- },
- })
- }
-}
-
-impl AsRef<libc::itimerspec> for TimerSpec {
- fn as_ref(&self) -> &libc::itimerspec {
- &self.0
- }
-}
-
-impl From<Expiration> for TimerSpec {
- fn from(expiration: Expiration) -> TimerSpec {
- match expiration {
- Expiration::OneShot(t) => TimerSpec(libc::itimerspec {
- it_interval: libc::timespec {
- tv_sec: 0,
- tv_nsec: 0,
- },
- it_value: *t.as_ref(),
- }),
- Expiration::IntervalDelayed(start, interval) => TimerSpec(libc::itimerspec {
- it_interval: *interval.as_ref(),
- it_value: *start.as_ref(),
- }),
- Expiration::Interval(t) => TimerSpec(libc::itimerspec {
- it_interval: *t.as_ref(),
- it_value: *t.as_ref(),
- }),
- }
- }
-}
-
-impl From<TimerSpec> for Expiration {
- fn from(timerspec: TimerSpec) -> Expiration {
- match timerspec {
- TimerSpec(libc::itimerspec {
- it_interval:
- libc::timespec {
- tv_sec: 0,
- tv_nsec: 0,
- },
- it_value: ts,
- }) => Expiration::OneShot(ts.into()),
- TimerSpec(libc::itimerspec {
- it_interval: int_ts,
- it_value: val_ts,
- }) => {
- if (int_ts.tv_sec == val_ts.tv_sec) && (int_ts.tv_nsec == val_ts.tv_nsec) {
- Expiration::Interval(int_ts.into())
- } else {
- Expiration::IntervalDelayed(val_ts.into(), int_ts.into())
- }
- }
- }
- }
-}
-
-/// An enumeration allowing the definition of the expiration time of an alarm,
-/// recurring or not.
-#[derive(Debug, Clone, Copy, PartialEq)]
-pub enum Expiration {
- OneShot(TimeSpec),
- IntervalDelayed(TimeSpec, TimeSpec),
- Interval(TimeSpec),
-}
-
-impl TimerFd {
- /// Creates a new timer based on the clock defined by `clockid`. The
- /// underlying fd can be assigned specific flags with `flags` (CLOEXEC,
- /// NONBLOCK). The underlying fd will be closed on drop.
- pub fn new(clockid: ClockId, flags: TimerFlags) -> Result<Self> {
- Errno::result(unsafe { libc::timerfd_create(clockid as i32, flags.bits()) })
- .map(|fd| Self { fd })
- }
-
- /// Sets a new alarm on the timer.
- ///
- /// # Types of alarm
- ///
- /// There are 3 types of alarms you can set:
- ///
- /// - one shot: the alarm will trigger once after the specified amount of
- /// time.
- /// Example: I want an alarm to go off in 60s and then disables itself.
- ///
- /// - interval: the alarm will trigger every specified interval of time.
- /// Example: I want an alarm to go off every 60s. The alarm will first
- /// go off 60s after I set it and every 60s after that. The alarm will
- /// not disable itself.
- ///
- /// - interval delayed: the alarm will trigger after a certain amount of
- /// time and then trigger at a specified interval.
- /// Example: I want an alarm to go off every 60s but only start in 1h.
- /// The alarm will first trigger 1h after I set it and then every 60s
- /// after that. The alarm will not disable itself.
- ///
- /// # Relative vs absolute alarm
- ///
- /// If you do not set any `TimerSetTimeFlags`, then the `TimeSpec` you pass
- /// to the `Expiration` you want is relative. If however you want an alarm
- /// to go off at a certain point in time, you can set `TFD_TIMER_ABSTIME`.
- /// Then the one shot TimeSpec and the delay TimeSpec of the delayed
- /// interval are going to be interpreted as absolute.
- ///
- /// # Disabling alarms
- ///
- /// Note: Only one alarm can be set for any given timer. Setting a new alarm
- /// actually removes the previous one.
- ///
- /// Note: Setting a one shot alarm with a 0s TimeSpec disables the alarm
- /// altogether.
- pub fn set(&self, expiration: Expiration, flags: TimerSetTimeFlags) -> Result<()> {
- let timerspec: TimerSpec = expiration.into();
- Errno::result(unsafe {
- libc::timerfd_settime(
- self.fd,
- flags.bits(),
- timerspec.as_ref(),
- std::ptr::null_mut(),
- )
- })
- .map(drop)
- }
-
- /// Get the parameters for the alarm currently set, if any.
- pub fn get(&self) -> Result<Option<Expiration>> {
- let mut timerspec = TimerSpec::none();
- let timerspec_ptr: *mut libc::itimerspec = &mut timerspec.0;
-
- Errno::result(unsafe { libc::timerfd_gettime(self.fd, timerspec_ptr) }).map(|_| {
- if timerspec.0.it_interval.tv_sec == 0
- && timerspec.0.it_interval.tv_nsec == 0
- && timerspec.0.it_value.tv_sec == 0
- && timerspec.0.it_value.tv_nsec == 0
- {
- None
- } else {
- Some(timerspec.into())
- }
- })
- }
-
- /// Remove the alarm if any is set.
- pub fn unset(&self) -> Result<()> {
- Errno::result(unsafe {
- libc::timerfd_settime(
- self.fd,
- TimerSetTimeFlags::empty().bits(),
- TimerSpec::none().as_ref(),
- std::ptr::null_mut(),
- )
- })
- .map(drop)
- }
-
- /// Wait for the configured alarm to expire.
- ///
- /// Note: If the alarm is unset, then you will wait forever.
- pub fn wait(&self) -> Result<()> {
- loop {
- if let Err(e) = read(self.fd, &mut [0u8; 8]) {
- match e {
- Error::Sys(Errno::EINTR) => continue,
- _ => return Err(e),
- }
- } else {
- break;
- }
- }
-
- Ok(())
- }
-}
-
-impl Drop for TimerFd {
- fn drop(&mut self) {
- if !std::thread::panicking() {
- let result = Errno::result(unsafe {
- libc::close(self.fd)
- });
- if let Err(Error::Sys(Errno::EBADF)) = result {
- panic!("close of TimerFd encountered EBADF");
- }
- }
- }
-}
diff --git a/vendor/nix-0.20.0/src/sys/uio.rs b/vendor/nix-0.20.0/src/sys/uio.rs
deleted file mode 100644
index 6533422..0000000
--- a/vendor/nix-0.20.0/src/sys/uio.rs
+++ /dev/null
@@ -1,202 +0,0 @@
-// Silence invalid warnings due to rust-lang/rust#16719
-#![allow(improper_ctypes)]
-
-use crate::Result;
-use crate::errno::Errno;
-use libc::{self, c_int, c_void, size_t, off_t};
-use std::marker::PhantomData;
-use std::os::unix::io::RawFd;
-
-pub fn writev(fd: RawFd, iov: &[IoVec<&[u8]>]) -> Result<usize> {
- let res = unsafe { libc::writev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) };
-
- Errno::result(res).map(|r| r as usize)
-}
-
-pub fn readv(fd: RawFd, iov: &mut [IoVec<&mut [u8]>]) -> Result<usize> {
- let res = unsafe { libc::readv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) };
-
- Errno::result(res).map(|r| r as usize)
-}
-
-/// Write to `fd` at `offset` from buffers in `iov`.
-///
-/// Buffers in `iov` will be written in order until all buffers have been written
-/// or an error occurs. The file offset is not changed.
-///
-/// See also: [`writev`](fn.writev.html) and [`pwrite`](fn.pwrite.html)
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
-pub fn pwritev(fd: RawFd, iov: &[IoVec<&[u8]>],
- offset: off_t) -> Result<usize> {
- let res = unsafe {
- libc::pwritev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset)
- };
-
- Errno::result(res).map(|r| r as usize)
-}
-
-/// Read from `fd` at `offset` filling buffers in `iov`.
-///
-/// Buffers in `iov` will be filled in order until all buffers have been filled,
-/// no more bytes are available, or an error occurs. The file offset is not
-/// changed.
-///
-/// See also: [`readv`](fn.readv.html) and [`pread`](fn.pread.html)
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
-pub fn preadv(fd: RawFd, iov: &[IoVec<&mut [u8]>],
- offset: off_t) -> Result<usize> {
- let res = unsafe {
- libc::preadv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset)
- };
-
- Errno::result(res).map(|r| r as usize)
-}
-
-pub fn pwrite(fd: RawFd, buf: &[u8], offset: off_t) -> Result<usize> {
- let res = unsafe {
- libc::pwrite(fd, buf.as_ptr() as *const c_void, buf.len() as size_t,
- offset)
- };
-
- Errno::result(res).map(|r| r as usize)
-}
-
-pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result<usize>{
- let res = unsafe {
- libc::pread(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t,
- offset)
- };
-
- Errno::result(res).map(|r| r as usize)
-}
-
-/// A slice of memory in a remote process, starting at address `base`
-/// and consisting of `len` bytes.
-///
-/// This is the same underlying C structure as [`IoVec`](struct.IoVec.html),
-/// except that it refers to memory in some other process, and is
-/// therefore not represented in Rust by an actual slice as `IoVec` is. It
-/// is used with [`process_vm_readv`](fn.process_vm_readv.html)
-/// and [`process_vm_writev`](fn.process_vm_writev.html).
-#[cfg(target_os = "linux")]
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct RemoteIoVec {
- /// The starting address of this slice (`iov_base`).
- pub base: usize,
- /// The number of bytes in this slice (`iov_len`).
- pub len: usize,
-}
-
-/// Write data directly to another process's virtual memory
-/// (see [`process_vm_writev`(2)]).
-///
-/// `local_iov` is a list of [`IoVec`]s containing the data to be written,
-/// and `remote_iov` is a list of [`RemoteIoVec`]s identifying where the
-/// data should be written in the target process. On success, returns the
-/// number of bytes written, which will always be a whole
-/// number of `remote_iov` chunks.
-///
-/// This requires the same permissions as debugging the process using
-/// [ptrace]: you must either be a privileged process (with
-/// `CAP_SYS_PTRACE`), or you must be running as the same user as the
-/// target process and the OS must have unprivileged debugging enabled.
-///
-/// This function is only available on Linux.
-///
-/// [`process_vm_writev`(2)]: http://man7.org/linux/man-pages/man2/process_vm_writev.2.html
-/// [ptrace]: ../ptrace/index.html
-/// [`IoVec`]: struct.IoVec.html
-/// [`RemoteIoVec`]: struct.RemoteIoVec.html
-#[cfg(target_os = "linux")]
-pub fn process_vm_writev(
- pid: crate::unistd::Pid,
- local_iov: &[IoVec<&[u8]>],
- remote_iov: &[RemoteIoVec]) -> Result<usize>
-{
- let res = unsafe {
- libc::process_vm_writev(pid.into(),
- local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
- remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0)
- };
-
- Errno::result(res).map(|r| r as usize)
-}
-
-/// Read data directly from another process's virtual memory
-/// (see [`process_vm_readv`(2)]).
-///
-/// `local_iov` is a list of [`IoVec`]s containing the buffer to copy
-/// data into, and `remote_iov` is a list of [`RemoteIoVec`]s identifying
-/// where the source data is in the target process. On success,
-/// returns the number of bytes written, which will always be a whole
-/// number of `remote_iov` chunks.
-///
-/// This requires the same permissions as debugging the process using
-/// [`ptrace`]: you must either be a privileged process (with
-/// `CAP_SYS_PTRACE`), or you must be running as the same user as the
-/// target process and the OS must have unprivileged debugging enabled.
-///
-/// This function is only available on Linux.
-///
-/// [`process_vm_readv`(2)]: http://man7.org/linux/man-pages/man2/process_vm_readv.2.html
-/// [`ptrace`]: ../ptrace/index.html
-/// [`IoVec`]: struct.IoVec.html
-/// [`RemoteIoVec`]: struct.RemoteIoVec.html
-#[cfg(any(target_os = "linux"))]
-pub fn process_vm_readv(
- pid: crate::unistd::Pid,
- local_iov: &[IoVec<&mut [u8]>],
- remote_iov: &[RemoteIoVec]) -> Result<usize>
-{
- let res = unsafe {
- libc::process_vm_readv(pid.into(),
- local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
- remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0)
- };
-
- Errno::result(res).map(|r| r as usize)
-}
-
-#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct IoVec<T>(libc::iovec, PhantomData<T>);
-
-impl<T> IoVec<T> {
- #[inline]
- pub fn as_slice(&self) -> &[u8] {
- use std::slice;
-
- unsafe {
- slice::from_raw_parts(
- self.0.iov_base as *const u8,
- self.0.iov_len as usize)
- }
- }
-}
-
-impl<'a> IoVec<&'a [u8]> {
- pub fn from_slice(buf: &'a [u8]) -> IoVec<&'a [u8]> {
- IoVec(libc::iovec {
- iov_base: buf.as_ptr() as *mut c_void,
- iov_len: buf.len() as size_t,
- }, PhantomData)
- }
-}
-
-impl<'a> IoVec<&'a mut [u8]> {
- pub fn from_mut_slice(buf: &'a mut [u8]) -> IoVec<&'a mut [u8]> {
- IoVec(libc::iovec {
- iov_base: buf.as_ptr() as *mut c_void,
- iov_len: buf.len() as size_t,
- }, PhantomData)
- }
-}
diff --git a/vendor/nix-0.20.0/src/sys/utsname.rs b/vendor/nix-0.20.0/src/sys/utsname.rs
deleted file mode 100644
index bf1a814..0000000
--- a/vendor/nix-0.20.0/src/sys/utsname.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-use std::mem;
-use libc::{self, c_char};
-use std::ffi::CStr;
-use std::str::from_utf8_unchecked;
-
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-#[repr(transparent)]
-pub struct UtsName(libc::utsname);
-
-impl UtsName {
- pub fn sysname(&self) -> &str {
- to_str(&(&self.0.sysname as *const c_char ) as *const *const c_char)
- }
-
- pub fn nodename(&self) -> &str {
- to_str(&(&self.0.nodename as *const c_char ) as *const *const c_char)
- }
-
- pub fn release(&self) -> &str {
- to_str(&(&self.0.release as *const c_char ) as *const *const c_char)
- }
-
- pub fn version(&self) -> &str {
- to_str(&(&self.0.version as *const c_char ) as *const *const c_char)
- }
-
- pub fn machine(&self) -> &str {
- to_str(&(&self.0.machine as *const c_char ) as *const *const c_char)
- }
-}
-
-pub fn uname() -> UtsName {
- unsafe {
- let mut ret = mem::MaybeUninit::uninit();
- libc::uname(ret.as_mut_ptr());
- UtsName(ret.assume_init())
- }
-}
-
-#[inline]
-fn to_str<'a>(s: *const *const c_char) -> &'a str {
- unsafe {
- let res = CStr::from_ptr(*s).to_bytes();
- from_utf8_unchecked(res)
- }
-}
-
-#[cfg(test)]
-mod test {
- #[cfg(target_os = "linux")]
- #[test]
- pub fn test_uname_linux() {
- assert_eq!(super::uname().sysname(), "Linux");
- }
-
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- #[test]
- pub fn test_uname_darwin() {
- assert_eq!(super::uname().sysname(), "Darwin");
- }
-
- #[cfg(target_os = "freebsd")]
- #[test]
- pub fn test_uname_freebsd() {
- assert_eq!(super::uname().sysname(), "FreeBSD");
- }
-}
diff --git a/vendor/nix-0.20.0/src/sys/wait.rs b/vendor/nix-0.20.0/src/sys/wait.rs
deleted file mode 100644
index faf8543..0000000
--- a/vendor/nix-0.20.0/src/sys/wait.rs
+++ /dev/null
@@ -1,242 +0,0 @@
-use crate::errno::Errno;
-use crate::sys::signal::Signal;
-use crate::unistd::Pid;
-use crate::Result;
-use cfg_if::cfg_if;
-use libc::{self, c_int};
-use std::convert::TryFrom;
-
-libc_bitflags!(
- pub struct WaitPidFlag: c_int {
- WNOHANG;
- WUNTRACED;
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "redox",
- target_os = "macos",
- target_os = "netbsd"))]
- WEXITED;
- WCONTINUED;
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "redox",
- target_os = "macos",
- target_os = "netbsd"))]
- WSTOPPED;
- /// Don't reap, just poll status.
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "redox",
- target_os = "macos",
- target_os = "netbsd"))]
- WNOWAIT;
- /// Don't wait on children of other threads in this group
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
- __WNOTHREAD;
- /// Wait on all children, regardless of type
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
- __WALL;
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
- __WCLONE;
- }
-);
-
-/// Possible return values from `wait()` or `waitpid()`.
-///
-/// Each status (other than `StillAlive`) describes a state transition
-/// in a child process `Pid`, such as the process exiting or stopping,
-/// plus additional data about the transition if any.
-///
-/// Note that there are two Linux-specific enum variants, `PtraceEvent`
-/// and `PtraceSyscall`. Portable code should avoid exhaustively
-/// matching on `WaitStatus`.
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum WaitStatus {
- /// The process exited normally (as with `exit()` or returning from
- /// `main`) with the given exit code. This case matches the C macro
- /// `WIFEXITED(status)`; the second field is `WEXITSTATUS(status)`.
- Exited(Pid, i32),
- /// The process was killed by the given signal. The third field
- /// indicates whether the signal generated a core dump. This case
- /// matches the C macro `WIFSIGNALED(status)`; the last two fields
- /// correspond to `WTERMSIG(status)` and `WCOREDUMP(status)`.
- Signaled(Pid, Signal, bool),
- /// The process is alive, but was stopped by the given signal. This
- /// is only reported if `WaitPidFlag::WUNTRACED` was passed. This
- /// case matches the C macro `WIFSTOPPED(status)`; the second field
- /// is `WSTOPSIG(status)`.
- Stopped(Pid, Signal),
- /// The traced process was stopped by a `PTRACE_EVENT_*` event. See
- /// [`nix::sys::ptrace`] and [`ptrace`(2)] for more information. All
- /// currently-defined events use `SIGTRAP` as the signal; the third
- /// field is the `PTRACE_EVENT_*` value of the event.
- ///
- /// [`nix::sys::ptrace`]: ../ptrace/index.html
- /// [`ptrace`(2)]: http://man7.org/linux/man-pages/man2/ptrace.2.html
- #[cfg(any(target_os = "linux", target_os = "android"))]
- PtraceEvent(Pid, Signal, c_int),
- /// The traced process was stopped by execution of a system call,
- /// and `PTRACE_O_TRACESYSGOOD` is in effect. See [`ptrace`(2)] for
- /// more information.
- ///
- /// [`ptrace`(2)]: http://man7.org/linux/man-pages/man2/ptrace.2.html
- #[cfg(any(target_os = "linux", target_os = "android"))]
- PtraceSyscall(Pid),
- /// The process was previously stopped but has resumed execution
- /// after receiving a `SIGCONT` signal. This is only reported if
- /// `WaitPidFlag::WCONTINUED` was passed. This case matches the C
- /// macro `WIFCONTINUED(status)`.
- Continued(Pid),
- /// There are currently no state changes to report in any awaited
- /// child process. This is only returned if `WaitPidFlag::WNOHANG`
- /// was used (otherwise `wait()` or `waitpid()` would block until
- /// there was something to report).
- StillAlive,
-}
-
-impl WaitStatus {
- /// Extracts the PID from the WaitStatus unless it equals StillAlive.
- pub fn pid(&self) -> Option<Pid> {
- use self::WaitStatus::*;
- match *self {
- Exited(p, _) | Signaled(p, _, _) | Stopped(p, _) | Continued(p) => Some(p),
- StillAlive => None,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- PtraceEvent(p, _, _) | PtraceSyscall(p) => Some(p),
- }
- }
-}
-
-fn exited(status: i32) -> bool {
- libc::WIFEXITED(status)
-}
-
-fn exit_status(status: i32) -> i32 {
- libc::WEXITSTATUS(status)
-}
-
-fn signaled(status: i32) -> bool {
- libc::WIFSIGNALED(status)
-}
-
-fn term_signal(status: i32) -> Result<Signal> {
- Signal::try_from(libc::WTERMSIG(status))
-}
-
-fn dumped_core(status: i32) -> bool {
- libc::WCOREDUMP(status)
-}
-
-fn stopped(status: i32) -> bool {
- libc::WIFSTOPPED(status)
-}
-
-fn stop_signal(status: i32) -> Result<Signal> {
- Signal::try_from(libc::WSTOPSIG(status))
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-fn syscall_stop(status: i32) -> bool {
- // From ptrace(2), setting PTRACE_O_TRACESYSGOOD has the effect
- // of delivering SIGTRAP | 0x80 as the signal number for syscall
- // stops. This allows easily distinguishing syscall stops from
- // genuine SIGTRAP signals.
- libc::WSTOPSIG(status) == libc::SIGTRAP | 0x80
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-fn stop_additional(status: i32) -> c_int {
- (status >> 16) as c_int
-}
-
-fn continued(status: i32) -> bool {
- libc::WIFCONTINUED(status)
-}
-
-impl WaitStatus {
- /// Convert a raw `wstatus` as returned by `waitpid`/`wait` into a `WaitStatus`
- ///
- /// # Errors
- ///
- /// Returns an `Error` corresponding to `EINVAL` for invalid status values.
- ///
- /// # Examples
- ///
- /// Convert a `wstatus` obtained from `libc::waitpid` into a `WaitStatus`:
- ///
- /// ```
- /// use nix::sys::wait::WaitStatus;
- /// use nix::sys::signal::Signal;
- /// let pid = nix::unistd::Pid::from_raw(1);
- /// let status = WaitStatus::from_raw(pid, 0x0002);
- /// assert_eq!(status, Ok(WaitStatus::Signaled(pid, Signal::SIGINT, false)));
- /// ```
- pub fn from_raw(pid: Pid, status: i32) -> Result<WaitStatus> {
- Ok(if exited(status) {
- WaitStatus::Exited(pid, exit_status(status))
- } else if signaled(status) {
- WaitStatus::Signaled(pid, term_signal(status)?, dumped_core(status))
- } else if stopped(status) {
- cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
- fn decode_stopped(pid: Pid, status: i32) -> Result<WaitStatus> {
- let status_additional = stop_additional(status);
- Ok(if syscall_stop(status) {
- WaitStatus::PtraceSyscall(pid)
- } else if status_additional == 0 {
- WaitStatus::Stopped(pid, stop_signal(status)?)
- } else {
- WaitStatus::PtraceEvent(pid, stop_signal(status)?,
- stop_additional(status))
- })
- }
- } else {
- fn decode_stopped(pid: Pid, status: i32) -> Result<WaitStatus> {
- Ok(WaitStatus::Stopped(pid, stop_signal(status)?))
- }
- }
- }
- return decode_stopped(pid, status);
- } else {
- assert!(continued(status));
- WaitStatus::Continued(pid)
- })
- }
-}
-
-pub fn waitpid<P: Into<Option<Pid>>>(pid: P, options: Option<WaitPidFlag>) -> Result<WaitStatus> {
- use self::WaitStatus::*;
-
- let mut status: i32 = 0;
-
- let option_bits = match options {
- Some(bits) => bits.bits(),
- None => 0,
- };
-
- let res = unsafe {
- libc::waitpid(
- pid.into().unwrap_or_else(|| Pid::from_raw(-1)).into(),
- &mut status as *mut c_int,
- option_bits,
- )
- };
-
- match Errno::result(res)? {
- 0 => Ok(StillAlive),
- res => WaitStatus::from_raw(Pid::from_raw(res), status),
- }
-}
-
-pub fn wait() -> Result<WaitStatus> {
- waitpid(None, None)
-}
diff --git a/vendor/nix-0.20.0/src/time.rs b/vendor/nix-0.20.0/src/time.rs
deleted file mode 100644
index e6c3f8d..0000000
--- a/vendor/nix-0.20.0/src/time.rs
+++ /dev/null
@@ -1,260 +0,0 @@
-use crate::sys::time::TimeSpec;
-#[cfg(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
-))]
-use crate::{unistd::Pid, Error};
-use crate::{Errno, Result};
-use libc::{self, clockid_t};
-use std::mem::MaybeUninit;
-
-/// Clock identifier
-///
-/// Newtype pattern around `clockid_t` (which is just alias). It pervents bugs caused by
-/// accidentally passing wrong value.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
-pub struct ClockId(clockid_t);
-
-impl ClockId {
- /// Creates `ClockId` from raw `clockid_t`
- pub fn from_raw(clk_id: clockid_t) -> Self {
- ClockId(clk_id)
- }
-
- /// Returns `ClockId` of a `pid` CPU-time clock
- #[cfg(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
- ))]
- pub fn pid_cpu_clock_id(pid: Pid) -> Result<Self> {
- clock_getcpuclockid(pid)
- }
-
- /// Returns resolution of the clock id
- #[cfg(not(target_os = "redox"))]
- pub fn res(self) -> Result<TimeSpec> {
- clock_getres(self)
- }
-
- /// Returns the current time on the clock id
- pub fn now(self) -> Result<TimeSpec> {
- clock_gettime(self)
- }
-
- /// Sets time to `timespec` on the clock id
- #[cfg(not(any(
- target_os = "macos",
- target_os = "ios",
- all(
- not(any(target_env = "uclibc", target_env = "newlibc")),
- any(target_os = "redox", target_os = "hermit",),
- ),
- )))]
- pub fn set_time(self, timespec: TimeSpec) -> Result<()> {
- clock_settime(self, timespec)
- }
-
- /// Gets the raw `clockid_t` wrapped by `self`
- pub fn as_raw(self) -> clockid_t {
- self.0
- }
-
- #[cfg(any(
- target_os = "fuchsia",
- all(
- not(any(target_env = "uclibc", target_env = "newlib")),
- any(target_os = "linux", target_os = "android", target_os = "emscripten"),
- )
- ))]
- pub const CLOCK_BOOTTIME: ClockId = ClockId(libc::CLOCK_BOOTTIME);
- #[cfg(any(
- target_os = "fuchsia",
- all(
- not(any(target_env = "uclibc", target_env = "newlib")),
- any(target_os = "linux", target_os = "android", target_os = "emscripten")
- )
- ))]
- pub const CLOCK_BOOTTIME_ALARM: ClockId = ClockId(libc::CLOCK_BOOTTIME_ALARM);
- pub const CLOCK_MONOTONIC: ClockId = ClockId(libc::CLOCK_MONOTONIC);
- #[cfg(any(
- target_os = "fuchsia",
- all(
- not(any(target_env = "uclibc", target_env = "newlib")),
- any(target_os = "linux", target_os = "android", target_os = "emscripten")
- )
- ))]
- pub const CLOCK_MONOTONIC_COARSE: ClockId = ClockId(libc::CLOCK_MONOTONIC_COARSE);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- pub const CLOCK_MONOTONIC_FAST: ClockId = ClockId(libc::CLOCK_MONOTONIC_FAST);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- pub const CLOCK_MONOTONIC_PRECISE: ClockId = ClockId(libc::CLOCK_MONOTONIC_PRECISE);
- #[cfg(any(
- target_os = "fuchsia",
- all(
- not(any(target_env = "uclibc", target_env = "newlib")),
- any(target_os = "linux", target_os = "android", target_os = "emscripten")
- )
- ))]
- pub const CLOCK_MONOTONIC_RAW: ClockId = ClockId(libc::CLOCK_MONOTONIC_RAW);
- #[cfg(any(
- target_os = "fuchsia",
- target_env = "uclibc",
- target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly",
- all(
- not(target_env = "newlib"),
- any(target_os = "linux", target_os = "android", target_os = "emscripten")
- )
- ))]
- pub const CLOCK_PROCESS_CPUTIME_ID: ClockId = ClockId(libc::CLOCK_PROCESS_CPUTIME_ID);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- pub const CLOCK_PROF: ClockId = ClockId(libc::CLOCK_PROF);
- pub const CLOCK_REALTIME: ClockId = ClockId(libc::CLOCK_REALTIME);
- #[cfg(any(
- target_os = "fuchsia",
- all(
- not(any(target_env = "uclibc", target_env = "newlib")),
- any(target_os = "linux", target_os = "android", target_os = "emscripten")
- )
- ))]
- pub const CLOCK_REALTIME_ALARM: ClockId = ClockId(libc::CLOCK_REALTIME_ALARM);
- #[cfg(any(
- target_os = "fuchsia",
- all(
- not(any(target_env = "uclibc", target_env = "newlib")),
- any(target_os = "linux", target_os = "android", target_os = "emscripten")
- )
- ))]
- pub const CLOCK_REALTIME_COARSE: ClockId = ClockId(libc::CLOCK_REALTIME_COARSE);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- pub const CLOCK_REALTIME_FAST: ClockId = ClockId(libc::CLOCK_REALTIME_FAST);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- pub const CLOCK_REALTIME_PRECISE: ClockId = ClockId(libc::CLOCK_REALTIME_PRECISE);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- pub const CLOCK_SECOND: ClockId = ClockId(libc::CLOCK_SECOND);
- #[cfg(any(
- target_os = "fuchsia",
- all(
- not(any(target_env = "uclibc", target_env = "newlib")),
- any(
- target_os = "emscripten",
- all(target_os = "linux", target_env = "musl")
- )
- )
- ))]
- pub const CLOCK_SGI_CYCLE: ClockId = ClockId(libc::CLOCK_SGI_CYCLE);
- #[cfg(any(
- target_os = "fuchsia",
- all(
- not(any(target_env = "uclibc", target_env = "newlib")),
- any(
- target_os = "emscripten",
- all(target_os = "linux", target_env = "musl")
- )
- )
- ))]
- pub const CLOCK_TAI: ClockId = ClockId(libc::CLOCK_TAI);
- #[cfg(any(
- target_env = "uclibc",
- target_os = "fuchsia",
- target_os = "ios",
- target_os = "macos",
- target_os = "freebsd",
- target_os = "dragonfly",
- all(
- not(target_env = "newlib"),
- any(target_os = "linux", target_os = "android", target_os = "emscripten",),
- ),
- ))]
- pub const CLOCK_THREAD_CPUTIME_ID: ClockId = ClockId(libc::CLOCK_THREAD_CPUTIME_ID);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- pub const CLOCK_UPTIME: ClockId = ClockId(libc::CLOCK_UPTIME);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- pub const CLOCK_UPTIME_FAST: ClockId = ClockId(libc::CLOCK_UPTIME_FAST);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- pub const CLOCK_UPTIME_PRECISE: ClockId = ClockId(libc::CLOCK_UPTIME_PRECISE);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- pub const CLOCK_VIRTUAL: ClockId = ClockId(libc::CLOCK_VIRTUAL);
-}
-
-impl Into<clockid_t> for ClockId {
- fn into(self) -> clockid_t {
- self.as_raw()
- }
-}
-
-impl From<clockid_t> for ClockId {
- fn from(clk_id: clockid_t) -> Self {
- ClockId::from_raw(clk_id)
- }
-}
-
-impl std::fmt::Display for ClockId {
- fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
- std::fmt::Display::fmt(&self.0, f)
- }
-}
-
-/// Get the resolution of the specified clock, (see
-/// [clock_getres(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_getres.html)).
-#[cfg(not(target_os = "redox"))]
-pub fn clock_getres(clock_id: ClockId) -> Result<TimeSpec> {
- let mut c_time: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
- let ret = unsafe { libc::clock_getres(clock_id.as_raw(), c_time.as_mut_ptr()) };
- Errno::result(ret)?;
- let res = unsafe { c_time.assume_init() };
- Ok(TimeSpec::from(res))
-}
-
-/// Get the time of the specified clock, (see
-/// [clock_gettime(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_gettime.html)).
-pub fn clock_gettime(clock_id: ClockId) -> Result<TimeSpec> {
- let mut c_time: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
- let ret = unsafe { libc::clock_gettime(clock_id.as_raw(), c_time.as_mut_ptr()) };
- Errno::result(ret)?;
- let res = unsafe { c_time.assume_init() };
- Ok(TimeSpec::from(res))
-}
-
-/// Set the time of the specified clock, (see
-/// [clock_settime(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_settime.html)).
-#[cfg(not(any(
- target_os = "macos",
- target_os = "ios",
- all(
- not(any(target_env = "uclibc", target_env = "newlibc")),
- any(target_os = "redox", target_os = "hermit",),
- ),
-)))]
-pub fn clock_settime(clock_id: ClockId, timespec: TimeSpec) -> Result<()> {
- let ret = unsafe { libc::clock_settime(clock_id.as_raw(), timespec.as_ref()) };
- Errno::result(ret).map(drop)
-}
-
-/// Get the clock id of the specified process id, (see
-/// [clock_getcpuclockid(3)](https://pubs.opengroup.org/onlinepubs/009695399/functions/clock_getcpuclockid.html)).
-#[cfg(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
-))]
-pub fn clock_getcpuclockid(pid: Pid) -> Result<ClockId> {
- let mut clk_id: MaybeUninit<libc::clockid_t> = MaybeUninit::uninit();
- let ret = unsafe { libc::clock_getcpuclockid(pid.into(), clk_id.as_mut_ptr()) };
- if ret == 0 {
- let res = unsafe { clk_id.assume_init() };
- Ok(ClockId::from(res))
- } else {
- Err(Error::Sys(Errno::from_i32(ret)))
- }
-}
diff --git a/vendor/nix-0.20.0/src/ucontext.rs b/vendor/nix-0.20.0/src/ucontext.rs
deleted file mode 100644
index a5b8cc7..0000000
--- a/vendor/nix-0.20.0/src/ucontext.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-use libc;
-#[cfg(not(target_env = "musl"))]
-use crate::Result;
-#[cfg(not(target_env = "musl"))]
-use crate::errno::Errno;
-#[cfg(not(target_env = "musl"))]
-use std::mem;
-use crate::sys::signal::SigSet;
-
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct UContext {
- context: libc::ucontext_t,
-}
-
-impl UContext {
- #[cfg(not(target_env = "musl"))]
- pub fn get() -> Result<UContext> {
- let mut context = mem::MaybeUninit::<libc::ucontext_t>::uninit();
- let res = unsafe { libc::getcontext(context.as_mut_ptr()) };
- Errno::result(res).map(|_| unsafe {
- UContext { context: context.assume_init()}
- })
- }
-
- #[cfg(not(target_env = "musl"))]
- pub fn set(&self) -> Result<()> {
- let res = unsafe {
- libc::setcontext(&self.context as *const libc::ucontext_t)
- };
- Errno::result(res).map(drop)
- }
-
- pub fn sigmask_mut(&mut self) -> &mut SigSet {
- unsafe {
- &mut *(&mut self.context.uc_sigmask as *mut libc::sigset_t as *mut SigSet)
- }
- }
-
- pub fn sigmask(&self) -> &SigSet {
- unsafe {
- &*(&self.context.uc_sigmask as *const libc::sigset_t as *const SigSet)
- }
- }
-}
diff --git a/vendor/nix-0.20.0/src/unistd.rs b/vendor/nix-0.20.0/src/unistd.rs
deleted file mode 100644
index 7a4517e..0000000
--- a/vendor/nix-0.20.0/src/unistd.rs
+++ /dev/null
@@ -1,2829 +0,0 @@
-//! Safe wrappers around functions found in libc "unistd.h" header
-
-#[cfg(not(target_os = "redox"))]
-use cfg_if::cfg_if;
-use crate::errno::{self, Errno};
-use crate::{Error, Result, NixPath};
-#[cfg(not(target_os = "redox"))]
-use crate::fcntl::{AtFlags, at_rawfd};
-use crate::fcntl::{FdFlag, OFlag, fcntl};
-use crate::fcntl::FcntlArg::F_SETFD;
-use libc::{self, c_char, c_void, c_int, c_long, c_uint, size_t, pid_t, off_t,
- uid_t, gid_t, mode_t, PATH_MAX};
-use std::{fmt, mem, ptr};
-use std::convert::Infallible;
-use std::ffi::{CStr, OsString};
-#[cfg(not(target_os = "redox"))]
-use std::ffi::{CString, OsStr};
-use std::os::unix::ffi::OsStringExt;
-#[cfg(not(target_os = "redox"))]
-use std::os::unix::ffi::OsStrExt;
-use std::os::unix::io::RawFd;
-use std::path::PathBuf;
-use crate::sys::stat::Mode;
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use self::pivot_root::*;
-
-#[cfg(any(target_os = "android", target_os = "freebsd",
- target_os = "linux", target_os = "openbsd"))]
-pub use self::setres::*;
-
-/// User identifier
-///
-/// Newtype pattern around `uid_t` (which is just alias). It prevents bugs caused by accidentally
-/// passing wrong value.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub struct Uid(uid_t);
-
-impl Uid {
- /// Creates `Uid` from raw `uid_t`.
- pub fn from_raw(uid: uid_t) -> Self {
- Uid(uid)
- }
-
- /// Returns Uid of calling process. This is practically a more Rusty alias for `getuid`.
- pub fn current() -> Self {
- getuid()
- }
-
- /// Returns effective Uid of calling process. This is practically a more Rusty alias for `geteuid`.
- pub fn effective() -> Self {
- geteuid()
- }
-
- /// Returns true if the `Uid` represents privileged user - root. (If it equals zero.)
- pub fn is_root(self) -> bool {
- self == ROOT
- }
-
- /// Get the raw `uid_t` wrapped by `self`.
- pub fn as_raw(self) -> uid_t {
- self.0
- }
-}
-
-impl From<Uid> for uid_t {
- fn from(uid: Uid) -> Self {
- uid.0
- }
-}
-
-impl fmt::Display for Uid {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Display::fmt(&self.0, f)
- }
-}
-
-/// Constant for UID = 0
-pub const ROOT: Uid = Uid(0);
-
-/// Group identifier
-///
-/// Newtype pattern around `gid_t` (which is just alias). It prevents bugs caused by accidentally
-/// passing wrong value.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub struct Gid(gid_t);
-
-impl Gid {
- /// Creates `Gid` from raw `gid_t`.
- pub fn from_raw(gid: gid_t) -> Self {
- Gid(gid)
- }
-
- /// Returns Gid of calling process. This is practically a more Rusty alias for `getgid`.
- pub fn current() -> Self {
- getgid()
- }
-
- /// Returns effective Gid of calling process. This is practically a more Rusty alias for `getegid`.
- pub fn effective() -> Self {
- getegid()
- }
-
- /// Get the raw `gid_t` wrapped by `self`.
- pub fn as_raw(self) -> gid_t {
- self.0
- }
-}
-
-impl From<Gid> for gid_t {
- fn from(gid: Gid) -> Self {
- gid.0
- }
-}
-
-impl fmt::Display for Gid {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Display::fmt(&self.0, f)
- }
-}
-
-/// Process identifier
-///
-/// Newtype pattern around `pid_t` (which is just alias). It prevents bugs caused by accidentally
-/// passing wrong value.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
-pub struct Pid(pid_t);
-
-impl Pid {
- /// Creates `Pid` from raw `pid_t`.
- pub fn from_raw(pid: pid_t) -> Self {
- Pid(pid)
- }
-
- /// Returns PID of calling process
- pub fn this() -> Self {
- getpid()
- }
-
- /// Returns PID of parent of calling process
- pub fn parent() -> Self {
- getppid()
- }
-
- /// Get the raw `pid_t` wrapped by `self`.
- pub fn as_raw(self) -> pid_t {
- self.0
- }
-}
-
-impl From<Pid> for pid_t {
- fn from(pid: Pid) -> Self {
- pid.0
- }
-}
-
-impl fmt::Display for Pid {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Display::fmt(&self.0, f)
- }
-}
-
-
-/// Represents the successful result of calling `fork`
-///
-/// When `fork` is called, the process continues execution in the parent process
-/// and in the new child. This return type can be examined to determine whether
-/// you are now executing in the parent process or in the child.
-#[derive(Clone, Copy, Debug)]
-pub enum ForkResult {
- Parent { child: Pid },
- Child,
-}
-
-impl ForkResult {
-
- /// Return `true` if this is the child process of the `fork()`
- #[inline]
- pub fn is_child(self) -> bool {
- match self {
- ForkResult::Child => true,
- _ => false
- }
- }
-
- /// Returns `true` if this is the parent process of the `fork()`
- #[inline]
- pub fn is_parent(self) -> bool {
- !self.is_child()
- }
-}
-
-/// Create a new child process duplicating the parent process ([see
-/// fork(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html)).
-///
-/// After calling the fork system call (successfully) two processes will
-/// be created that are identical with the exception of their pid and the
-/// return value of this function. As an example:
-///
-/// ```no_run
-/// use nix::unistd::{fork, ForkResult};
-///
-/// match unsafe{fork()} {
-/// Ok(ForkResult::Parent { child, .. }) => {
-/// println!("Continuing execution in parent process, new child has pid: {}", child);
-/// }
-/// Ok(ForkResult::Child) => println!("I'm a new child process"),
-/// Err(_) => println!("Fork failed"),
-/// }
-/// ```
-///
-/// This will print something like the following (order indeterministic). The
-/// thing to note is that you end up with two processes continuing execution
-/// immediately after the fork call but with different match arms.
-///
-/// ```text
-/// Continuing execution in parent process, new child has pid: 1234
-/// I'm a new child process
-/// ```
-///
-/// # Safety
-///
-/// In a multithreaded program, only [async-signal-safe] functions like `pause`
-/// and `_exit` may be called by the child (the parent isn't restricted). Note
-/// that memory allocation may **not** be async-signal-safe and thus must be
-/// prevented.
-///
-/// Those functions are only a small subset of your operating system's API, so
-/// special care must be taken to only invoke code you can control and audit.
-///
-/// [async-signal-safe]: http://man7.org/linux/man-pages/man7/signal-safety.7.html
-#[inline]
-pub unsafe fn fork() -> Result<ForkResult> {
- use self::ForkResult::*;
- let res = libc::fork();
-
- Errno::result(res).map(|res| match res {
- 0 => Child,
- res => Parent { child: Pid(res) },
- })
-}
-
-/// Get the pid of this process (see
-/// [getpid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpid.html)).
-///
-/// Since you are running code, there is always a pid to return, so there
-/// is no error case that needs to be handled.
-#[inline]
-pub fn getpid() -> Pid {
- Pid(unsafe { libc::getpid() })
-}
-
-/// Get the pid of this processes' parent (see
-/// [getpid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getppid.html)).
-///
-/// There is always a parent pid to return, so there is no error case that needs
-/// to be handled.
-#[inline]
-pub fn getppid() -> Pid {
- Pid(unsafe { libc::getppid() }) // no error handling, according to man page: "These functions are always successful."
-}
-
-/// Set a process group ID (see
-/// [setpgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setpgid.html)).
-///
-/// Set the process group id (PGID) of a particular process. If a pid of zero
-/// is specified, then the pid of the calling process is used. Process groups
-/// may be used to group together a set of processes in order for the OS to
-/// apply some operations across the group.
-///
-/// `setsid()` may be used to create a new process group.
-#[inline]
-pub fn setpgid(pid: Pid, pgid: Pid) -> Result<()> {
- let res = unsafe { libc::setpgid(pid.into(), pgid.into()) };
- Errno::result(res).map(drop)
-}
-#[inline]
-pub fn getpgid(pid: Option<Pid>) -> Result<Pid> {
- let res = unsafe { libc::getpgid(pid.unwrap_or(Pid(0)).into()) };
- Errno::result(res).map(Pid)
-}
-
-/// Create new session and set process group id (see
-/// [setsid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsid.html)).
-#[inline]
-pub fn setsid() -> Result<Pid> {
- Errno::result(unsafe { libc::setsid() }).map(Pid)
-}
-
-/// Get the process group ID of a session leader
-/// [getsid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsid.html).
-///
-/// Obtain the process group ID of the process that is the session leader of the process specified
-/// by pid. If pid is zero, it specifies the calling process.
-#[inline]
-#[cfg(not(target_os = "redox"))]
-pub fn getsid(pid: Option<Pid>) -> Result<Pid> {
- let res = unsafe { libc::getsid(pid.unwrap_or(Pid(0)).into()) };
- Errno::result(res).map(Pid)
-}
-
-
-/// Get the terminal foreground process group (see
-/// [tcgetpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetpgrp.html)).
-///
-/// Get the group process id (GPID) of the foreground process group on the
-/// terminal associated to file descriptor (FD).
-#[inline]
-pub fn tcgetpgrp(fd: c_int) -> Result<Pid> {
- let res = unsafe { libc::tcgetpgrp(fd) };
- Errno::result(res).map(Pid)
-}
-/// Set the terminal foreground process group (see
-/// [tcgetpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetpgrp.html)).
-///
-/// Get the group process id (PGID) to the foreground process group on the
-/// terminal associated to file descriptor (FD).
-#[inline]
-pub fn tcsetpgrp(fd: c_int, pgrp: Pid) -> Result<()> {
- let res = unsafe { libc::tcsetpgrp(fd, pgrp.into()) };
- Errno::result(res).map(drop)
-}
-
-
-/// Get the group id of the calling process (see
-///[getpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgrp.html)).
-///
-/// Get the process group id (PGID) of the calling process.
-/// According to the man page it is always successful.
-#[inline]
-pub fn getpgrp() -> Pid {
- Pid(unsafe { libc::getpgrp() })
-}
-
-/// Get the caller's thread ID (see
-/// [gettid(2)](http://man7.org/linux/man-pages/man2/gettid.2.html).
-///
-/// This function is only available on Linux based systems. In a single
-/// threaded process, the main thread will have the same ID as the process. In
-/// a multithreaded process, each thread will have a unique thread id but the
-/// same process ID.
-///
-/// No error handling is required as a thread id should always exist for any
-/// process, even if threads are not being used.
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[inline]
-pub fn gettid() -> Pid {
- Pid(unsafe { libc::syscall(libc::SYS_gettid) as pid_t })
-}
-
-/// Create a copy of the specified file descriptor (see
-/// [dup(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)).
-///
-/// The new file descriptor will be have a new index but refer to the same
-/// resource as the old file descriptor and the old and new file descriptors may
-/// be used interchangeably. The new and old file descriptor share the same
-/// underlying resource, offset, and file status flags. The actual index used
-/// for the file descriptor will be the lowest fd index that is available.
-///
-/// The two file descriptors do not share file descriptor flags (e.g. `OFlag::FD_CLOEXEC`).
-#[inline]
-pub fn dup(oldfd: RawFd) -> Result<RawFd> {
- let res = unsafe { libc::dup(oldfd) };
-
- Errno::result(res)
-}
-
-/// Create a copy of the specified file descriptor using the specified fd (see
-/// [dup(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)).
-///
-/// This function behaves similar to `dup()` except that it will try to use the
-/// specified fd instead of allocating a new one. See the man pages for more
-/// detail on the exact behavior of this function.
-#[inline]
-pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
- let res = unsafe { libc::dup2(oldfd, newfd) };
-
- Errno::result(res)
-}
-
-/// Create a new copy of the specified file descriptor using the specified fd
-/// and flags (see [dup(2)](http://man7.org/linux/man-pages/man2/dup.2.html)).
-///
-/// This function behaves similar to `dup2()` but allows for flags to be
-/// specified.
-pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
- dup3_polyfill(oldfd, newfd, flags)
-}
-
-#[inline]
-fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
- if oldfd == newfd {
- return Err(Error::Sys(Errno::EINVAL));
- }
-
- let fd = dup2(oldfd, newfd)?;
-
- if flags.contains(OFlag::O_CLOEXEC) {
- if let Err(e) = fcntl(fd, F_SETFD(FdFlag::FD_CLOEXEC)) {
- let _ = close(fd);
- return Err(e);
- }
- }
-
- Ok(fd)
-}
-
-/// Change the current working directory of the calling process (see
-/// [chdir(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html)).
-///
-/// This function may fail in a number of different scenarios. See the man
-/// pages for additional details on possible failure cases.
-#[inline]
-pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
- let res = path.with_nix_path(|cstr| {
- unsafe { libc::chdir(cstr.as_ptr()) }
- })?;
-
- Errno::result(res).map(drop)
-}
-
-/// Change the current working directory of the process to the one
-/// given as an open file descriptor (see
-/// [fchdir(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchdir.html)).
-///
-/// This function may fail in a number of different scenarios. See the man
-/// pages for additional details on possible failure cases.
-#[inline]
-#[cfg(not(target_os = "fuchsia"))]
-pub fn fchdir(dirfd: RawFd) -> Result<()> {
- let res = unsafe { libc::fchdir(dirfd) };
-
- Errno::result(res).map(drop)
-}
-
-/// Creates new directory `path` with access rights `mode`. (see [mkdir(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdir.html))
-///
-/// # Errors
-///
-/// There are several situations where mkdir might fail:
-///
-/// - current user has insufficient rights in the parent directory
-/// - the path already exists
-/// - the path name is too long (longer than `PATH_MAX`, usually 4096 on linux, 1024 on OS X)
-///
-/// # Example
-///
-/// ```rust
-/// use nix::unistd;
-/// use nix::sys::stat;
-/// use tempfile::tempdir;
-///
-/// fn main() {
-/// let tmp_dir1 = tempdir().unwrap();
-/// let tmp_dir2 = tmp_dir1.path().join("new_dir");
-///
-/// // create new directory and give read, write and execute rights to the owner
-/// match unistd::mkdir(&tmp_dir2, stat::Mode::S_IRWXU) {
-/// Ok(_) => println!("created {:?}", tmp_dir2),
-/// Err(err) => println!("Error creating directory: {}", err),
-/// }
-/// }
-/// ```
-#[inline]
-pub fn mkdir<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
- let res = path.with_nix_path(|cstr| {
- unsafe { libc::mkdir(cstr.as_ptr(), mode.bits() as mode_t) }
- })?;
-
- Errno::result(res).map(drop)
-}
-
-/// Creates new fifo special file (named pipe) with path `path` and access rights `mode`.
-///
-/// # Errors
-///
-/// There are several situations where mkfifo might fail:
-///
-/// - current user has insufficient rights in the parent directory
-/// - the path already exists
-/// - the path name is too long (longer than `PATH_MAX`, usually 4096 on linux, 1024 on OS X)
-///
-/// For a full list consult
-/// [posix specification](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifo.html)
-///
-/// # Example
-///
-/// ```rust
-/// use nix::unistd;
-/// use nix::sys::stat;
-/// use tempfile::tempdir;
-///
-/// fn main() {
-/// let tmp_dir = tempdir().unwrap();
-/// let fifo_path = tmp_dir.path().join("foo.pipe");
-///
-/// // create new fifo and give read, write and execute rights to the owner
-/// match unistd::mkfifo(&fifo_path, stat::Mode::S_IRWXU) {
-/// Ok(_) => println!("created {:?}", fifo_path),
-/// Err(err) => println!("Error creating fifo: {}", err),
-/// }
-/// }
-/// ```
-#[inline]
-#[cfg(not(target_os = "redox"))] // RedoxFS does not support fifo yet
-pub fn mkfifo<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
- let res = path.with_nix_path(|cstr| {
- unsafe { libc::mkfifo(cstr.as_ptr(), mode.bits() as mode_t) }
- })?;
-
- Errno::result(res).map(drop)
-}
-
-/// Creates new fifo special file (named pipe) with path `path` and access rights `mode`.
-///
-/// If `dirfd` has a value, then `path` is relative to directory associated with the file descriptor.
-///
-/// If `dirfd` is `None`, then `path` is relative to the current working directory.
-///
-/// # References
-///
-/// [mkfifoat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifoat.html).
-// mkfifoat is not implemented in OSX or android
-#[inline]
-#[cfg(not(any(
- target_os = "macos", target_os = "ios",
- target_os = "android", target_os = "redox")))]
-pub fn mkfifoat<P: ?Sized + NixPath>(dirfd: Option<RawFd>, path: &P, mode: Mode) -> Result<()> {
- let res = path.with_nix_path(|cstr| unsafe {
- libc::mkfifoat(at_rawfd(dirfd), cstr.as_ptr(), mode.bits() as mode_t)
- })?;
-
- Errno::result(res).map(drop)
-}
-
-/// Creates a symbolic link at `path2` which points to `path1`.
-///
-/// If `dirfd` has a value, then `path2` is relative to directory associated
-/// with the file descriptor.
-///
-/// If `dirfd` is `None`, then `path2` is relative to the current working
-/// directory. This is identical to `libc::symlink(path1, path2)`.
-///
-/// See also [symlinkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html).
-#[cfg(not(target_os = "redox"))]
-pub fn symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
- path1: &P1,
- dirfd: Option<RawFd>,
- path2: &P2) -> Result<()> {
- let res =
- path1.with_nix_path(|path1| {
- path2.with_nix_path(|path2| {
- unsafe {
- libc::symlinkat(
- path1.as_ptr(),
- dirfd.unwrap_or(libc::AT_FDCWD),
- path2.as_ptr()
- )
- }
- })
- })??;
- Errno::result(res).map(drop)
-}
-
-// Double the buffer capacity up to limit. In case it already has
-// reached the limit, return Errno::ERANGE.
-fn reserve_double_buffer_size<T>(buf: &mut Vec<T>, limit: usize) -> Result<()> {
- use std::cmp::min;
-
- if buf.capacity() >= limit {
- return Err(Error::Sys(Errno::ERANGE))
- }
-
- let capacity = min(buf.capacity() * 2, limit);
- buf.reserve(capacity);
-
- Ok(())
-}
-
-/// Returns the current directory as a `PathBuf`
-///
-/// Err is returned if the current user doesn't have the permission to read or search a component
-/// of the current path.
-///
-/// # Example
-///
-/// ```rust
-/// use nix::unistd;
-///
-/// fn main() {
-/// // assume that we are allowed to get current directory
-/// let dir = unistd::getcwd().unwrap();
-/// println!("The current directory is {:?}", dir);
-/// }
-/// ```
-#[inline]
-pub fn getcwd() -> Result<PathBuf> {
- let mut buf = Vec::with_capacity(512);
- loop {
- unsafe {
- let ptr = buf.as_mut_ptr() as *mut c_char;
-
- // The buffer must be large enough to store the absolute pathname plus
- // a terminating null byte, or else null is returned.
- // To safely handle this we start with a reasonable size (512 bytes)
- // and double the buffer size upon every error
- if !libc::getcwd(ptr, buf.capacity()).is_null() {
- let len = CStr::from_ptr(buf.as_ptr() as *const c_char).to_bytes().len();
- buf.set_len(len);
- buf.shrink_to_fit();
- return Ok(PathBuf::from(OsString::from_vec(buf)));
- } else {
- let error = Errno::last();
- // ERANGE means buffer was too small to store directory name
- if error != Errno::ERANGE {
- return Err(Error::Sys(error));
- }
- }
-
- // Trigger the internal buffer resizing logic.
- reserve_double_buffer_size(&mut buf, PATH_MAX as usize)?;
- }
- }
-}
-
-/// Computes the raw UID and GID values to pass to a `*chown` call.
-fn chown_raw_ids(owner: Option<Uid>, group: Option<Gid>) -> (libc::uid_t, libc::gid_t) {
- // According to the POSIX specification, -1 is used to indicate that owner and group
- // are not to be changed. Since uid_t and gid_t are unsigned types, we have to wrap
- // around to get -1.
- let uid = owner.map(Into::into)
- .unwrap_or_else(|| (0 as uid_t).wrapping_sub(1));
- let gid = group.map(Into::into)
- .unwrap_or_else(|| (0 as gid_t).wrapping_sub(1));
- (uid, gid)
-}
-
-/// Change the ownership of the file at `path` to be owned by the specified
-/// `owner` (user) and `group` (see
-/// [chown(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/chown.html)).
-///
-/// The owner/group for the provided path name will not be modified if `None` is
-/// provided for that argument. Ownership change will be attempted for the path
-/// only if `Some` owner/group is provided.
-#[inline]
-pub fn chown<P: ?Sized + NixPath>(path: &P, owner: Option<Uid>, group: Option<Gid>) -> Result<()> {
- let res = path.with_nix_path(|cstr| {
- let (uid, gid) = chown_raw_ids(owner, group);
- unsafe { libc::chown(cstr.as_ptr(), uid, gid) }
- })?;
-
- Errno::result(res).map(drop)
-}
-
-/// Change the ownership of the file referred to by the open file descriptor `fd` to be owned by
-/// the specified `owner` (user) and `group` (see
-/// [fchown(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchown.html)).
-///
-/// The owner/group for the provided file will not be modified if `None` is
-/// provided for that argument. Ownership change will be attempted for the path
-/// only if `Some` owner/group is provided.
-#[inline]
-pub fn fchown(fd: RawFd, owner: Option<Uid>, group: Option<Gid>) -> Result<()> {
- let (uid, gid) = chown_raw_ids(owner, group);
- let res = unsafe { libc::fchown(fd, uid, gid) };
- Errno::result(res).map(drop)
-}
-
-/// Flags for `fchownat` function.
-#[derive(Clone, Copy, Debug)]
-pub enum FchownatFlags {
- FollowSymlink,
- NoFollowSymlink,
-}
-
-/// Change the ownership of the file at `path` to be owned by the specified
-/// `owner` (user) and `group`.
-///
-/// The owner/group for the provided path name will not be modified if `None` is
-/// provided for that argument. Ownership change will be attempted for the path
-/// only if `Some` owner/group is provided.
-///
-/// The file to be changed is determined relative to the directory associated
-/// with the file descriptor `dirfd` or the current working directory
-/// if `dirfd` is `None`.
-///
-/// If `flag` is `FchownatFlags::NoFollowSymlink` and `path` names a symbolic link,
-/// then the mode of the symbolic link is changed.
-///
-/// `fchownat(None, path, mode, FchownatFlags::NoFollowSymlink)` is identical to
-/// a call `libc::lchown(path, mode)`. That's why `lchmod` is unimplemented in
-/// the `nix` crate.
-///
-/// # References
-///
-/// [fchownat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchownat.html).
-#[cfg(not(target_os = "redox"))]
-pub fn fchownat<P: ?Sized + NixPath>(
- dirfd: Option<RawFd>,
- path: &P,
- owner: Option<Uid>,
- group: Option<Gid>,
- flag: FchownatFlags,
-) -> Result<()> {
- let atflag =
- match flag {
- FchownatFlags::FollowSymlink => AtFlags::empty(),
- FchownatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
- };
- let res = path.with_nix_path(|cstr| unsafe {
- let (uid, gid) = chown_raw_ids(owner, group);
- libc::fchownat(at_rawfd(dirfd), cstr.as_ptr(), uid, gid,
- atflag.bits() as libc::c_int)
- })?;
-
- Errno::result(res).map(drop)
-}
-
-fn to_exec_array<S: AsRef<CStr>>(args: &[S]) -> Vec<*const c_char> {
- use std::iter::once;
- args.iter().map(|s| s.as_ref().as_ptr()).chain(once(ptr::null())).collect()
-}
-
-/// Replace the current process image with a new one (see
-/// [exec(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
-///
-/// See the `::nix::unistd::execve` system call for additional details. `execv`
-/// performs the same action but does not allow for customization of the
-/// environment for the new process.
-#[inline]
-pub fn execv<S: AsRef<CStr>>(path: &CStr, argv: &[S]) -> Result<Infallible> {
- let args_p = to_exec_array(argv);
-
- unsafe {
- libc::execv(path.as_ptr(), args_p.as_ptr())
- };
-
- Err(Error::Sys(Errno::last()))
-}
-
-
-/// Replace the current process image with a new one (see
-/// [execve(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
-///
-/// The execve system call allows for another process to be "called" which will
-/// replace the current process image. That is, this process becomes the new
-/// command that is run. On success, this function will not return. Instead,
-/// the new program will run until it exits.
-///
-/// `::nix::unistd::execv` and `::nix::unistd::execve` take as arguments a slice
-/// of `::std::ffi::CString`s for `args` and `env` (for `execve`). Each element
-/// in the `args` list is an argument to the new process. Each element in the
-/// `env` list should be a string in the form "key=value".
-#[inline]
-pub fn execve<SA: AsRef<CStr>, SE: AsRef<CStr>>(path: &CStr, args: &[SA], env: &[SE]) -> Result<Infallible> {
- let args_p = to_exec_array(args);
- let env_p = to_exec_array(env);
-
- unsafe {
- libc::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
- };
-
- Err(Error::Sys(Errno::last()))
-}
-
-/// Replace the current process image with a new one and replicate shell `PATH`
-/// searching behavior (see
-/// [exec(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
-///
-/// See `::nix::unistd::execve` for additional details. `execvp` behaves the
-/// same as execv except that it will examine the `PATH` environment variables
-/// for file names not specified with a leading slash. For example, `execv`
-/// would not work if "bash" was specified for the path argument, but `execvp`
-/// would assuming that a bash executable was on the system `PATH`.
-#[inline]
-pub fn execvp<S: AsRef<CStr>>(filename: &CStr, args: &[S]) -> Result<Infallible> {
- let args_p = to_exec_array(args);
-
- unsafe {
- libc::execvp(filename.as_ptr(), args_p.as_ptr())
- };
-
- Err(Error::Sys(Errno::last()))
-}
-
-/// Replace the current process image with a new one and replicate shell `PATH`
-/// searching behavior (see
-/// [`execvpe(3)`](http://man7.org/linux/man-pages/man3/exec.3.html)).
-///
-/// This functions like a combination of `execvp(2)` and `execve(2)` to pass an
-/// environment and have a search path. See these two for additional
-/// information.
-#[cfg(any(target_os = "haiku",
- target_os = "linux",
- target_os = "openbsd"))]
-pub fn execvpe<SA: AsRef<CStr>, SE: AsRef<CStr>>(filename: &CStr, args: &[SA], env: &[SE]) -> Result<Infallible> {
- let args_p = to_exec_array(args);
- let env_p = to_exec_array(env);
-
- unsafe {
- libc::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
- };
-
- Err(Error::Sys(Errno::last()))
-}
-
-/// Replace the current process image with a new one (see
-/// [fexecve(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fexecve.html)).
-///
-/// The `fexecve` function allows for another process to be "called" which will
-/// replace the current process image. That is, this process becomes the new
-/// command that is run. On success, this function will not return. Instead,
-/// the new program will run until it exits.
-///
-/// This function is similar to `execve`, except that the program to be executed
-/// is referenced as a file descriptor instead of a path.
-// Note for NetBSD and OpenBSD: although rust-lang/libc includes it (under
-// unix/bsd/netbsdlike/) fexecve is not currently implemented on NetBSD nor on
-// OpenBSD.
-#[cfg(any(target_os = "android",
- target_os = "linux",
- target_os = "freebsd"))]
-#[inline]
-pub fn fexecve<SA: AsRef<CStr> ,SE: AsRef<CStr>>(fd: RawFd, args: &[SA], env: &[SE]) -> Result<Infallible> {
- let args_p = to_exec_array(args);
- let env_p = to_exec_array(env);
-
- unsafe {
- libc::fexecve(fd, args_p.as_ptr(), env_p.as_ptr())
- };
-
- Err(Error::Sys(Errno::last()))
-}
-
-/// Execute program relative to a directory file descriptor (see
-/// [execveat(2)](http://man7.org/linux/man-pages/man2/execveat.2.html)).
-///
-/// The `execveat` function allows for another process to be "called" which will
-/// replace the current process image. That is, this process becomes the new
-/// command that is run. On success, this function will not return. Instead,
-/// the new program will run until it exits.
-///
-/// This function is similar to `execve`, except that the program to be executed
-/// is referenced as a file descriptor to the base directory plus a path.
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[inline]
-pub fn execveat<SA: AsRef<CStr>,SE: AsRef<CStr>>(dirfd: RawFd, pathname: &CStr, args: &[SA],
- env: &[SE], flags: super::fcntl::AtFlags) -> Result<Infallible> {
- let args_p = to_exec_array(args);
- let env_p = to_exec_array(env);
-
- unsafe {
- libc::syscall(libc::SYS_execveat, dirfd, pathname.as_ptr(),
- args_p.as_ptr(), env_p.as_ptr(), flags);
- };
-
- Err(Error::Sys(Errno::last()))
-}
-
-/// Daemonize this process by detaching from the controlling terminal (see
-/// [daemon(3)](http://man7.org/linux/man-pages/man3/daemon.3.html)).
-///
-/// When a process is launched it is typically associated with a parent and it,
-/// in turn, by its controlling terminal/process. In order for a process to run
-/// in the "background" it must daemonize itself by detaching itself. Under
-/// posix, this is done by doing the following:
-///
-/// 1. Parent process (this one) forks
-/// 2. Parent process exits
-/// 3. Child process continues to run.
-///
-/// `nochdir`:
-///
-/// * `nochdir = true`: The current working directory after daemonizing will
-/// be the current working directory.
-/// * `nochdir = false`: The current working directory after daemonizing will
-/// be the root direcory, `/`.
-///
-/// `noclose`:
-///
-/// * `noclose = true`: The process' current stdin, stdout, and stderr file
-/// descriptors will remain identical after daemonizing.
-/// * `noclose = false`: The process' stdin, stdout, and stderr will point to
-/// `/dev/null` after daemonizing.
-#[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
-pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
- let res = unsafe { libc::daemon(nochdir as c_int, noclose as c_int) };
- Errno::result(res).map(drop)
-}
-
-/// Set the system host name (see
-/// [sethostname(2)](http://man7.org/linux/man-pages/man2/gethostname.2.html)).
-///
-/// Given a name, attempt to update the system host name to the given string.
-/// On some systems, the host name is limited to as few as 64 bytes. An error
-/// will be return if the name is not valid or the current process does not have
-/// permissions to update the host name.
-#[cfg(not(target_os = "redox"))]
-pub fn sethostname<S: AsRef<OsStr>>(name: S) -> Result<()> {
- // Handle some differences in type of the len arg across platforms.
- cfg_if! {
- if #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos", ))] {
- type sethostname_len_t = c_int;
- } else {
- type sethostname_len_t = size_t;
- }
- }
- let ptr = name.as_ref().as_bytes().as_ptr() as *const c_char;
- let len = name.as_ref().len() as sethostname_len_t;
-
- let res = unsafe { libc::sethostname(ptr, len) };
- Errno::result(res).map(drop)
-}
-
-/// Get the host name and store it in the provided buffer, returning a pointer
-/// the `CStr` in that buffer on success (see
-/// [gethostname(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html)).
-///
-/// This function call attempts to get the host name for the running system and
-/// store it in a provided buffer. The buffer will be populated with bytes up
-/// to the length of the provided slice including a NUL terminating byte. If
-/// the hostname is longer than the length provided, no error will be provided.
-/// The posix specification does not specify whether implementations will
-/// null-terminate in this case, but the nix implementation will ensure that the
-/// buffer is null terminated in this case.
-///
-/// ```no_run
-/// use nix::unistd;
-///
-/// let mut buf = [0u8; 64];
-/// let hostname_cstr = unistd::gethostname(&mut buf).expect("Failed getting hostname");
-/// let hostname = hostname_cstr.to_str().expect("Hostname wasn't valid UTF-8");
-/// println!("Hostname: {}", hostname);
-/// ```
-pub fn gethostname(buffer: &mut [u8]) -> Result<&CStr> {
- let ptr = buffer.as_mut_ptr() as *mut c_char;
- let len = buffer.len() as size_t;
-
- let res = unsafe { libc::gethostname(ptr, len) };
- Errno::result(res).map(|_| {
- buffer[len - 1] = 0; // ensure always null-terminated
- unsafe { CStr::from_ptr(buffer.as_ptr() as *const c_char) }
- })
-}
-
-/// Close a raw file descriptor
-///
-/// Be aware that many Rust types implicitly close-on-drop, including
-/// `std::fs::File`. Explicitly closing them with this method too can result in
-/// a double-close condition, which can cause confusing `EBADF` errors in
-/// seemingly unrelated code. Caveat programmer. See also
-/// [close(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html).
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::os::unix::io::AsRawFd;
-/// use nix::unistd::close;
-///
-/// fn main() {
-/// let f = tempfile::tempfile().unwrap();
-/// close(f.as_raw_fd()).unwrap(); // Bad! f will also close on drop!
-/// }
-/// ```
-///
-/// ```rust
-/// use std::os::unix::io::IntoRawFd;
-/// use nix::unistd::close;
-///
-/// fn main() {
-/// let f = tempfile::tempfile().unwrap();
-/// close(f.into_raw_fd()).unwrap(); // Good. into_raw_fd consumes f
-/// }
-/// ```
-pub fn close(fd: RawFd) -> Result<()> {
- let res = unsafe { libc::close(fd) };
- Errno::result(res).map(drop)
-}
-
-/// Read from a raw file descriptor.
-///
-/// See also [read(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html)
-pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
- let res = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) };
-
- Errno::result(res).map(|r| r as usize)
-}
-
-/// Write to a raw file descriptor.
-///
-/// See also [write(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html)
-pub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> {
- let res = unsafe { libc::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) };
-
- Errno::result(res).map(|r| r as usize)
-}
-
-/// Directive that tells [`lseek`] and [`lseek64`] what the offset is relative to.
-///
-/// [`lseek`]: ./fn.lseek.html
-/// [`lseek64`]: ./fn.lseek64.html
-#[repr(i32)]
-#[derive(Clone, Copy, Debug)]
-pub enum Whence {
- /// Specify an offset relative to the start of the file.
- SeekSet = libc::SEEK_SET,
- /// Specify an offset relative to the current file location.
- SeekCur = libc::SEEK_CUR,
- /// Specify an offset relative to the end of the file.
- SeekEnd = libc::SEEK_END,
- /// Specify an offset relative to the next location in the file greater than or
- /// equal to offset that contains some data. If offset points to
- /// some data, then the file offset is set to offset.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
- SeekData = libc::SEEK_DATA,
- /// Specify an offset relative to the next hole in the file greater than
- /// or equal to offset. If offset points into the middle of a hole, then
- /// the file offset should be set to offset. If there is no hole past offset,
- /// then the file offset should be adjusted to the end of the file (i.e., there
- /// is an implicit hole at the end of any file).
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
- SeekHole = libc::SEEK_HOLE
-}
-
-/// Move the read/write file offset.
-///
-/// See also [lseek(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html)
-pub fn lseek(fd: RawFd, offset: off_t, whence: Whence) -> Result<off_t> {
- let res = unsafe { libc::lseek(fd, offset, whence as i32) };
-
- Errno::result(res).map(|r| r as off_t)
-}
-
-#[cfg(any(target_os = "linux", target_os = "android"))]
-pub fn lseek64(fd: RawFd, offset: libc::off64_t, whence: Whence) -> Result<libc::off64_t> {
- let res = unsafe { libc::lseek64(fd, offset, whence as i32) };
-
- Errno::result(res).map(|r| r as libc::off64_t)
-}
-
-/// Create an interprocess channel.
-///
-/// See also [pipe(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html)
-pub fn pipe() -> Result<(RawFd, RawFd)> {
- unsafe {
- let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit();
-
- let res = libc::pipe(fds.as_mut_ptr() as *mut c_int);
-
- Errno::result(res)?;
-
- Ok((fds.assume_init()[0], fds.assume_init()[1]))
- }
-}
-
-/// Like `pipe`, but allows setting certain file descriptor flags.
-///
-/// The following flags are supported, and will be set atomically as the pipe is
-/// created:
-///
-/// `O_CLOEXEC`: Set the close-on-exec flag for the new file descriptors.
-#[cfg_attr(target_os = "linux", doc = "`O_DIRECT`: Create a pipe that performs I/O in \"packet\" mode. ")]
-#[cfg_attr(target_os = "netbsd", doc = "`O_NOSIGPIPE`: Return `EPIPE` instead of raising `SIGPIPE`. ")]
-/// `O_NONBLOCK`: Set the non-blocking flag for the ends of the pipe.
-///
-/// See also [pipe(2)](http://man7.org/linux/man-pages/man2/pipe.2.html)
-#[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "emscripten",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "redox",
- target_os = "netbsd",
- target_os = "openbsd"))]
-pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
- let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit();
-
- let res = unsafe {
- libc::pipe2(fds.as_mut_ptr() as *mut c_int, flags.bits())
- };
-
- Errno::result(res)?;
-
- unsafe { Ok((fds.assume_init()[0], fds.assume_init()[1])) }
-}
-
-/// Truncate a file to a specified length
-///
-/// See also
-/// [truncate(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html)
-#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-pub fn truncate<P: ?Sized + NixPath>(path: &P, len: off_t) -> Result<()> {
- let res = path.with_nix_path(|cstr| {
- unsafe {
- libc::truncate(cstr.as_ptr(), len)
- }
- })?;
-
- Errno::result(res).map(drop)
-}
-
-/// Truncate a file to a specified length
-///
-/// See also
-/// [ftruncate(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html)
-pub fn ftruncate(fd: RawFd, len: off_t) -> Result<()> {
- Errno::result(unsafe { libc::ftruncate(fd, len) }).map(drop)
-}
-
-pub fn isatty(fd: RawFd) -> Result<bool> {
- unsafe {
- // ENOTTY means `fd` is a valid file descriptor, but not a TTY, so
- // we return `Ok(false)`
- if libc::isatty(fd) == 1 {
- Ok(true)
- } else {
- match Errno::last() {
- Errno::ENOTTY => Ok(false),
- err => Err(Error::Sys(err)),
- }
- }
- }
-}
-
-/// Flags for `linkat` function.
-#[derive(Clone, Copy, Debug)]
-pub enum LinkatFlags {
- SymlinkFollow,
- NoSymlinkFollow,
-}
-
-/// Link one file to another file
-///
-/// Creates a new link (directory entry) at `newpath` for the existing file at `oldpath`. In the
-/// case of a relative `oldpath`, the path is interpreted relative to the directory associated
-/// with file descriptor `olddirfd` instead of the current working directory and similiarly for
-/// `newpath` and file descriptor `newdirfd`. In case `flag` is LinkatFlags::SymlinkFollow and
-/// `oldpath` names a symoblic link, a new link for the target of the symbolic link is created.
-/// If either `olddirfd` or `newdirfd` is `None`, `AT_FDCWD` is used respectively where `oldpath`
-/// and/or `newpath` is then interpreted relative to the current working directory of the calling
-/// process. If either `oldpath` or `newpath` is absolute, then `dirfd` is ignored.
-///
-/// # References
-/// See also [linkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html)
-#[cfg(not(target_os = "redox"))] // RedoxFS does not support symlinks yet
-pub fn linkat<P: ?Sized + NixPath>(
- olddirfd: Option<RawFd>,
- oldpath: &P,
- newdirfd: Option<RawFd>,
- newpath: &P,
- flag: LinkatFlags,
-) -> Result<()> {
-
- let atflag =
- match flag {
- LinkatFlags::SymlinkFollow => AtFlags::AT_SYMLINK_FOLLOW,
- LinkatFlags::NoSymlinkFollow => AtFlags::empty(),
- };
-
- let res =
- oldpath.with_nix_path(|oldcstr| {
- newpath.with_nix_path(|newcstr| {
- unsafe {
- libc::linkat(
- at_rawfd(olddirfd),
- oldcstr.as_ptr(),
- at_rawfd(newdirfd),
- newcstr.as_ptr(),
- atflag.bits() as libc::c_int
- )
- }
- })
- })??;
- Errno::result(res).map(drop)
-}
-
-
-/// Remove a directory entry
-///
-/// See also [unlink(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html)
-pub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> {
- let res = path.with_nix_path(|cstr| {
- unsafe {
- libc::unlink(cstr.as_ptr())
- }
- })?;
- Errno::result(res).map(drop)
-}
-
-/// Flags for `unlinkat` function.
-#[derive(Clone, Copy, Debug)]
-pub enum UnlinkatFlags {
- RemoveDir,
- NoRemoveDir,
-}
-
-/// Remove a directory entry
-///
-/// In the case of a relative path, the directory entry to be removed is determined relative to
-/// the directory associated with the file descriptor `dirfd` or the current working directory
-/// if `dirfd` is `None`. In the case of an absolute `path` `dirfd` is ignored. If `flag` is
-/// `UnlinkatFlags::RemoveDir` then removal of the directory entry specified by `dirfd` and `path`
-/// is performed.
-///
-/// # References
-/// See also [unlinkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html)
-#[cfg(not(target_os = "redox"))]
-pub fn unlinkat<P: ?Sized + NixPath>(
- dirfd: Option<RawFd>,
- path: &P,
- flag: UnlinkatFlags,
-) -> Result<()> {
- let atflag =
- match flag {
- UnlinkatFlags::RemoveDir => AtFlags::AT_REMOVEDIR,
- UnlinkatFlags::NoRemoveDir => AtFlags::empty(),
- };
- let res = path.with_nix_path(|cstr| {
- unsafe {
- libc::unlinkat(at_rawfd(dirfd), cstr.as_ptr(), atflag.bits() as libc::c_int)
- }
- })?;
- Errno::result(res).map(drop)
-}
-
-
-#[inline]
-#[cfg(not(target_os = "fuchsia"))]
-pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
- let res = path.with_nix_path(|cstr| {
- unsafe { libc::chroot(cstr.as_ptr()) }
- })?;
-
- Errno::result(res).map(drop)
-}
-
-/// Commit filesystem caches to disk
-///
-/// See also [sync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sync.html)
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
-pub fn sync() {
- unsafe { libc::sync() };
-}
-
-/// Synchronize changes to a file
-///
-/// See also [fsync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html)
-#[inline]
-pub fn fsync(fd: RawFd) -> Result<()> {
- let res = unsafe { libc::fsync(fd) };
-
- Errno::result(res).map(drop)
-}
-
-/// Synchronize the data of a file
-///
-/// See also
-/// [fdatasync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html)
-// `fdatasync(2) is in POSIX, but in libc it is only defined in `libc::notbsd`.
-// TODO: exclude only Apple systems after https://github.com/rust-lang/libc/pull/211
-#[cfg(any(target_os = "linux",
- target_os = "android",
- target_os = "emscripten"))]
-#[inline]
-pub fn fdatasync(fd: RawFd) -> Result<()> {
- let res = unsafe { libc::fdatasync(fd) };
-
- Errno::result(res).map(drop)
-}
-
-/// Get a real user ID
-///
-/// See also [getuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getuid.html)
-// POSIX requires that getuid is always successful, so no need to check return
-// value or errno.
-#[inline]
-pub fn getuid() -> Uid {
- Uid(unsafe { libc::getuid() })
-}
-
-/// Get the effective user ID
-///
-/// See also [geteuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html)
-// POSIX requires that geteuid is always successful, so no need to check return
-// value or errno.
-#[inline]
-pub fn geteuid() -> Uid {
- Uid(unsafe { libc::geteuid() })
-}
-
-/// Get the real group ID
-///
-/// See also [getgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getgid.html)
-// POSIX requires that getgid is always successful, so no need to check return
-// value or errno.
-#[inline]
-pub fn getgid() -> Gid {
- Gid(unsafe { libc::getgid() })
-}
-
-/// Get the effective group ID
-///
-/// See also [getegid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getegid.html)
-// POSIX requires that getegid is always successful, so no need to check return
-// value or errno.
-#[inline]
-pub fn getegid() -> Gid {
- Gid(unsafe { libc::getegid() })
-}
-
-/// Set the effective user ID
-///
-/// See also [seteuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/seteuid.html)
-#[inline]
-pub fn seteuid(euid: Uid) -> Result<()> {
- let res = unsafe { libc::seteuid(euid.into()) };
-
- Errno::result(res).map(drop)
-}
-
-/// Set the effective group ID
-///
-/// See also [setegid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setegid.html)
-#[inline]
-pub fn setegid(egid: Gid) -> Result<()> {
- let res = unsafe { libc::setegid(egid.into()) };
-
- Errno::result(res).map(drop)
-}
-
-/// Set the user ID
-///
-/// See also [setuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setuid.html)
-#[inline]
-pub fn setuid(uid: Uid) -> Result<()> {
- let res = unsafe { libc::setuid(uid.into()) };
-
- Errno::result(res).map(drop)
-}
-
-/// Set the group ID
-///
-/// See also [setgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setgid.html)
-#[inline]
-pub fn setgid(gid: Gid) -> Result<()> {
- let res = unsafe { libc::setgid(gid.into()) };
-
- Errno::result(res).map(drop)
-}
-
-/// Set the user identity used for filesystem checks per-thread.
-/// On both success and failure, this call returns the previous filesystem user
-/// ID of the caller.
-///
-/// See also [setfsuid(2)](http://man7.org/linux/man-pages/man2/setfsuid.2.html)
-#[cfg(any(target_os = "linux", target_os = "android"))]
-pub fn setfsuid(uid: Uid) -> Uid {
- let prev_fsuid = unsafe { libc::setfsuid(uid.into()) };
- Uid::from_raw(prev_fsuid as uid_t)
-}
-
-/// Set the group identity used for filesystem checks per-thread.
-/// On both success and failure, this call returns the previous filesystem group
-/// ID of the caller.
-///
-/// See also [setfsgid(2)](http://man7.org/linux/man-pages/man2/setfsgid.2.html)
-#[cfg(any(target_os = "linux", target_os = "android"))]
-pub fn setfsgid(gid: Gid) -> Gid {
- let prev_fsgid = unsafe { libc::setfsgid(gid.into()) };
- Gid::from_raw(prev_fsgid as gid_t)
-}
-
-/// Get the list of supplementary group IDs of the calling process.
-///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html)
-///
-/// **Note:** This function is not available for Apple platforms. On those
-/// platforms, checking group membership should be achieved via communication
-/// with the `opendirectoryd` service.
-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-pub fn getgroups() -> Result<Vec<Gid>> {
- // First get the maximum number of groups. The value returned
- // shall always be greater than or equal to one and less than or
- // equal to the value of {NGROUPS_MAX} + 1.
- let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) {
- Ok(Some(n)) => (n + 1) as usize,
- Ok(None) | Err(_) => <usize>::max_value(),
- };
-
- // Next, get the number of groups so we can size our Vec
- let ngroups = unsafe { libc::getgroups(0, ptr::null_mut()) };
-
- // Now actually get the groups. We try multiple times in case the number of
- // groups has changed since the first call to getgroups() and the buffer is
- // now too small.
- let mut groups = Vec::<Gid>::with_capacity(Errno::result(ngroups)? as usize);
- loop {
- // FIXME: On the platforms we currently support, the `Gid` struct has
- // the same representation in memory as a bare `gid_t`. This is not
- // necessarily the case on all Rust platforms, though. See RFC 1785.
- let ngroups = unsafe {
- libc::getgroups(groups.capacity() as c_int, groups.as_mut_ptr() as *mut gid_t)
- };
-
- match Errno::result(ngroups) {
- Ok(s) => {
- unsafe { groups.set_len(s as usize) };
- return Ok(groups);
- },
- Err(Error::Sys(Errno::EINVAL)) => {
- // EINVAL indicates that the buffer size was too
- // small, resize it up to ngroups_max as limit.
- reserve_double_buffer_size(&mut groups, ngroups_max)
- .or(Err(Error::Sys(Errno::EINVAL)))?;
- },
- Err(e) => return Err(e)
- }
- }
-}
-
-/// Set the list of supplementary group IDs for the calling process.
-///
-/// [Further reading](http://man7.org/linux/man-pages/man2/getgroups.2.html)
-///
-/// **Note:** This function is not available for Apple platforms. On those
-/// platforms, group membership management should be achieved via communication
-/// with the `opendirectoryd` service.
-///
-/// # Examples
-///
-/// `setgroups` can be used when dropping privileges from the root user to a
-/// specific user and group. For example, given the user `www-data` with UID
-/// `33` and the group `backup` with the GID `34`, one could switch the user as
-/// follows:
-///
-/// ```rust,no_run
-/// # use std::error::Error;
-/// # use nix::unistd::*;
-/// #
-/// # fn try_main() -> Result<(), Box<Error>> {
-/// let uid = Uid::from_raw(33);
-/// let gid = Gid::from_raw(34);
-/// setgroups(&[gid])?;
-/// setgid(gid)?;
-/// setuid(uid)?;
-/// #
-/// # Ok(())
-/// # }
-/// #
-/// # try_main().unwrap();
-/// ```
-#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
-pub fn setgroups(groups: &[Gid]) -> Result<()> {
- cfg_if! {
- if #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))] {
- type setgroups_ngroups_t = c_int;
- } else {
- type setgroups_ngroups_t = size_t;
- }
- }
- // FIXME: On the platforms we currently support, the `Gid` struct has the
- // same representation in memory as a bare `gid_t`. This is not necessarily
- // the case on all Rust platforms, though. See RFC 1785.
- let res = unsafe {
- libc::setgroups(groups.len() as setgroups_ngroups_t, groups.as_ptr() as *const gid_t)
- };
-
- Errno::result(res).map(drop)
-}
-
-/// Calculate the supplementary group access list.
-///
-/// Gets the group IDs of all groups that `user` is a member of. The additional
-/// group `group` is also added to the list.
-///
-/// [Further reading](http://man7.org/linux/man-pages/man3/getgrouplist.3.html)
-///
-/// **Note:** This function is not available for Apple platforms. On those
-/// platforms, checking group membership should be achieved via communication
-/// with the `opendirectoryd` service.
-///
-/// # Errors
-///
-/// Although the `getgrouplist()` call does not return any specific
-/// errors on any known platforms, this implementation will return a system
-/// error of `EINVAL` if the number of groups to be fetched exceeds the
-/// `NGROUPS_MAX` sysconf value. This mimics the behaviour of `getgroups()`
-/// and `setgroups()`. Additionally, while some implementations will return a
-/// partial list of groups when `NGROUPS_MAX` is exceeded, this implementation
-/// will only ever return the complete list or else an error.
-#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
-pub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> {
- let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) {
- Ok(Some(n)) => n as c_int,
- Ok(None) | Err(_) => <c_int>::max_value(),
- };
- use std::cmp::min;
- let mut ngroups = min(ngroups_max, 8);
- let mut groups = Vec::<Gid>::with_capacity(ngroups as usize);
- cfg_if! {
- if #[cfg(any(target_os = "ios", target_os = "macos"))] {
- type getgrouplist_group_t = c_int;
- } else {
- type getgrouplist_group_t = gid_t;
- }
- }
- let gid: gid_t = group.into();
- loop {
- let ret = unsafe {
- libc::getgrouplist(user.as_ptr(),
- gid as getgrouplist_group_t,
- groups.as_mut_ptr() as *mut getgrouplist_group_t,
- &mut ngroups)
- };
-
- // BSD systems only return 0 or -1, Linux returns ngroups on success.
- if ret >= 0 {
- unsafe { groups.set_len(ngroups as usize) };
- return Ok(groups);
- } else if ret == -1 {
- // Returns -1 if ngroups is too small, but does not set errno.
- // BSD systems will still fill the groups buffer with as many
- // groups as possible, but Linux manpages do not mention this
- // behavior.
- reserve_double_buffer_size(&mut groups, ngroups_max as usize)
- .or_else(|_| Err(Error::invalid_argument()))?;
- }
- }
-}
-
-/// Initialize the supplementary group access list.
-///
-/// Sets the supplementary group IDs for the calling process using all groups
-/// that `user` is a member of. The additional group `group` is also added to
-/// the list.
-///
-/// [Further reading](http://man7.org/linux/man-pages/man3/initgroups.3.html)
-///
-/// **Note:** This function is not available for Apple platforms. On those
-/// platforms, group membership management should be achieved via communication
-/// with the `opendirectoryd` service.
-///
-/// # Examples
-///
-/// `initgroups` can be used when dropping privileges from the root user to
-/// another user. For example, given the user `www-data`, we could look up the
-/// UID and GID for the user in the system's password database (usually found
-/// in `/etc/passwd`). If the `www-data` user's UID and GID were `33` and `33`,
-/// respectively, one could switch the user as follows:
-///
-/// ```rust,no_run
-/// # use std::error::Error;
-/// # use std::ffi::CString;
-/// # use nix::unistd::*;
-/// #
-/// # fn try_main() -> Result<(), Box<Error>> {
-/// let user = CString::new("www-data").unwrap();
-/// let uid = Uid::from_raw(33);
-/// let gid = Gid::from_raw(33);
-/// initgroups(&user, gid)?;
-/// setgid(gid)?;
-/// setuid(uid)?;
-/// #
-/// # Ok(())
-/// # }
-/// #
-/// # try_main().unwrap();
-/// ```
-#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
-pub fn initgroups(user: &CStr, group: Gid) -> Result<()> {
- cfg_if! {
- if #[cfg(any(target_os = "ios", target_os = "macos"))] {
- type initgroups_group_t = c_int;
- } else {
- type initgroups_group_t = gid_t;
- }
- }
- let gid: gid_t = group.into();
- let res = unsafe { libc::initgroups(user.as_ptr(), gid as initgroups_group_t) };
-
- Errno::result(res).map(drop)
-}
-
-/// Suspend the thread until a signal is received.
-///
-/// See also [pause(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pause.html).
-#[inline]
-#[cfg(not(target_os = "redox"))]
-pub fn pause() {
- unsafe { libc::pause() };
-}
-
-pub mod alarm {
- //! Alarm signal scheduling.
- //!
- //! Scheduling an alarm will trigger a `SIGALRM` signal when the time has
- //! elapsed, which has to be caught, because the default action for the
- //! signal is to terminate the program. This signal also can't be ignored
- //! because the system calls like `pause` will not be interrupted, see the
- //! second example below.
- //!
- //! # Examples
- //!
- //! Canceling an alarm:
- //!
- //! ```
- //! use nix::unistd::alarm;
- //!
- //! // Set an alarm for 60 seconds from now.
- //! alarm::set(60);
- //!
- //! // Cancel the above set alarm, which returns the number of seconds left
- //! // of the previously set alarm.
- //! assert_eq!(alarm::cancel(), Some(60));
- //! ```
- //!
- //! Scheduling an alarm and waiting for the signal:
- //!
-#![cfg_attr(target_os = "redox", doc = " ```rust,ignore")]
-#![cfg_attr(not(target_os = "redox"), doc = " ```rust")]
- //! use std::time::{Duration, Instant};
- //!
- //! use nix::unistd::{alarm, pause};
- //! use nix::sys::signal::*;
- //!
- //! // We need to setup an empty signal handler to catch the alarm signal,
- //! // otherwise the program will be terminated once the signal is delivered.
- //! extern fn signal_handler(_: nix::libc::c_int) { }
- //! let sa = SigAction::new(
- //! SigHandler::Handler(signal_handler),
- //! SaFlags::empty(),
- //! SigSet::empty()
- //! );
- //! unsafe {
- //! sigaction(Signal::SIGALRM, &sa);
- //! }
- //!
- //! // Set an alarm for 1 second from now.
- //! alarm::set(1);
- //!
- //! let start = Instant::now();
- //! // Pause the process until the alarm signal is received.
- //! let mut sigset = SigSet::empty();
- //! sigset.add(Signal::SIGALRM);
- //! sigset.wait();
- //!
- //! assert!(start.elapsed() >= Duration::from_secs(1));
- //! ```
- //!
- //! # References
- //!
- //! See also [alarm(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/alarm.html).
-
- /// Schedule an alarm signal.
- ///
- /// This will cause the system to generate a `SIGALRM` signal for the
- /// process after the specified number of seconds have elapsed.
- ///
- /// Returns the leftover time of a previously set alarm if there was one.
- pub fn set(secs: libc::c_uint) -> Option<libc::c_uint> {
- assert!(secs != 0, "passing 0 to `alarm::set` is not allowed, to cancel an alarm use `alarm::cancel`");
- alarm(secs)
- }
-
- /// Cancel an previously set alarm signal.
- ///
- /// Returns the leftover time of a previously set alarm if there was one.
- pub fn cancel() -> Option<libc::c_uint> {
- alarm(0)
- }
-
- fn alarm(secs: libc::c_uint) -> Option<libc::c_uint> {
- match unsafe { libc::alarm(secs) } {
- 0 => None,
- secs => Some(secs),
- }
- }
-}
-
-/// Suspend execution for an interval of time
-///
-/// See also [sleep(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/sleep.html#tag_03_705_05)
-// Per POSIX, does not fail
-#[inline]
-pub fn sleep(seconds: c_uint) -> c_uint {
- unsafe { libc::sleep(seconds) }
-}
-
-#[cfg(not(target_os = "redox"))]
-pub mod acct {
- use crate::{Result, NixPath};
- use crate::errno::Errno;
- use std::ptr;
-
- /// Enable process accounting
- ///
- /// See also [acct(2)](https://linux.die.net/man/2/acct)
- pub fn enable<P: ?Sized + NixPath>(filename: &P) -> Result<()> {
- let res = filename.with_nix_path(|cstr| {
- unsafe { libc::acct(cstr.as_ptr()) }
- })?;
-
- Errno::result(res).map(drop)
- }
-
- /// Disable process accounting
- pub fn disable() -> Result<()> {
- let res = unsafe { libc::acct(ptr::null()) };
-
- Errno::result(res).map(drop)
- }
-}
-
-/// Creates a regular file which persists even after process termination
-///
-/// * `template`: a path whose 6 rightmost characters must be X, e.g. `/tmp/tmpfile_XXXXXX`
-/// * returns: tuple of file descriptor and filename
-///
-/// Err is returned either if no temporary filename could be created or the template doesn't
-/// end with XXXXXX
-///
-/// See also [mkstemp(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkstemp.html)
-///
-/// # Example
-///
-/// ```rust
-/// use nix::unistd;
-///
-/// let _ = match unistd::mkstemp("/tmp/tempfile_XXXXXX") {
-/// Ok((fd, path)) => {
-/// unistd::unlink(path.as_path()).unwrap(); // flag file to be deleted at app termination
-/// fd
-/// }
-/// Err(e) => panic!("mkstemp failed: {}", e)
-/// };
-/// // do something with fd
-/// ```
-#[inline]
-pub fn mkstemp<P: ?Sized + NixPath>(template: &P) -> Result<(RawFd, PathBuf)> {
- let mut path = template.with_nix_path(|path| {path.to_bytes_with_nul().to_owned()})?;
- let p = path.as_mut_ptr() as *mut _;
- let fd = unsafe { libc::mkstemp(p) };
- let last = path.pop(); // drop the trailing nul
- debug_assert!(last == Some(b'\0'));
- let pathname = OsString::from_vec(path);
- Errno::result(fd)?;
- Ok((fd, PathBuf::from(pathname)))
-}
-
-/// Variable names for `pathconf`
-///
-/// Nix uses the same naming convention for these variables as the
-/// [getconf(1)](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html) utility.
-/// That is, `PathconfVar` variables have the same name as the abstract
-/// variables shown in the `pathconf(2)` man page. Usually, it's the same as
-/// the C variable name without the leading `_PC_`.
-///
-/// POSIX 1003.1-2008 standardizes all of these variables, but some OSes choose
-/// not to implement variables that cannot change at runtime.
-///
-/// # References
-///
-/// - [pathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html)
-/// - [limits.h](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html)
-/// - [unistd.h](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html)
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-#[repr(i32)]
-pub enum PathconfVar {
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux",
- target_os = "netbsd", target_os = "openbsd", target_os = "redox"))]
- /// Minimum number of bits needed to represent, as a signed integer value,
- /// the maximum size of a regular file allowed in the specified directory.
- FILESIZEBITS = libc::_PC_FILESIZEBITS,
- /// Maximum number of links to a single file.
- LINK_MAX = libc::_PC_LINK_MAX,
- /// Maximum number of bytes in a terminal canonical input line.
- MAX_CANON = libc::_PC_MAX_CANON,
- /// Minimum number of bytes for which space is available in a terminal input
- /// queue; therefore, the maximum number of bytes a conforming application
- /// may require to be typed as input before reading them.
- MAX_INPUT = libc::_PC_MAX_INPUT,
- /// Maximum number of bytes in a filename (not including the terminating
- /// null of a filename string).
- NAME_MAX = libc::_PC_NAME_MAX,
- /// Maximum number of bytes the implementation will store as a pathname in a
- /// user-supplied buffer of unspecified size, including the terminating null
- /// character. Minimum number the implementation will accept as the maximum
- /// number of bytes in a pathname.
- PATH_MAX = libc::_PC_PATH_MAX,
- /// Maximum number of bytes that is guaranteed to be atomic when writing to
- /// a pipe.
- PIPE_BUF = libc::_PC_PIPE_BUF,
- #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "linux",
- target_os = "netbsd", target_os = "openbsd", target_os = "redox"))]
- /// Symbolic links can be created.
- POSIX2_SYMLINKS = libc::_PC_2_SYMLINKS,
- #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
- target_os = "linux", target_os = "openbsd", target_os = "redox"))]
- /// Minimum number of bytes of storage actually allocated for any portion of
- /// a file.
- POSIX_ALLOC_SIZE_MIN = libc::_PC_ALLOC_SIZE_MIN,
- #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
- target_os = "linux", target_os = "openbsd"))]
- /// Recommended increment for file transfer sizes between the
- /// `POSIX_REC_MIN_XFER_SIZE` and `POSIX_REC_MAX_XFER_SIZE` values.
- POSIX_REC_INCR_XFER_SIZE = libc::_PC_REC_INCR_XFER_SIZE,
- #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
- target_os = "linux", target_os = "openbsd", target_os = "redox"))]
- /// Maximum recommended file transfer size.
- POSIX_REC_MAX_XFER_SIZE = libc::_PC_REC_MAX_XFER_SIZE,
- #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
- target_os = "linux", target_os = "openbsd", target_os = "redox"))]
- /// Minimum recommended file transfer size.
- POSIX_REC_MIN_XFER_SIZE = libc::_PC_REC_MIN_XFER_SIZE,
- #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
- target_os = "linux", target_os = "openbsd", target_os = "redox"))]
- /// Recommended file transfer buffer alignment.
- POSIX_REC_XFER_ALIGN = libc::_PC_REC_XFER_ALIGN,
- #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
- target_os = "linux", target_os = "netbsd", target_os = "openbsd",
- target_os = "redox"))]
- /// Maximum number of bytes in a symbolic link.
- SYMLINK_MAX = libc::_PC_SYMLINK_MAX,
- /// The use of `chown` and `fchown` is restricted to a process with
- /// appropriate privileges, and to changing the group ID of a file only to
- /// the effective group ID of the process or to one of its supplementary
- /// group IDs.
- _POSIX_CHOWN_RESTRICTED = libc::_PC_CHOWN_RESTRICTED,
- /// Pathname components longer than {NAME_MAX} generate an error.
- _POSIX_NO_TRUNC = libc::_PC_NO_TRUNC,
- /// This symbol shall be defined to be the value of a character that shall
- /// disable terminal special character handling.
- _POSIX_VDISABLE = libc::_PC_VDISABLE,
- #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
- target_os = "linux", target_os = "openbsd", target_os = "redox"))]
- /// Asynchronous input or output operations may be performed for the
- /// associated file.
- _POSIX_ASYNC_IO = libc::_PC_ASYNC_IO,
- #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
- target_os = "linux", target_os = "openbsd", target_os = "redox"))]
- /// Prioritized input or output operations may be performed for the
- /// associated file.
- _POSIX_PRIO_IO = libc::_PC_PRIO_IO,
- #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
- target_os = "linux", target_os = "netbsd", target_os = "openbsd",
- target_os = "redox"))]
- /// Synchronized input or output operations may be performed for the
- /// associated file.
- _POSIX_SYNC_IO = libc::_PC_SYNC_IO,
- #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))]
- /// The resolution in nanoseconds for all file timestamps.
- _POSIX_TIMESTAMP_RESOLUTION = libc::_PC_TIMESTAMP_RESOLUTION
-}
-
-/// Like `pathconf`, but works with file descriptors instead of paths (see
-/// [fpathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html))
-///
-/// # Parameters
-///
-/// - `fd`: The file descriptor whose variable should be interrogated
-/// - `var`: The pathconf variable to lookup
-///
-/// # Returns
-///
-/// - `Ok(Some(x))`: the variable's limit (for limit variables) or its
-/// implementation level (for option variables). Implementation levels are
-/// usually a decimal-coded date, such as 200112 for POSIX 2001.12
-/// - `Ok(None)`: the variable has no limit (for limit variables) or is
-/// unsupported (for option variables)
-/// - `Err(x)`: an error occurred
-pub fn fpathconf(fd: RawFd, var: PathconfVar) -> Result<Option<c_long>> {
- let raw = unsafe {
- Errno::clear();
- libc::fpathconf(fd, var as c_int)
- };
- if raw == -1 {
- if errno::errno() == 0 {
- Ok(None)
- } else {
- Err(Error::Sys(Errno::last()))
- }
- } else {
- Ok(Some(raw))
- }
-}
-
-/// Get path-dependent configurable system variables (see
-/// [pathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html))
-///
-/// Returns the value of a path-dependent configurable system variable. Most
-/// supported variables also have associated compile-time constants, but POSIX
-/// allows their values to change at runtime. There are generally two types of
-/// `pathconf` variables: options and limits. See [pathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html) for more details.
-///
-/// # Parameters
-///
-/// - `path`: Lookup the value of `var` for this file or directory
-/// - `var`: The `pathconf` variable to lookup
-///
-/// # Returns
-///
-/// - `Ok(Some(x))`: the variable's limit (for limit variables) or its
-/// implementation level (for option variables). Implementation levels are
-/// usually a decimal-coded date, such as 200112 for POSIX 2001.12
-/// - `Ok(None)`: the variable has no limit (for limit variables) or is
-/// unsupported (for option variables)
-/// - `Err(x)`: an error occurred
-pub fn pathconf<P: ?Sized + NixPath>(path: &P, var: PathconfVar) -> Result<Option<c_long>> {
- let raw = path.with_nix_path(|cstr| {
- unsafe {
- Errno::clear();
- libc::pathconf(cstr.as_ptr(), var as c_int)
- }
- })?;
- if raw == -1 {
- if errno::errno() == 0 {
- Ok(None)
- } else {
- Err(Error::Sys(Errno::last()))
- }
- } else {
- Ok(Some(raw))
- }
-}
-
-/// Variable names for `sysconf`
-///
-/// Nix uses the same naming convention for these variables as the
-/// [getconf(1)](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html) utility.
-/// That is, `SysconfVar` variables have the same name as the abstract variables
-/// shown in the `sysconf(3)` man page. Usually, it's the same as the C
-/// variable name without the leading `_SC_`.
-///
-/// All of these symbols are standardized by POSIX 1003.1-2008, but haven't been
-/// implemented by all platforms.
-///
-/// # References
-///
-/// - [sysconf(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html)
-/// - [unistd.h](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html)
-/// - [limits.h](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html)
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-#[repr(i32)]
-pub enum SysconfVar {
- /// Maximum number of I/O operations in a single list I/O call supported by
- /// the implementation.
- #[cfg(not(target_os = "redox"))]
- AIO_LISTIO_MAX = libc::_SC_AIO_LISTIO_MAX,
- /// Maximum number of outstanding asynchronous I/O operations supported by
- /// the implementation.
- #[cfg(not(target_os = "redox"))]
- AIO_MAX = libc::_SC_AIO_MAX,
- #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
- target_os = "ios", target_os="linux", target_os = "macos",
- target_os="openbsd"))]
- /// The maximum amount by which a process can decrease its asynchronous I/O
- /// priority level from its own scheduling priority.
- AIO_PRIO_DELTA_MAX = libc::_SC_AIO_PRIO_DELTA_MAX,
- /// Maximum length of argument to the exec functions including environment data.
- ARG_MAX = libc::_SC_ARG_MAX,
- /// Maximum number of functions that may be registered with `atexit`.
- #[cfg(not(target_os = "redox"))]
- ATEXIT_MAX = libc::_SC_ATEXIT_MAX,
- /// Maximum obase values allowed by the bc utility.
- #[cfg(not(target_os = "redox"))]
- BC_BASE_MAX = libc::_SC_BC_BASE_MAX,
- /// Maximum number of elements permitted in an array by the bc utility.
- #[cfg(not(target_os = "redox"))]
- BC_DIM_MAX = libc::_SC_BC_DIM_MAX,
- /// Maximum scale value allowed by the bc utility.
- #[cfg(not(target_os = "redox"))]
- BC_SCALE_MAX = libc::_SC_BC_SCALE_MAX,
- /// Maximum length of a string constant accepted by the bc utility.
- #[cfg(not(target_os = "redox"))]
- BC_STRING_MAX = libc::_SC_BC_STRING_MAX,
- /// Maximum number of simultaneous processes per real user ID.
- CHILD_MAX = libc::_SC_CHILD_MAX,
- // The number of clock ticks per second.
- CLK_TCK = libc::_SC_CLK_TCK,
- /// Maximum number of weights that can be assigned to an entry of the
- /// LC_COLLATE order keyword in the locale definition file
- #[cfg(not(target_os = "redox"))]
- COLL_WEIGHTS_MAX = libc::_SC_COLL_WEIGHTS_MAX,
- /// Maximum number of timer expiration overruns.
- #[cfg(not(target_os = "redox"))]
- DELAYTIMER_MAX = libc::_SC_DELAYTIMER_MAX,
- /// Maximum number of expressions that can be nested within parentheses by
- /// the expr utility.
- #[cfg(not(target_os = "redox"))]
- EXPR_NEST_MAX = libc::_SC_EXPR_NEST_MAX,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// Maximum length of a host name (not including the terminating null) as
- /// returned from the `gethostname` function
- HOST_NAME_MAX = libc::_SC_HOST_NAME_MAX,
- /// Maximum number of iovec structures that one process has available for
- /// use with `readv` or `writev`.
- #[cfg(not(target_os = "redox"))]
- IOV_MAX = libc::_SC_IOV_MAX,
- /// Unless otherwise noted, the maximum length, in bytes, of a utility's
- /// input line (either standard input or another file), when the utility is
- /// described as processing text files. The length includes room for the
- /// trailing <newline>.
- #[cfg(not(target_os = "redox"))]
- LINE_MAX = libc::_SC_LINE_MAX,
- /// Maximum length of a login name.
- LOGIN_NAME_MAX = libc::_SC_LOGIN_NAME_MAX,
- /// Maximum number of simultaneous supplementary group IDs per process.
- NGROUPS_MAX = libc::_SC_NGROUPS_MAX,
- /// Initial size of `getgrgid_r` and `getgrnam_r` data buffers
- #[cfg(not(target_os = "redox"))]
- GETGR_R_SIZE_MAX = libc::_SC_GETGR_R_SIZE_MAX,
- /// Initial size of `getpwuid_r` and `getpwnam_r` data buffers
- #[cfg(not(target_os = "redox"))]
- GETPW_R_SIZE_MAX = libc::_SC_GETPW_R_SIZE_MAX,
- /// The maximum number of open message queue descriptors a process may hold.
- #[cfg(not(target_os = "redox"))]
- MQ_OPEN_MAX = libc::_SC_MQ_OPEN_MAX,
- /// The maximum number of message priorities supported by the implementation.
- #[cfg(not(target_os = "redox"))]
- MQ_PRIO_MAX = libc::_SC_MQ_PRIO_MAX,
- /// A value one greater than the maximum value that the system may assign to
- /// a newly-created file descriptor.
- OPEN_MAX = libc::_SC_OPEN_MAX,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="openbsd"))]
- /// The implementation supports the Advisory Information option.
- _POSIX_ADVISORY_INFO = libc::_SC_ADVISORY_INFO,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation supports barriers.
- _POSIX_BARRIERS = libc::_SC_BARRIERS,
- /// The implementation supports asynchronous input and output.
- #[cfg(not(target_os = "redox"))]
- _POSIX_ASYNCHRONOUS_IO = libc::_SC_ASYNCHRONOUS_IO,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation supports clock selection.
- _POSIX_CLOCK_SELECTION = libc::_SC_CLOCK_SELECTION,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation supports the Process CPU-Time Clocks option.
- _POSIX_CPUTIME = libc::_SC_CPUTIME,
- /// The implementation supports the File Synchronization option.
- #[cfg(not(target_os = "redox"))]
- _POSIX_FSYNC = libc::_SC_FSYNC,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="openbsd"))]
- /// The implementation supports the IPv6 option.
- _POSIX_IPV6 = libc::_SC_IPV6,
- /// The implementation supports job control.
- #[cfg(not(target_os = "redox"))]
- _POSIX_JOB_CONTROL = libc::_SC_JOB_CONTROL,
- /// The implementation supports memory mapped Files.
- #[cfg(not(target_os = "redox"))]
- _POSIX_MAPPED_FILES = libc::_SC_MAPPED_FILES,
- /// The implementation supports the Process Memory Locking option.
- #[cfg(not(target_os = "redox"))]
- _POSIX_MEMLOCK = libc::_SC_MEMLOCK,
- /// The implementation supports the Range Memory Locking option.
- #[cfg(not(target_os = "redox"))]
- _POSIX_MEMLOCK_RANGE = libc::_SC_MEMLOCK_RANGE,
- /// The implementation supports memory protection.
- #[cfg(not(target_os = "redox"))]
- _POSIX_MEMORY_PROTECTION = libc::_SC_MEMORY_PROTECTION,
- /// The implementation supports the Message Passing option.
- #[cfg(not(target_os = "redox"))]
- _POSIX_MESSAGE_PASSING = libc::_SC_MESSAGE_PASSING,
- /// The implementation supports the Monotonic Clock option.
- #[cfg(not(target_os = "redox"))]
- _POSIX_MONOTONIC_CLOCK = libc::_SC_MONOTONIC_CLOCK,
- #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
- target_os = "ios", target_os="linux", target_os = "macos",
- target_os="openbsd"))]
- /// The implementation supports the Prioritized Input and Output option.
- _POSIX_PRIORITIZED_IO = libc::_SC_PRIORITIZED_IO,
- /// The implementation supports the Process Scheduling option.
- #[cfg(not(target_os = "redox"))]
- _POSIX_PRIORITY_SCHEDULING = libc::_SC_PRIORITY_SCHEDULING,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="openbsd"))]
- /// The implementation supports the Raw Sockets option.
- _POSIX_RAW_SOCKETS = libc::_SC_RAW_SOCKETS,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation supports read-write locks.
- _POSIX_READER_WRITER_LOCKS = libc::_SC_READER_WRITER_LOCKS,
- #[cfg(any(target_os = "android", target_os="dragonfly", target_os="freebsd",
- target_os = "ios", target_os="linux", target_os = "macos",
- target_os = "openbsd"))]
- /// The implementation supports realtime signals.
- _POSIX_REALTIME_SIGNALS = libc::_SC_REALTIME_SIGNALS,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation supports the Regular Expression Handling option.
- _POSIX_REGEXP = libc::_SC_REGEXP,
- /// Each process has a saved set-user-ID and a saved set-group-ID.
- #[cfg(not(target_os = "redox"))]
- _POSIX_SAVED_IDS = libc::_SC_SAVED_IDS,
- /// The implementation supports semaphores.
- #[cfg(not(target_os = "redox"))]
- _POSIX_SEMAPHORES = libc::_SC_SEMAPHORES,
- /// The implementation supports the Shared Memory Objects option.
- #[cfg(not(target_os = "redox"))]
- _POSIX_SHARED_MEMORY_OBJECTS = libc::_SC_SHARED_MEMORY_OBJECTS,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation supports the POSIX shell.
- _POSIX_SHELL = libc::_SC_SHELL,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation supports the Spawn option.
- _POSIX_SPAWN = libc::_SC_SPAWN,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation supports spin locks.
- _POSIX_SPIN_LOCKS = libc::_SC_SPIN_LOCKS,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="openbsd"))]
- /// The implementation supports the Process Sporadic Server option.
- _POSIX_SPORADIC_SERVER = libc::_SC_SPORADIC_SERVER,
- #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
- target_os="openbsd"))]
- _POSIX_SS_REPL_MAX = libc::_SC_SS_REPL_MAX,
- /// The implementation supports the Synchronized Input and Output option.
- #[cfg(not(target_os = "redox"))]
- _POSIX_SYNCHRONIZED_IO = libc::_SC_SYNCHRONIZED_IO,
- /// The implementation supports the Thread Stack Address Attribute option.
- #[cfg(not(target_os = "redox"))]
- _POSIX_THREAD_ATTR_STACKADDR = libc::_SC_THREAD_ATTR_STACKADDR,
- /// The implementation supports the Thread Stack Size Attribute option.
- #[cfg(not(target_os = "redox"))]
- _POSIX_THREAD_ATTR_STACKSIZE = libc::_SC_THREAD_ATTR_STACKSIZE,
- #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
- target_os="netbsd", target_os="openbsd"))]
- /// The implementation supports the Thread CPU-Time Clocks option.
- _POSIX_THREAD_CPUTIME = libc::_SC_THREAD_CPUTIME,
- /// The implementation supports the Non-Robust Mutex Priority Inheritance
- /// option.
- #[cfg(not(target_os = "redox"))]
- _POSIX_THREAD_PRIO_INHERIT = libc::_SC_THREAD_PRIO_INHERIT,
- /// The implementation supports the Non-Robust Mutex Priority Protection option.
- #[cfg(not(target_os = "redox"))]
- _POSIX_THREAD_PRIO_PROTECT = libc::_SC_THREAD_PRIO_PROTECT,
- /// The implementation supports the Thread Execution Scheduling option.
- #[cfg(not(target_os = "redox"))]
- _POSIX_THREAD_PRIORITY_SCHEDULING = libc::_SC_THREAD_PRIORITY_SCHEDULING,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation supports the Thread Process-Shared Synchronization
- /// option.
- _POSIX_THREAD_PROCESS_SHARED = libc::_SC_THREAD_PROCESS_SHARED,
- #[cfg(any(target_os="dragonfly", target_os="linux", target_os="openbsd"))]
- /// The implementation supports the Robust Mutex Priority Inheritance option.
- _POSIX_THREAD_ROBUST_PRIO_INHERIT = libc::_SC_THREAD_ROBUST_PRIO_INHERIT,
- #[cfg(any(target_os="dragonfly", target_os="linux", target_os="openbsd"))]
- /// The implementation supports the Robust Mutex Priority Protection option.
- _POSIX_THREAD_ROBUST_PRIO_PROTECT = libc::_SC_THREAD_ROBUST_PRIO_PROTECT,
- /// The implementation supports thread-safe functions.
- #[cfg(not(target_os = "redox"))]
- _POSIX_THREAD_SAFE_FUNCTIONS = libc::_SC_THREAD_SAFE_FUNCTIONS,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="openbsd"))]
- /// The implementation supports the Thread Sporadic Server option.
- _POSIX_THREAD_SPORADIC_SERVER = libc::_SC_THREAD_SPORADIC_SERVER,
- /// The implementation supports threads.
- #[cfg(not(target_os = "redox"))]
- _POSIX_THREADS = libc::_SC_THREADS,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="openbsd"))]
- /// The implementation supports timeouts.
- _POSIX_TIMEOUTS = libc::_SC_TIMEOUTS,
- /// The implementation supports timers.
- #[cfg(not(target_os = "redox"))]
- _POSIX_TIMERS = libc::_SC_TIMERS,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="openbsd"))]
- /// The implementation supports the Trace option.
- _POSIX_TRACE = libc::_SC_TRACE,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="openbsd"))]
- /// The implementation supports the Trace Event Filter option.
- _POSIX_TRACE_EVENT_FILTER = libc::_SC_TRACE_EVENT_FILTER,
- #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
- target_os="openbsd"))]
- _POSIX_TRACE_EVENT_NAME_MAX = libc::_SC_TRACE_EVENT_NAME_MAX,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="openbsd"))]
- /// The implementation supports the Trace Inherit option.
- _POSIX_TRACE_INHERIT = libc::_SC_TRACE_INHERIT,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="openbsd"))]
- /// The implementation supports the Trace Log option.
- _POSIX_TRACE_LOG = libc::_SC_TRACE_LOG,
- #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
- target_os="openbsd"))]
- _POSIX_TRACE_NAME_MAX = libc::_SC_TRACE_NAME_MAX,
- #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
- target_os="openbsd"))]
- _POSIX_TRACE_SYS_MAX = libc::_SC_TRACE_SYS_MAX,
- #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
- target_os="openbsd"))]
- _POSIX_TRACE_USER_EVENT_MAX = libc::_SC_TRACE_USER_EVENT_MAX,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="openbsd"))]
- /// The implementation supports the Typed Memory Objects option.
- _POSIX_TYPED_MEMORY_OBJECTS = libc::_SC_TYPED_MEMORY_OBJECTS,
- /// Integer value indicating version of this standard (C-language binding)
- /// to which the implementation conforms. For implementations conforming to
- /// POSIX.1-2008, the value shall be 200809L.
- _POSIX_VERSION = libc::_SC_VERSION,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation provides a C-language compilation environment with
- /// 32-bit `int`, `long`, `pointer`, and `off_t` types.
- _POSIX_V6_ILP32_OFF32 = libc::_SC_V6_ILP32_OFF32,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation provides a C-language compilation environment with
- /// 32-bit `int`, `long`, and pointer types and an `off_t` type using at
- /// least 64 bits.
- _POSIX_V6_ILP32_OFFBIG = libc::_SC_V6_ILP32_OFFBIG,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation provides a C-language compilation environment with
- /// 32-bit `int` and 64-bit `long`, `pointer`, and `off_t` types.
- _POSIX_V6_LP64_OFF64 = libc::_SC_V6_LP64_OFF64,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation provides a C-language compilation environment with an
- /// `int` type using at least 32 bits and `long`, pointer, and `off_t` types
- /// using at least 64 bits.
- _POSIX_V6_LPBIG_OFFBIG = libc::_SC_V6_LPBIG_OFFBIG,
- /// The implementation supports the C-Language Binding option.
- #[cfg(not(target_os = "redox"))]
- _POSIX2_C_BIND = libc::_SC_2_C_BIND,
- /// The implementation supports the C-Language Development Utilities option.
- #[cfg(not(target_os = "redox"))]
- _POSIX2_C_DEV = libc::_SC_2_C_DEV,
- /// The implementation supports the Terminal Characteristics option.
- #[cfg(not(target_os = "redox"))]
- _POSIX2_CHAR_TERM = libc::_SC_2_CHAR_TERM,
- /// The implementation supports the FORTRAN Development Utilities option.
- #[cfg(not(target_os = "redox"))]
- _POSIX2_FORT_DEV = libc::_SC_2_FORT_DEV,
- /// The implementation supports the FORTRAN Runtime Utilities option.
- #[cfg(not(target_os = "redox"))]
- _POSIX2_FORT_RUN = libc::_SC_2_FORT_RUN,
- /// The implementation supports the creation of locales by the localedef
- /// utility.
- #[cfg(not(target_os = "redox"))]
- _POSIX2_LOCALEDEF = libc::_SC_2_LOCALEDEF,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation supports the Batch Environment Services and Utilities
- /// option.
- _POSIX2_PBS = libc::_SC_2_PBS,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation supports the Batch Accounting option.
- _POSIX2_PBS_ACCOUNTING = libc::_SC_2_PBS_ACCOUNTING,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation supports the Batch Checkpoint/Restart option.
- _POSIX2_PBS_CHECKPOINT = libc::_SC_2_PBS_CHECKPOINT,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation supports the Locate Batch Job Request option.
- _POSIX2_PBS_LOCATE = libc::_SC_2_PBS_LOCATE,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation supports the Batch Job Message Request option.
- _POSIX2_PBS_MESSAGE = libc::_SC_2_PBS_MESSAGE,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- /// The implementation supports the Track Batch Job Request option.
- _POSIX2_PBS_TRACK = libc::_SC_2_PBS_TRACK,
- /// The implementation supports the Software Development Utilities option.
- #[cfg(not(target_os = "redox"))]
- _POSIX2_SW_DEV = libc::_SC_2_SW_DEV,
- /// The implementation supports the User Portability Utilities option.
- #[cfg(not(target_os = "redox"))]
- _POSIX2_UPE = libc::_SC_2_UPE,
- /// Integer value indicating version of the Shell and Utilities volume of
- /// POSIX.1 to which the implementation conforms.
- #[cfg(not(target_os = "redox"))]
- _POSIX2_VERSION = libc::_SC_2_VERSION,
- /// The size of a system page in bytes.
- ///
- /// POSIX also defines an alias named `PAGESIZE`, but Rust does not allow two
- /// enum constants to have the same value, so nix omits `PAGESIZE`.
- PAGE_SIZE = libc::_SC_PAGE_SIZE,
- #[cfg(not(target_os = "redox"))]
- PTHREAD_DESTRUCTOR_ITERATIONS = libc::_SC_THREAD_DESTRUCTOR_ITERATIONS,
- #[cfg(not(target_os = "redox"))]
- PTHREAD_KEYS_MAX = libc::_SC_THREAD_KEYS_MAX,
- #[cfg(not(target_os = "redox"))]
- PTHREAD_STACK_MIN = libc::_SC_THREAD_STACK_MIN,
- #[cfg(not(target_os = "redox"))]
- PTHREAD_THREADS_MAX = libc::_SC_THREAD_THREADS_MAX,
- RE_DUP_MAX = libc::_SC_RE_DUP_MAX,
- #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
- target_os = "ios", target_os="linux", target_os = "macos",
- target_os="openbsd"))]
- RTSIG_MAX = libc::_SC_RTSIG_MAX,
- #[cfg(not(target_os = "redox"))]
- SEM_NSEMS_MAX = libc::_SC_SEM_NSEMS_MAX,
- #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
- target_os = "ios", target_os="linux", target_os = "macos",
- target_os="openbsd"))]
- SEM_VALUE_MAX = libc::_SC_SEM_VALUE_MAX,
- #[cfg(any(target_os = "android", target_os="dragonfly", target_os="freebsd",
- target_os = "ios", target_os="linux", target_os = "macos",
- target_os = "openbsd"))]
- SIGQUEUE_MAX = libc::_SC_SIGQUEUE_MAX,
- STREAM_MAX = libc::_SC_STREAM_MAX,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="netbsd",
- target_os="openbsd"))]
- SYMLOOP_MAX = libc::_SC_SYMLOOP_MAX,
- #[cfg(not(target_os = "redox"))]
- TIMER_MAX = libc::_SC_TIMER_MAX,
- TTY_NAME_MAX = libc::_SC_TTY_NAME_MAX,
- TZNAME_MAX = libc::_SC_TZNAME_MAX,
- #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
- target_os = "ios", target_os="linux", target_os = "macos",
- target_os="openbsd"))]
- /// The implementation supports the X/Open Encryption Option Group.
- _XOPEN_CRYPT = libc::_SC_XOPEN_CRYPT,
- #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
- target_os = "ios", target_os="linux", target_os = "macos",
- target_os="openbsd"))]
- /// The implementation supports the Issue 4, Version 2 Enhanced
- /// Internationalization Option Group.
- _XOPEN_ENH_I18N = libc::_SC_XOPEN_ENH_I18N,
- #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
- target_os = "ios", target_os="linux", target_os = "macos",
- target_os="openbsd"))]
- _XOPEN_LEGACY = libc::_SC_XOPEN_LEGACY,
- #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
- target_os = "ios", target_os="linux", target_os = "macos",
- target_os="openbsd"))]
- /// The implementation supports the X/Open Realtime Option Group.
- _XOPEN_REALTIME = libc::_SC_XOPEN_REALTIME,
- #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
- target_os = "ios", target_os="linux", target_os = "macos",
- target_os="openbsd"))]
- /// The implementation supports the X/Open Realtime Threads Option Group.
- _XOPEN_REALTIME_THREADS = libc::_SC_XOPEN_REALTIME_THREADS,
- /// The implementation supports the Issue 4, Version 2 Shared Memory Option
- /// Group.
- #[cfg(not(target_os = "redox"))]
- _XOPEN_SHM = libc::_SC_XOPEN_SHM,
- #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
- target_os="linux", target_os = "macos", target_os="openbsd"))]
- /// The implementation supports the XSI STREAMS Option Group.
- _XOPEN_STREAMS = libc::_SC_XOPEN_STREAMS,
- #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
- target_os = "ios", target_os="linux", target_os = "macos",
- target_os="openbsd"))]
- /// The implementation supports the XSI option
- _XOPEN_UNIX = libc::_SC_XOPEN_UNIX,
- #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
- target_os = "ios", target_os="linux", target_os = "macos",
- target_os="openbsd"))]
- /// Integer value indicating version of the X/Open Portability Guide to
- /// which the implementation conforms.
- _XOPEN_VERSION = libc::_SC_XOPEN_VERSION,
-}
-
-/// Get configurable system variables (see
-/// [sysconf(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html))
-///
-/// Returns the value of a configurable system variable. Most supported
-/// variables also have associated compile-time constants, but POSIX
-/// allows their values to change at runtime. There are generally two types of
-/// sysconf variables: options and limits. See sysconf(3) for more details.
-///
-/// # Returns
-///
-/// - `Ok(Some(x))`: the variable's limit (for limit variables) or its
-/// implementation level (for option variables). Implementation levels are
-/// usually a decimal-coded date, such as 200112 for POSIX 2001.12
-/// - `Ok(None)`: the variable has no limit (for limit variables) or is
-/// unsupported (for option variables)
-/// - `Err(x)`: an error occurred
-pub fn sysconf(var: SysconfVar) -> Result<Option<c_long>> {
- let raw = unsafe {
- Errno::clear();
- libc::sysconf(var as c_int)
- };
- if raw == -1 {
- if errno::errno() == 0 {
- Ok(None)
- } else {
- Err(Error::Sys(Errno::last()))
- }
- } else {
- Ok(Some(raw))
- }
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-mod pivot_root {
- use crate::{Result, NixPath};
- use crate::errno::Errno;
-
- pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
- new_root: &P1, put_old: &P2) -> Result<()> {
- let res = new_root.with_nix_path(|new_root| {
- put_old.with_nix_path(|put_old| {
- unsafe {
- libc::syscall(libc::SYS_pivot_root, new_root.as_ptr(), put_old.as_ptr())
- }
- })
- })??;
-
- Errno::result(res).map(drop)
- }
-}
-
-#[cfg(any(target_os = "android", target_os = "freebsd",
- target_os = "linux", target_os = "openbsd"))]
-mod setres {
- use crate::Result;
- use crate::errno::Errno;
- use super::{Uid, Gid};
-
- /// Sets the real, effective, and saved uid.
- /// ([see setresuid(2)](http://man7.org/linux/man-pages/man2/setresuid.2.html))
- ///
- /// * `ruid`: real user id
- /// * `euid`: effective user id
- /// * `suid`: saved user id
- /// * returns: Ok or libc error code.
- ///
- /// Err is returned if the user doesn't have permission to set this UID.
- #[inline]
- pub fn setresuid(ruid: Uid, euid: Uid, suid: Uid) -> Result<()> {
- let res = unsafe { libc::setresuid(ruid.into(), euid.into(), suid.into()) };
-
- Errno::result(res).map(drop)
- }
-
- /// Sets the real, effective, and saved gid.
- /// ([see setresuid(2)](http://man7.org/linux/man-pages/man2/setresuid.2.html))
- ///
- /// * `rgid`: real group id
- /// * `egid`: effective group id
- /// * `sgid`: saved group id
- /// * returns: Ok or libc error code.
- ///
- /// Err is returned if the user doesn't have permission to set this GID.
- #[inline]
- pub fn setresgid(rgid: Gid, egid: Gid, sgid: Gid) -> Result<()> {
- let res = unsafe { libc::setresgid(rgid.into(), egid.into(), sgid.into()) };
-
- Errno::result(res).map(drop)
- }
-}
-
-libc_bitflags!{
- /// Options for access()
- pub struct AccessFlags : c_int {
- /// Test for existence of file.
- F_OK;
- /// Test for read permission.
- R_OK;
- /// Test for write permission.
- W_OK;
- /// Test for execute (search) permission.
- X_OK;
- }
-}
-
-/// Checks the file named by `path` for accessibility according to the flags given by `amode`
-/// See [access(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/access.html)
-pub fn access<P: ?Sized + NixPath>(path: &P, amode: AccessFlags) -> Result<()> {
- let res = path.with_nix_path(|cstr| {
- unsafe {
- libc::access(cstr.as_ptr(), amode.bits)
- }
- })?;
- Errno::result(res).map(drop)
-}
-
-/// Representation of a User, based on `libc::passwd`
-///
-/// The reason some fields in this struct are `String` and others are `CString` is because some
-/// fields are based on the user's locale, which could be non-UTF8, while other fields are
-/// guaranteed to conform to [`NAME_REGEX`](https://serverfault.com/a/73101/407341), which only
-/// contains ASCII.
-#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
-#[derive(Debug, Clone, PartialEq)]
-pub struct User {
- /// Username
- pub name: String,
- /// User password (probably encrypted)
- pub passwd: CString,
- /// User ID
- pub uid: Uid,
- /// Group ID
- pub gid: Gid,
- /// User information
- #[cfg(not(target_os = "android"))]
- pub gecos: CString,
- /// Home directory
- pub dir: PathBuf,
- /// Path to shell
- pub shell: PathBuf,
- /// Login class
- #[cfg(not(any(target_os = "android", target_os = "fuchsia",
- target_os = "linux")))]
- pub class: CString,
- /// Last password change
- #[cfg(not(any(target_os = "android", target_os = "fuchsia",
- target_os = "linux")))]
- pub change: libc::time_t,
- /// Expiration time of account
- #[cfg(not(any(target_os = "android", target_os = "fuchsia",
- target_os = "linux")))]
- pub expire: libc::time_t
-}
-
-#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
-impl From<&libc::passwd> for User {
- fn from(pw: &libc::passwd) -> User {
- unsafe {
- User {
- name: CStr::from_ptr((*pw).pw_name).to_string_lossy().into_owned(),
- passwd: CString::new(CStr::from_ptr((*pw).pw_passwd).to_bytes()).unwrap(),
- #[cfg(not(target_os = "android"))]
- gecos: CString::new(CStr::from_ptr((*pw).pw_gecos).to_bytes()).unwrap(),
- dir: PathBuf::from(OsStr::from_bytes(CStr::from_ptr((*pw).pw_dir).to_bytes())),
- shell: PathBuf::from(OsStr::from_bytes(CStr::from_ptr((*pw).pw_shell).to_bytes())),
- uid: Uid::from_raw((*pw).pw_uid),
- gid: Gid::from_raw((*pw).pw_gid),
- #[cfg(not(any(target_os = "android", target_os = "fuchsia",
- target_os = "linux")))]
- class: CString::new(CStr::from_ptr((*pw).pw_class).to_bytes()).unwrap(),
- #[cfg(not(any(target_os = "android", target_os = "fuchsia",
- target_os = "linux")))]
- change: (*pw).pw_change,
- #[cfg(not(any(target_os = "android", target_os = "fuchsia",
- target_os = "linux")))]
- expire: (*pw).pw_expire
- }
- }
- }
-}
-
-#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
-impl User {
- fn from_anything<F>(f: F) -> Result<Option<Self>>
- where
- F: Fn(*mut libc::passwd,
- *mut libc::c_char,
- libc::size_t,
- *mut *mut libc::passwd) -> libc::c_int
- {
- let buflimit = 16384;
- let bufsize = match sysconf(SysconfVar::GETPW_R_SIZE_MAX) {
- Ok(Some(n)) => n as usize,
- Ok(None) | Err(_) => buflimit as usize,
- };
-
- let mut cbuf = Vec::with_capacity(bufsize);
- let mut pwd = mem::MaybeUninit::<libc::passwd>::uninit();
- let mut res = ptr::null_mut();
-
- loop {
- let error = f(pwd.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res);
- if error == 0 {
- if res.is_null() {
- return Ok(None);
- } else {
- let pwd = unsafe { pwd.assume_init() };
- return Ok(Some(User::from(&pwd)));
- }
- } else if Errno::last() == Errno::ERANGE {
- // Trigger the internal buffer resizing logic.
- reserve_double_buffer_size(&mut cbuf, buflimit)?;
- } else {
- return Err(Error::Sys(Errno::last()));
- }
- }
- }
-
- /// Get a user by UID.
- ///
- /// Internally, this function calls
- /// [getpwuid_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
- ///
- /// # Examples
- ///
- /// ```
- /// use nix::unistd::{Uid, User};
- /// // Returns an Result<Option<User>>, thus the double unwrap.
- /// let res = User::from_uid(Uid::from_raw(0)).unwrap().unwrap();
- /// assert!(res.name == "root");
- /// ```
- pub fn from_uid(uid: Uid) -> Result<Option<Self>> {
- User::from_anything(|pwd, cbuf, cap, res| {
- unsafe { libc::getpwuid_r(uid.0, pwd, cbuf, cap, res) }
- })
- }
-
- /// Get a user by name.
- ///
- /// Internally, this function calls
- /// [getpwnam_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
- ///
- /// # Examples
- ///
- /// ```
- /// use nix::unistd::User;
- /// // Returns an Result<Option<User>>, thus the double unwrap.
- /// let res = User::from_name("root").unwrap().unwrap();
- /// assert!(res.name == "root");
- /// ```
- pub fn from_name(name: &str) -> Result<Option<Self>> {
- let name = CString::new(name).unwrap();
- User::from_anything(|pwd, cbuf, cap, res| {
- unsafe { libc::getpwnam_r(name.as_ptr(), pwd, cbuf, cap, res) }
- })
- }
-}
-
-/// Representation of a Group, based on `libc::group`
-#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
-#[derive(Debug, Clone, PartialEq)]
-pub struct Group {
- /// Group name
- pub name: String,
- /// Group password
- pub passwd: CString,
- /// Group ID
- pub gid: Gid,
- /// List of Group members
- pub mem: Vec<String>
-}
-
-#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
-impl From<&libc::group> for Group {
- fn from(gr: &libc::group) -> Group {
- unsafe {
- Group {
- name: CStr::from_ptr((*gr).gr_name).to_string_lossy().into_owned(),
- passwd: CString::new(CStr::from_ptr((*gr).gr_passwd).to_bytes()).unwrap(),
- gid: Gid::from_raw((*gr).gr_gid),
- mem: Group::members((*gr).gr_mem)
- }
- }
- }
-}
-
-#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
-impl Group {
- unsafe fn members(mem: *mut *mut c_char) -> Vec<String> {
- let mut ret = Vec::new();
-
- for i in 0.. {
- let u = mem.offset(i);
- if (*u).is_null() {
- break;
- } else {
- let s = CStr::from_ptr(*u).to_string_lossy().into_owned();
- ret.push(s);
- }
- }
-
- ret
- }
-
- fn from_anything<F>(f: F) -> Result<Option<Self>>
- where
- F: Fn(*mut libc::group,
- *mut libc::c_char,
- libc::size_t,
- *mut *mut libc::group) -> libc::c_int
- {
- let buflimit = 16384;
- let bufsize = match sysconf(SysconfVar::GETGR_R_SIZE_MAX) {
- Ok(Some(n)) => n as usize,
- Ok(None) | Err(_) => buflimit as usize,
- };
-
- let mut cbuf = Vec::with_capacity(bufsize);
- let mut grp = mem::MaybeUninit::<libc::group>::uninit();
- let mut res = ptr::null_mut();
-
- loop {
- let error = f(grp.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res);
- if error == 0 {
- if res.is_null() {
- return Ok(None);
- } else {
- let grp = unsafe { grp.assume_init() };
- return Ok(Some(Group::from(&grp)));
- }
- } else if Errno::last() == Errno::ERANGE {
- // Trigger the internal buffer resizing logic.
- reserve_double_buffer_size(&mut cbuf, buflimit)?;
- } else {
- return Err(Error::Sys(Errno::last()));
- }
- }
- }
-
- /// Get a group by GID.
- ///
- /// Internally, this function calls
- /// [getgrgid_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
- ///
- /// # Examples
- ///
- // Disable this test on all OS except Linux as root group may not exist.
- #[cfg_attr(not(target_os = "linux"), doc = " ```no_run")]
- #[cfg_attr(target_os = "linux", doc = " ```")]
- /// use nix::unistd::{Gid, Group};
- /// // Returns an Result<Option<Group>>, thus the double unwrap.
- /// let res = Group::from_gid(Gid::from_raw(0)).unwrap().unwrap();
- /// assert!(res.name == "root");
- /// ```
- pub fn from_gid(gid: Gid) -> Result<Option<Self>> {
- Group::from_anything(|grp, cbuf, cap, res| {
- unsafe { libc::getgrgid_r(gid.0, grp, cbuf, cap, res) }
- })
- }
-
- /// Get a group by name.
- ///
- /// Internally, this function calls
- /// [getgrnam_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
- ///
- /// # Examples
- ///
- // Disable this test on all OS except Linux as root group may not exist.
- #[cfg_attr(not(target_os = "linux"), doc = " ```no_run")]
- #[cfg_attr(target_os = "linux", doc = " ```")]
- /// use nix::unistd::Group;
- /// // Returns an Result<Option<Group>>, thus the double unwrap.
- /// let res = Group::from_name("root").unwrap().unwrap();
- /// assert!(res.name == "root");
- /// ```
- pub fn from_name(name: &str) -> Result<Option<Self>> {
- let name = CString::new(name).unwrap();
- Group::from_anything(|grp, cbuf, cap, res| {
- unsafe { libc::getgrnam_r(name.as_ptr(), grp, cbuf, cap, res) }
- })
- }
-}
-
-/// Get the name of the terminal device that is open on file descriptor fd
-/// (see [`ttyname(3)`](http://man7.org/linux/man-pages/man3/ttyname.3.html)).
-#[cfg(not(target_os = "fuchsia"))]
-pub fn ttyname(fd: RawFd) -> Result<PathBuf> {
- const PATH_MAX: usize = libc::PATH_MAX as usize;
- let mut buf = vec![0_u8; PATH_MAX];
- let c_buf = buf.as_mut_ptr() as *mut libc::c_char;
-
- let ret = unsafe { libc::ttyname_r(fd, c_buf, buf.len()) };
- if ret != 0 {
- return Err(Error::Sys(Errno::from_i32(ret)));
- }
-
- let nul = buf.iter().position(|c| *c == b'\0').unwrap();
- buf.truncate(nul);
- Ok(OsString::from_vec(buf).into())
-}
-
-/// Get the effective user ID and group ID associated with a Unix domain socket.
-///
-/// See also [getpeereid(3)](https://www.freebsd.org/cgi/man.cgi?query=getpeereid)
-#[cfg(any(
- target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "dragonfly",
-))]
-pub fn getpeereid(fd: RawFd) -> Result<(Uid, Gid)> {
- let mut uid = 1;
- let mut gid = 1;
-
- let ret = unsafe { libc::getpeereid(fd, &mut uid, &mut gid) };
-
- Errno::result(ret).map(|_| (Uid(uid), Gid(gid)))
-}
diff --git a/vendor/nix-0.20.0/test/common/mod.rs b/vendor/nix-0.20.0/test/common/mod.rs
deleted file mode 100644
index a871b47..0000000
--- a/vendor/nix-0.20.0/test/common/mod.rs
+++ /dev/null
@@ -1,127 +0,0 @@
-use cfg_if::cfg_if;
-
-#[macro_export] macro_rules! skip {
- ($($reason: expr),+) => {
- use ::std::io::{self, Write};
-
- let stderr = io::stderr();
- let mut handle = stderr.lock();
- writeln!(handle, $($reason),+).unwrap();
- return;
- }
-}
-
-cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
- #[macro_export] macro_rules! require_capability {
- ($capname:ident) => {
- use ::caps::{Capability, CapSet, has_cap};
-
- if !has_cap(None, CapSet::Effective, Capability::$capname)
- .unwrap()
- {
- skip!("Insufficient capabilities. Skipping test.");
- }
- }
- }
- } else if #[cfg(not(target_os = "redox"))] {
- #[macro_export] macro_rules! require_capability {
- ($capname:ident) => {}
- }
- }
-}
-
-#[cfg(any(target_os = "linux", target_os= "android"))]
-#[macro_export] macro_rules! skip_if_cirrus {
- ($reason:expr) => {
- if std::env::var_os("CIRRUS_CI").is_some() {
- skip!("{}", $reason);
- }
- }
-}
-
-#[cfg(target_os = "freebsd")]
-#[macro_export] macro_rules! skip_if_jailed {
- ($name:expr) => {
- use ::sysctl::CtlValue;
-
- if let CtlValue::Int(1) = ::sysctl::value("security.jail.jailed")
- .unwrap()
- {
- skip!("{} cannot run in a jail. Skipping test.", $name);
- }
- }
-}
-
-#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-#[macro_export] macro_rules! skip_if_not_root {
- ($name:expr) => {
- use nix::unistd::Uid;
-
- if !Uid::current().is_root() {
- skip!("{} requires root privileges. Skipping test.", $name);
- }
- };
-}
-
-cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
- #[macro_export] macro_rules! skip_if_seccomp {
- ($name:expr) => {
- if let Ok(s) = std::fs::read_to_string("/proc/self/status") {
- for l in s.lines() {
- let mut fields = l.split_whitespace();
- if fields.next() == Some("Seccomp:") &&
- fields.next() != Some("0")
- {
- skip!("{} cannot be run in Seccomp mode. Skipping test.",
- stringify!($name));
- }
- }
- }
- }
- }
- } else if #[cfg(not(target_os = "redox"))] {
- #[macro_export] macro_rules! skip_if_seccomp {
- ($name:expr) => {}
- }
- }
-}
-
-cfg_if! {
- if #[cfg(target_os = "linux")] {
- #[macro_export] macro_rules! require_kernel_version {
- ($name:expr, $version_requirement:expr) => {
- use semver::{Version, VersionReq};
-
- let version_requirement = VersionReq::parse($version_requirement)
- .expect("Bad match_version provided");
-
- let uname = nix::sys::utsname::uname();
- println!("{}", uname.sysname());
- println!("{}", uname.nodename());
- println!("{}", uname.release());
- println!("{}", uname.version());
- println!("{}", uname.machine());
-
- // Fix stuff that the semver parser can't handle
- let fixed_release = &uname.release().to_string()
- // Fedora 33 reports version as 4.18.el8_2.x86_64 or
- // 5.18.200-fc33.x86_64. Remove the underscore.
- .replace("_", "-")
- // Cirrus-CI reports version as 4.19.112+ . Remove the +
- .replace("+", "");
- let mut version = Version::parse(fixed_release).unwrap();
-
- //Keep only numeric parts
- version.pre.clear();
- version.build.clear();
-
- if !version_requirement.matches(&version) {
- skip!("Skip {} because kernel version `{}` doesn't match the requirement `{}`",
- stringify!($name), version, version_requirement);
- }
- }
- }
- }
-}
diff --git a/vendor/nix-0.20.0/test/sys/mod.rs b/vendor/nix-0.20.0/test/sys/mod.rs
deleted file mode 100644
index 14b0378..0000000
--- a/vendor/nix-0.20.0/test/sys/mod.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-mod test_signal;
-
-// NOTE: DragonFly lacks a kernel-level implementation of Posix AIO as of
-// this writing. There is an user-level implementation, but whether aio
-// works or not heavily depends on which pthread implementation is chosen
-// by the user at link time. For this reason we do not want to run aio test
-// cases on DragonFly.
-#[cfg(any(target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd"))]
-mod test_aio;
-#[cfg(target_os = "linux")]
-mod test_signalfd;
-#[cfg(not(target_os = "redox"))]
-mod test_socket;
-#[cfg(not(target_os = "redox"))]
-mod test_sockopt;
-#[cfg(not(target_os = "redox"))]
-mod test_select;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-mod test_sysinfo;
-#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-mod test_termios;
-#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-mod test_ioctl;
-mod test_wait;
-mod test_uio;
-
-#[cfg(target_os = "linux")]
-mod test_epoll;
-#[cfg(target_os = "linux")]
-mod test_inotify;
-mod test_pthread;
-#[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
-mod test_ptrace;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-mod test_timerfd;
diff --git a/vendor/nix-0.20.0/test/sys/test_aio.rs b/vendor/nix-0.20.0/test/sys/test_aio.rs
deleted file mode 100644
index 3878da9..0000000
--- a/vendor/nix-0.20.0/test/sys/test_aio.rs
+++ /dev/null
@@ -1,666 +0,0 @@
-use bytes::{Bytes, BytesMut};
-use libc::{c_int, c_void};
-use nix::{Error, Result};
-use nix::errno::*;
-use nix::sys::aio::*;
-use nix::sys::signal::{SaFlags, SigAction, sigaction, SigevNotify, SigHandler, Signal, SigSet};
-use nix::sys::time::{TimeSpec, TimeValLike};
-use std::io::{Write, Read, Seek, SeekFrom};
-use std::ops::Deref;
-use std::os::unix::io::AsRawFd;
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::{thread, time};
-use tempfile::tempfile;
-
-// Helper that polls an AioCb for completion or error
-fn poll_aio(aiocb: &mut AioCb) -> Result<()> {
- loop {
- let err = aiocb.error();
- if err != Err(Error::from(Errno::EINPROGRESS)) { return err; };
- thread::sleep(time::Duration::from_millis(10));
- }
-}
-
-#[test]
-fn test_accessors() {
- let mut rbuf = vec![0; 4];
- let aiocb = AioCb::from_mut_slice( 1001,
- 2, //offset
- &mut rbuf,
- 42, //priority
- SigevNotify::SigevSignal {
- signal: Signal::SIGUSR2,
- si_value: 99
- },
- LioOpcode::LIO_NOP);
- assert_eq!(1001, aiocb.fd());
- assert_eq!(Some(LioOpcode::LIO_NOP), aiocb.lio_opcode());
- assert_eq!(4, aiocb.nbytes());
- assert_eq!(2, aiocb.offset());
- assert_eq!(42, aiocb.priority());
- let sev = aiocb.sigevent().sigevent();
- assert_eq!(Signal::SIGUSR2 as i32, sev.sigev_signo);
- assert_eq!(99, sev.sigev_value.sival_ptr as i64);
-}
-
-// Tests AioCb.cancel. We aren't trying to test the OS's implementation, only
-// our bindings. So it's sufficient to check that AioCb.cancel returned any
-// AioCancelStat value.
-#[test]
-#[cfg_attr(target_env = "musl", ignore)]
-fn test_cancel() {
- let wbuf: &[u8] = b"CDEF";
-
- let f = tempfile().unwrap();
- let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
- 0, //offset
- wbuf,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_NOP);
- aiocb.write().unwrap();
- let err = aiocb.error();
- assert!(err == Ok(()) || err == Err(Error::from(Errno::EINPROGRESS)));
-
- let cancelstat = aiocb.cancel();
- assert!(cancelstat.is_ok());
-
- // Wait for aiocb to complete, but don't care whether it succeeded
- let _ = poll_aio(&mut aiocb);
- let _ = aiocb.aio_return();
-}
-
-// Tests using aio_cancel_all for all outstanding IOs.
-#[test]
-#[cfg_attr(target_env = "musl", ignore)]
-fn test_aio_cancel_all() {
- let wbuf: &[u8] = b"CDEF";
-
- let f = tempfile().unwrap();
- let mut aiocb = AioCb::from_slice(f.as_raw_fd(),
- 0, //offset
- wbuf,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_NOP);
- aiocb.write().unwrap();
- let err = aiocb.error();
- assert!(err == Ok(()) || err == Err(Error::from(Errno::EINPROGRESS)));
-
- let cancelstat = aio_cancel_all(f.as_raw_fd());
- assert!(cancelstat.is_ok());
-
- // Wait for aiocb to complete, but don't care whether it succeeded
- let _ = poll_aio(&mut aiocb);
- let _ = aiocb.aio_return();
-}
-
-#[test]
-#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-fn test_fsync() {
- const INITIAL: &[u8] = b"abcdef123456";
- let mut f = tempfile().unwrap();
- f.write_all(INITIAL).unwrap();
- let mut aiocb = AioCb::from_fd( f.as_raw_fd(),
- 0, //priority
- SigevNotify::SigevNone);
- let err = aiocb.fsync(AioFsyncMode::O_SYNC);
- assert!(err.is_ok());
- poll_aio(&mut aiocb).unwrap();
- aiocb.aio_return().unwrap();
-}
-
-/// `AioCb::fsync` should not modify the `AioCb` object if `libc::aio_fsync` returns
-/// an error
-// Skip on Linux, because Linux's AIO implementation can't detect errors
-// synchronously
-#[test]
-#[cfg(any(target_os = "freebsd", target_os = "macos"))]
-fn test_fsync_error() {
- use std::mem;
-
- const INITIAL: &[u8] = b"abcdef123456";
- // Create an invalid AioFsyncMode
- let mode = unsafe { mem::transmute(666) };
- let mut f = tempfile().unwrap();
- f.write_all(INITIAL).unwrap();
- let mut aiocb = AioCb::from_fd( f.as_raw_fd(),
- 0, //priority
- SigevNotify::SigevNone);
- let err = aiocb.fsync(mode);
- assert!(err.is_err());
-}
-
-#[test]
-#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-// On Travis, aio_suspend hits an assertion within glibc. This is either a bug
-// in Travis's version of glibc or Linux. Either way, we must skip the test.
-// https://github.com/nix-rust/nix/issues/1099
-#[cfg_attr(target_os = "linux", ignore)]
-// On Cirrus, aio_suspend is failing with EINVAL
-// https://github.com/nix-rust/nix/issues/1361
-#[cfg_attr(target_os = "macos", ignore)]
-fn test_aio_suspend() {
- const INITIAL: &[u8] = b"abcdef123456";
- const WBUF: &[u8] = b"CDEFG";
- let timeout = TimeSpec::seconds(10);
- let mut rbuf = vec![0; 4];
- let rlen = rbuf.len();
- let mut f = tempfile().unwrap();
- f.write_all(INITIAL).unwrap();
-
- let mut wcb = AioCb::from_slice( f.as_raw_fd(),
- 2, //offset
- WBUF,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_WRITE);
-
- let mut rcb = AioCb::from_mut_slice( f.as_raw_fd(),
- 8, //offset
- &mut rbuf,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_READ);
- wcb.write().unwrap();
- rcb.read().unwrap();
- loop {
- {
- let cbbuf = [&wcb, &rcb];
- let r = aio_suspend(&cbbuf[..], Some(timeout));
- match r {
- Err(Error::Sys(Errno::EINTR)) => continue,
- Err(e) => panic!("aio_suspend returned {:?}", e),
- Ok(_) => ()
- };
- }
- if rcb.error() != Err(Error::from(Errno::EINPROGRESS)) &&
- wcb.error() != Err(Error::from(Errno::EINPROGRESS)) {
- break
- }
- }
-
- assert_eq!(wcb.aio_return().unwrap() as usize, WBUF.len());
- assert_eq!(rcb.aio_return().unwrap() as usize, rlen);
-}
-
-// Test a simple aio operation with no completion notification. We must poll
-// for completion
-#[test]
-#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-fn test_read() {
- const INITIAL: &[u8] = b"abcdef123456";
- let mut rbuf = vec![0; 4];
- const EXPECT: &[u8] = b"cdef";
- let mut f = tempfile().unwrap();
- f.write_all(INITIAL).unwrap();
- {
- let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(),
- 2, //offset
- &mut rbuf,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_NOP);
- aiocb.read().unwrap();
-
- let err = poll_aio(&mut aiocb);
- assert_eq!(err, Ok(()));
- assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
- }
-
- assert_eq!(EXPECT, rbuf.deref().deref());
-}
-
-/// `AioCb::read` should not modify the `AioCb` object if `libc::aio_read`
-/// returns an error
-// Skip on Linux, because Linux's AIO implementation can't detect errors
-// synchronously
-#[test]
-#[cfg(any(target_os = "freebsd", target_os = "macos"))]
-fn test_read_error() {
- const INITIAL: &[u8] = b"abcdef123456";
- let mut rbuf = vec![0; 4];
- let mut f = tempfile().unwrap();
- f.write_all(INITIAL).unwrap();
- let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(),
- -1, //an invalid offset
- &mut rbuf,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_NOP);
- assert!(aiocb.read().is_err());
-}
-
-// Tests from_mut_slice
-#[test]
-#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-fn test_read_into_mut_slice() {
- const INITIAL: &[u8] = b"abcdef123456";
- let mut rbuf = vec![0; 4];
- const EXPECT: &[u8] = b"cdef";
- let mut f = tempfile().unwrap();
- f.write_all(INITIAL).unwrap();
- {
- let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(),
- 2, //offset
- &mut rbuf,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_NOP);
- aiocb.read().unwrap();
-
- let err = poll_aio(&mut aiocb);
- assert_eq!(err, Ok(()));
- assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
- }
-
- assert_eq!(rbuf, EXPECT);
-}
-
-// Tests from_ptr
-#[test]
-#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-fn test_read_into_pointer() {
- const INITIAL: &[u8] = b"abcdef123456";
- let mut rbuf = vec![0; 4];
- const EXPECT: &[u8] = b"cdef";
- let mut f = tempfile().unwrap();
- f.write_all(INITIAL).unwrap();
- {
- // Safety: ok because rbuf lives until after poll_aio
- let mut aiocb = unsafe {
- AioCb::from_mut_ptr( f.as_raw_fd(),
- 2, //offset
- rbuf.as_mut_ptr() as *mut c_void,
- rbuf.len(),
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_NOP)
- };
- aiocb.read().unwrap();
-
- let err = poll_aio(&mut aiocb);
- assert_eq!(err, Ok(()));
- assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
- }
-
- assert_eq!(rbuf, EXPECT);
-}
-
-// Test reading into an immutable buffer. It should fail
-// FIXME: This test fails to panic on Linux/musl
-#[test]
-#[should_panic(expected = "Can't read into an immutable buffer")]
-#[cfg_attr(target_env = "musl", ignore)]
-fn test_read_immutable_buffer() {
- let rbuf: &[u8] = b"CDEF";
- let f = tempfile().unwrap();
- let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
- 2, //offset
- rbuf,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_NOP);
- aiocb.read().unwrap();
-}
-
-
-// Test a simple aio operation with no completion notification. We must poll
-// for completion. Unlike test_aio_read, this test uses AioCb::from_slice
-#[test]
-#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-fn test_write() {
- const INITIAL: &[u8] = b"abcdef123456";
- let wbuf = "CDEF".to_string().into_bytes();
- let mut rbuf = Vec::new();
- const EXPECT: &[u8] = b"abCDEF123456";
-
- let mut f = tempfile().unwrap();
- f.write_all(INITIAL).unwrap();
- let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
- 2, //offset
- &wbuf,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_NOP);
- aiocb.write().unwrap();
-
- let err = poll_aio(&mut aiocb);
- assert_eq!(err, Ok(()));
- assert_eq!(aiocb.aio_return().unwrap() as usize, wbuf.len());
-
- f.seek(SeekFrom::Start(0)).unwrap();
- let len = f.read_to_end(&mut rbuf).unwrap();
- assert_eq!(len, EXPECT.len());
- assert_eq!(rbuf, EXPECT);
-}
-
-// Tests `AioCb::from_boxed_slice` with `Bytes`
-#[test]
-#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-fn test_write_bytes() {
- const INITIAL: &[u8] = b"abcdef123456";
- let wbuf = Box::new(Bytes::from(&b"CDEF"[..]));
- let mut rbuf = Vec::new();
- const EXPECT: &[u8] = b"abCDEF123456";
- let expected_len = wbuf.len();
-
- let mut f = tempfile().unwrap();
- f.write_all(INITIAL).unwrap();
- let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
- 2, //offset
- wbuf,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_NOP);
- aiocb.write().unwrap();
-
- let err = poll_aio(&mut aiocb);
- assert_eq!(err, Ok(()));
- assert_eq!(aiocb.aio_return().unwrap() as usize, expected_len);
-
- f.seek(SeekFrom::Start(0)).unwrap();
- let len = f.read_to_end(&mut rbuf).unwrap();
- assert_eq!(len, EXPECT.len());
- assert_eq!(rbuf, EXPECT);
-}
-
-// Tests `AioCb::from_boxed_mut_slice` with `BytesMut`
-#[test]
-#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-fn test_read_bytes_mut_small() {
- const INITIAL: &[u8] = b"abcdef";
- let rbuf = Box::new(BytesMut::from(vec![0; 4]));
- const EXPECT: &[u8] = b"cdef";
- let mut f = tempfile().unwrap();
- f.write_all(INITIAL).unwrap();
-
- let mut aiocb = AioCb::from_boxed_mut_slice( f.as_raw_fd(),
- 2, //offset
- rbuf,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_NOP);
- aiocb.read().unwrap();
-
- let err = poll_aio(&mut aiocb);
- assert_eq!(err, Ok(()));
- assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
- let buffer = aiocb.boxed_mut_slice().unwrap();
- assert_eq!(buffer.borrow(), EXPECT);
-}
-
-// Tests `AioCb::from_ptr`
-#[test]
-#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-fn test_write_from_pointer() {
- const INITIAL: &[u8] = b"abcdef123456";
- let wbuf = "CDEF".to_string().into_bytes();
- let mut rbuf = Vec::new();
- const EXPECT: &[u8] = b"abCDEF123456";
-
- let mut f = tempfile().unwrap();
- f.write_all(INITIAL).unwrap();
- // Safety: ok because aiocb outlives poll_aio
- let mut aiocb = unsafe {
- AioCb::from_ptr( f.as_raw_fd(),
- 2, //offset
- wbuf.as_ptr() as *const c_void,
- wbuf.len(),
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_NOP)
- };
- aiocb.write().unwrap();
-
- let err = poll_aio(&mut aiocb);
- assert_eq!(err, Ok(()));
- assert_eq!(aiocb.aio_return().unwrap() as usize, wbuf.len());
-
- f.seek(SeekFrom::Start(0)).unwrap();
- let len = f.read_to_end(&mut rbuf).unwrap();
- assert_eq!(len, EXPECT.len());
- assert_eq!(rbuf, EXPECT);
-}
-
-/// `AioCb::write` should not modify the `AioCb` object if `libc::aio_write`
-/// returns an error
-// Skip on Linux, because Linux's AIO implementation can't detect errors
-// synchronously
-#[test]
-#[cfg(any(target_os = "freebsd", target_os = "macos"))]
-fn test_write_error() {
- let wbuf = "CDEF".to_string().into_bytes();
- let mut aiocb = AioCb::from_slice( 666, // An invalid file descriptor
- 0, //offset
- &wbuf,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_NOP);
- assert!(aiocb.write().is_err());
-}
-
-lazy_static! {
- pub static ref SIGNALED: AtomicBool = AtomicBool::new(false);
-}
-
-extern fn sigfunc(_: c_int) {
- SIGNALED.store(true, Ordering::Relaxed);
-}
-
-// Test an aio operation with completion delivered by a signal
-// FIXME: This test is ignored on mips because of failures in qemu in CI
-#[test]
-#[cfg_attr(any(all(target_env = "musl", target_arch = "x86_64"), target_arch = "mips", target_arch = "mips64"), ignore)]
-fn test_write_sigev_signal() {
- let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
- let sa = SigAction::new(SigHandler::Handler(sigfunc),
- SaFlags::SA_RESETHAND,
- SigSet::empty());
- SIGNALED.store(false, Ordering::Relaxed);
- unsafe { sigaction(Signal::SIGUSR2, &sa) }.unwrap();
-
- const INITIAL: &[u8] = b"abcdef123456";
- const WBUF: &[u8] = b"CDEF";
- let mut rbuf = Vec::new();
- const EXPECT: &[u8] = b"abCDEF123456";
-
- let mut f = tempfile().unwrap();
- f.write_all(INITIAL).unwrap();
- let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
- 2, //offset
- WBUF,
- 0, //priority
- SigevNotify::SigevSignal {
- signal: Signal::SIGUSR2,
- si_value: 0 //TODO: validate in sigfunc
- },
- LioOpcode::LIO_NOP);
- aiocb.write().unwrap();
- while !SIGNALED.load(Ordering::Relaxed) {
- thread::sleep(time::Duration::from_millis(10));
- }
-
- assert_eq!(aiocb.aio_return().unwrap() as usize, WBUF.len());
- f.seek(SeekFrom::Start(0)).unwrap();
- let len = f.read_to_end(&mut rbuf).unwrap();
- assert_eq!(len, EXPECT.len());
- assert_eq!(rbuf, EXPECT);
-}
-
-// Test LioCb::listio with LIO_WAIT, so all AIO ops should be complete by the
-// time listio returns.
-#[test]
-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-fn test_liocb_listio_wait() {
- const INITIAL: &[u8] = b"abcdef123456";
- const WBUF: &[u8] = b"CDEF";
- let mut rbuf = vec![0; 4];
- let rlen = rbuf.len();
- let mut rbuf2 = Vec::new();
- const EXPECT: &[u8] = b"abCDEF123456";
- let mut f = tempfile().unwrap();
-
- f.write_all(INITIAL).unwrap();
-
- {
- let wcb = AioCb::from_slice( f.as_raw_fd(),
- 2, //offset
- WBUF,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_WRITE);
-
- let rcb = AioCb::from_mut_slice( f.as_raw_fd(),
- 8, //offset
- &mut rbuf,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_READ);
- let mut liocb = LioCb::with_capacity(2);
- liocb.aiocbs.push(wcb);
- liocb.aiocbs.push(rcb);
- let err = liocb.listio(LioMode::LIO_WAIT, SigevNotify::SigevNone);
- err.expect("lio_listio");
-
- assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
- assert_eq!(liocb.aio_return(1).unwrap() as usize, rlen);
- }
- assert_eq!(rbuf.deref().deref(), b"3456");
-
- f.seek(SeekFrom::Start(0)).unwrap();
- let len = f.read_to_end(&mut rbuf2).unwrap();
- assert_eq!(len, EXPECT.len());
- assert_eq!(rbuf2, EXPECT);
-}
-
-// Test LioCb::listio with LIO_NOWAIT and no SigEvent, so we must use some other
-// mechanism to check for the individual AioCb's completion.
-#[test]
-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-fn test_liocb_listio_nowait() {
- const INITIAL: &[u8] = b"abcdef123456";
- const WBUF: &[u8] = b"CDEF";
- let mut rbuf = vec![0; 4];
- let rlen = rbuf.len();
- let mut rbuf2 = Vec::new();
- const EXPECT: &[u8] = b"abCDEF123456";
- let mut f = tempfile().unwrap();
-
- f.write_all(INITIAL).unwrap();
-
- {
- let wcb = AioCb::from_slice( f.as_raw_fd(),
- 2, //offset
- WBUF,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_WRITE);
-
- let rcb = AioCb::from_mut_slice( f.as_raw_fd(),
- 8, //offset
- &mut rbuf,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_READ);
- let mut liocb = LioCb::with_capacity(2);
- liocb.aiocbs.push(wcb);
- liocb.aiocbs.push(rcb);
- let err = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone);
- err.expect("lio_listio");
-
- poll_aio(&mut liocb.aiocbs[0]).unwrap();
- poll_aio(&mut liocb.aiocbs[1]).unwrap();
- assert_eq!(liocb.aiocbs[0].aio_return().unwrap() as usize, WBUF.len());
- assert_eq!(liocb.aiocbs[1].aio_return().unwrap() as usize, rlen);
- }
- assert_eq!(rbuf.deref().deref(), b"3456");
-
- f.seek(SeekFrom::Start(0)).unwrap();
- let len = f.read_to_end(&mut rbuf2).unwrap();
- assert_eq!(len, EXPECT.len());
- assert_eq!(rbuf2, EXPECT);
-}
-
-// Test LioCb::listio with LIO_NOWAIT and a SigEvent to indicate when all
-// AioCb's are complete.
-// FIXME: This test is ignored on mips/mips64 because of failures in qemu in CI.
-#[test]
-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-#[cfg_attr(any(target_arch = "mips", target_arch = "mips64", target_env = "musl"), ignore)]
-fn test_liocb_listio_signal() {
- let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
- const INITIAL: &[u8] = b"abcdef123456";
- const WBUF: &[u8] = b"CDEF";
- let mut rbuf = vec![0; 4];
- let rlen = rbuf.len();
- let mut rbuf2 = Vec::new();
- const EXPECT: &[u8] = b"abCDEF123456";
- let mut f = tempfile().unwrap();
- let sa = SigAction::new(SigHandler::Handler(sigfunc),
- SaFlags::SA_RESETHAND,
- SigSet::empty());
- let sigev_notify = SigevNotify::SigevSignal { signal: Signal::SIGUSR2,
- si_value: 0 };
-
- f.write_all(INITIAL).unwrap();
-
- {
- let wcb = AioCb::from_slice( f.as_raw_fd(),
- 2, //offset
- WBUF,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_WRITE);
-
- let rcb = AioCb::from_mut_slice( f.as_raw_fd(),
- 8, //offset
- &mut rbuf,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_READ);
- let mut liocb = LioCb::with_capacity(2);
- liocb.aiocbs.push(wcb);
- liocb.aiocbs.push(rcb);
- SIGNALED.store(false, Ordering::Relaxed);
- unsafe { sigaction(Signal::SIGUSR2, &sa) }.unwrap();
- let err = liocb.listio(LioMode::LIO_NOWAIT, sigev_notify);
- err.expect("lio_listio");
- while !SIGNALED.load(Ordering::Relaxed) {
- thread::sleep(time::Duration::from_millis(10));
- }
-
- assert_eq!(liocb.aiocbs[0].aio_return().unwrap() as usize, WBUF.len());
- assert_eq!(liocb.aiocbs[1].aio_return().unwrap() as usize, rlen);
- }
- assert_eq!(rbuf.deref().deref(), b"3456");
-
- f.seek(SeekFrom::Start(0)).unwrap();
- let len = f.read_to_end(&mut rbuf2).unwrap();
- assert_eq!(len, EXPECT.len());
- assert_eq!(rbuf2, EXPECT);
-}
-
-// Try to use LioCb::listio to read into an immutable buffer. It should fail
-// FIXME: This test fails to panic on Linux/musl
-#[test]
-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-#[should_panic(expected = "Can't read into an immutable buffer")]
-#[cfg_attr(target_env = "musl", ignore)]
-fn test_liocb_listio_read_immutable() {
- let rbuf: &[u8] = b"abcd";
- let f = tempfile().unwrap();
-
-
- let mut liocb = LioCb::from(vec![
- AioCb::from_slice( f.as_raw_fd(),
- 2, //offset
- rbuf,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_READ)
- ]);
- let _ = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone);
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_aio_drop.rs b/vendor/nix-0.20.0/test/sys/test_aio_drop.rs
deleted file mode 100644
index 784ee3e..0000000
--- a/vendor/nix-0.20.0/test/sys/test_aio_drop.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-// Test dropping an AioCb that hasn't yet finished.
-// This must happen in its own process, because on OSX this test seems to hose
-// the AIO subsystem and causes subsequent tests to fail
-#[test]
-#[should_panic(expected = "Dropped an in-progress AioCb")]
-#[cfg(all(not(target_env = "musl"),
- any(target_os = "linux",
- target_os = "ios",
- target_os = "macos",
- target_os = "freebsd",
- target_os = "netbsd")))]
-#[cfg_attr(target_env = "gnu", ignore = "Occasionally fails in Travis; glibc bug suspected")]
-fn test_drop() {
- use nix::sys::aio::*;
- use nix::sys::signal::*;
- use std::os::unix::io::AsRawFd;
- use tempfile::tempfile;
-
- const WBUF: &[u8] = b"CDEF";
-
- let f = tempfile().unwrap();
- f.set_len(6).unwrap();
- let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
- 2, //offset
- WBUF,
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_NOP);
- aiocb.write().unwrap();
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_epoll.rs b/vendor/nix-0.20.0/test/sys/test_epoll.rs
deleted file mode 100644
index e0dc513..0000000
--- a/vendor/nix-0.20.0/test/sys/test_epoll.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-use nix::sys::epoll::{EpollCreateFlags, EpollFlags, EpollOp, EpollEvent};
-use nix::sys::epoll::{epoll_create1, epoll_ctl};
-use nix::Error;
-use nix::errno::Errno;
-
-#[test]
-pub fn test_epoll_errno() {
- let efd = epoll_create1(EpollCreateFlags::empty()).unwrap();
- let result = epoll_ctl(efd, EpollOp::EpollCtlDel, 1, None);
- assert!(result.is_err());
- assert_eq!(result.unwrap_err(), Error::Sys(Errno::ENOENT));
-
- let result = epoll_ctl(efd, EpollOp::EpollCtlAdd, 1, None);
- assert!(result.is_err());
- assert_eq!(result.unwrap_err(), Error::Sys(Errno::EINVAL));
-}
-
-#[test]
-pub fn test_epoll_ctl() {
- let efd = epoll_create1(EpollCreateFlags::empty()).unwrap();
- let mut event = EpollEvent::new(EpollFlags::EPOLLIN | EpollFlags::EPOLLERR, 1);
- epoll_ctl(efd, EpollOp::EpollCtlAdd, 1, &mut event).unwrap();
- epoll_ctl(efd, EpollOp::EpollCtlDel, 1, None).unwrap();
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_inotify.rs b/vendor/nix-0.20.0/test/sys/test_inotify.rs
deleted file mode 100644
index a8ead46..0000000
--- a/vendor/nix-0.20.0/test/sys/test_inotify.rs
+++ /dev/null
@@ -1,65 +0,0 @@
-use nix::sys::inotify::{AddWatchFlags,InitFlags,Inotify};
-use nix::Error;
-use nix::errno::Errno;
-use tempfile;
-use std::ffi::OsString;
-use std::fs::{rename, File};
-
-#[test]
-pub fn test_inotify() {
- let instance = Inotify::init(InitFlags::IN_NONBLOCK)
- .unwrap();
- let tempdir = tempfile::tempdir().unwrap();
-
- instance.add_watch(tempdir.path(), AddWatchFlags::IN_ALL_EVENTS).unwrap();
-
- let events = instance.read_events();
- assert_eq!(events.unwrap_err(), Error::Sys(Errno::EAGAIN));
-
- File::create(tempdir.path().join("test")).unwrap();
-
- let events = instance.read_events().unwrap();
- assert_eq!(events[0].name, Some(OsString::from("test")));
-}
-
-#[test]
-pub fn test_inotify_multi_events() {
- let instance = Inotify::init(InitFlags::IN_NONBLOCK)
- .unwrap();
- let tempdir = tempfile::tempdir().unwrap();
-
- instance.add_watch(tempdir.path(), AddWatchFlags::IN_ALL_EVENTS).unwrap();
-
- let events = instance.read_events();
- assert_eq!(events.unwrap_err(), Error::Sys(Errno::EAGAIN));
-
- File::create(tempdir.path().join("test")).unwrap();
- rename(tempdir.path().join("test"), tempdir.path().join("test2")).unwrap();
-
- // Now there should be 5 events in queue:
- // - IN_CREATE on test
- // - IN_OPEN on test
- // - IN_CLOSE_WRITE on test
- // - IN_MOVED_FROM on test with a cookie
- // - IN_MOVED_TO on test2 with the same cookie
-
- let events = instance.read_events().unwrap();
- assert_eq!(events.len(), 5);
-
- assert_eq!(events[0].mask, AddWatchFlags::IN_CREATE);
- assert_eq!(events[0].name, Some(OsString::from("test")));
-
- assert_eq!(events[1].mask, AddWatchFlags::IN_OPEN);
- assert_eq!(events[1].name, Some(OsString::from("test")));
-
- assert_eq!(events[2].mask, AddWatchFlags::IN_CLOSE_WRITE);
- assert_eq!(events[2].name, Some(OsString::from("test")));
-
- assert_eq!(events[3].mask, AddWatchFlags::IN_MOVED_FROM);
- assert_eq!(events[3].name, Some(OsString::from("test")));
-
- assert_eq!(events[4].mask, AddWatchFlags::IN_MOVED_TO);
- assert_eq!(events[4].name, Some(OsString::from("test2")));
-
- assert_eq!(events[3].cookie, events[4].cookie);
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_ioctl.rs b/vendor/nix-0.20.0/test/sys/test_ioctl.rs
deleted file mode 100644
index fa4510a..0000000
--- a/vendor/nix-0.20.0/test/sys/test_ioctl.rs
+++ /dev/null
@@ -1,339 +0,0 @@
-#![allow(dead_code)]
-
-// Simple tests to ensure macro generated fns compile
-ioctl_none_bad!(do_bad, 0x1234);
-ioctl_read_bad!(do_bad_read, 0x1234, u16);
-ioctl_write_int_bad!(do_bad_write_int, 0x1234);
-ioctl_write_ptr_bad!(do_bad_write_ptr, 0x1234, u8);
-ioctl_readwrite_bad!(do_bad_readwrite, 0x1234, u32);
-ioctl_none!(do_none, 0, 0);
-ioctl_read!(read_test, 0, 0, u32);
-ioctl_write_int!(write_ptr_int, 0, 0);
-ioctl_write_ptr!(write_ptr_u8, 0, 0, u8);
-ioctl_write_ptr!(write_ptr_u32, 0, 0, u32);
-ioctl_write_ptr!(write_ptr_u64, 0, 0, u64);
-ioctl_readwrite!(readwrite_test, 0, 0, u64);
-ioctl_read_buf!(readbuf_test, 0, 0, u32);
-const SPI_IOC_MAGIC: u8 = b'k';
-const SPI_IOC_MESSAGE: u8 = 0;
-ioctl_write_buf!(writebuf_test_consts, SPI_IOC_MAGIC, SPI_IOC_MESSAGE, u8);
-ioctl_write_buf!(writebuf_test_u8, 0, 0, u8);
-ioctl_write_buf!(writebuf_test_u32, 0, 0, u32);
-ioctl_write_buf!(writebuf_test_u64, 0, 0, u64);
-ioctl_readwrite_buf!(readwritebuf_test, 0, 0, u32);
-
-// See C code for source of values for op calculations (does NOT work for mips/powerpc):
-// https://gist.github.com/posborne/83ea6880770a1aef332e
-//
-// TODO: Need a way to compute these constants at test time. Using precomputed
-// values is fragile and needs to be maintained.
-
-#[cfg(any(target_os = "linux", target_os = "android"))]
-mod linux {
- #[test]
- fn test_op_none() {
- if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
- assert_eq!(request_code_none!(b'q', 10) as u32, 0x2000_710A);
- assert_eq!(request_code_none!(b'a', 255) as u32, 0x2000_61FF);
- } else {
- assert_eq!(request_code_none!(b'q', 10) as u32, 0x0000_710A);
- assert_eq!(request_code_none!(b'a', 255) as u32, 0x0000_61FF);
- }
- }
-
- #[test]
- fn test_op_write() {
- if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
- assert_eq!(request_code_write!(b'z', 10, 1) as u32, 0x8001_7A0A);
- assert_eq!(request_code_write!(b'z', 10, 512) as u32, 0x8200_7A0A);
- } else {
- assert_eq!(request_code_write!(b'z', 10, 1) as u32, 0x4001_7A0A);
- assert_eq!(request_code_write!(b'z', 10, 512) as u32, 0x4200_7A0A);
- }
- }
-
- #[cfg(target_pointer_width = "64")]
- #[test]
- fn test_op_write_64() {
- if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){
- assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32) as u32,
- 0x8000_7A0A);
- } else {
- assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32) as u32,
- 0x4000_7A0A);
- }
-
- }
-
- #[test]
- fn test_op_read() {
- if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
- assert_eq!(request_code_read!(b'z', 10, 1) as u32, 0x4001_7A0A);
- assert_eq!(request_code_read!(b'z', 10, 512) as u32, 0x4200_7A0A);
- } else {
- assert_eq!(request_code_read!(b'z', 10, 1) as u32, 0x8001_7A0A);
- assert_eq!(request_code_read!(b'z', 10, 512) as u32, 0x8200_7A0A);
- }
- }
-
- #[cfg(target_pointer_width = "64")]
- #[test]
- fn test_op_read_64() {
- if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){
- assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32) as u32,
- 0x4000_7A0A);
- } else {
- assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32) as u32,
- 0x8000_7A0A);
- }
- }
-
- #[test]
- fn test_op_read_write() {
- assert_eq!(request_code_readwrite!(b'z', 10, 1) as u32, 0xC001_7A0A);
- assert_eq!(request_code_readwrite!(b'z', 10, 512) as u32, 0xC200_7A0A);
- }
-
- #[cfg(target_pointer_width = "64")]
- #[test]
- fn test_op_read_write_64() {
- assert_eq!(request_code_readwrite!(b'z', 10, (1 as u64) << 32) as u32,
- 0xC000_7A0A);
- }
-}
-
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
-mod bsd {
- #[test]
- fn test_op_none() {
- assert_eq!(request_code_none!(b'q', 10), 0x2000_710A);
- assert_eq!(request_code_none!(b'a', 255), 0x2000_61FF);
- }
-
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[test]
- fn test_op_write_int() {
- assert_eq!(request_code_write_int!(b'v', 4), 0x2004_7604);
- assert_eq!(request_code_write_int!(b'p', 2), 0x2004_7002);
- }
-
- #[test]
- fn test_op_write() {
- assert_eq!(request_code_write!(b'z', 10, 1), 0x8001_7A0A);
- assert_eq!(request_code_write!(b'z', 10, 512), 0x8200_7A0A);
- }
-
- #[cfg(target_pointer_width = "64")]
- #[test]
- fn test_op_write_64() {
- assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32), 0x8000_7A0A);
- }
-
- #[test]
- fn test_op_read() {
- assert_eq!(request_code_read!(b'z', 10, 1), 0x4001_7A0A);
- assert_eq!(request_code_read!(b'z', 10, 512), 0x4200_7A0A);
- }
-
- #[cfg(target_pointer_width = "64")]
- #[test]
- fn test_op_read_64() {
- assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32), 0x4000_7A0A);
- }
-
- #[test]
- fn test_op_read_write() {
- assert_eq!(request_code_readwrite!(b'z', 10, 1), 0xC001_7A0A);
- assert_eq!(request_code_readwrite!(b'z', 10, 512), 0xC200_7A0A);
- }
-
- #[cfg(target_pointer_width = "64")]
- #[test]
- fn test_op_read_write_64() {
- assert_eq!(request_code_readwrite!(b'z', 10, (1 as u64) << 32), 0xC000_7A0A);
- }
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-mod linux_ioctls {
- use std::mem;
- use std::os::unix::io::AsRawFd;
-
- use tempfile::tempfile;
- use libc::{TCGETS, TCSBRK, TCSETS, TIOCNXCL, termios};
-
- use nix::Error::Sys;
- use nix::errno::Errno::{ENOTTY, ENOSYS};
-
- ioctl_none_bad!(tiocnxcl, TIOCNXCL);
- #[test]
- fn test_ioctl_none_bad() {
- let file = tempfile().unwrap();
- let res = unsafe { tiocnxcl(file.as_raw_fd()) };
- assert_eq!(res, Err(Sys(ENOTTY)));
- }
-
- ioctl_read_bad!(tcgets, TCGETS, termios);
- #[test]
- fn test_ioctl_read_bad() {
- let file = tempfile().unwrap();
- let mut termios = unsafe { mem::zeroed() };
- let res = unsafe { tcgets(file.as_raw_fd(), &mut termios) };
- assert_eq!(res, Err(Sys(ENOTTY)));
- }
-
- ioctl_write_int_bad!(tcsbrk, TCSBRK);
- #[test]
- fn test_ioctl_write_int_bad() {
- let file = tempfile().unwrap();
- let res = unsafe { tcsbrk(file.as_raw_fd(), 0) };
- assert_eq!(res, Err(Sys(ENOTTY)));
- }
-
- ioctl_write_ptr_bad!(tcsets, TCSETS, termios);
- #[test]
- fn test_ioctl_write_ptr_bad() {
- let file = tempfile().unwrap();
- let termios: termios = unsafe { mem::zeroed() };
- let res = unsafe { tcsets(file.as_raw_fd(), &termios) };
- assert_eq!(res, Err(Sys(ENOTTY)));
- }
-
- // FIXME: Find a suitable example for `ioctl_readwrite_bad`
-
- // From linux/videodev2.h
- ioctl_none!(log_status, b'V', 70);
- #[test]
- fn test_ioctl_none() {
- let file = tempfile().unwrap();
- let res = unsafe { log_status(file.as_raw_fd()) };
- assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
- }
-
- #[repr(C)]
- pub struct v4l2_audio {
- index: u32,
- name: [u8; 32],
- capability: u32,
- mode: u32,
- reserved: [u32; 2],
- }
-
- // From linux/videodev2.h
- ioctl_write_ptr!(s_audio, b'V', 34, v4l2_audio);
- #[test]
- fn test_ioctl_write_ptr() {
- let file = tempfile().unwrap();
- let data: v4l2_audio = unsafe { mem::zeroed() };
- let res = unsafe { s_audio(file.as_raw_fd(), &data) };
- assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
- }
-
- // From linux/net/bluetooth/hci_sock.h
- const HCI_IOC_MAGIC: u8 = b'H';
- const HCI_IOC_HCIDEVUP: u8 = 201;
- ioctl_write_int!(hcidevup, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
- #[test]
- fn test_ioctl_write_int() {
- let file = tempfile().unwrap();
- let res = unsafe { hcidevup(file.as_raw_fd(), 0) };
- assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
- }
-
- // From linux/videodev2.h
- ioctl_read!(g_audio, b'V', 33, v4l2_audio);
- #[test]
- fn test_ioctl_read() {
- let file = tempfile().unwrap();
- let mut data: v4l2_audio = unsafe { mem::zeroed() };
- let res = unsafe { g_audio(file.as_raw_fd(), &mut data) };
- assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
- }
-
- // From linux/videodev2.h
- ioctl_readwrite!(enum_audio, b'V', 65, v4l2_audio);
- #[test]
- fn test_ioctl_readwrite() {
- let file = tempfile().unwrap();
- let mut data: v4l2_audio = unsafe { mem::zeroed() };
- let res = unsafe { enum_audio(file.as_raw_fd(), &mut data) };
- assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
- }
-
- // FIXME: Find a suitable example for `ioctl_read_buf`.
-
- #[repr(C)]
- pub struct spi_ioc_transfer {
- tx_buf: u64,
- rx_buf: u64,
- len: u32,
- speed_hz: u32,
- delay_usecs: u16,
- bits_per_word: u8,
- cs_change: u8,
- tx_nbits: u8,
- rx_nbits: u8,
- pad: u16,
- }
-
- // From linux/spi/spidev.h
- ioctl_write_buf!(spi_ioc_message, super::SPI_IOC_MAGIC, super::SPI_IOC_MESSAGE, spi_ioc_transfer);
- #[test]
- fn test_ioctl_write_buf() {
- let file = tempfile().unwrap();
- let data: [spi_ioc_transfer; 4] = unsafe { mem::zeroed() };
- let res = unsafe { spi_ioc_message(file.as_raw_fd(), &data[..]) };
- assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
- }
-
- // FIXME: Find a suitable example for `ioctl_readwrite_buf`.
-}
-
-#[cfg(target_os = "freebsd")]
-mod freebsd_ioctls {
- use std::mem;
- use std::os::unix::io::AsRawFd;
-
- use tempfile::tempfile;
- use libc::termios;
-
- use nix::Error::Sys;
- use nix::errno::Errno::ENOTTY;
-
- // From sys/sys/ttycom.h
- const TTY_IOC_MAGIC: u8 = b't';
- const TTY_IOC_TYPE_NXCL: u8 = 14;
- const TTY_IOC_TYPE_GETA: u8 = 19;
- const TTY_IOC_TYPE_SETA: u8 = 20;
-
- ioctl_none!(tiocnxcl, TTY_IOC_MAGIC, TTY_IOC_TYPE_NXCL);
- #[test]
- fn test_ioctl_none() {
- let file = tempfile().unwrap();
- let res = unsafe { tiocnxcl(file.as_raw_fd()) };
- assert_eq!(res, Err(Sys(ENOTTY)));
- }
-
- ioctl_read!(tiocgeta, TTY_IOC_MAGIC, TTY_IOC_TYPE_GETA, termios);
- #[test]
- fn test_ioctl_read() {
- let file = tempfile().unwrap();
- let mut termios = unsafe { mem::zeroed() };
- let res = unsafe { tiocgeta(file.as_raw_fd(), &mut termios) };
- assert_eq!(res, Err(Sys(ENOTTY)));
- }
-
- ioctl_write_ptr!(tiocseta, TTY_IOC_MAGIC, TTY_IOC_TYPE_SETA, termios);
- #[test]
- fn test_ioctl_write_ptr() {
- let file = tempfile().unwrap();
- let termios: termios = unsafe { mem::zeroed() };
- let res = unsafe { tiocseta(file.as_raw_fd(), &termios) };
- assert_eq!(res, Err(Sys(ENOTTY)));
- }
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_lio_listio_resubmit.rs b/vendor/nix-0.20.0/test/sys/test_lio_listio_resubmit.rs
deleted file mode 100644
index 0795370..0000000
--- a/vendor/nix-0.20.0/test/sys/test_lio_listio_resubmit.rs
+++ /dev/null
@@ -1,107 +0,0 @@
-// vim: tw=80
-
-// Annoyingly, Cargo is unable to conditionally build an entire test binary. So
-// we must disable the test here rather than in Cargo.toml
-#![cfg(target_os = "freebsd")]
-
-use nix::Error;
-use nix::errno::*;
-use nix::libc::off_t;
-use nix::sys::aio::*;
-use nix::sys::signal::SigevNotify;
-use nix::unistd::{SysconfVar, sysconf};
-use std::os::unix::io::AsRawFd;
-use std::{thread, time};
-use sysctl::CtlValue;
-use tempfile::tempfile;
-
-const BYTES_PER_OP: usize = 512;
-
-/// Attempt to collect final status for all of `liocb`'s operations, freeing
-/// system resources
-fn finish_liocb(liocb: &mut LioCb) {
- for j in 0..liocb.aiocbs.len() {
- loop {
- let e = liocb.error(j);
- match e {
- Ok(()) => break,
- Err(Error::Sys(Errno::EINPROGRESS)) =>
- thread::sleep(time::Duration::from_millis(10)),
- Err(x) => panic!("aio_error({:?})", x)
- }
- }
- assert_eq!(liocb.aio_return(j).unwrap(), BYTES_PER_OP as isize);
- }
-}
-
-// Deliberately exceed system resource limits, causing lio_listio to return EIO.
-// This test must run in its own process since it deliberately uses all AIO
-// resources. ATM it is only enabled on FreeBSD, because I don't know how to
-// check system AIO limits on other operating systems.
-#[test]
-fn test_lio_listio_resubmit() {
- let mut resubmit_count = 0;
-
- // Lookup system resource limits
- let alm = sysconf(SysconfVar::AIO_LISTIO_MAX)
- .expect("sysconf").unwrap() as usize;
- let maqpp = if let CtlValue::Int(x) = sysctl::value(
- "vfs.aio.max_aio_queue_per_proc").unwrap(){
- x as usize
- } else {
- panic!("unknown sysctl");
- };
-
- // Find lio_listio sizes that satisfy the AIO_LISTIO_MAX constraint and also
- // result in a final lio_listio call that can only partially be queued
- let target_ops = maqpp + alm / 2;
- let num_listios = (target_ops + alm - 3) / (alm - 2);
- let ops_per_listio = (target_ops + num_listios - 1) / num_listios;
- assert!((num_listios - 1) * ops_per_listio < maqpp,
- "the last lio_listio won't make any progress; fix the algorithm");
- println!("Using {:?} LioCbs of {:?} operations apiece", num_listios,
- ops_per_listio);
-
- let f = tempfile().unwrap();
- let buffer_set = (0..num_listios).map(|_| {
- (0..ops_per_listio).map(|_| {
- vec![0u8; BYTES_PER_OP]
- }).collect::<Vec<_>>()
- }).collect::<Vec<_>>();
-
- let mut liocbs = (0..num_listios).map(|i| {
- let mut liocb = LioCb::with_capacity(ops_per_listio);
- for j in 0..ops_per_listio {
- let offset = (BYTES_PER_OP * (i * ops_per_listio + j)) as off_t;
- let wcb = AioCb::from_slice( f.as_raw_fd(),
- offset,
- &buffer_set[i][j][..],
- 0, //priority
- SigevNotify::SigevNone,
- LioOpcode::LIO_WRITE);
- liocb.aiocbs.push(wcb);
- }
- let mut err = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone);
- while err == Err(Error::Sys(Errno::EIO)) ||
- err == Err(Error::Sys(Errno::EAGAIN)) ||
- err == Err(Error::Sys(Errno::EINTR)) {
- //
- thread::sleep(time::Duration::from_millis(10));
- resubmit_count += 1;
- err = liocb.listio_resubmit(LioMode::LIO_NOWAIT,
- SigevNotify::SigevNone);
- }
- liocb
- }).collect::<Vec<_>>();
-
- // Ensure that every AioCb completed
- for liocb in liocbs.iter_mut() {
- finish_liocb(liocb);
- }
-
- if resubmit_count > 0 {
- println!("Resubmitted {:?} times, test passed", resubmit_count);
- } else {
- println!("Never resubmitted. Test ambiguous");
- }
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_mman.rs b/vendor/nix-0.20.0/test/sys/test_mman.rs
deleted file mode 100644
index 152fff6..0000000
--- a/vendor/nix-0.20.0/test/sys/test_mman.rs
+++ /dev/null
@@ -1,80 +0,0 @@
-use nix::Error;
-use nix::libc::{c_void, size_t};
-use nix::sys::mman::{mmap, MapFlags, ProtFlags};
-
-#[cfg(target_os = "linux")]
-use nix::sys::mman::{mremap, MRemapFlags};
-
-#[test]
-fn test_mmap_anonymous() {
- let ref mut byte = unsafe {
- let ptr = mmap(std::ptr::null_mut(), 1,
- ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
- MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS, -1, 0)
- .unwrap();
- *(ptr as * mut u8)
- };
- assert_eq !(*byte, 0x00u8);
- *byte = 0xffu8;
- assert_eq !(*byte, 0xffu8);
-}
-
-#[test]
-#[cfg(target_os = "linux")]
-fn test_mremap_grow() {
- const ONE_K : size_t = 1024;
- let slice : &mut[u8] = unsafe {
- let mem = mmap(std::ptr::null_mut(), ONE_K,
- ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
- MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE, -1, 0)
- .unwrap();
- std::slice::from_raw_parts_mut(mem as * mut u8, ONE_K)
- };
- assert_eq !(slice[ONE_K - 1], 0x00);
- slice[ONE_K - 1] = 0xFF;
- assert_eq !(slice[ONE_K - 1], 0xFF);
-
- let slice : &mut[u8] = unsafe {
- let mem = mremap(slice.as_mut_ptr() as * mut c_void, ONE_K, 10 * ONE_K,
- MRemapFlags::MREMAP_MAYMOVE, None)
- .unwrap();
- std::slice::from_raw_parts_mut(mem as * mut u8, 10 * ONE_K)
- };
-
- // The first KB should still have the old data in it.
- assert_eq !(slice[ONE_K - 1], 0xFF);
-
- // The additional range should be zero-init'd and accessible.
- assert_eq !(slice[10 * ONE_K - 1], 0x00);
- slice[10 * ONE_K - 1] = 0xFF;
- assert_eq !(slice[10 * ONE_K - 1], 0xFF);
-}
-
-#[test]
-#[cfg(target_os = "linux")]
-fn test_mremap_shrink() {
- const ONE_K : size_t = 1024;
- let slice : &mut[u8] = unsafe {
- let mem = mmap(std::ptr::null_mut(), 10 * ONE_K,
- ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
- MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE, -1, 0)
- .unwrap();
- std::slice::from_raw_parts_mut(mem as * mut u8, ONE_K)
- };
- assert_eq !(slice[ONE_K - 1], 0x00);
- slice[ONE_K - 1] = 0xFF;
- assert_eq !(slice[ONE_K - 1], 0xFF);
-
- let slice : &mut[u8] = unsafe {
- let mem = mremap(slice.as_mut_ptr() as * mut c_void, 10 * ONE_K, ONE_K,
- MRemapFlags::empty(), None)
- .unwrap();
- // Since we didn't supply MREMAP_MAYMOVE, the address should be the
- // same.
- assert_eq !(mem, slice.as_mut_ptr() as * mut c_void);
- std::slice::from_raw_parts_mut(mem as * mut u8, ONE_K)
- };
-
- // The first KB should still be accessible and have the old data in it.
- assert_eq !(slice[ONE_K - 1], 0xFF);
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_pthread.rs b/vendor/nix-0.20.0/test/sys/test_pthread.rs
deleted file mode 100644
index 1fc3dd9..0000000
--- a/vendor/nix-0.20.0/test/sys/test_pthread.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-use nix::sys::pthread::*;
-
-#[cfg(any(target_env = "musl", target_os = "redox"))]
-#[test]
-fn test_pthread_self() {
- let tid = pthread_self();
- assert!(tid != ::std::ptr::null_mut());
-}
-
-#[cfg(not(any(target_env = "musl", target_os = "redox")))]
-#[test]
-fn test_pthread_self() {
- let tid = pthread_self();
- assert!(tid != 0);
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_ptrace.rs b/vendor/nix-0.20.0/test/sys/test_ptrace.rs
deleted file mode 100644
index b9793b3..0000000
--- a/vendor/nix-0.20.0/test/sys/test_ptrace.rs
+++ /dev/null
@@ -1,178 +0,0 @@
-use nix::Error;
-use nix::errno::Errno;
-use nix::unistd::getpid;
-use nix::sys::ptrace;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-use nix::sys::ptrace::Options;
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-use std::mem;
-
-use crate::*;
-
-#[test]
-fn test_ptrace() {
- // Just make sure ptrace can be called at all, for now.
- // FIXME: qemu-user doesn't implement ptrace on all arches, so permit ENOSYS
- require_capability!(CAP_SYS_PTRACE);
- let err = ptrace::attach(getpid()).unwrap_err();
- assert!(err == Error::Sys(Errno::EPERM) || err == Error::Sys(Errno::EINVAL) ||
- err == Error::Sys(Errno::ENOSYS));
-}
-
-// Just make sure ptrace_setoptions can be called at all, for now.
-#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
-fn test_ptrace_setoptions() {
- require_capability!(CAP_SYS_PTRACE);
- let err = ptrace::setoptions(getpid(), Options::PTRACE_O_TRACESYSGOOD).unwrap_err();
- assert!(err != Error::UnsupportedOperation);
-}
-
-// Just make sure ptrace_getevent can be called at all, for now.
-#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
-fn test_ptrace_getevent() {
- require_capability!(CAP_SYS_PTRACE);
- let err = ptrace::getevent(getpid()).unwrap_err();
- assert!(err != Error::UnsupportedOperation);
-}
-
-// Just make sure ptrace_getsiginfo can be called at all, for now.
-#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
-fn test_ptrace_getsiginfo() {
- require_capability!(CAP_SYS_PTRACE);
- if let Err(Error::UnsupportedOperation) = ptrace::getsiginfo(getpid()) {
- panic!("ptrace_getsiginfo returns Error::UnsupportedOperation!");
- }
-}
-
-// Just make sure ptrace_setsiginfo can be called at all, for now.
-#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
-fn test_ptrace_setsiginfo() {
- require_capability!(CAP_SYS_PTRACE);
- let siginfo = unsafe { mem::zeroed() };
- if let Err(Error::UnsupportedOperation) = ptrace::setsiginfo(getpid(), &siginfo) {
- panic!("ptrace_setsiginfo returns Error::UnsupportedOperation!");
- }
-}
-
-
-#[test]
-fn test_ptrace_cont() {
- use nix::sys::ptrace;
- use nix::sys::signal::{raise, Signal};
- use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus};
- use nix::unistd::fork;
- use nix::unistd::ForkResult::*;
-
- require_capability!(CAP_SYS_PTRACE);
-
- let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-
- // FIXME: qemu-user doesn't implement ptrace on all architectures
- // and retunrs ENOSYS in this case.
- // We (ab)use this behavior to detect the affected platforms
- // and skip the test then.
- // On valid platforms the ptrace call should return Errno::EPERM, this
- // is already tested by `test_ptrace`.
- let err = ptrace::attach(getpid()).unwrap_err();
- if err == Error::Sys(Errno::ENOSYS) {
- return;
- }
-
- match unsafe{fork()}.expect("Error: Fork Failed") {
- Child => {
- ptrace::traceme().unwrap();
- // As recommended by ptrace(2), raise SIGTRAP to pause the child
- // until the parent is ready to continue
- loop {
- raise(Signal::SIGTRAP).unwrap();
- }
-
- },
- Parent { child } => {
- assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTRAP)));
- ptrace::cont(child, None).unwrap();
- assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTRAP)));
- ptrace::cont(child, Some(Signal::SIGKILL)).unwrap();
- match waitpid(child, None) {
- Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) if pid == child => {
- // FIXME It's been observed on some systems (apple) the
- // tracee may not be killed but remain as a zombie process
- // affecting other wait based tests. Add an extra kill just
- // to make sure there are no zombies.
- let _ = waitpid(child, Some(WaitPidFlag::WNOHANG));
- while ptrace::cont(child, Some(Signal::SIGKILL)).is_ok() {
- let _ = waitpid(child, Some(WaitPidFlag::WNOHANG));
- }
- }
- _ => panic!("The process should have been killed"),
- }
- },
- }
-}
-
-// ptrace::{setoptions, getregs} are only available in these platforms
-#[cfg(all(target_os = "linux",
- any(target_arch = "x86_64",
- target_arch = "x86"),
- target_env = "gnu"))]
-#[test]
-fn test_ptrace_syscall() {
- use nix::sys::signal::kill;
- use nix::sys::ptrace;
- use nix::sys::signal::Signal;
- use nix::sys::wait::{waitpid, WaitStatus};
- use nix::unistd::fork;
- use nix::unistd::getpid;
- use nix::unistd::ForkResult::*;
-
- require_capability!(CAP_SYS_PTRACE);
-
- let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-
- match unsafe{fork()}.expect("Error: Fork Failed") {
- Child => {
- ptrace::traceme().unwrap();
- // first sigstop until parent is ready to continue
- let pid = getpid();
- kill(pid, Signal::SIGSTOP).unwrap();
- kill(pid, Signal::SIGTERM).unwrap();
- unsafe { ::libc::_exit(0); }
- },
-
- Parent { child } => {
- assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGSTOP)));
-
- // set this option to recognize syscall-stops
- ptrace::setoptions(child, ptrace::Options::PTRACE_O_TRACESYSGOOD).unwrap();
-
- #[cfg(target_arch = "x86_64")]
- let get_syscall_id = || ptrace::getregs(child).unwrap().orig_rax as libc::c_long;
-
- #[cfg(target_arch = "x86")]
- let get_syscall_id = || ptrace::getregs(child).unwrap().orig_eax as libc::c_long;
-
- // kill entry
- ptrace::syscall(child, None).unwrap();
- assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
- assert_eq!(get_syscall_id(), ::libc::SYS_kill);
-
- // kill exit
- ptrace::syscall(child, None).unwrap();
- assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
- assert_eq!(get_syscall_id(), ::libc::SYS_kill);
-
- // receive signal
- ptrace::syscall(child, None).unwrap();
- assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTERM)));
-
- // inject signal
- ptrace::syscall(child, Signal::SIGTERM).unwrap();
- assert_eq!(waitpid(child, None), Ok(WaitStatus::Signaled(child, Signal::SIGTERM, false)));
- },
- }
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_select.rs b/vendor/nix-0.20.0/test/sys/test_select.rs
deleted file mode 100644
index 3795108..0000000
--- a/vendor/nix-0.20.0/test/sys/test_select.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-use nix::sys::select::*;
-use nix::unistd::{pipe, write};
-use nix::sys::signal::SigSet;
-use nix::sys::time::{TimeSpec, TimeValLike};
-
-#[test]
-pub fn test_pselect() {
- let _mtx = crate::SIGNAL_MTX
- .lock()
- .expect("Mutex got poisoned by another test");
-
- let (r1, w1) = pipe().unwrap();
- write(w1, b"hi!").unwrap();
- let (r2, _w2) = pipe().unwrap();
-
- let mut fd_set = FdSet::new();
- fd_set.insert(r1);
- fd_set.insert(r2);
-
- let timeout = TimeSpec::seconds(10);
- let sigmask = SigSet::empty();
- assert_eq!(
- 1,
- pselect(None, &mut fd_set, None, None, &timeout, &sigmask).unwrap()
- );
- assert!(fd_set.contains(r1));
- assert!(!fd_set.contains(r2));
-}
-
-#[test]
-pub fn test_pselect_nfds2() {
- let (r1, w1) = pipe().unwrap();
- write(w1, b"hi!").unwrap();
- let (r2, _w2) = pipe().unwrap();
-
- let mut fd_set = FdSet::new();
- fd_set.insert(r1);
- fd_set.insert(r2);
-
- let timeout = TimeSpec::seconds(10);
- assert_eq!(
- 1,
- pselect(
- ::std::cmp::max(r1, r2) + 1,
- &mut fd_set,
- None,
- None,
- &timeout,
- None
- ).unwrap()
- );
- assert!(fd_set.contains(r1));
- assert!(!fd_set.contains(r2));
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_signal.rs b/vendor/nix-0.20.0/test/sys/test_signal.rs
deleted file mode 100644
index ae22527..0000000
--- a/vendor/nix-0.20.0/test/sys/test_signal.rs
+++ /dev/null
@@ -1,115 +0,0 @@
-use libc;
-#[cfg(not(target_os = "redox"))]
-use nix::Error;
-use nix::sys::signal::*;
-use nix::unistd::*;
-use std::convert::TryFrom;
-use std::sync::atomic::{AtomicBool, Ordering};
-
-#[test]
-fn test_kill_none() {
- kill(getpid(), None).expect("Should be able to send signal to myself.");
-}
-
-#[test]
-#[cfg(not(target_os = "fuchsia"))]
-fn test_killpg_none() {
- killpg(getpgrp(), None)
- .expect("Should be able to send signal to my process group.");
-}
-
-#[test]
-fn test_old_sigaction_flags() {
- let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-
- extern "C" fn handler(_: ::libc::c_int) {}
- let act = SigAction::new(
- SigHandler::Handler(handler),
- SaFlags::empty(),
- SigSet::empty(),
- );
- let oact = unsafe { sigaction(SIGINT, &act) }.unwrap();
- let _flags = oact.flags();
- let oact = unsafe { sigaction(SIGINT, &act) }.unwrap();
- let _flags = oact.flags();
-}
-
-#[test]
-fn test_sigprocmask_noop() {
- sigprocmask(SigmaskHow::SIG_BLOCK, None, None)
- .expect("this should be an effective noop");
-}
-
-#[test]
-fn test_sigprocmask() {
- let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-
- // This needs to be a signal that rust doesn't use in the test harness.
- const SIGNAL: Signal = Signal::SIGCHLD;
-
- let mut old_signal_set = SigSet::empty();
- sigprocmask(SigmaskHow::SIG_BLOCK, None, Some(&mut old_signal_set))
- .expect("expect to be able to retrieve old signals");
-
- // Make sure the old set doesn't contain the signal, otherwise the following
- // test don't make sense.
- assert_eq!(old_signal_set.contains(SIGNAL), false,
- "the {:?} signal is already blocked, please change to a \
- different one", SIGNAL);
-
- // Now block the signal.
- let mut signal_set = SigSet::empty();
- signal_set.add(SIGNAL);
- sigprocmask(SigmaskHow::SIG_BLOCK, Some(&signal_set), None)
- .expect("expect to be able to block signals");
-
- // And test it again, to make sure the change was effective.
- old_signal_set.clear();
- sigprocmask(SigmaskHow::SIG_BLOCK, None, Some(&mut old_signal_set))
- .expect("expect to be able to retrieve old signals");
- assert_eq!(old_signal_set.contains(SIGNAL), true,
- "expected the {:?} to be blocked", SIGNAL);
-
- // Reset the signal.
- sigprocmask(SigmaskHow::SIG_UNBLOCK, Some(&signal_set), None)
- .expect("expect to be able to block signals");
-}
-
-lazy_static! {
- static ref SIGNALED: AtomicBool = AtomicBool::new(false);
-}
-
-extern fn test_sigaction_handler(signal: libc::c_int) {
- let signal = Signal::try_from(signal).unwrap();
- SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed);
-}
-
-#[cfg(not(target_os = "redox"))]
-extern fn test_sigaction_action(_: libc::c_int, _: *mut libc::siginfo_t, _: *mut libc::c_void) {}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_signal_sigaction() {
- let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-
- let action_handler = SigHandler::SigAction(test_sigaction_action);
- assert_eq!(unsafe { signal(Signal::SIGINT, action_handler) }.unwrap_err(), Error::UnsupportedOperation);
-}
-
-#[test]
-fn test_signal() {
- let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-
- unsafe { signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap();
- raise(Signal::SIGINT).unwrap();
- assert_eq!(unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), SigHandler::SigIgn);
-
- let handler = SigHandler::Handler(test_sigaction_handler);
- assert_eq!(unsafe { signal(Signal::SIGINT, handler) }.unwrap(), SigHandler::SigDfl);
- raise(Signal::SIGINT).unwrap();
- assert!(SIGNALED.load(Ordering::Relaxed));
- assert_eq!(unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), handler);
-
- // Restore default signal handler
- unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap();
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_signalfd.rs b/vendor/nix-0.20.0/test/sys/test_signalfd.rs
deleted file mode 100644
index af04c22..0000000
--- a/vendor/nix-0.20.0/test/sys/test_signalfd.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-use std::convert::TryFrom;
-
-#[test]
-fn test_signalfd() {
- use nix::sys::signalfd::SignalFd;
- use nix::sys::signal::{self, raise, Signal, SigSet};
-
- // Grab the mutex for altering signals so we don't interfere with other tests.
- let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-
- // Block the SIGUSR1 signal from automatic processing for this thread
- let mut mask = SigSet::empty();
- mask.add(signal::SIGUSR1);
- mask.thread_block().unwrap();
-
- let mut fd = SignalFd::new(&mask).unwrap();
-
- // Send a SIGUSR1 signal to the current process. Note that this uses `raise` instead of `kill`
- // because `kill` with `getpid` isn't correct during multi-threaded execution like during a
- // cargo test session. Instead use `raise` which does the correct thing by default.
- raise(signal::SIGUSR1).expect("Error: raise(SIGUSR1) failed");
-
- // And now catch that same signal.
- let res = fd.read_signal().unwrap().unwrap();
- let signo = Signal::try_from(res.ssi_signo as i32).unwrap();
- assert_eq!(signo, signal::SIGUSR1);
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_socket.rs b/vendor/nix-0.20.0/test/sys/test_socket.rs
deleted file mode 100644
index 7eab28c..0000000
--- a/vendor/nix-0.20.0/test/sys/test_socket.rs
+++ /dev/null
@@ -1,1543 +0,0 @@
-use nix::sys::socket::{AddressFamily, InetAddr, UnixAddr, getsockname};
-use std::collections::hash_map::DefaultHasher;
-use std::hash::{Hash, Hasher};
-use std::net::{self, Ipv6Addr, SocketAddr, SocketAddrV6};
-use std::os::unix::io::RawFd;
-use std::path::Path;
-use std::slice;
-use std::str::FromStr;
-use libc::c_char;
-use tempfile;
-#[cfg(any(target_os = "linux", target_os= "android"))]
-use crate::*;
-
-#[test]
-pub fn test_inetv4_addr_to_sock_addr() {
- let actual: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap();
- let addr = InetAddr::from_std(&actual);
-
- match addr {
- InetAddr::V4(addr) => {
- let ip: u32 = 0x7f00_0001;
- let port: u16 = 3000;
- let saddr = addr.sin_addr.s_addr;
-
- assert_eq!(saddr, ip.to_be());
- assert_eq!(addr.sin_port, port.to_be());
- }
- _ => panic!("nope"),
- }
-
- assert_eq!(addr.to_str(), "127.0.0.1:3000");
-
- let inet = addr.to_std();
- assert_eq!(actual, inet);
-}
-
-#[test]
-pub fn test_inetv6_addr_to_sock_addr() {
- let port: u16 = 3000;
- let flowinfo: u32 = 1;
- let scope_id: u32 = 2;
- let ip: Ipv6Addr = "fe80::1".parse().unwrap();
-
- let actual = SocketAddr::V6(SocketAddrV6::new(ip, port, flowinfo, scope_id));
- let addr = InetAddr::from_std(&actual);
-
- match addr {
- InetAddr::V6(addr) => {
- assert_eq!(addr.sin6_port, port.to_be());
- assert_eq!(addr.sin6_flowinfo, flowinfo);
- assert_eq!(addr.sin6_scope_id, scope_id);
- }
- _ => panic!("nope"),
- }
-
- assert_eq!(actual, addr.to_std());
-}
-
-#[test]
-pub fn test_path_to_sock_addr() {
- let path = "/foo/bar";
- let actual = Path::new(path);
- let addr = UnixAddr::new(actual).unwrap();
-
- let expect: &[c_char] = unsafe {
- slice::from_raw_parts(path.as_bytes().as_ptr() as *const c_char, path.len())
- };
- assert_eq!(&addr.0.sun_path[..8], expect);
-
- assert_eq!(addr.path(), Some(actual));
-}
-
-fn calculate_hash<T: Hash>(t: &T) -> u64 {
- let mut s = DefaultHasher::new();
- t.hash(&mut s);
- s.finish()
-}
-
-#[test]
-pub fn test_addr_equality_path() {
- let path = "/foo/bar";
- let actual = Path::new(path);
- let addr1 = UnixAddr::new(actual).unwrap();
- let mut addr2 = addr1.clone();
-
- addr2.0.sun_path[10] = 127;
-
- assert_eq!(addr1, addr2);
- assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[test]
-pub fn test_abstract_sun_path_too_long() {
- let name = String::from("nix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0testttttnix\0abstract\0test\0make\0sure\0this\0is\0long\0enough");
- let addr = UnixAddr::new_abstract(name.as_bytes());
- assert!(addr.is_err());
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[test]
-pub fn test_addr_equality_abstract() {
- let name = String::from("nix\0abstract\0test");
- let addr1 = UnixAddr::new_abstract(name.as_bytes()).unwrap();
- let mut addr2 = addr1.clone();
-
- assert_eq!(addr1, addr2);
- assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));
-
- addr2.0.sun_path[17] = 127;
- assert_ne!(addr1, addr2);
- assert_ne!(calculate_hash(&addr1), calculate_hash(&addr2));
-}
-
-// Test getting/setting abstract addresses (without unix socket creation)
-#[cfg(target_os = "linux")]
-#[test]
-pub fn test_abstract_uds_addr() {
- let empty = String::new();
- let addr = UnixAddr::new_abstract(empty.as_bytes()).unwrap();
- let sun_path: [u8; 0] = [];
- assert_eq!(addr.as_abstract(), Some(&sun_path[..]));
-
- let name = String::from("nix\0abstract\0test");
- let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
- let sun_path = [
- 110u8, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116
- ];
- assert_eq!(addr.as_abstract(), Some(&sun_path[..]));
- assert_eq!(addr.path(), None);
-
- // Internally, name is null-prefixed (abstract namespace)
- assert_eq!(addr.0.sun_path[0], 0);
-}
-
-#[test]
-pub fn test_getsockname() {
- use nix::sys::socket::{socket, AddressFamily, SockType, SockFlag};
- use nix::sys::socket::{bind, SockAddr};
-
- let tempdir = tempfile::tempdir().unwrap();
- let sockname = tempdir.path().join("sock");
- let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
- .expect("socket failed");
- let sockaddr = SockAddr::new_unix(&sockname).unwrap();
- bind(sock, &sockaddr).expect("bind failed");
- assert_eq!(sockaddr.to_str(),
- getsockname(sock).expect("getsockname failed").to_str());
-}
-
-#[test]
-pub fn test_socketpair() {
- use nix::unistd::{read, write};
- use nix::sys::socket::{socketpair, AddressFamily, SockType, SockFlag};
-
- let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
- .unwrap();
- write(fd1, b"hello").unwrap();
- let mut buf = [0;5];
- read(fd2, &mut buf).unwrap();
-
- assert_eq!(&buf[..], b"hello");
-}
-
-mod recvfrom {
- use nix::Result;
- use nix::sys::socket::*;
- use std::thread;
- use super::*;
-
- const MSG: &'static [u8] = b"Hello, World!";
-
- fn sendrecv<Fs, Fr>(rsock: RawFd, ssock: RawFd, f_send: Fs, mut f_recv: Fr) -> Option<SockAddr>
- where
- Fs: Fn(RawFd, &[u8], MsgFlags) -> Result<usize> + Send + 'static,
- Fr: FnMut(usize, Option<SockAddr>),
- {
- let mut buf: [u8; 13] = [0u8; 13];
- let mut l = 0;
- let mut from = None;
-
- let send_thread = thread::spawn(move || {
- let mut l = 0;
- while l < std::mem::size_of_val(MSG) {
- l += f_send(ssock, &MSG[l..], MsgFlags::empty()).unwrap();
- }
- });
-
- while l < std::mem::size_of_val(MSG) {
- let (len, from_) = recvfrom(rsock, &mut buf[l..]).unwrap();
- f_recv(len, from_);
- from = from_;
- l += len;
- }
- assert_eq!(&buf, MSG);
- send_thread.join().unwrap();
- from
- }
-
- #[test]
- pub fn stream() {
- let (fd2, fd1) = socketpair(AddressFamily::Unix, SockType::Stream,
- None, SockFlag::empty()).unwrap();
- // Ignore from for stream sockets
- let _ = sendrecv(fd1, fd2, |s, m, flags| {
- send(s, m, flags)
- }, |_, _| {});
- }
-
- #[test]
- pub fn udp() {
- let std_sa = SocketAddr::from_str("127.0.0.1:6789").unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- let sock_addr = SockAddr::new_inet(inet_addr);
- let rsock = socket(AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None
- ).unwrap();
- bind(rsock, &sock_addr).unwrap();
- let ssock = socket(
- AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None,
- ).expect("send socket failed");
- let from = sendrecv(rsock, ssock, move |s, m, flags| {
- sendto(s, m, &sock_addr, flags)
- },|_, _| {});
- // UDP sockets should set the from address
- assert_eq!(AddressFamily::Inet, from.unwrap().family());
- }
-
- #[cfg(target_os = "linux")]
- mod udp_offload {
- use super::*;
- use nix::sys::uio::IoVec;
- use nix::sys::socket::sockopt::{UdpGroSegment, UdpGsoSegment};
-
- #[test]
- // Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU
- // support is suspected.
- #[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
- pub fn gso() {
- require_kernel_version!(udp_offload::gso, ">= 4.18");
-
- // In this test, we send the data and provide a GSO segment size.
- // Since we are sending the buffer of size 13, six UDP packets
- // with size 2 and two UDP packet with size 1 will be sent.
- let segment_size: u16 = 2;
-
- let std_sa = SocketAddr::from_str("127.0.0.1:6791").unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- let sock_addr = SockAddr::new_inet(inet_addr);
- let rsock = socket(AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None
- ).unwrap();
-
- setsockopt(rsock, UdpGsoSegment, &(segment_size as _))
- .expect("setsockopt UDP_SEGMENT failed");
-
- bind(rsock, &sock_addr).unwrap();
- let ssock = socket(
- AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None,
- ).expect("send socket failed");
-
- let mut num_packets_received: i32 = 0;
-
- sendrecv(rsock, ssock, move |s, m, flags| {
- let iov = [IoVec::from_slice(m)];
- let cmsg = ControlMessage::UdpGsoSegments(&segment_size);
- sendmsg(s, &iov, &[cmsg], flags, Some(&sock_addr))
- }, {
- let num_packets_received_ref = &mut num_packets_received;
-
- move |len, _| {
- // check that we receive UDP packets with payload size
- // less or equal to segment size
- assert!(len <= segment_size as usize);
- *num_packets_received_ref += 1;
- }
- });
-
- // Buffer size is 13, we will receive six packets of size 2,
- // and one packet of size 1.
- assert_eq!(7, num_packets_received);
- }
-
- #[test]
- // Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU
- // support is suspected.
- #[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
- pub fn gro() {
- require_kernel_version!(udp_offload::gro, ">= 5.3");
-
- // It's hard to guarantee receiving GRO packets. Just checking
- // that `setsockopt` doesn't fail with error
-
- let rsock = socket(AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None
- ).unwrap();
-
- setsockopt(rsock, UdpGroSegment, &true)
- .expect("setsockopt UDP_GRO failed");
- }
- }
-
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
- ))]
- #[test]
- pub fn udp_sendmmsg() {
- use nix::sys::uio::IoVec;
-
- let std_sa = SocketAddr::from_str("127.0.0.1:6793").unwrap();
- let std_sa2 = SocketAddr::from_str("127.0.0.1:6794").unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- let inet_addr2 = InetAddr::from_std(&std_sa2);
- let sock_addr = SockAddr::new_inet(inet_addr);
- let sock_addr2 = SockAddr::new_inet(inet_addr2);
-
- let rsock = socket(AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None
- ).unwrap();
- bind(rsock, &sock_addr).unwrap();
- let ssock = socket(
- AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None,
- ).expect("send socket failed");
-
- let from = sendrecv(rsock, ssock, move |s, m, flags| {
- let iov = [IoVec::from_slice(m)];
- let mut msgs = Vec::new();
- msgs.push(
- SendMmsgData {
- iov: &iov,
- cmsgs: &[],
- addr: Some(sock_addr),
- _lt: Default::default(),
- });
-
- let batch_size = 15;
-
- for _ in 0..batch_size {
- msgs.push(
- SendMmsgData {
- iov: &iov,
- cmsgs: &[],
- addr: Some(sock_addr2),
- _lt: Default::default(),
- }
- );
- }
- sendmmsg(s, msgs.iter(), flags)
- .map(move |sent_bytes| {
- assert!(sent_bytes.len() >= 1);
- for sent in &sent_bytes {
- assert_eq!(*sent, m.len());
- }
- sent_bytes.len()
- })
- }, |_, _ | {});
- // UDP sockets should set the from address
- assert_eq!(AddressFamily::Inet, from.unwrap().family());
- }
-
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
- ))]
- #[test]
- pub fn udp_recvmmsg() {
- use nix::sys::uio::IoVec;
- use nix::sys::socket::{MsgFlags, recvmmsg};
-
- const NUM_MESSAGES_SENT: usize = 2;
- const DATA: [u8; 2] = [1,2];
-
- let std_sa = SocketAddr::from_str("127.0.0.1:6798").unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- let sock_addr = SockAddr::new_inet(inet_addr);
-
- let rsock = socket(AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None
- ).unwrap();
- bind(rsock, &sock_addr).unwrap();
- let ssock = socket(
- AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None,
- ).expect("send socket failed");
-
- let send_thread = thread::spawn(move || {
- for _ in 0..NUM_MESSAGES_SENT {
- sendto(ssock, &DATA[..], &sock_addr, MsgFlags::empty()).unwrap();
- }
- });
-
- let mut msgs = std::collections::LinkedList::new();
-
- // Buffers to receive exactly `NUM_MESSAGES_SENT` messages
- let mut receive_buffers = [[0u8; 32]; NUM_MESSAGES_SENT];
- let iovs: Vec<_> = receive_buffers.iter_mut().map(|buf| {
- [IoVec::from_mut_slice(&mut buf[..])]
- }).collect();
-
- for iov in &iovs {
- msgs.push_back(RecvMmsgData {
- iov: iov,
- cmsg_buffer: None,
- })
- };
-
- let res = recvmmsg(rsock, &mut msgs, MsgFlags::empty(), None).expect("recvmmsg");
- assert_eq!(res.len(), DATA.len());
-
- for RecvMsg { address, bytes, .. } in res.into_iter() {
- assert_eq!(AddressFamily::Inet, address.unwrap().family());
- assert_eq!(DATA.len(), bytes);
- }
-
- for buf in &receive_buffers {
- assert_eq!(&buf[..DATA.len()], DATA);
- }
-
- send_thread.join().unwrap();
- }
-
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
- ))]
- #[test]
- pub fn udp_recvmmsg_dontwait_short_read() {
- use nix::sys::uio::IoVec;
- use nix::sys::socket::{MsgFlags, recvmmsg};
-
- const NUM_MESSAGES_SENT: usize = 2;
- const DATA: [u8; 4] = [1,2,3,4];
-
- let std_sa = SocketAddr::from_str("127.0.0.1:6799").unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- let sock_addr = SockAddr::new_inet(inet_addr);
-
- let rsock = socket(AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None
- ).unwrap();
- bind(rsock, &sock_addr).unwrap();
- let ssock = socket(
- AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None,
- ).expect("send socket failed");
-
- let send_thread = thread::spawn(move || {
- for _ in 0..NUM_MESSAGES_SENT {
- sendto(ssock, &DATA[..], &sock_addr, MsgFlags::empty()).unwrap();
- }
- });
- // Ensure we've sent all the messages before continuing so `recvmmsg`
- // will return right away
- send_thread.join().unwrap();
-
- let mut msgs = std::collections::LinkedList::new();
-
- // Buffers to receive >`NUM_MESSAGES_SENT` messages to ensure `recvmmsg`
- // will return when there are fewer than requested messages in the
- // kernel buffers when using `MSG_DONTWAIT`.
- let mut receive_buffers = [[0u8; 32]; NUM_MESSAGES_SENT + 2];
- let iovs: Vec<_> = receive_buffers.iter_mut().map(|buf| {
- [IoVec::from_mut_slice(&mut buf[..])]
- }).collect();
-
- for iov in &iovs {
- msgs.push_back(RecvMmsgData {
- iov: iov,
- cmsg_buffer: None,
- })
- };
-
- let res = recvmmsg(rsock, &mut msgs, MsgFlags::MSG_DONTWAIT, None).expect("recvmmsg");
- assert_eq!(res.len(), NUM_MESSAGES_SENT);
-
- for RecvMsg { address, bytes, .. } in res.into_iter() {
- assert_eq!(AddressFamily::Inet, address.unwrap().family());
- assert_eq!(DATA.len(), bytes);
- }
-
- for buf in &receive_buffers[..NUM_MESSAGES_SENT] {
- assert_eq!(&buf[..DATA.len()], DATA);
- }
- }
-}
-
-// Test error handling of our recvmsg wrapper
-#[test]
-pub fn test_recvmsg_ebadf() {
- use nix::Error;
- use nix::errno::Errno;
- use nix::sys::socket::{MsgFlags, recvmsg};
- use nix::sys::uio::IoVec;
-
- let mut buf = [0u8; 5];
- let iov = [IoVec::from_mut_slice(&mut buf[..])];
- let fd = -1; // Bad file descriptor
- let r = recvmsg(fd, &iov, None, MsgFlags::empty());
- assert_eq!(r.err().unwrap(), Error::Sys(Errno::EBADF));
-}
-
-// Disable the test on emulated platforms due to a bug in QEMU versions <
-// 2.12.0. https://bugs.launchpad.net/qemu/+bug/1701808
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
-#[test]
-pub fn test_scm_rights() {
- use nix::sys::uio::IoVec;
- use nix::unistd::{pipe, read, write, close};
- use nix::sys::socket::{socketpair, sendmsg, recvmsg,
- AddressFamily, SockType, SockFlag,
- ControlMessage, ControlMessageOwned, MsgFlags};
-
- let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
- .unwrap();
- let (r, w) = pipe().unwrap();
- let mut received_r: Option<RawFd> = None;
-
- {
- let iov = [IoVec::from_slice(b"hello")];
- let fds = [r];
- let cmsg = ControlMessage::ScmRights(&fds);
- assert_eq!(sendmsg(fd1, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5);
- close(r).unwrap();
- close(fd1).unwrap();
- }
-
- {
- let mut buf = [0u8; 5];
- let iov = [IoVec::from_mut_slice(&mut buf[..])];
- let mut cmsgspace = cmsg_space!([RawFd; 1]);
- let msg = recvmsg(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
-
- for cmsg in msg.cmsgs() {
- if let ControlMessageOwned::ScmRights(fd) = cmsg {
- assert_eq!(received_r, None);
- assert_eq!(fd.len(), 1);
- received_r = Some(fd[0]);
- } else {
- panic!("unexpected cmsg");
- }
- }
- assert_eq!(msg.bytes, 5);
- assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
- close(fd2).unwrap();
- }
-
- let received_r = received_r.expect("Did not receive passed fd");
- // Ensure that the received file descriptor works
- write(w, b"world").unwrap();
- let mut buf = [0u8; 5];
- read(received_r, &mut buf).unwrap();
- assert_eq!(&buf[..], b"world");
- close(received_r).unwrap();
- close(w).unwrap();
-}
-
-// Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "i686")), ignore)]
-#[cfg(any(target_os = "linux", target_os= "android"))]
-#[test]
-pub fn test_af_alg_cipher() {
- use libc;
- use nix::sys::uio::IoVec;
- use nix::unistd::read;
- use nix::sys::socket::{socket, sendmsg, bind, accept, setsockopt,
- AddressFamily, SockType, SockFlag, SockAddr,
- ControlMessage, MsgFlags};
- use nix::sys::socket::sockopt::AlgSetKey;
-
- skip_if_cirrus!("Fails for an unknown reason Cirrus CI. Bug #1352");
- // Travis's seccomp profile blocks AF_ALG
- // https://docs.docker.com/engine/security/seccomp/
- skip_if_seccomp!(test_af_alg_cipher);
-
- let alg_type = "skcipher";
- let alg_name = "ctr-aes-aesni";
- // 256-bits secret key
- let key = vec![0u8; 32];
- // 16-bytes IV
- let iv_len = 16;
- let iv = vec![1u8; iv_len];
- // 256-bytes plain payload
- let payload_len = 256;
- let payload = vec![2u8; payload_len];
-
- let sock = socket(AddressFamily::Alg, SockType::SeqPacket, SockFlag::empty(), None)
- .expect("socket failed");
-
- let sockaddr = SockAddr::new_alg(alg_type, alg_name);
- bind(sock, &sockaddr).expect("bind failed");
-
- if let SockAddr::Alg(alg) = sockaddr {
- assert_eq!(alg.alg_name().to_string_lossy(), alg_name);
- assert_eq!(alg.alg_type().to_string_lossy(), alg_type);
- } else {
- panic!("unexpected SockAddr");
- }
-
- setsockopt(sock, AlgSetKey::default(), &key).expect("setsockopt");
- let session_socket = accept(sock).expect("accept failed");
-
- let msgs = [ControlMessage::AlgSetOp(&libc::ALG_OP_ENCRYPT), ControlMessage::AlgSetIv(iv.as_slice())];
- let iov = IoVec::from_slice(&payload);
- sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg encrypt");
-
- // allocate buffer for encrypted data
- let mut encrypted = vec![0u8; payload_len];
- let num_bytes = read(session_socket, &mut encrypted).expect("read encrypt");
- assert_eq!(num_bytes, payload_len);
-
- let iov = IoVec::from_slice(&encrypted);
-
- let iv = vec![1u8; iv_len];
-
- let msgs = [ControlMessage::AlgSetOp(&libc::ALG_OP_DECRYPT), ControlMessage::AlgSetIv(iv.as_slice())];
- sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg decrypt");
-
- // allocate buffer for decrypted data
- let mut decrypted = vec![0u8; payload_len];
- let num_bytes = read(session_socket, &mut decrypted).expect("read decrypt");
-
- assert_eq!(num_bytes, payload_len);
- assert_eq!(decrypted, payload);
-}
-
-// Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "i686")), ignore)]
-#[cfg(any(target_os = "linux", target_os= "android"))]
-#[test]
-pub fn test_af_alg_aead() {
- use libc::{ALG_OP_DECRYPT, ALG_OP_ENCRYPT};
- use nix::sys::uio::IoVec;
- use nix::unistd::{read, close};
- use nix::sys::socket::{socket, sendmsg, bind, accept, setsockopt,
- AddressFamily, SockType, SockFlag, SockAddr,
- ControlMessage, MsgFlags};
- use nix::sys::socket::sockopt::{AlgSetKey, AlgSetAeadAuthSize};
-
- skip_if_cirrus!("Fails for an unknown reason Cirrus CI. Bug #1352");
- // Travis's seccomp profile blocks AF_ALG
- // https://docs.docker.com/engine/security/seccomp/
- skip_if_seccomp!(test_af_alg_aead);
-
- let auth_size = 4usize;
- let assoc_size = 16u32;
-
- let alg_type = "aead";
- let alg_name = "gcm(aes)";
- // 256-bits secret key
- let key = vec![0u8; 32];
- // 12-bytes IV
- let iv_len = 12;
- let iv = vec![1u8; iv_len];
- // 256-bytes plain payload
- let payload_len = 256;
- let mut payload = vec![2u8; payload_len + (assoc_size as usize) + auth_size];
-
- for i in 0..assoc_size {
- payload[i as usize] = 10;
- }
-
- let len = payload.len();
-
- for i in 0..auth_size {
- payload[len - 1 - i] = 0;
- }
-
- let sock = socket(AddressFamily::Alg, SockType::SeqPacket, SockFlag::empty(), None)
- .expect("socket failed");
-
- let sockaddr = SockAddr::new_alg(alg_type, alg_name);
- bind(sock, &sockaddr).expect("bind failed");
-
- setsockopt(sock, AlgSetAeadAuthSize, &auth_size).expect("setsockopt AlgSetAeadAuthSize");
- setsockopt(sock, AlgSetKey::default(), &key).expect("setsockopt AlgSetKey");
- let session_socket = accept(sock).expect("accept failed");
-
- let msgs = [
- ControlMessage::AlgSetOp(&ALG_OP_ENCRYPT),
- ControlMessage::AlgSetIv(iv.as_slice()),
- ControlMessage::AlgSetAeadAssoclen(&assoc_size)];
- let iov = IoVec::from_slice(&payload);
- sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg encrypt");
-
- // allocate buffer for encrypted data
- let mut encrypted = vec![0u8; (assoc_size as usize) + payload_len + auth_size];
- let num_bytes = read(session_socket, &mut encrypted).expect("read encrypt");
- assert_eq!(num_bytes, payload_len + auth_size + (assoc_size as usize));
- close(session_socket).expect("close");
-
- for i in 0..assoc_size {
- encrypted[i as usize] = 10;
- }
-
- let iov = IoVec::from_slice(&encrypted);
-
- let iv = vec![1u8; iv_len];
-
- let session_socket = accept(sock).expect("accept failed");
-
- let msgs = [
- ControlMessage::AlgSetOp(&ALG_OP_DECRYPT),
- ControlMessage::AlgSetIv(iv.as_slice()),
- ControlMessage::AlgSetAeadAssoclen(&assoc_size),
- ];
- sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg decrypt");
-
- // allocate buffer for decrypted data
- let mut decrypted = vec![0u8; payload_len + (assoc_size as usize) + auth_size];
- let num_bytes = read(session_socket, &mut decrypted).expect("read decrypt");
-
- assert!(num_bytes >= payload_len + (assoc_size as usize));
- assert_eq!(decrypted[(assoc_size as usize)..(payload_len + (assoc_size as usize))], payload[(assoc_size as usize)..payload_len + (assoc_size as usize)]);
-}
-
-// Verify `ControlMessage::Ipv4PacketInfo` for `sendmsg`.
-// This creates a (udp) socket bound to localhost, then sends a message to
-// itself but uses Ipv4PacketInfo to force the source address to be localhost.
-//
-// This would be a more interesting test if we could assume that the test host
-// has more than one IP address (since we could select a different address to
-// test from).
-#[cfg(any(target_os = "linux",
- target_os = "macos",
- target_os = "netbsd"))]
-#[test]
-pub fn test_sendmsg_ipv4packetinfo() {
- use nix::sys::uio::IoVec;
- use nix::sys::socket::{socket, sendmsg, bind,
- AddressFamily, SockType, SockFlag, SockAddr,
- ControlMessage, MsgFlags};
-
- let sock = socket(AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None)
- .expect("socket failed");
-
- let std_sa = SocketAddr::from_str("127.0.0.1:4000").unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- let sock_addr = SockAddr::new_inet(inet_addr);
-
- bind(sock, &sock_addr).expect("bind failed");
-
- let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
- let iov = [IoVec::from_slice(&slice)];
-
- if let InetAddr::V4(sin) = inet_addr {
- let pi = libc::in_pktinfo {
- ipi_ifindex: 0, /* Unspecified interface */
- ipi_addr: libc::in_addr { s_addr: 0 },
- ipi_spec_dst: sin.sin_addr,
- };
-
- let cmsg = [ControlMessage::Ipv4PacketInfo(&pi)];
-
- sendmsg(sock, &iov, &cmsg, MsgFlags::empty(), Some(&sock_addr))
- .expect("sendmsg");
- } else {
- panic!("No IPv4 addresses available for testing?");
- }
-}
-
-// Verify `ControlMessage::Ipv6PacketInfo` for `sendmsg`.
-// This creates a (udp) socket bound to ip6-localhost, then sends a message to
-// itself but uses Ipv6PacketInfo to force the source address to be
-// ip6-localhost.
-//
-// This would be a more interesting test if we could assume that the test host
-// has more than one IP address (since we could select a different address to
-// test from).
-#[cfg(any(target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "freebsd"))]
-#[test]
-pub fn test_sendmsg_ipv6packetinfo() {
- use nix::Error;
- use nix::errno::Errno;
- use nix::sys::uio::IoVec;
- use nix::sys::socket::{socket, sendmsg, bind,
- AddressFamily, SockType, SockFlag, SockAddr,
- ControlMessage, MsgFlags};
-
- let sock = socket(AddressFamily::Inet6,
- SockType::Datagram,
- SockFlag::empty(),
- None)
- .expect("socket failed");
-
- let std_sa = SocketAddr::from_str("[::1]:6000").unwrap();
- let inet_addr = InetAddr::from_std(&std_sa);
- let sock_addr = SockAddr::new_inet(inet_addr);
-
- match bind(sock, &sock_addr) {
- Err(Error::Sys(Errno::EADDRNOTAVAIL)) => {
- println!("IPv6 not available, skipping test.");
- return;
- },
- _ => (),
- }
-
- let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
- let iov = [IoVec::from_slice(&slice)];
-
- if let InetAddr::V6(sin) = inet_addr {
- let pi = libc::in6_pktinfo {
- ipi6_ifindex: 0, /* Unspecified interface */
- ipi6_addr: sin.sin6_addr,
- };
-
- let cmsg = [ControlMessage::Ipv6PacketInfo(&pi)];
-
- sendmsg(sock, &iov, &cmsg, MsgFlags::empty(), Some(&sock_addr))
- .expect("sendmsg");
- } else {
- println!("No IPv6 addresses available for testing: skipping testing Ipv6PacketInfo");
- }
-}
-
-/// Tests that passing multiple fds using a single `ControlMessage` works.
-// Disable the test on emulated platforms due to a bug in QEMU versions <
-// 2.12.0. https://bugs.launchpad.net/qemu/+bug/1701808
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
-#[test]
-fn test_scm_rights_single_cmsg_multiple_fds() {
- use std::os::unix::net::UnixDatagram;
- use std::os::unix::io::{RawFd, AsRawFd};
- use std::thread;
- use nix::sys::socket::{ControlMessage, ControlMessageOwned, MsgFlags,
- sendmsg, recvmsg};
- use nix::sys::uio::IoVec;
- use libc;
-
- let (send, receive) = UnixDatagram::pair().unwrap();
- let thread = thread::spawn(move || {
- let mut buf = [0u8; 8];
- let iovec = [IoVec::from_mut_slice(&mut buf)];
- let mut space = cmsg_space!([RawFd; 2]);
- let msg = recvmsg(
- receive.as_raw_fd(),
- &iovec,
- Some(&mut space),
- MsgFlags::empty()
- ).unwrap();
- assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
-
- let mut cmsgs = msg.cmsgs();
- match cmsgs.next() {
- Some(ControlMessageOwned::ScmRights(fds)) => {
- assert_eq!(fds.len(), 2,
- "unexpected fd count (expected 2 fds, got {})",
- fds.len());
- },
- _ => panic!(),
- }
- assert!(cmsgs.next().is_none(), "unexpected control msg");
-
- assert_eq!(msg.bytes, 8);
- assert_eq!(iovec[0].as_slice(), [1u8, 2, 3, 4, 5, 6, 7, 8]);
- });
-
- let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
- let iov = [IoVec::from_slice(&slice)];
- let fds = [libc::STDIN_FILENO, libc::STDOUT_FILENO]; // pass stdin and stdout
- let cmsg = [ControlMessage::ScmRights(&fds)];
- sendmsg(send.as_raw_fd(), &iov, &cmsg, MsgFlags::empty(), None).unwrap();
- thread.join().unwrap();
-}
-
-// Verify `sendmsg` builds a valid `msghdr` when passing an empty
-// `cmsgs` argument. This should result in a msghdr with a nullptr
-// msg_control field and a msg_controllen of 0 when calling into the
-// raw `sendmsg`.
-#[test]
-pub fn test_sendmsg_empty_cmsgs() {
- use nix::sys::uio::IoVec;
- use nix::unistd::close;
- use nix::sys::socket::{socketpair, sendmsg, recvmsg,
- AddressFamily, SockType, SockFlag, MsgFlags};
-
- let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
- .unwrap();
-
- {
- let iov = [IoVec::from_slice(b"hello")];
- assert_eq!(sendmsg(fd1, &iov, &[], MsgFlags::empty(), None).unwrap(), 5);
- close(fd1).unwrap();
- }
-
- {
- let mut buf = [0u8; 5];
- let iov = [IoVec::from_mut_slice(&mut buf[..])];
- let mut cmsgspace = cmsg_space!([RawFd; 1]);
- let msg = recvmsg(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
-
- for _ in msg.cmsgs() {
- panic!("unexpected cmsg");
- }
- assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
- assert_eq!(msg.bytes, 5);
- close(fd2).unwrap();
- }
-}
-
-#[cfg(any(
- target_os = "android",
- target_os = "linux",
- target_os = "freebsd",
- target_os = "dragonfly",
-))]
-#[test]
-fn test_scm_credentials() {
- use nix::sys::uio::IoVec;
- use nix::unistd::{close, getpid, getuid, getgid};
- use nix::sys::socket::{socketpair, sendmsg, recvmsg,
- AddressFamily, SockType, SockFlag,
- ControlMessage, ControlMessageOwned, MsgFlags,
- UnixCredentials};
- #[cfg(any(target_os = "android", target_os = "linux"))]
- use nix::sys::socket::{setsockopt, sockopt::PassCred};
-
- let (send, recv) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
- .unwrap();
- #[cfg(any(target_os = "android", target_os = "linux"))]
- setsockopt(recv, PassCred, &true).unwrap();
-
- {
- let iov = [IoVec::from_slice(b"hello")];
- #[cfg(any(target_os = "android", target_os = "linux"))]
- let cred = UnixCredentials::new();
- #[cfg(any(target_os = "android", target_os = "linux"))]
- let cmsg = ControlMessage::ScmCredentials(&cred);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- let cmsg = ControlMessage::ScmCreds;
- assert_eq!(sendmsg(send, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5);
- close(send).unwrap();
- }
-
- {
- let mut buf = [0u8; 5];
- let iov = [IoVec::from_mut_slice(&mut buf[..])];
- let mut cmsgspace = cmsg_space!(UnixCredentials);
- let msg = recvmsg(recv, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
- let mut received_cred = None;
-
- for cmsg in msg.cmsgs() {
- let cred = match cmsg {
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessageOwned::ScmCredentials(cred) => cred,
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- ControlMessageOwned::ScmCreds(cred) => cred,
- other => panic!("unexpected cmsg {:?}", other),
- };
- assert!(received_cred.is_none());
- assert_eq!(cred.pid(), getpid().as_raw());
- assert_eq!(cred.uid(), getuid().as_raw());
- assert_eq!(cred.gid(), getgid().as_raw());
- received_cred = Some(cred);
- }
- received_cred.expect("no creds received");
- assert_eq!(msg.bytes, 5);
- assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
- close(recv).unwrap();
- }
-}
-
-/// Ensure that we can send `SCM_CREDENTIALS` and `SCM_RIGHTS` with a single
-/// `sendmsg` call.
-#[cfg(any(target_os = "android", target_os = "linux"))]
-// qemu's handling of multiple cmsgs is bugged, ignore tests on non-x86
-// see https://bugs.launchpad.net/qemu/+bug/1781280
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "x86")), ignore)]
-#[test]
-fn test_scm_credentials_and_rights() {
- use libc;
-
- let space = cmsg_space!(libc::ucred, RawFd);
- test_impl_scm_credentials_and_rights(space);
-}
-
-/// Ensure that passing a an oversized control message buffer to recvmsg
-/// still works.
-#[cfg(any(target_os = "android", target_os = "linux"))]
-// qemu's handling of multiple cmsgs is bugged, ignore tests on non-x86
-// see https://bugs.launchpad.net/qemu/+bug/1781280
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "x86")), ignore)]
-#[test]
-fn test_too_large_cmsgspace() {
- let space = vec![0u8; 1024];
- test_impl_scm_credentials_and_rights(space);
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
- use libc::ucred;
- use nix::sys::uio::IoVec;
- use nix::unistd::{pipe, write, close, getpid, getuid, getgid};
- use nix::sys::socket::{socketpair, sendmsg, recvmsg, setsockopt,
- SockType, SockFlag,
- ControlMessage, ControlMessageOwned, MsgFlags};
- use nix::sys::socket::sockopt::PassCred;
-
- let (send, recv) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
- .unwrap();
- setsockopt(recv, PassCred, &true).unwrap();
-
- let (r, w) = pipe().unwrap();
- let mut received_r: Option<RawFd> = None;
-
- {
- let iov = [IoVec::from_slice(b"hello")];
- let cred = ucred {
- pid: getpid().as_raw(),
- uid: getuid().as_raw(),
- gid: getgid().as_raw(),
- }.into();
- let fds = [r];
- let cmsgs = [
- ControlMessage::ScmCredentials(&cred),
- ControlMessage::ScmRights(&fds),
- ];
- assert_eq!(sendmsg(send, &iov, &cmsgs, MsgFlags::empty(), None).unwrap(), 5);
- close(r).unwrap();
- close(send).unwrap();
- }
-
- {
- let mut buf = [0u8; 5];
- let iov = [IoVec::from_mut_slice(&mut buf[..])];
- let msg = recvmsg(recv, &iov, Some(&mut space), MsgFlags::empty()).unwrap();
- let mut received_cred = None;
-
- assert_eq!(msg.cmsgs().count(), 2, "expected 2 cmsgs");
-
- for cmsg in msg.cmsgs() {
- match cmsg {
- ControlMessageOwned::ScmRights(fds) => {
- assert_eq!(received_r, None, "already received fd");
- assert_eq!(fds.len(), 1);
- received_r = Some(fds[0]);
- }
- ControlMessageOwned::ScmCredentials(cred) => {
- assert!(received_cred.is_none());
- assert_eq!(cred.pid(), getpid().as_raw());
- assert_eq!(cred.uid(), getuid().as_raw());
- assert_eq!(cred.gid(), getgid().as_raw());
- received_cred = Some(cred);
- }
- _ => panic!("unexpected cmsg"),
- }
- }
- received_cred.expect("no creds received");
- assert_eq!(msg.bytes, 5);
- assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
- close(recv).unwrap();
- }
-
- let received_r = received_r.expect("Did not receive passed fd");
- // Ensure that the received file descriptor works
- write(w, b"world").unwrap();
- let mut buf = [0u8; 5];
- read(received_r, &mut buf).unwrap();
- assert_eq!(&buf[..], b"world");
- close(received_r).unwrap();
- close(w).unwrap();
-}
-
-// Test creating and using named unix domain sockets
-#[test]
-pub fn test_unixdomain() {
- use nix::sys::socket::{SockType, SockFlag};
- use nix::sys::socket::{bind, socket, connect, listen, accept, SockAddr};
- use nix::unistd::{read, write, close};
- use std::thread;
-
- let tempdir = tempfile::tempdir().unwrap();
- let sockname = tempdir.path().join("sock");
- let s1 = socket(AddressFamily::Unix, SockType::Stream,
- SockFlag::empty(), None).expect("socket failed");
- let sockaddr = SockAddr::new_unix(&sockname).unwrap();
- bind(s1, &sockaddr).expect("bind failed");
- listen(s1, 10).expect("listen failed");
-
- let thr = thread::spawn(move || {
- let s2 = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
- .expect("socket failed");
- connect(s2, &sockaddr).expect("connect failed");
- write(s2, b"hello").expect("write failed");
- close(s2).unwrap();
- });
-
- let s3 = accept(s1).expect("accept failed");
-
- let mut buf = [0;5];
- read(s3, &mut buf).unwrap();
- close(s3).unwrap();
- close(s1).unwrap();
- thr.join().unwrap();
-
- assert_eq!(&buf[..], b"hello");
-}
-
-// Test creating and using named system control sockets
-#[cfg(any(target_os = "macos", target_os = "ios"))]
-#[test]
-pub fn test_syscontrol() {
- use nix::Error;
- use nix::errno::Errno;
- use nix::sys::socket::{socket, SockAddr, SockType, SockFlag, SockProtocol};
-
- let fd = socket(AddressFamily::System, SockType::Datagram,
- SockFlag::empty(), SockProtocol::KextControl)
- .expect("socket failed");
- let _sockaddr = SockAddr::new_sys_control(fd, "com.apple.net.utun_control", 0).expect("resolving sys_control name failed");
- assert_eq!(SockAddr::new_sys_control(fd, "foo.bar.lol", 0).err(), Some(Error::Sys(Errno::ENOENT)));
-
- // requires root privileges
- // connect(fd, &sockaddr).expect("connect failed");
-}
-
-#[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
-))]
-fn loopback_address(family: AddressFamily) -> Option<nix::ifaddrs::InterfaceAddress> {
- use std::io;
- use std::io::Write;
- use nix::ifaddrs::getifaddrs;
- use nix::sys::socket::SockAddr;
- use nix::net::if_::*;
-
- let addrs = match getifaddrs() {
- Ok(iter) => iter,
- Err(e) => {
- let stdioerr = io::stderr();
- let mut handle = stdioerr.lock();
- writeln!(handle, "getifaddrs: {:?}", e).unwrap();
- return None;
- },
- };
- // return first address matching family
- for ifaddr in addrs {
- if ifaddr.flags.contains(InterfaceFlags::IFF_LOOPBACK) {
- match ifaddr.address {
- Some(SockAddr::Inet(InetAddr::V4(..))) => {
- match family {
- AddressFamily::Inet => return Some(ifaddr),
- _ => continue
- }
- },
- Some(SockAddr::Inet(InetAddr::V6(..))) => {
- match family {
- AddressFamily::Inet6 => return Some(ifaddr),
- _ => continue
- }
- },
- _ => continue,
- }
- }
- }
- None
-}
-
-#[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
-))]
-// qemu doesn't seem to be emulating this correctly in these architectures
-#[cfg_attr(any(
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "powerpc64",
-), ignore)]
-#[test]
-pub fn test_recv_ipv4pktinfo() {
- use libc;
- use nix::sys::socket::sockopt::Ipv4PacketInfo;
- use nix::sys::socket::{bind, SockFlag, SockType};
- use nix::sys::socket::{getsockname, setsockopt, socket};
- use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
- use nix::sys::uio::IoVec;
- use nix::net::if_::*;
-
- let lo_ifaddr = loopback_address(AddressFamily::Inet);
- let (lo_name, lo) = match lo_ifaddr {
- Some(ifaddr) => (ifaddr.interface_name,
- ifaddr.address.expect("Expect IPv4 address on interface")),
- None => return,
- };
- let receive = socket(
- AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None,
- ).expect("receive socket failed");
- bind(receive, &lo).expect("bind failed");
- let sa = getsockname(receive).expect("getsockname failed");
- setsockopt(receive, Ipv4PacketInfo, &true).expect("setsockopt failed");
-
- {
- let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
- let iov = [IoVec::from_slice(&slice)];
-
- let send = socket(
- AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None,
- ).expect("send socket failed");
- sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)).expect("sendmsg failed");
- }
-
- {
- let mut buf = [0u8; 8];
- let iovec = [IoVec::from_mut_slice(&mut buf)];
- let mut space = cmsg_space!(libc::in_pktinfo);
- let msg = recvmsg(
- receive,
- &iovec,
- Some(&mut space),
- MsgFlags::empty(),
- ).expect("recvmsg failed");
- assert!(
- !msg.flags
- .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)
- );
-
- let mut cmsgs = msg.cmsgs();
- match cmsgs.next() {
- Some(ControlMessageOwned::Ipv4PacketInfo(pktinfo)) => {
- let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
- assert_eq!(
- pktinfo.ipi_ifindex as libc::c_uint,
- i,
- "unexpected ifindex (expected {}, got {})",
- i,
- pktinfo.ipi_ifindex
- );
- }
- _ => (),
- }
- assert!(cmsgs.next().is_none(), "unexpected additional control msg");
- assert_eq!(msg.bytes, 8);
- assert_eq!(
- iovec[0].as_slice(),
- [1u8, 2, 3, 4, 5, 6, 7, 8]
- );
- }
-}
-
-#[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
-))]
-// qemu doesn't seem to be emulating this correctly in these architectures
-#[cfg_attr(any(
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "powerpc64",
-), ignore)]
-#[test]
-pub fn test_recvif() {
- use libc;
- use nix::net::if_::*;
- use nix::sys::socket::sockopt::{Ipv4RecvIf, Ipv4RecvDstAddr};
- use nix::sys::socket::{bind, SockFlag, SockType};
- use nix::sys::socket::{getsockname, setsockopt, socket, SockAddr};
- use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
- use nix::sys::uio::IoVec;
-
- let lo_ifaddr = loopback_address(AddressFamily::Inet);
- let (lo_name, lo) = match lo_ifaddr {
- Some(ifaddr) => (ifaddr.interface_name,
- ifaddr.address.expect("Expect IPv4 address on interface")),
- None => return,
- };
- let receive = socket(
- AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None,
- ).expect("receive socket failed");
- bind(receive, &lo).expect("bind failed");
- let sa = getsockname(receive).expect("getsockname failed");
- setsockopt(receive, Ipv4RecvIf, &true).expect("setsockopt IP_RECVIF failed");
- setsockopt(receive, Ipv4RecvDstAddr, &true).expect("setsockopt IP_RECVDSTADDR failed");
-
- {
- let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
- let iov = [IoVec::from_slice(&slice)];
-
- let send = socket(
- AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None,
- ).expect("send socket failed");
- sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)).expect("sendmsg failed");
- }
-
- {
- let mut buf = [0u8; 8];
- let iovec = [IoVec::from_mut_slice(&mut buf)];
- let mut space = cmsg_space!(libc::sockaddr_dl, libc::in_addr);
- let msg = recvmsg(
- receive,
- &iovec,
- Some(&mut space),
- MsgFlags::empty(),
- ).expect("recvmsg failed");
- assert!(
- !msg.flags
- .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)
- );
- assert_eq!(msg.cmsgs().count(), 2, "expected 2 cmsgs");
-
- let mut rx_recvif = false;
- let mut rx_recvdstaddr = false;
- for cmsg in msg.cmsgs() {
- match cmsg {
- ControlMessageOwned::Ipv4RecvIf(dl) => {
- rx_recvif = true;
- let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
- assert_eq!(
- dl.sdl_index as libc::c_uint,
- i,
- "unexpected ifindex (expected {}, got {})",
- i,
- dl.sdl_index
- );
- },
- ControlMessageOwned::Ipv4RecvDstAddr(addr) => {
- rx_recvdstaddr = true;
- if let SockAddr::Inet(InetAddr::V4(a)) = lo {
- assert_eq!(a.sin_addr.s_addr,
- addr.s_addr,
- "unexpected destination address (expected {}, got {})",
- a.sin_addr.s_addr,
- addr.s_addr);
- } else {
- panic!("unexpected Sockaddr");
- }
- },
- _ => panic!("unexpected additional control msg"),
- }
- }
- assert_eq!(rx_recvif, true);
- assert_eq!(rx_recvdstaddr, true);
- assert_eq!(msg.bytes, 8);
- assert_eq!(
- iovec[0].as_slice(),
- [1u8, 2, 3, 4, 5, 6, 7, 8]
- );
- }
-}
-
-#[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
-))]
-// qemu doesn't seem to be emulating this correctly in these architectures
-#[cfg_attr(any(
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "powerpc64",
-), ignore)]
-#[test]
-pub fn test_recv_ipv6pktinfo() {
- use libc;
- use nix::net::if_::*;
- use nix::sys::socket::sockopt::Ipv6RecvPacketInfo;
- use nix::sys::socket::{bind, SockFlag, SockType};
- use nix::sys::socket::{getsockname, setsockopt, socket};
- use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
- use nix::sys::uio::IoVec;
-
- let lo_ifaddr = loopback_address(AddressFamily::Inet6);
- let (lo_name, lo) = match lo_ifaddr {
- Some(ifaddr) => (ifaddr.interface_name,
- ifaddr.address.expect("Expect IPv4 address on interface")),
- None => return,
- };
- let receive = socket(
- AddressFamily::Inet6,
- SockType::Datagram,
- SockFlag::empty(),
- None,
- ).expect("receive socket failed");
- bind(receive, &lo).expect("bind failed");
- let sa = getsockname(receive).expect("getsockname failed");
- setsockopt(receive, Ipv6RecvPacketInfo, &true).expect("setsockopt failed");
-
- {
- let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
- let iov = [IoVec::from_slice(&slice)];
-
- let send = socket(
- AddressFamily::Inet6,
- SockType::Datagram,
- SockFlag::empty(),
- None,
- ).expect("send socket failed");
- sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)).expect("sendmsg failed");
- }
-
- {
- let mut buf = [0u8; 8];
- let iovec = [IoVec::from_mut_slice(&mut buf)];
- let mut space = cmsg_space!(libc::in6_pktinfo);
- let msg = recvmsg(
- receive,
- &iovec,
- Some(&mut space),
- MsgFlags::empty(),
- ).expect("recvmsg failed");
- assert!(
- !msg.flags
- .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)
- );
-
- let mut cmsgs = msg.cmsgs();
- match cmsgs.next() {
- Some(ControlMessageOwned::Ipv6PacketInfo(pktinfo)) => {
- let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
- assert_eq!(
- pktinfo.ipi6_ifindex,
- i,
- "unexpected ifindex (expected {}, got {})",
- i,
- pktinfo.ipi6_ifindex
- );
- }
- _ => (),
- }
- assert!(cmsgs.next().is_none(), "unexpected additional control msg");
- assert_eq!(msg.bytes, 8);
- assert_eq!(
- iovec[0].as_slice(),
- [1u8, 2, 3, 4, 5, 6, 7, 8]
- );
- }
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[test]
-pub fn test_vsock() {
- use libc;
- use nix::Error;
- use nix::errno::Errno;
- use nix::sys::socket::{AddressFamily, socket, bind, connect, listen,
- SockAddr, SockType, SockFlag};
- use nix::unistd::{close};
- use std::thread;
-
- let port: u32 = 3000;
-
- let s1 = socket(AddressFamily::Vsock, SockType::Stream,
- SockFlag::empty(), None)
- .expect("socket failed");
-
- // VMADDR_CID_HYPERVISOR and VMADDR_CID_LOCAL are reserved, so we expect
- // an EADDRNOTAVAIL error.
- let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_HYPERVISOR, port);
- assert_eq!(bind(s1, &sockaddr).err(),
- Some(Error::Sys(Errno::EADDRNOTAVAIL)));
-
- let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_LOCAL, port);
- assert_eq!(bind(s1, &sockaddr).err(),
- Some(Error::Sys(Errno::EADDRNOTAVAIL)));
-
-
- let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_ANY, port);
- assert_eq!(bind(s1, &sockaddr), Ok(()));
- listen(s1, 10).expect("listen failed");
-
- let thr = thread::spawn(move || {
- let cid: u32 = libc::VMADDR_CID_HOST;
-
- let s2 = socket(AddressFamily::Vsock, SockType::Stream,
- SockFlag::empty(), None)
- .expect("socket failed");
-
- let sockaddr = SockAddr::new_vsock(cid, port);
-
- // The current implementation does not support loopback devices, so,
- // for now, we expect a failure on the connect.
- assert_ne!(connect(s2, &sockaddr), Ok(()));
-
- close(s2).unwrap();
- });
-
- close(s1).unwrap();
- thr.join().unwrap();
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_sockopt.rs b/vendor/nix-0.20.0/test/sys/test_sockopt.rs
deleted file mode 100644
index 5606593..0000000
--- a/vendor/nix-0.20.0/test/sys/test_sockopt.rs
+++ /dev/null
@@ -1,96 +0,0 @@
-use rand::{thread_rng, Rng};
-use nix::sys::socket::{socket, sockopt, getsockopt, setsockopt, AddressFamily, SockType, SockFlag, SockProtocol};
-#[cfg(any(target_os = "android", target_os = "linux"))]
-use crate::*;
-
-#[cfg(target_os = "linux")]
-#[test]
-fn is_so_mark_functional() {
- use nix::sys::socket::sockopt;
-
- require_capability!(CAP_NET_ADMIN);
-
- let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
- setsockopt(s, sockopt::Mark, &1337).unwrap();
- let mark = getsockopt(s, sockopt::Mark).unwrap();
- assert_eq!(mark, 1337);
-}
-
-#[test]
-fn test_so_buf() {
- let fd = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), SockProtocol::Udp)
- .unwrap();
- let bufsize: usize = thread_rng().gen_range(4096, 131_072);
- setsockopt(fd, sockopt::SndBuf, &bufsize).unwrap();
- let actual = getsockopt(fd, sockopt::SndBuf).unwrap();
- assert!(actual >= bufsize);
- setsockopt(fd, sockopt::RcvBuf, &bufsize).unwrap();
- let actual = getsockopt(fd, sockopt::RcvBuf).unwrap();
- assert!(actual >= bufsize);
-}
-
-// The CI doesn't supported getsockopt and setsockopt on emulated processors.
-// It's beleived that a QEMU issue, the tests run ok on a fully emulated system.
-// Current CI just run the binary with QEMU but the Kernel remains the same as the host.
-// So the syscall doesn't work properly unless the kernel is also emulated.
-#[test]
-#[cfg(all(
- any(target_arch = "x86", target_arch = "x86_64"),
- any(target_os = "freebsd", target_os = "linux")
-))]
-fn test_tcp_congestion() {
- use std::ffi::OsString;
-
- let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
-
- let val = getsockopt(fd, sockopt::TcpCongestion).unwrap();
- setsockopt(fd, sockopt::TcpCongestion, &val).unwrap();
-
- setsockopt(fd, sockopt::TcpCongestion, &OsString::from("tcp_congestion_does_not_exist")).unwrap_err();
-
- assert_eq!(
- getsockopt(fd, sockopt::TcpCongestion).unwrap(),
- val
- );
-}
-
-#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
-fn test_bindtodevice() {
- skip_if_not_root!("test_bindtodevice");
-
- let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
-
- let val = getsockopt(fd, sockopt::BindToDevice).unwrap();
- setsockopt(fd, sockopt::BindToDevice, &val).unwrap();
-
- assert_eq!(
- getsockopt(fd, sockopt::BindToDevice).unwrap(),
- val
- );
-}
-
-#[test]
-fn test_so_tcp_keepalive() {
- let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), SockProtocol::Tcp).unwrap();
- setsockopt(fd, sockopt::KeepAlive, &true).unwrap();
- assert_eq!(getsockopt(fd, sockopt::KeepAlive).unwrap(), true);
-
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "nacl"))] {
- let x = getsockopt(fd, sockopt::TcpKeepIdle).unwrap();
- setsockopt(fd, sockopt::TcpKeepIdle, &(x + 1)).unwrap();
- assert_eq!(getsockopt(fd, sockopt::TcpKeepIdle).unwrap(), x + 1);
-
- let x = getsockopt(fd, sockopt::TcpKeepCount).unwrap();
- setsockopt(fd, sockopt::TcpKeepCount, &(x + 1)).unwrap();
- assert_eq!(getsockopt(fd, sockopt::TcpKeepCount).unwrap(), x + 1);
-
- let x = getsockopt(fd, sockopt::TcpKeepInterval).unwrap();
- setsockopt(fd, sockopt::TcpKeepInterval, &(x + 1)).unwrap();
- assert_eq!(getsockopt(fd, sockopt::TcpKeepInterval).unwrap(), x + 1);
- }
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_sysinfo.rs b/vendor/nix-0.20.0/test/sys/test_sysinfo.rs
deleted file mode 100644
index 73e6586..0000000
--- a/vendor/nix-0.20.0/test/sys/test_sysinfo.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-use nix::sys::sysinfo::*;
-
-#[test]
-fn sysinfo_works() {
- let info = sysinfo().unwrap();
-
- let (l1, l5, l15) = info.load_average();
- assert!(l1 >= 0.0);
- assert!(l5 >= 0.0);
- assert!(l15 >= 0.0);
-
- info.uptime(); // just test Duration construction
-
- assert!(info.swap_free() <= info.swap_total(),
- "more swap available than installed (free: {}, total: {})",
- info.swap_free(),
- info.swap_total());
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_termios.rs b/vendor/nix-0.20.0/test/sys/test_termios.rs
deleted file mode 100644
index 00aeb2f..0000000
--- a/vendor/nix-0.20.0/test/sys/test_termios.rs
+++ /dev/null
@@ -1,130 +0,0 @@
-use std::os::unix::prelude::*;
-use tempfile::tempfile;
-
-use nix::{Error, fcntl};
-use nix::errno::Errno;
-use nix::pty::openpty;
-use nix::sys::termios::{self, LocalFlags, OutputFlags, tcgetattr};
-use nix::unistd::{read, write, close};
-
-/// Helper function analogous to `std::io::Write::write_all`, but for `RawFd`s
-fn write_all(f: RawFd, buf: &[u8]) {
- let mut len = 0;
- while len < buf.len() {
- len += write(f, &buf[len..]).unwrap();
- }
-}
-
-// Test tcgetattr on a terminal
-#[test]
-fn test_tcgetattr_pty() {
- // openpty uses ptname(3) internally
- let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-
- let pty = openpty(None, None).expect("openpty failed");
- assert!(termios::tcgetattr(pty.slave).is_ok());
- close(pty.master).expect("closing the master failed");
- close(pty.slave).expect("closing the slave failed");
-}
-
-// Test tcgetattr on something that isn't a terminal
-#[test]
-fn test_tcgetattr_enotty() {
- let file = tempfile().unwrap();
- assert_eq!(termios::tcgetattr(file.as_raw_fd()).err(),
- Some(Error::Sys(Errno::ENOTTY)));
-}
-
-// Test tcgetattr on an invalid file descriptor
-#[test]
-fn test_tcgetattr_ebadf() {
- assert_eq!(termios::tcgetattr(-1).err(),
- Some(Error::Sys(Errno::EBADF)));
-}
-
-// Test modifying output flags
-#[test]
-fn test_output_flags() {
- // openpty uses ptname(3) internally
- let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-
- // Open one pty to get attributes for the second one
- let mut termios = {
- let pty = openpty(None, None).expect("openpty failed");
- assert!(pty.master > 0);
- assert!(pty.slave > 0);
- let termios = tcgetattr(pty.slave).expect("tcgetattr failed");
- close(pty.master).unwrap();
- close(pty.slave).unwrap();
- termios
- };
-
- // Make sure postprocessing '\r' isn't specified by default or this test is useless.
- assert!(!termios.output_flags.contains(OutputFlags::OPOST | OutputFlags::OCRNL));
-
- // Specify that '\r' characters should be transformed to '\n'
- // OPOST is specified to enable post-processing
- termios.output_flags.insert(OutputFlags::OPOST | OutputFlags::OCRNL);
-
- // Open a pty
- let pty = openpty(None, &termios).unwrap();
- assert!(pty.master > 0);
- assert!(pty.slave > 0);
-
- // Write into the master
- let string = "foofoofoo\r";
- write_all(pty.master, string.as_bytes());
-
- // Read from the slave verifying that the output has been properly transformed
- let mut buf = [0u8; 10];
- crate::read_exact(pty.slave, &mut buf);
- let transformed_string = "foofoofoo\n";
- close(pty.master).unwrap();
- close(pty.slave).unwrap();
- assert_eq!(&buf, transformed_string.as_bytes());
-}
-
-// Test modifying local flags
-#[test]
-fn test_local_flags() {
- // openpty uses ptname(3) internally
- let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-
- // Open one pty to get attributes for the second one
- let mut termios = {
- let pty = openpty(None, None).unwrap();
- assert!(pty.master > 0);
- assert!(pty.slave > 0);
- let termios = tcgetattr(pty.slave).unwrap();
- close(pty.master).unwrap();
- close(pty.slave).unwrap();
- termios
- };
-
- // Make sure echo is specified by default or this test is useless.
- assert!(termios.local_flags.contains(LocalFlags::ECHO));
-
- // Disable local echo
- termios.local_flags.remove(LocalFlags::ECHO);
-
- // Open a new pty with our modified termios settings
- let pty = openpty(None, &termios).unwrap();
- assert!(pty.master > 0);
- assert!(pty.slave > 0);
-
- // Set the master is in nonblocking mode or reading will never return.
- let flags = fcntl::fcntl(pty.master, fcntl::F_GETFL).unwrap();
- let new_flags = fcntl::OFlag::from_bits_truncate(flags) | fcntl::OFlag::O_NONBLOCK;
- fcntl::fcntl(pty.master, fcntl::F_SETFL(new_flags)).unwrap();
-
- // Write into the master
- let string = "foofoofoo\r";
- write_all(pty.master, string.as_bytes());
-
- // Try to read from the master, which should not have anything as echoing was disabled.
- let mut buf = [0u8; 10];
- let read = read(pty.master, &mut buf).unwrap_err();
- close(pty.master).unwrap();
- close(pty.slave).unwrap();
- assert_eq!(read, Error::Sys(Errno::EAGAIN));
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_timerfd.rs b/vendor/nix-0.20.0/test/sys/test_timerfd.rs
deleted file mode 100644
index 24fb2ac..0000000
--- a/vendor/nix-0.20.0/test/sys/test_timerfd.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-use nix::sys::time::{TimeSpec, TimeValLike};
-use nix::sys::timerfd::{ClockId, Expiration, TimerFd, TimerFlags, TimerSetTimeFlags};
-use std::time::Instant;
-
-#[test]
-pub fn test_timerfd_oneshot() {
- let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();
-
- let before = Instant::now();
-
- timer
- .set(
- Expiration::OneShot(TimeSpec::seconds(1)),
- TimerSetTimeFlags::empty(),
- )
- .unwrap();
-
- timer.wait().unwrap();
-
- let millis = before.elapsed().as_millis();
- assert!(millis > 900);
-}
-
-#[test]
-pub fn test_timerfd_interval() {
- let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();
-
- let before = Instant::now();
- timer
- .set(
- Expiration::IntervalDelayed(TimeSpec::seconds(1), TimeSpec::seconds(2)),
- TimerSetTimeFlags::empty(),
- )
- .unwrap();
-
- timer.wait().unwrap();
-
- let start_delay = before.elapsed().as_millis();
- assert!(start_delay > 900);
-
- timer.wait().unwrap();
-
- let interval_delay = before.elapsed().as_millis();
- assert!(interval_delay > 2900);
-}
-
-#[test]
-pub fn test_timerfd_unset() {
- let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();
-
- timer
- .set(
- Expiration::OneShot(TimeSpec::seconds(1)),
- TimerSetTimeFlags::empty(),
- )
- .unwrap();
-
- timer.unset().unwrap();
-
- assert!(timer.get().unwrap() == None);
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_uio.rs b/vendor/nix-0.20.0/test/sys/test_uio.rs
deleted file mode 100644
index 8d22bf1..0000000
--- a/vendor/nix-0.20.0/test/sys/test_uio.rs
+++ /dev/null
@@ -1,247 +0,0 @@
-use nix::sys::uio::*;
-use nix::unistd::*;
-use rand::{thread_rng, Rng};
-use rand::distributions::Alphanumeric;
-use std::{cmp, iter};
-use std::fs::{OpenOptions};
-use std::os::unix::io::AsRawFd;
-
-#[cfg(not(target_os = "redox"))]
-use tempfile::tempfile;
-use tempfile::tempdir;
-
-#[test]
-fn test_writev() {
- let mut to_write = Vec::with_capacity(16 * 128);
- for _ in 0..16 {
- let s: String = thread_rng().sample_iter(&Alphanumeric).take(128).collect();
- let b = s.as_bytes();
- to_write.extend(b.iter().cloned());
- }
- // Allocate and fill iovecs
- let mut iovecs = Vec::new();
- let mut consumed = 0;
- while consumed < to_write.len() {
- let left = to_write.len() - consumed;
- let slice_len = if left <= 64 { left } else { thread_rng().gen_range(64, cmp::min(256, left)) };
- let b = &to_write[consumed..consumed+slice_len];
- iovecs.push(IoVec::from_slice(b));
- consumed += slice_len;
- }
- let pipe_res = pipe();
- assert!(pipe_res.is_ok());
- let (reader, writer) = pipe_res.ok().unwrap();
- // FileDesc will close its filedesc (reader).
- let mut read_buf: Vec<u8> = iter::repeat(0u8).take(128 * 16).collect();
- // Blocking io, should write all data.
- let write_res = writev(writer, &iovecs);
- // Successful write
- assert!(write_res.is_ok());
- let written = write_res.ok().unwrap();
- // Check whether we written all data
- assert_eq!(to_write.len(), written);
- let read_res = read(reader, &mut read_buf[..]);
- // Successful read
- assert!(read_res.is_ok());
- let read = read_res.ok().unwrap() as usize;
- // Check we have read as much as we written
- assert_eq!(read, written);
- // Check equality of written and read data
- assert_eq!(&to_write, &read_buf);
- let close_res = close(writer);
- assert!(close_res.is_ok());
- let close_res = close(reader);
- assert!(close_res.is_ok());
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_readv() {
- let s:String = thread_rng().sample_iter(&Alphanumeric).take(128).collect();
- let to_write = s.as_bytes().to_vec();
- let mut storage = Vec::new();
- let mut allocated = 0;
- while allocated < to_write.len() {
- let left = to_write.len() - allocated;
- let vec_len = if left <= 64 { left } else { thread_rng().gen_range(64, cmp::min(256, left)) };
- let v: Vec<u8> = iter::repeat(0u8).take(vec_len).collect();
- storage.push(v);
- allocated += vec_len;
- }
- let mut iovecs = Vec::with_capacity(storage.len());
- for v in &mut storage {
- iovecs.push(IoVec::from_mut_slice(&mut v[..]));
- }
- let pipe_res = pipe();
- assert!(pipe_res.is_ok());
- let (reader, writer) = pipe_res.ok().unwrap();
- // Blocking io, should write all data.
- let write_res = write(writer, &to_write);
- // Successful write
- assert!(write_res.is_ok());
- let read_res = readv(reader, &mut iovecs[..]);
- assert!(read_res.is_ok());
- let read = read_res.ok().unwrap();
- // Check whether we've read all data
- assert_eq!(to_write.len(), read);
- // Cccumulate data from iovecs
- let mut read_buf = Vec::with_capacity(to_write.len());
- for iovec in &iovecs {
- read_buf.extend(iovec.as_slice().iter().cloned());
- }
- // Check whether iovecs contain all written data
- assert_eq!(read_buf.len(), to_write.len());
- // Check equality of written and read data
- assert_eq!(&read_buf, &to_write);
- let close_res = close(reader);
- assert!(close_res.is_ok());
- let close_res = close(writer);
- assert!(close_res.is_ok());
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_pwrite() {
- use std::io::Read;
-
- let mut file = tempfile().unwrap();
- let buf = [1u8;8];
- assert_eq!(Ok(8), pwrite(file.as_raw_fd(), &buf, 8));
- let mut file_content = Vec::new();
- file.read_to_end(&mut file_content).unwrap();
- let mut expected = vec![0u8;8];
- expected.extend(vec![1;8]);
- assert_eq!(file_content, expected);
-}
-
-#[test]
-fn test_pread() {
- use std::io::Write;
-
- let tempdir = tempdir().unwrap();
-
- let path = tempdir.path().join("pread_test_file");
- let mut file = OpenOptions::new().write(true).read(true).create(true)
- .truncate(true).open(path).unwrap();
- let file_content: Vec<u8> = (0..64).collect();
- file.write_all(&file_content).unwrap();
-
- let mut buf = [0u8;16];
- assert_eq!(Ok(16), pread(file.as_raw_fd(), &mut buf, 16));
- let expected: Vec<_> = (16..32).collect();
- assert_eq!(&buf[..], &expected[..]);
-}
-
-#[test]
-#[cfg(target_os = "linux")]
-fn test_pwritev() {
- use std::io::Read;
-
- let to_write: Vec<u8> = (0..128).collect();
- let expected: Vec<u8> = [vec![0;100], to_write.clone()].concat();
-
- let iovecs = [
- IoVec::from_slice(&to_write[0..17]),
- IoVec::from_slice(&to_write[17..64]),
- IoVec::from_slice(&to_write[64..128]),
- ];
-
- let tempdir = tempdir().unwrap();
-
- // pwritev them into a temporary file
- let path = tempdir.path().join("pwritev_test_file");
- let mut file = OpenOptions::new().write(true).read(true).create(true)
- .truncate(true).open(path).unwrap();
-
- let written = pwritev(file.as_raw_fd(), &iovecs, 100).ok().unwrap();
- assert_eq!(written, to_write.len());
-
- // Read the data back and make sure it matches
- let mut contents = Vec::new();
- file.read_to_end(&mut contents).unwrap();
- assert_eq!(contents, expected);
-}
-
-#[test]
-#[cfg(target_os = "linux")]
-fn test_preadv() {
- use std::io::Write;
-
- let to_write: Vec<u8> = (0..200).collect();
- let expected: Vec<u8> = (100..200).collect();
-
- let tempdir = tempdir().unwrap();
-
- let path = tempdir.path().join("preadv_test_file");
-
- let mut file = OpenOptions::new().read(true).write(true).create(true)
- .truncate(true).open(path).unwrap();
- file.write_all(&to_write).unwrap();
-
- let mut buffers: Vec<Vec<u8>> = vec![
- vec![0; 24],
- vec![0; 1],
- vec![0; 75],
- ];
-
- {
- // Borrow the buffers into IoVecs and preadv into them
- let iovecs: Vec<_> = buffers.iter_mut().map(
- |buf| IoVec::from_mut_slice(&mut buf[..])).collect();
- assert_eq!(Ok(100), preadv(file.as_raw_fd(), &iovecs, 100));
- }
-
- let all = buffers.concat();
- assert_eq!(all, expected);
-}
-
-#[test]
-#[cfg(target_os = "linux")]
-// FIXME: qemu-user doesn't implement process_vm_readv/writev on most arches
-#[cfg_attr(not(any(target_arch = "x86", target_arch = "x86_64")), ignore)]
-fn test_process_vm_readv() {
- use nix::unistd::ForkResult::*;
- use nix::sys::signal::*;
- use nix::sys::wait::*;
- use crate::*;
-
- require_capability!(CAP_SYS_PTRACE);
- let _ = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-
- // Pre-allocate memory in the child, since allocation isn't safe
- // post-fork (~= async-signal-safe)
- let mut vector = vec![1u8, 2, 3, 4, 5];
-
- let (r, w) = pipe().unwrap();
- match unsafe{fork()}.expect("Error: Fork Failed") {
- Parent { child } => {
- close(w).unwrap();
- // wait for child
- read(r, &mut [0u8]).unwrap();
- close(r).unwrap();
-
- let ptr = vector.as_ptr() as usize;
- let remote_iov = RemoteIoVec { base: ptr, len: 5 };
- let mut buf = vec![0u8; 5];
-
- let ret = process_vm_readv(child,
- &[IoVec::from_mut_slice(&mut buf)],
- &[remote_iov]);
-
- kill(child, SIGTERM).unwrap();
- waitpid(child, None).unwrap();
-
- assert_eq!(Ok(5), ret);
- assert_eq!(20u8, buf.iter().sum());
- },
- Child => {
- let _ = close(r);
- for i in &mut vector {
- *i += 1;
- }
- let _ = write(w, b"\0");
- let _ = close(w);
- loop { let _ = pause(); }
- },
- }
-}
diff --git a/vendor/nix-0.20.0/test/sys/test_wait.rs b/vendor/nix-0.20.0/test/sys/test_wait.rs
deleted file mode 100644
index 5bb298e..0000000
--- a/vendor/nix-0.20.0/test/sys/test_wait.rs
+++ /dev/null
@@ -1,107 +0,0 @@
-use nix::Error;
-use nix::unistd::*;
-use nix::unistd::ForkResult::*;
-use nix::sys::signal::*;
-use nix::sys::wait::*;
-use libc::_exit;
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_wait_signal() {
- let _ = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-
- // Safe: The child only calls `pause` and/or `_exit`, which are async-signal-safe.
- match unsafe{fork()}.expect("Error: Fork Failed") {
- Child => {
- pause();
- unsafe { _exit(123) }
- },
- Parent { child } => {
- kill(child, Some(SIGKILL)).expect("Error: Kill Failed");
- assert_eq!(waitpid(child, None), Ok(WaitStatus::Signaled(child, SIGKILL, false)));
- },
- }
-}
-
-#[test]
-fn test_wait_exit() {
- let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-
- // Safe: Child only calls `_exit`, which is async-signal-safe.
- match unsafe{fork()}.expect("Error: Fork Failed") {
- Child => unsafe { _exit(12); },
- Parent { child } => {
- assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 12)));
- },
- }
-}
-
-#[test]
-fn test_waitstatus_from_raw() {
- let pid = Pid::from_raw(1);
- assert_eq!(WaitStatus::from_raw(pid, 0x0002), Ok(WaitStatus::Signaled(pid, Signal::SIGINT, false)));
- assert_eq!(WaitStatus::from_raw(pid, 0x0200), Ok(WaitStatus::Exited(pid, 2)));
- assert_eq!(WaitStatus::from_raw(pid, 0x7f7f), Err(Error::invalid_argument()));
-}
-
-#[test]
-fn test_waitstatus_pid() {
- let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-
- match unsafe{fork()}.unwrap() {
- Child => unsafe { _exit(0) },
- Parent { child } => {
- let status = waitpid(child, None).unwrap();
- assert_eq!(status.pid(), Some(child));
- }
- }
-}
-
-#[cfg(any(target_os = "linux", target_os = "android"))]
-// FIXME: qemu-user doesn't implement ptrace on most arches
-#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-mod ptrace {
- use nix::sys::ptrace::{self, Options, Event};
- use nix::sys::signal::*;
- use nix::sys::wait::*;
- use nix::unistd::*;
- use nix::unistd::ForkResult::*;
- use libc::_exit;
- use crate::*;
-
- fn ptrace_child() -> ! {
- ptrace::traceme().unwrap();
- // As recommended by ptrace(2), raise SIGTRAP to pause the child
- // until the parent is ready to continue
- raise(SIGTRAP).unwrap();
- unsafe { _exit(0) }
- }
-
- fn ptrace_parent(child: Pid) {
- // Wait for the raised SIGTRAP
- assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, SIGTRAP)));
- // We want to test a syscall stop and a PTRACE_EVENT stop
- assert!(ptrace::setoptions(child, Options::PTRACE_O_TRACESYSGOOD | Options::PTRACE_O_TRACEEXIT).is_ok());
-
- // First, stop on the next system call, which will be exit()
- assert!(ptrace::syscall(child, None).is_ok());
- assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
- // Then get the ptrace event for the process exiting
- assert!(ptrace::cont(child, None).is_ok());
- assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceEvent(child, SIGTRAP, Event::PTRACE_EVENT_EXIT as i32)));
- // Finally get the normal wait() result, now that the process has exited
- assert!(ptrace::cont(child, None).is_ok());
- assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 0)));
- }
-
- #[test]
- fn test_wait_ptrace() {
- require_capability!(CAP_SYS_PTRACE);
- let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-
- match unsafe{fork()}.expect("Error: Fork Failed") {
- Child => ptrace_child(),
- Parent { child } => ptrace_parent(child),
- }
- }
-}
diff --git a/vendor/nix-0.20.0/test/test.rs b/vendor/nix-0.20.0/test/test.rs
deleted file mode 100644
index 5a5330b..0000000
--- a/vendor/nix-0.20.0/test/test.rs
+++ /dev/null
@@ -1,100 +0,0 @@
-#[macro_use]
-extern crate cfg_if;
-#[cfg_attr(not(target_os = "redox"), macro_use)]
-extern crate nix;
-#[macro_use]
-extern crate lazy_static;
-
-mod common;
-mod sys;
-#[cfg(not(target_os = "redox"))]
-mod test_dir;
-mod test_fcntl;
-#[cfg(any(target_os = "android",
- target_os = "linux"))]
-mod test_kmod;
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "fushsia",
- target_os = "linux",
- target_os = "netbsd"))]
-mod test_mq;
-#[cfg(not(target_os = "redox"))]
-mod test_net;
-mod test_nix_path;
-mod test_poll;
-#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-mod test_pty;
-#[cfg(any(target_os = "android",
- target_os = "linux"))]
-mod test_sched;
-#[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
-mod test_sendfile;
-mod test_stat;
-mod test_time;
-mod test_unistd;
-
-use std::os::unix::io::RawFd;
-use std::path::PathBuf;
-use std::sync::{Mutex, RwLock, RwLockWriteGuard};
-use nix::unistd::{chdir, getcwd, read};
-
-
-/// Helper function analogous to `std::io::Read::read_exact`, but for `RawFD`s
-fn read_exact(f: RawFd, buf: &mut [u8]) {
- let mut len = 0;
- while len < buf.len() {
- // get_mut would be better than split_at_mut, but it requires nightly
- let (_, remaining) = buf.split_at_mut(len);
- len += read(f, remaining).unwrap();
- }
-}
-
-lazy_static! {
- /// Any test that changes the process's current working directory must grab
- /// the RwLock exclusively. Any process that cares about the current
- /// working directory must grab it shared.
- pub static ref CWD_LOCK: RwLock<()> = RwLock::new(());
- /// Any test that creates child processes must grab this mutex, regardless
- /// of what it does with those children.
- pub static ref FORK_MTX: Mutex<()> = Mutex::new(());
- /// Any test that changes the process's supplementary groups must grab this
- /// mutex
- pub static ref GROUPS_MTX: Mutex<()> = Mutex::new(());
- /// Any tests that loads or unloads kernel modules must grab this mutex
- pub static ref KMOD_MTX: Mutex<()> = Mutex::new(());
- /// Any test that calls ptsname(3) must grab this mutex.
- pub static ref PTSNAME_MTX: Mutex<()> = Mutex::new(());
- /// Any test that alters signal handling must grab this mutex.
- pub static ref SIGNAL_MTX: Mutex<()> = Mutex::new(());
-}
-
-/// RAII object that restores a test's original directory on drop
-struct DirRestore<'a> {
- d: PathBuf,
- _g: RwLockWriteGuard<'a, ()>
-}
-
-impl<'a> DirRestore<'a> {
- fn new() -> Self {
- let guard = crate::CWD_LOCK.write()
- .expect("Lock got poisoned by another test");
- DirRestore{
- _g: guard,
- d: getcwd().unwrap(),
- }
- }
-}
-
-impl<'a> Drop for DirRestore<'a> {
- fn drop(&mut self) {
- let r = chdir(&self.d);
- if std::thread::panicking() {
- r.unwrap();
- }
- }
-}
diff --git a/vendor/nix-0.20.0/test/test_clearenv.rs b/vendor/nix-0.20.0/test/test_clearenv.rs
deleted file mode 100644
index 28a7768..0000000
--- a/vendor/nix-0.20.0/test/test_clearenv.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-use std::env;
-
-#[test]
-fn clearenv() {
- env::set_var("FOO", "BAR");
- unsafe { nix::env::clearenv() }.unwrap();
- assert_eq!(env::var("FOO").unwrap_err(), env::VarError::NotPresent);
- assert_eq!(env::vars().count(), 0);
-}
diff --git a/vendor/nix-0.20.0/test/test_dir.rs b/vendor/nix-0.20.0/test/test_dir.rs
deleted file mode 100644
index 505277e..0000000
--- a/vendor/nix-0.20.0/test/test_dir.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-use nix::dir::{Dir, Type};
-use nix::fcntl::OFlag;
-use nix::sys::stat::Mode;
-use std::fs::File;
-use tempfile::tempdir;
-
-#[test]
-fn read() {
- let tmp = tempdir().unwrap();
- File::create(&tmp.path().join("foo")).unwrap();
- ::std::os::unix::fs::symlink("foo", tmp.path().join("bar")).unwrap();
- let mut dir = Dir::open(tmp.path(), OFlag::O_DIRECTORY | OFlag::O_RDONLY | OFlag::O_CLOEXEC,
- Mode::empty()).unwrap();
- let mut entries: Vec<_> = dir.iter().map(|e| e.unwrap()).collect();
- entries.sort_by(|a, b| a.file_name().cmp(b.file_name()));
- let entry_names: Vec<_> = entries
- .iter()
- .map(|e| e.file_name().to_str().unwrap().to_owned())
- .collect();
- assert_eq!(&entry_names[..], &[".", "..", "bar", "foo"]);
-
- // Check file types. The system is allowed to return DT_UNKNOWN (aka None here) but if it does
- // return a type, ensure it's correct.
- assert!(&[Some(Type::Directory), None].contains(&entries[0].file_type())); // .: dir
- assert!(&[Some(Type::Directory), None].contains(&entries[1].file_type())); // ..: dir
- assert!(&[Some(Type::Symlink), None].contains(&entries[2].file_type())); // bar: symlink
- assert!(&[Some(Type::File), None].contains(&entries[3].file_type())); // foo: regular file
-}
-
-#[test]
-fn rewind() {
- let tmp = tempdir().unwrap();
- let mut dir = Dir::open(tmp.path(), OFlag::O_DIRECTORY | OFlag::O_RDONLY | OFlag::O_CLOEXEC,
- Mode::empty()).unwrap();
- let entries1: Vec<_> = dir.iter().map(|e| e.unwrap().file_name().to_owned()).collect();
- let entries2: Vec<_> = dir.iter().map(|e| e.unwrap().file_name().to_owned()).collect();
- let entries3: Vec<_> = dir.into_iter().map(|e| e.unwrap().file_name().to_owned()).collect();
- assert_eq!(entries1, entries2);
- assert_eq!(entries2, entries3);
-}
-
-#[test]
-fn ebadf() {
- assert_eq!(Dir::from_fd(-1).unwrap_err(), nix::Error::Sys(nix::errno::Errno::EBADF));
-}
diff --git a/vendor/nix-0.20.0/test/test_fcntl.rs b/vendor/nix-0.20.0/test/test_fcntl.rs
deleted file mode 100644
index 5d1bafe..0000000
--- a/vendor/nix-0.20.0/test/test_fcntl.rs
+++ /dev/null
@@ -1,417 +0,0 @@
-#[cfg(not(target_os = "redox"))]
-use nix::Error;
-#[cfg(not(target_os = "redox"))]
-use nix::errno::*;
-#[cfg(not(target_os = "redox"))]
-use nix::fcntl::{open, OFlag, readlink};
-#[cfg(not(target_os = "redox"))]
-use nix::fcntl::{openat, readlinkat, renameat};
-#[cfg(not(target_os = "redox"))]
-use nix::sys::stat::Mode;
-#[cfg(not(target_os = "redox"))]
-use nix::unistd::{close, read};
-#[cfg(not(target_os = "redox"))]
-use tempfile::{self, NamedTempFile};
-#[cfg(not(target_os = "redox"))]
-use std::fs::File;
-#[cfg(not(target_os = "redox"))]
-use std::io::prelude::*;
-#[cfg(not(target_os = "redox"))]
-use std::os::unix::fs;
-
-use crate::*;
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_openat() {
- const CONTENTS: &[u8] = b"abcd";
- let mut tmp = NamedTempFile::new().unwrap();
- tmp.write_all(CONTENTS).unwrap();
-
- let dirfd = open(tmp.path().parent().unwrap(),
- OFlag::empty(),
- Mode::empty()).unwrap();
- let fd = openat(dirfd,
- tmp.path().file_name().unwrap(),
- OFlag::O_RDONLY,
- Mode::empty()).unwrap();
-
- let mut buf = [0u8; 1024];
- assert_eq!(4, read(fd, &mut buf).unwrap());
- assert_eq!(CONTENTS, &buf[0..4]);
-
- close(fd).unwrap();
- close(dirfd).unwrap();
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_renameat() {
- let old_dir = tempfile::tempdir().unwrap();
- let old_dirfd = open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
- let old_path = old_dir.path().join("old");
- File::create(&old_path).unwrap();
- let new_dir = tempfile::tempdir().unwrap();
- let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
- renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap();
- assert_eq!(renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap_err(),
- Error::Sys(Errno::ENOENT));
- close(old_dirfd).unwrap();
- close(new_dirfd).unwrap();
- assert!(new_dir.path().join("new").exists());
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_readlink() {
- let tempdir = tempfile::tempdir().unwrap();
- let src = tempdir.path().join("a");
- let dst = tempdir.path().join("b");
- println!("a: {:?}, b: {:?}", &src, &dst);
- fs::symlink(&src.as_path(), &dst.as_path()).unwrap();
- let dirfd = open(tempdir.path(),
- OFlag::empty(),
- Mode::empty()).unwrap();
- let expected_dir = src.to_str().unwrap();
-
- assert_eq!(readlink(&dst).unwrap().to_str().unwrap(), expected_dir);
- assert_eq!(readlinkat(dirfd, "b").unwrap().to_str().unwrap(), expected_dir);
-
-}
-
-#[cfg(any(target_os = "linux", target_os = "android"))]
-mod linux_android {
- use std::fs::File;
- use std::io::prelude::*;
- use std::io::{BufRead, BufReader, SeekFrom};
- use std::os::unix::prelude::*;
-
- use libc::loff_t;
-
- use nix::fcntl::*;
- use nix::sys::stat::fstat;
- use nix::sys::uio::IoVec;
- use nix::unistd::{close, pipe, read, write};
-
- use tempfile::{tempfile, NamedTempFile};
-
- use crate::*;
-
- /// This test creates a temporary file containing the contents
- /// 'foobarbaz' and uses the `copy_file_range` call to transfer
- /// 3 bytes at offset 3 (`bar`) to another empty file at offset 0. The
- /// resulting file is read and should contain the contents `bar`.
- /// The from_offset should be updated by the call to reflect
- /// the 3 bytes read (6).
- ///
- /// FIXME: This test is disabled for linux based builds, because Travis
- /// Linux version is too old for `copy_file_range`.
- #[test]
- #[ignore]
- fn test_copy_file_range() {
- const CONTENTS: &[u8] = b"foobarbaz";
-
- let mut tmp1 = tempfile().unwrap();
- let mut tmp2 = tempfile().unwrap();
-
- tmp1.write_all(CONTENTS).unwrap();
- tmp1.flush().unwrap();
-
- let mut from_offset: i64 = 3;
- copy_file_range(
- tmp1.as_raw_fd(),
- Some(&mut from_offset),
- tmp2.as_raw_fd(),
- None,
- 3,
- )
- .unwrap();
-
- let mut res: String = String::new();
- tmp2.seek(SeekFrom::Start(0)).unwrap();
- tmp2.read_to_string(&mut res).unwrap();
-
- assert_eq!(res, String::from("bar"));
- assert_eq!(from_offset, 6);
- }
-
- #[test]
- fn test_splice() {
- const CONTENTS: &[u8] = b"abcdef123456";
- let mut tmp = tempfile().unwrap();
- tmp.write_all(CONTENTS).unwrap();
-
- let (rd, wr) = pipe().unwrap();
- let mut offset: loff_t = 5;
- let res = splice(tmp.as_raw_fd(), Some(&mut offset),
- wr, None, 2, SpliceFFlags::empty()).unwrap();
-
- assert_eq!(2, res);
-
- let mut buf = [0u8; 1024];
- assert_eq!(2, read(rd, &mut buf).unwrap());
- assert_eq!(b"f1", &buf[0..2]);
- assert_eq!(7, offset);
-
- close(rd).unwrap();
- close(wr).unwrap();
- }
-
- #[test]
- fn test_tee() {
- let (rd1, wr1) = pipe().unwrap();
- let (rd2, wr2) = pipe().unwrap();
-
- write(wr1, b"abc").unwrap();
- let res = tee(rd1, wr2, 2, SpliceFFlags::empty()).unwrap();
-
- assert_eq!(2, res);
-
- let mut buf = [0u8; 1024];
-
- // Check the tee'd bytes are at rd2.
- assert_eq!(2, read(rd2, &mut buf).unwrap());
- assert_eq!(b"ab", &buf[0..2]);
-
- // Check all the bytes are still at rd1.
- assert_eq!(3, read(rd1, &mut buf).unwrap());
- assert_eq!(b"abc", &buf[0..3]);
-
- close(rd1).unwrap();
- close(wr1).unwrap();
- close(rd2).unwrap();
- close(wr2).unwrap();
- }
-
- #[test]
- fn test_vmsplice() {
- let (rd, wr) = pipe().unwrap();
-
- let buf1 = b"abcdef";
- let buf2 = b"defghi";
- let mut iovecs = Vec::with_capacity(2);
- iovecs.push(IoVec::from_slice(&buf1[0..3]));
- iovecs.push(IoVec::from_slice(&buf2[0..3]));
-
- let res = vmsplice(wr, &iovecs[..], SpliceFFlags::empty()).unwrap();
-
- assert_eq!(6, res);
-
- // Check the bytes can be read at rd.
- let mut buf = [0u8; 32];
- assert_eq!(6, read(rd, &mut buf).unwrap());
- assert_eq!(b"abcdef", &buf[0..6]);
-
- close(rd).unwrap();
- close(wr).unwrap();
- }
-
- #[test]
- fn test_fallocate() {
- let tmp = NamedTempFile::new().unwrap();
-
- let fd = tmp.as_raw_fd();
- fallocate(fd, FallocateFlags::empty(), 0, 100).unwrap();
-
- // Check if we read exactly 100 bytes
- let mut buf = [0u8; 200];
- assert_eq!(100, read(fd, &mut buf).unwrap());
- }
-
- // The tests below are disabled for the listed targets
- // due to OFD locks not being available in the kernel/libc
- // versions used in the CI environment, probably because
- // they run under QEMU.
-
- #[test]
- #[cfg(not(any(target_arch = "aarch64",
- target_arch = "arm",
- target_arch = "armv7",
- target_arch = "x86",
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "mips64el",
- target_arch = "powerpc64",
- target_arch = "powerpc64le",
- target_env = "musl")))]
- fn test_ofd_write_lock() {
- let tmp = NamedTempFile::new().unwrap();
-
- let fd = tmp.as_raw_fd();
- let statfs = nix::sys::statfs::fstatfs(&tmp).unwrap();
- if statfs.filesystem_type() == nix::sys::statfs::OVERLAYFS_SUPER_MAGIC {
- // OverlayFS is a union file system. It returns one inode value in
- // stat(2), but a different one shows up in /proc/locks. So we must
- // skip the test.
- skip!("/proc/locks does not work on overlayfs");
- }
- let inode = fstat(fd).expect("fstat failed").st_ino as usize;
-
- let mut flock = libc::flock {
- l_type: libc::F_WRLCK as libc::c_short,
- l_whence: libc::SEEK_SET as libc::c_short,
- l_start: 0,
- l_len: 0,
- l_pid: 0,
- };
- fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("write lock failed");
- assert_eq!(
- Some(("OFDLCK".to_string(), "WRITE".to_string())),
- lock_info(inode)
- );
-
- flock.l_type = libc::F_UNLCK as libc::c_short;
- fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("write unlock failed");
- assert_eq!(None, lock_info(inode));
- }
-
- #[test]
- #[cfg(not(any(target_arch = "aarch64",
- target_arch = "arm",
- target_arch = "armv7",
- target_arch = "x86",
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "mips64el",
- target_arch = "powerpc64",
- target_arch = "powerpc64le",
- target_env = "musl")))]
- fn test_ofd_read_lock() {
- let tmp = NamedTempFile::new().unwrap();
-
- let fd = tmp.as_raw_fd();
- let statfs = nix::sys::statfs::fstatfs(&tmp).unwrap();
- if statfs.filesystem_type() == nix::sys::statfs::OVERLAYFS_SUPER_MAGIC {
- // OverlayFS is a union file system. It returns one inode value in
- // stat(2), but a different one shows up in /proc/locks. So we must
- // skip the test.
- skip!("/proc/locks does not work on overlayfs");
- }
- let inode = fstat(fd).expect("fstat failed").st_ino as usize;
-
- let mut flock = libc::flock {
- l_type: libc::F_RDLCK as libc::c_short,
- l_whence: libc::SEEK_SET as libc::c_short,
- l_start: 0,
- l_len: 0,
- l_pid: 0,
- };
- fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("read lock failed");
- assert_eq!(
- Some(("OFDLCK".to_string(), "READ".to_string())),
- lock_info(inode)
- );
-
- flock.l_type = libc::F_UNLCK as libc::c_short;
- fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("read unlock failed");
- assert_eq!(None, lock_info(inode));
- }
-
- fn lock_info(inode: usize) -> Option<(String, String)> {
- let file = File::open("/proc/locks").expect("open /proc/locks failed");
- let buf = BufReader::new(file);
-
- for line in buf.lines() {
- let line = line.unwrap();
- let parts: Vec<_> = line.split_whitespace().collect();
- let lock_type = parts[1];
- let lock_access = parts[3];
- let ino_parts: Vec<_> = parts[5].split(':').collect();
- let ino: usize = ino_parts[2].parse().unwrap();
- if ino == inode {
- return Some((lock_type.to_string(), lock_access.to_string()));
- }
- }
- None
- }
-}
-
-#[cfg(any(target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- any(target_os = "wasi", target_env = "wasi"),
- target_env = "uclibc",
- target_os = "freebsd"))]
-mod test_posix_fadvise {
-
- use tempfile::NamedTempFile;
- use std::os::unix::io::{RawFd, AsRawFd};
- use nix::errno::Errno;
- use nix::fcntl::*;
- use nix::unistd::pipe;
-
- #[test]
- fn test_success() {
- let tmp = NamedTempFile::new().unwrap();
- let fd = tmp.as_raw_fd();
- let res = posix_fadvise(fd, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED).unwrap();
-
- assert_eq!(res, 0);
- }
-
- #[test]
- fn test_errno() {
- let (rd, _wr) = pipe().unwrap();
- let errno = posix_fadvise(rd as RawFd, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED)
- .unwrap();
- assert_eq!(errno, Errno::ESPIPE as i32);
- }
-}
-
-#[cfg(any(target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- any(target_os = "wasi", target_env = "wasi"),
- target_os = "freebsd"))]
-mod test_posix_fallocate {
-
- use tempfile::NamedTempFile;
- use std::{io::Read, os::unix::io::{RawFd, AsRawFd}};
- use nix::errno::Errno;
- use nix::fcntl::*;
- use nix::unistd::pipe;
-
- #[test]
- fn success() {
- const LEN: usize = 100;
- let mut tmp = NamedTempFile::new().unwrap();
- let fd = tmp.as_raw_fd();
- let res = posix_fallocate(fd, 0, LEN as libc::off_t);
- match res {
- Ok(_) => {
- let mut data = [1u8; LEN];
- assert_eq!(tmp.read(&mut data).expect("read failure"), LEN);
- assert_eq!(&data[..], &[0u8; LEN][..]);
- }
- Err(nix::Error::Sys(Errno::EINVAL)) => {
- // POSIX requires posix_fallocate to return EINVAL both for
- // invalid arguments (i.e. len < 0) and if the operation is not
- // supported by the file system.
- // There's no way to tell for sure whether the file system
- // supports posix_fallocate, so we must pass the test if it
- // returns EINVAL.
- }
- _ => res.unwrap(),
- }
- }
-
- #[test]
- fn errno() {
- let (rd, _wr) = pipe().unwrap();
- let err = posix_fallocate(rd as RawFd, 0, 100).unwrap_err();
- use nix::Error::Sys;
- match err {
- Sys(Errno::EINVAL)
- | Sys(Errno::ENODEV)
- | Sys(Errno::ESPIPE)
- | Sys(Errno::EBADF) => (),
- errno =>
- panic!(
- "unexpected errno {}",
- errno,
- ),
- }
- }
-}
diff --git a/vendor/nix-0.20.0/test/test_kmod/hello_mod/Makefile b/vendor/nix-0.20.0/test/test_kmod/hello_mod/Makefile
deleted file mode 100644
index 74c99b7..0000000
--- a/vendor/nix-0.20.0/test/test_kmod/hello_mod/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-obj-m += hello.o
-
-all:
- make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
-
-clean:
- make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean
diff --git a/vendor/nix-0.20.0/test/test_kmod/hello_mod/hello.c b/vendor/nix-0.20.0/test/test_kmod/hello_mod/hello.c
deleted file mode 100644
index 1c34987..0000000
--- a/vendor/nix-0.20.0/test/test_kmod/hello_mod/hello.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * SPDX-License-Identifier: GPL-2.0+ or MIT
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-
-static int number= 1;
-static char *who = "World";
-
-module_param(number, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-MODULE_PARM_DESC(myint, "Just some number");
-module_param(who, charp, 0000);
-MODULE_PARM_DESC(who, "Whot to greet");
-
-int init_module(void)
-{
- printk(KERN_INFO "Hello %s (%d)!\n", who, number);
- return 0;
-}
-
-void cleanup_module(void)
-{
- printk(KERN_INFO "Goodbye %s (%d)!\n", who, number);
-}
-
-MODULE_LICENSE("Dual MIT/GPL");
diff --git a/vendor/nix-0.20.0/test/test_kmod/mod.rs b/vendor/nix-0.20.0/test/test_kmod/mod.rs
deleted file mode 100644
index fb7260b..0000000
--- a/vendor/nix-0.20.0/test/test_kmod/mod.rs
+++ /dev/null
@@ -1,167 +0,0 @@
-use std::fs::copy;
-use std::path::PathBuf;
-use std::process::Command;
-use tempfile::{tempdir, TempDir};
-use crate::*;
-
-fn compile_kernel_module() -> (PathBuf, String, TempDir) {
- let _m = crate::FORK_MTX
- .lock()
- .expect("Mutex got poisoned by another test");
-
- let tmp_dir = tempdir().expect("unable to create temporary build directory");
-
- copy(
- "test/test_kmod/hello_mod/hello.c",
- &tmp_dir.path().join("hello.c"),
- ).expect("unable to copy hello.c to temporary build directory");
- copy(
- "test/test_kmod/hello_mod/Makefile",
- &tmp_dir.path().join("Makefile"),
- ).expect("unable to copy Makefile to temporary build directory");
-
- let status = Command::new("make")
- .current_dir(tmp_dir.path())
- .status()
- .expect("failed to run make");
-
- assert!(status.success());
-
- // Return the relative path of the build kernel module
- (tmp_dir.path().join("hello.ko"), "hello".to_owned(), tmp_dir)
-}
-
-use nix::errno::Errno;
-use nix::kmod::{delete_module, DeleteModuleFlags};
-use nix::kmod::{finit_module, init_module, ModuleInitFlags};
-use nix::Error;
-use std::ffi::CString;
-use std::fs::File;
-use std::io::Read;
-
-#[test]
-fn test_finit_and_delete_module() {
- require_capability!(CAP_SYS_MODULE);
- let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
- let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-
- let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
-
- let f = File::open(kmod_path).expect("unable to open kernel module");
- finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty())
- .expect("unable to load kernel module");
-
- delete_module(
- &CString::new(kmod_name).unwrap(),
- DeleteModuleFlags::empty(),
- ).expect("unable to unload kernel module");
-}
-
-#[test]
-fn test_finit_and_delete_modul_with_params() {
- require_capability!(CAP_SYS_MODULE);
- let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
- let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-
- let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
-
- let f = File::open(kmod_path).expect("unable to open kernel module");
- finit_module(
- &f,
- &CString::new("who=Rust number=2018").unwrap(),
- ModuleInitFlags::empty(),
- ).expect("unable to load kernel module");
-
- delete_module(
- &CString::new(kmod_name).unwrap(),
- DeleteModuleFlags::empty(),
- ).expect("unable to unload kernel module");
-}
-
-#[test]
-fn test_init_and_delete_module() {
- require_capability!(CAP_SYS_MODULE);
- let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
- let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-
- let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
-
- let mut f = File::open(kmod_path).expect("unable to open kernel module");
- let mut contents: Vec<u8> = Vec::new();
- f.read_to_end(&mut contents)
- .expect("unable to read kernel module content to buffer");
- init_module(&mut contents, &CString::new("").unwrap()).expect("unable to load kernel module");
-
- delete_module(
- &CString::new(kmod_name).unwrap(),
- DeleteModuleFlags::empty(),
- ).expect("unable to unload kernel module");
-}
-
-#[test]
-fn test_init_and_delete_module_with_params() {
- require_capability!(CAP_SYS_MODULE);
- let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
- let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-
- let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
-
- let mut f = File::open(kmod_path).expect("unable to open kernel module");
- let mut contents: Vec<u8> = Vec::new();
- f.read_to_end(&mut contents)
- .expect("unable to read kernel module content to buffer");
- init_module(&mut contents, &CString::new("who=Nix number=2015").unwrap())
- .expect("unable to load kernel module");
-
- delete_module(
- &CString::new(kmod_name).unwrap(),
- DeleteModuleFlags::empty(),
- ).expect("unable to unload kernel module");
-}
-
-#[test]
-fn test_finit_module_invalid() {
- require_capability!(CAP_SYS_MODULE);
- let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
- let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-
- let kmod_path = "/dev/zero";
-
- let f = File::open(kmod_path).expect("unable to open kernel module");
- let result = finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty());
-
- assert_eq!(result.unwrap_err(), Error::Sys(Errno::EINVAL));
-}
-
-#[test]
-fn test_finit_module_twice_and_delete_module() {
- require_capability!(CAP_SYS_MODULE);
- let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
- let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-
- let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
-
- let f = File::open(kmod_path).expect("unable to open kernel module");
- finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty())
- .expect("unable to load kernel module");
-
- let result = finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty());
-
- assert_eq!(result.unwrap_err(), Error::Sys(Errno::EEXIST));
-
- delete_module(
- &CString::new(kmod_name).unwrap(),
- DeleteModuleFlags::empty(),
- ).expect("unable to unload kernel module");
-}
-
-#[test]
-fn test_delete_module_not_loaded() {
- require_capability!(CAP_SYS_MODULE);
- let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
- let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-
- let result = delete_module(&CString::new("hello").unwrap(), DeleteModuleFlags::empty());
-
- assert_eq!(result.unwrap_err(), Error::Sys(Errno::ENOENT));
-}
diff --git a/vendor/nix-0.20.0/test/test_mount.rs b/vendor/nix-0.20.0/test/test_mount.rs
deleted file mode 100644
index c1b6c8a..0000000
--- a/vendor/nix-0.20.0/test/test_mount.rs
+++ /dev/null
@@ -1,237 +0,0 @@
-mod common;
-
-// Impelmentation note: to allow unprivileged users to run it, this test makes
-// use of user and mount namespaces. On systems that allow unprivileged user
-// namespaces (Linux >= 3.8 compiled with CONFIG_USER_NS), the test should run
-// without root.
-
-#[cfg(target_os = "linux")]
-mod test_mount {
- use std::fs::{self, File};
- use std::io::{self, Read, Write};
- use std::os::unix::fs::OpenOptionsExt;
- use std::os::unix::fs::PermissionsExt;
- use std::process::{self, Command};
-
- use libc::{EACCES, EROFS};
-
- use nix::errno::Errno;
- use nix::mount::{mount, umount, MsFlags};
- use nix::sched::{unshare, CloneFlags};
- use nix::sys::stat::{self, Mode};
- use nix::unistd::getuid;
-
- use tempfile;
-
- static SCRIPT_CONTENTS: &'static [u8] = b"#!/bin/sh
-exit 23";
-
- const EXPECTED_STATUS: i32 = 23;
-
- const NONE: Option<&'static [u8]> = None;
- pub fn test_mount_tmpfs_without_flags_allows_rwx() {
- let tempdir = tempfile::tempdir().unwrap();
-
- mount(NONE,
- tempdir.path(),
- Some(b"tmpfs".as_ref()),
- MsFlags::empty(),
- NONE)
- .unwrap_or_else(|e| panic!("mount failed: {}", e));
-
- let test_path = tempdir.path().join("test");
-
- // Verify write.
- fs::OpenOptions::new()
- .create(true)
- .write(true)
- .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits())
- .open(&test_path)
- .or_else(|e|
- if Errno::from_i32(e.raw_os_error().unwrap()) == Errno::EOVERFLOW {
- // Skip tests on certain Linux kernels which have a bug
- // regarding tmpfs in namespaces.
- // Ubuntu 14.04 and 16.04 are known to be affected; 16.10 is
- // not. There is no legitimate reason for open(2) to return
- // EOVERFLOW here.
- // https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1659087
- let stderr = io::stderr();
- let mut handle = stderr.lock();
- writeln!(handle, "Buggy Linux kernel detected. Skipping test.")
- .unwrap();
- process::exit(0);
- } else {
- panic!("open failed: {}", e);
- }
- )
- .and_then(|mut f| f.write(SCRIPT_CONTENTS))
- .unwrap_or_else(|e| panic!("write failed: {}", e));
-
- // Verify read.
- let mut buf = Vec::new();
- File::open(&test_path)
- .and_then(|mut f| f.read_to_end(&mut buf))
- .unwrap_or_else(|e| panic!("read failed: {}", e));
- assert_eq!(buf, SCRIPT_CONTENTS);
-
- // Verify execute.
- assert_eq!(EXPECTED_STATUS,
- Command::new(&test_path)
- .status()
- .unwrap_or_else(|e| panic!("exec failed: {}", e))
- .code()
- .unwrap_or_else(|| panic!("child killed by signal")));
-
- umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {}", e));
- }
-
- pub fn test_mount_rdonly_disallows_write() {
- let tempdir = tempfile::tempdir().unwrap();
-
- mount(NONE,
- tempdir.path(),
- Some(b"tmpfs".as_ref()),
- MsFlags::MS_RDONLY,
- NONE)
- .unwrap_or_else(|e| panic!("mount failed: {}", e));
-
- // EROFS: Read-only file system
- assert_eq!(EROFS as i32,
- File::create(tempdir.path().join("test")).unwrap_err().raw_os_error().unwrap());
-
- umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {}", e));
- }
-
- pub fn test_mount_noexec_disallows_exec() {
- let tempdir = tempfile::tempdir().unwrap();
-
- mount(NONE,
- tempdir.path(),
- Some(b"tmpfs".as_ref()),
- MsFlags::MS_NOEXEC,
- NONE)
- .unwrap_or_else(|e| panic!("mount failed: {}", e));
-
- let test_path = tempdir.path().join("test");
-
- fs::OpenOptions::new()
- .create(true)
- .write(true)
- .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits())
- .open(&test_path)
- .and_then(|mut f| f.write(SCRIPT_CONTENTS))
- .unwrap_or_else(|e| panic!("write failed: {}", e));
-
- // Verify that we cannot execute despite a+x permissions being set.
- let mode = stat::Mode::from_bits_truncate(fs::metadata(&test_path)
- .map(|md| md.permissions().mode())
- .unwrap_or_else(|e| {
- panic!("metadata failed: {}", e)
- }));
-
- assert!(mode.contains(Mode::S_IXUSR | Mode::S_IXGRP | Mode::S_IXOTH),
- "{:?} did not have execute permissions",
- &test_path);
-
- // EACCES: Permission denied
- assert_eq!(EACCES as i32,
- Command::new(&test_path).status().unwrap_err().raw_os_error().unwrap());
-
- umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {}", e));
- }
-
- pub fn test_mount_bind() {
- let tempdir = tempfile::tempdir().unwrap();
- let file_name = "test";
-
- {
- let mount_point = tempfile::tempdir().unwrap();
-
- mount(Some(tempdir.path()),
- mount_point.path(),
- NONE,
- MsFlags::MS_BIND,
- NONE)
- .unwrap_or_else(|e| panic!("mount failed: {}", e));
-
- fs::OpenOptions::new()
- .create(true)
- .write(true)
- .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits())
- .open(mount_point.path().join(file_name))
- .and_then(|mut f| f.write(SCRIPT_CONTENTS))
- .unwrap_or_else(|e| panic!("write failed: {}", e));
-
- umount(mount_point.path()).unwrap_or_else(|e| panic!("umount failed: {}", e));
- }
-
- // Verify the file written in the mount shows up in source directory, even
- // after unmounting.
-
- let mut buf = Vec::new();
- File::open(tempdir.path().join(file_name))
- .and_then(|mut f| f.read_to_end(&mut buf))
- .unwrap_or_else(|e| panic!("read failed: {}", e));
- assert_eq!(buf, SCRIPT_CONTENTS);
- }
-
- pub fn setup_namespaces() {
- // Hold on to the uid in the parent namespace.
- let uid = getuid();
-
- unshare(CloneFlags::CLONE_NEWNS | CloneFlags::CLONE_NEWUSER).unwrap_or_else(|e| {
- let stderr = io::stderr();
- let mut handle = stderr.lock();
- writeln!(handle,
- "unshare failed: {}. Are unprivileged user namespaces available?",
- e).unwrap();
- writeln!(handle, "mount is not being tested").unwrap();
- // Exit with success because not all systems support unprivileged user namespaces, and
- // that's not what we're testing for.
- process::exit(0);
- });
-
- // Map user as uid 1000.
- fs::OpenOptions::new()
- .write(true)
- .open("/proc/self/uid_map")
- .and_then(|mut f| f.write(format!("1000 {} 1\n", uid).as_bytes()))
- .unwrap_or_else(|e| panic!("could not write uid map: {}", e));
- }
-}
-
-
-// Test runner
-
-/// Mimic normal test output (hackishly).
-#[cfg(target_os = "linux")]
-macro_rules! run_tests {
- ( $($test_fn:ident),* ) => {{
- println!();
-
- $(
- print!("test test_mount::{} ... ", stringify!($test_fn));
- $test_fn();
- println!("ok");
- )*
-
- println!();
- }}
-}
-
-#[cfg(target_os = "linux")]
-fn main() {
- use test_mount::{setup_namespaces, test_mount_tmpfs_without_flags_allows_rwx,
- test_mount_rdonly_disallows_write, test_mount_noexec_disallows_exec,
- test_mount_bind};
- skip_if_cirrus!("Fails for an unknown reason Cirrus CI. Bug #1351");
- setup_namespaces();
-
- run_tests!(test_mount_tmpfs_without_flags_allows_rwx,
- test_mount_rdonly_disallows_write,
- test_mount_noexec_disallows_exec,
- test_mount_bind);
-}
-
-#[cfg(not(target_os = "linux"))]
-fn main() {}
diff --git a/vendor/nix-0.20.0/test/test_mq.rs b/vendor/nix-0.20.0/test/test_mq.rs
deleted file mode 100644
index 1667a35..0000000
--- a/vendor/nix-0.20.0/test/test_mq.rs
+++ /dev/null
@@ -1,150 +0,0 @@
-use std::ffi::CString;
-use std::str;
-
-use nix::errno::Errno::*;
-use nix::Error::Sys;
-use nix::mqueue::{mq_open, mq_close, mq_send, mq_receive, mq_attr_member_t};
-use nix::mqueue::{MqAttr, MQ_OFlag};
-use nix::sys::stat::Mode;
-
-#[test]
-fn test_mq_send_and_receive() {
- const MSG_SIZE: mq_attr_member_t = 32;
- let attr = MqAttr::new(0, 10, MSG_SIZE, 0);
- let mq_name= &CString::new(b"/a_nix_test_queue".as_ref()).unwrap();
-
- let oflag0 = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
- let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
- let r0 = mq_open(mq_name, oflag0, mode, Some(&attr));
- if let Err(Sys(ENOSYS)) = r0 {
- println!("message queues not supported or module not loaded?");
- return;
- };
- let mqd0 = r0.unwrap();
- let msg_to_send = "msg_1";
- mq_send(mqd0, msg_to_send.as_bytes(), 1).unwrap();
-
- let oflag1 = MQ_OFlag::O_CREAT | MQ_OFlag::O_RDONLY;
- let mqd1 = mq_open(mq_name, oflag1, mode, Some(&attr)).unwrap();
- let mut buf = [0u8; 32];
- let mut prio = 0u32;
- let len = mq_receive(mqd1, &mut buf, &mut prio).unwrap();
- assert_eq!(prio, 1);
-
- mq_close(mqd1).unwrap();
- mq_close(mqd0).unwrap();
- assert_eq!(msg_to_send, str::from_utf8(&buf[0..len]).unwrap());
-}
-
-
-#[test]
-#[cfg(not(any(target_os = "netbsd")))]
-fn test_mq_getattr() {
- use nix::mqueue::mq_getattr;
- const MSG_SIZE: mq_attr_member_t = 32;
- let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0);
- let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
- let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
- let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
- let r = mq_open(mq_name, oflag, mode, Some(&initial_attr));
- if let Err(Sys(ENOSYS)) = r {
- println!("message queues not supported or module not loaded?");
- return;
- };
- let mqd = r.unwrap();
-
- let read_attr = mq_getattr(mqd).unwrap();
- assert_eq!(read_attr, initial_attr);
- mq_close(mqd).unwrap();
-}
-
-// FIXME: Fix failures for mips in QEMU
-#[test]
-#[cfg(not(any(target_os = "netbsd")))]
-#[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
-fn test_mq_setattr() {
- use nix::mqueue::{mq_getattr, mq_setattr};
- const MSG_SIZE: mq_attr_member_t = 32;
- let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0);
- let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
- let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
- let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
- let r = mq_open(mq_name, oflag, mode, Some(&initial_attr));
- if let Err(Sys(ENOSYS)) = r {
- println!("message queues not supported or module not loaded?");
- return;
- };
- let mqd = r.unwrap();
-
- let new_attr = MqAttr::new(0, 20, MSG_SIZE * 2, 100);
- let old_attr = mq_setattr(mqd, &new_attr).unwrap();
- assert_eq!(old_attr, initial_attr);
-
- let new_attr_get = mq_getattr(mqd).unwrap();
- // The following tests make sense. No changes here because according to the Linux man page only
- // O_NONBLOCK can be set (see tests below)
- assert_ne!(new_attr_get, new_attr);
-
- let new_attr_non_blocking = MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as mq_attr_member_t, 10, MSG_SIZE, 0);
- mq_setattr(mqd, &new_attr_non_blocking).unwrap();
- let new_attr_get = mq_getattr(mqd).unwrap();
-
- // now the O_NONBLOCK flag has been set
- assert_ne!(new_attr_get, initial_attr);
- assert_eq!(new_attr_get, new_attr_non_blocking);
- mq_close(mqd).unwrap();
-}
-
-// FIXME: Fix failures for mips in QEMU
-#[test]
-#[cfg(not(any(target_os = "netbsd")))]
-#[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
-fn test_mq_set_nonblocking() {
- use nix::mqueue::{mq_getattr, mq_set_nonblock, mq_remove_nonblock};
- const MSG_SIZE: mq_attr_member_t = 32;
- let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0);
- let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
- let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
- let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
- let r = mq_open(mq_name, oflag, mode, Some(&initial_attr));
- if let Err(Sys(ENOSYS)) = r {
- println!("message queues not supported or module not loaded?");
- return;
- };
- let mqd = r.unwrap();
- mq_set_nonblock(mqd).unwrap();
- let new_attr = mq_getattr(mqd);
- assert_eq!(new_attr.unwrap().flags(), MQ_OFlag::O_NONBLOCK.bits() as mq_attr_member_t);
- mq_remove_nonblock(mqd).unwrap();
- let new_attr = mq_getattr(mqd);
- assert_eq!(new_attr.unwrap().flags(), 0);
- mq_close(mqd).unwrap();
-}
-
-#[test]
-#[cfg(not(any(target_os = "netbsd")))]
-fn test_mq_unlink() {
- use nix::mqueue::mq_unlink;
- const MSG_SIZE: mq_attr_member_t = 32;
- let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0);
- let mq_name_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap();
- let mq_name_not_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap();
- let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
- let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
- let r = mq_open(mq_name_opened, oflag, mode, Some(&initial_attr));
- if let Err(Sys(ENOSYS)) = r {
- println!("message queues not supported or module not loaded?");
- return;
- };
- let mqd = r.unwrap();
-
- let res_unlink = mq_unlink(mq_name_opened);
- assert_eq!(res_unlink, Ok(()) );
-
- let res_unlink_not_opened = mq_unlink(mq_name_not_opened);
- assert_eq!(res_unlink_not_opened, Err(Sys(ENOENT)) );
-
- mq_close(mqd).unwrap();
- let res_unlink_after_close = mq_unlink(mq_name_opened);
- assert_eq!(res_unlink_after_close, Err(Sys(ENOENT)) );
-}
diff --git a/vendor/nix-0.20.0/test/test_net.rs b/vendor/nix-0.20.0/test/test_net.rs
deleted file mode 100644
index b8940e7..0000000
--- a/vendor/nix-0.20.0/test/test_net.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-use nix::net::if_::*;
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-const LOOPBACK: &[u8] = b"lo";
-
-#[cfg(not(any(target_os = "android", target_os = "linux")))]
-const LOOPBACK: &[u8] = b"lo0";
-
-#[test]
-fn test_if_nametoindex() {
- assert!(if_nametoindex(&LOOPBACK[..]).is_ok());
-}
diff --git a/vendor/nix-0.20.0/test/test_nix_path.rs b/vendor/nix-0.20.0/test/test_nix_path.rs
deleted file mode 100644
index e69de29..0000000
--- a/vendor/nix-0.20.0/test/test_nix_path.rs
+++ /dev/null
diff --git a/vendor/nix-0.20.0/test/test_poll.rs b/vendor/nix-0.20.0/test/test_poll.rs
deleted file mode 100644
index a5e2d25..0000000
--- a/vendor/nix-0.20.0/test/test_poll.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-use nix::{
- Error,
- errno::Errno,
- poll::{PollFlags, poll, PollFd},
- unistd::{write, pipe}
-};
-
-macro_rules! loop_while_eintr {
- ($poll_expr: expr) => {
- loop {
- match $poll_expr {
- Ok(nfds) => break nfds,
- Err(Error::Sys(Errno::EINTR)) => (),
- Err(e) => panic!(e)
- }
- }
- }
-}
-
-#[test]
-fn test_poll() {
- let (r, w) = pipe().unwrap();
- let mut fds = [PollFd::new(r, PollFlags::POLLIN)];
-
- // Poll an idle pipe. Should timeout
- let nfds = loop_while_eintr!(poll(&mut fds, 100));
- assert_eq!(nfds, 0);
- assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));
-
- write(w, b".").unwrap();
-
- // Poll a readable pipe. Should return an event.
- let nfds = poll(&mut fds, 100).unwrap();
- assert_eq!(nfds, 1);
- assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
-}
-
-// ppoll(2) is the same as poll except for how it handles timeouts and signals.
-// Repeating the test for poll(2) should be sufficient to check that our
-// bindings are correct.
-#[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux"))]
-#[test]
-fn test_ppoll() {
- use nix::poll::ppoll;
- use nix::sys::signal::SigSet;
- use nix::sys::time::{TimeSpec, TimeValLike};
-
- let timeout = TimeSpec::milliseconds(1);
- let (r, w) = pipe().unwrap();
- let mut fds = [PollFd::new(r, PollFlags::POLLIN)];
-
- // Poll an idle pipe. Should timeout
- let sigset = SigSet::empty();
- let nfds = loop_while_eintr!(ppoll(&mut fds, Some(timeout), sigset));
- assert_eq!(nfds, 0);
- assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));
-
- write(w, b".").unwrap();
-
- // Poll a readable pipe. Should return an event.
- let nfds = ppoll(&mut fds, Some(timeout), SigSet::empty()).unwrap();
- assert_eq!(nfds, 1);
- assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
-}
diff --git a/vendor/nix-0.20.0/test/test_pty.rs b/vendor/nix-0.20.0/test/test_pty.rs
deleted file mode 100644
index ab347bb..0000000
--- a/vendor/nix-0.20.0/test/test_pty.rs
+++ /dev/null
@@ -1,275 +0,0 @@
-use std::fs::File;
-use std::io::{Read, Write};
-use std::path::Path;
-use std::os::unix::prelude::*;
-use tempfile::tempfile;
-
-use libc::{_exit, STDOUT_FILENO};
-use nix::fcntl::{OFlag, open};
-use nix::pty::*;
-use nix::sys::stat;
-use nix::sys::termios::*;
-use nix::unistd::{write, close, pause};
-
-/// Regression test for Issue #659
-/// This is the correct way to explicitly close a `PtyMaster`
-#[test]
-fn test_explicit_close() {
- let mut f = {
- let m = posix_openpt(OFlag::O_RDWR).unwrap();
- close(m.into_raw_fd()).unwrap();
- tempfile().unwrap()
- };
- // This should work. But if there's been a double close, then it will
- // return EBADF
- f.write_all(b"whatever").unwrap();
-}
-
-/// Test equivalence of `ptsname` and `ptsname_r`
-#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
-fn test_ptsname_equivalence() {
- let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-
- // Open a new PTTY master
- let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
- assert!(master_fd.as_raw_fd() > 0);
-
- // Get the name of the slave
- let slave_name = unsafe { ptsname(&master_fd) }.unwrap() ;
- let slave_name_r = ptsname_r(&master_fd).unwrap();
- assert_eq!(slave_name, slave_name_r);
-}
-
-/// Test data copying of `ptsname`
-// TODO need to run in a subprocess, since ptsname is non-reentrant
-#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
-fn test_ptsname_copy() {
- let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-
- // Open a new PTTY master
- let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
- assert!(master_fd.as_raw_fd() > 0);
-
- // Get the name of the slave
- let slave_name1 = unsafe { ptsname(&master_fd) }.unwrap();
- let slave_name2 = unsafe { ptsname(&master_fd) }.unwrap();
- assert_eq!(slave_name1, slave_name2);
- // Also make sure that the string was actually copied and they point to different parts of
- // memory.
- assert!(slave_name1.as_ptr() != slave_name2.as_ptr());
-}
-
-/// Test data copying of `ptsname_r`
-#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
-fn test_ptsname_r_copy() {
- // Open a new PTTY master
- let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
- assert!(master_fd.as_raw_fd() > 0);
-
- // Get the name of the slave
- let slave_name1 = ptsname_r(&master_fd).unwrap();
- let slave_name2 = ptsname_r(&master_fd).unwrap();
- assert_eq!(slave_name1, slave_name2);
- assert!(slave_name1.as_ptr() != slave_name2.as_ptr());
-}
-
-/// Test that `ptsname` returns different names for different devices
-#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
-fn test_ptsname_unique() {
- let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-
- // Open a new PTTY master
- let master1_fd = posix_openpt(OFlag::O_RDWR).unwrap();
- assert!(master1_fd.as_raw_fd() > 0);
-
- // Open a second PTTY master
- let master2_fd = posix_openpt(OFlag::O_RDWR).unwrap();
- assert!(master2_fd.as_raw_fd() > 0);
-
- // Get the name of the slave
- let slave_name1 = unsafe { ptsname(&master1_fd) }.unwrap();
- let slave_name2 = unsafe { ptsname(&master2_fd) }.unwrap();
- assert!(slave_name1 != slave_name2);
-}
-
-/// Common setup for testing PTTY pairs
-fn open_ptty_pair() -> (PtyMaster, File) {
- let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-
- // Open a new PTTY master
- let master = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed");
-
- // Allow a slave to be generated for it
- grantpt(&master).expect("grantpt failed");
- unlockpt(&master).expect("unlockpt failed");
-
- // Get the name of the slave
- let slave_name = unsafe { ptsname(&master) }.expect("ptsname failed");
-
- // Open the slave device
- let slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, stat::Mode::empty()).unwrap();
- let slave = unsafe { File::from_raw_fd(slave_fd) };
-
- (master, slave)
-}
-
-/// Test opening a master/slave PTTY pair
-///
-/// This uses a common `open_ptty_pair` because much of these functions aren't useful by
-/// themselves. So for this test we perform the basic act of getting a file handle for a
-/// master/slave PTTY pair, then just sanity-check the raw values.
-#[test]
-fn test_open_ptty_pair() {
- let (master, slave) = open_ptty_pair();
- assert!(master.as_raw_fd() > 0);
- assert!(slave.as_raw_fd() > 0);
-}
-
-/// Put the terminal in raw mode.
-fn make_raw(fd: RawFd) {
- let mut termios = tcgetattr(fd).unwrap();
- cfmakeraw(&mut termios);
- tcsetattr(fd, SetArg::TCSANOW, &termios).unwrap();
-}
-
-/// Test `io::Read` on the PTTY master
-#[test]
-fn test_read_ptty_pair() {
- let (mut master, mut slave) = open_ptty_pair();
- make_raw(slave.as_raw_fd());
-
- let mut buf = [0u8; 5];
- slave.write_all(b"hello").unwrap();
- master.read_exact(&mut buf).unwrap();
- assert_eq!(&buf, b"hello");
-}
-
-/// Test `io::Write` on the PTTY master
-#[test]
-fn test_write_ptty_pair() {
- let (mut master, mut slave) = open_ptty_pair();
- make_raw(slave.as_raw_fd());
-
- let mut buf = [0u8; 5];
- master.write_all(b"adios").unwrap();
- slave.read_exact(&mut buf).unwrap();
- assert_eq!(&buf, b"adios");
-}
-
-#[test]
-fn test_openpty() {
- // openpty uses ptname(3) internally
- let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-
- let pty = openpty(None, None).unwrap();
- assert!(pty.master > 0);
- assert!(pty.slave > 0);
-
- // Writing to one should be readable on the other one
- let string = "foofoofoo\n";
- let mut buf = [0u8; 10];
- write(pty.master, string.as_bytes()).unwrap();
- crate::read_exact(pty.slave, &mut buf);
-
- assert_eq!(&buf, string.as_bytes());
-
- // Read the echo as well
- let echoed_string = "foofoofoo\r\n";
- let mut buf = [0u8; 11];
- crate::read_exact(pty.master, &mut buf);
- assert_eq!(&buf, echoed_string.as_bytes());
-
- let string2 = "barbarbarbar\n";
- let echoed_string2 = "barbarbarbar\r\n";
- let mut buf = [0u8; 14];
- write(pty.slave, string2.as_bytes()).unwrap();
- crate::read_exact(pty.master, &mut buf);
-
- assert_eq!(&buf, echoed_string2.as_bytes());
-
- close(pty.master).unwrap();
- close(pty.slave).unwrap();
-}
-
-#[test]
-fn test_openpty_with_termios() {
- // openpty uses ptname(3) internally
- let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-
- // Open one pty to get attributes for the second one
- let mut termios = {
- let pty = openpty(None, None).unwrap();
- assert!(pty.master > 0);
- assert!(pty.slave > 0);
- let termios = tcgetattr(pty.slave).unwrap();
- close(pty.master).unwrap();
- close(pty.slave).unwrap();
- termios
- };
- // Make sure newlines are not transformed so the data is preserved when sent.
- termios.output_flags.remove(OutputFlags::ONLCR);
-
- let pty = openpty(None, &termios).unwrap();
- // Must be valid file descriptors
- assert!(pty.master > 0);
- assert!(pty.slave > 0);
-
- // Writing to one should be readable on the other one
- let string = "foofoofoo\n";
- let mut buf = [0u8; 10];
- write(pty.master, string.as_bytes()).unwrap();
- crate::read_exact(pty.slave, &mut buf);
-
- assert_eq!(&buf, string.as_bytes());
-
- // read the echo as well
- let echoed_string = "foofoofoo\n";
- crate::read_exact(pty.master, &mut buf);
- assert_eq!(&buf, echoed_string.as_bytes());
-
- let string2 = "barbarbarbar\n";
- let echoed_string2 = "barbarbarbar\n";
- let mut buf = [0u8; 13];
- write(pty.slave, string2.as_bytes()).unwrap();
- crate::read_exact(pty.master, &mut buf);
-
- assert_eq!(&buf, echoed_string2.as_bytes());
-
- close(pty.master).unwrap();
- close(pty.slave).unwrap();
-}
-
-#[test]
-fn test_forkpty() {
- use nix::unistd::ForkResult::*;
- use nix::sys::signal::*;
- use nix::sys::wait::wait;
- // forkpty calls openpty which uses ptname(3) internally.
- let _m0 = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
- // forkpty spawns a child process
- let _m1 = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-
- let string = "naninani\n";
- let echoed_string = "naninani\r\n";
- let pty = forkpty(None, None).unwrap();
- match pty.fork_result {
- Child => {
- write(STDOUT_FILENO, string.as_bytes()).unwrap();
- pause(); // we need the child to stay alive until the parent calls read
- unsafe { _exit(0); }
- },
- Parent { child } => {
- let mut buf = [0u8; 10];
- assert!(child.as_raw() > 0);
- crate::read_exact(pty.master, &mut buf);
- kill(child, SIGTERM).unwrap();
- wait().unwrap(); // keep other tests using generic wait from getting our child
- assert_eq!(&buf, echoed_string.as_bytes());
- close(pty.master).unwrap();
- },
- }
-}
diff --git a/vendor/nix-0.20.0/test/test_ptymaster_drop.rs b/vendor/nix-0.20.0/test/test_ptymaster_drop.rs
deleted file mode 100644
index ff939b9..0000000
--- a/vendor/nix-0.20.0/test/test_ptymaster_drop.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-mod t {
- use nix::fcntl::OFlag;
- use nix::pty::*;
- use nix::unistd::close;
- use std::os::unix::io::AsRawFd;
-
- /// Regression test for Issue #659
- ///
- /// `PtyMaster` should panic rather than double close the file descriptor
- /// This must run in its own test process because it deliberately creates a
- /// race condition.
- #[test]
- #[should_panic(expected = "Closing an invalid file descriptor!")]
- // In Travis on i686-unknown-linux-musl, this test gets SIGABRT. I don't
- // know why. It doesn't happen on any other target, and it doesn't happen
- // on my PC.
- #[cfg_attr(all(target_env = "musl", target_arch = "x86"), ignore)]
- fn test_double_close() {
- let m = posix_openpt(OFlag::O_RDWR).unwrap();
- close(m.as_raw_fd()).unwrap();
- drop(m); // should panic here
- }
-}
diff --git a/vendor/nix-0.20.0/test/test_sched.rs b/vendor/nix-0.20.0/test/test_sched.rs
deleted file mode 100644
index 922196a..0000000
--- a/vendor/nix-0.20.0/test/test_sched.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-use nix::sched::{sched_getaffinity, sched_setaffinity, CpuSet};
-use nix::unistd::Pid;
-
-#[test]
-fn test_sched_affinity() {
- // If pid is zero, then the mask of the calling process is returned.
- let initial_affinity = sched_getaffinity(Pid::from_raw(0)).unwrap();
- let mut at_least_one_cpu = false;
- let mut last_valid_cpu = 0;
- for field in 0..CpuSet::count() {
- if initial_affinity.is_set(field).unwrap() {
- at_least_one_cpu = true;
- last_valid_cpu = field;
- }
- }
- assert!(at_least_one_cpu);
-
- // Now restrict the running CPU
- let mut new_affinity = CpuSet::new();
- new_affinity.set(last_valid_cpu).unwrap();
- sched_setaffinity(Pid::from_raw(0), &new_affinity).unwrap();
-
- // And now re-check the affinity which should be only the one we set.
- let updated_affinity = sched_getaffinity(Pid::from_raw(0)).unwrap();
- for field in 0..CpuSet::count() {
- // Should be set only for the CPU we set previously
- assert_eq!(updated_affinity.is_set(field).unwrap(), field==last_valid_cpu)
- }
-
- // Finally, reset the initial CPU set
- sched_setaffinity(Pid::from_raw(0), &initial_affinity).unwrap();
-}
diff --git a/vendor/nix-0.20.0/test/test_sendfile.rs b/vendor/nix-0.20.0/test/test_sendfile.rs
deleted file mode 100644
index 3bc7932..0000000
--- a/vendor/nix-0.20.0/test/test_sendfile.rs
+++ /dev/null
@@ -1,129 +0,0 @@
-use std::io::prelude::*;
-use std::os::unix::prelude::*;
-
-use libc::off_t;
-use nix::sys::sendfile::*;
-use tempfile::tempfile;
-
-cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
- use nix::unistd::{close, pipe, read};
- } else if #[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))] {
- use std::net::Shutdown;
- use std::os::unix::net::UnixStream;
- }
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[test]
-fn test_sendfile_linux() {
- const CONTENTS: &[u8] = b"abcdef123456";
- let mut tmp = tempfile().unwrap();
- tmp.write_all(CONTENTS).unwrap();
-
- let (rd, wr) = pipe().unwrap();
- let mut offset: off_t = 5;
- let res = sendfile(wr, tmp.as_raw_fd(), Some(&mut offset), 2).unwrap();
-
- assert_eq!(2, res);
-
- let mut buf = [0u8; 1024];
- assert_eq!(2, read(rd, &mut buf).unwrap());
- assert_eq!(b"f1", &buf[0..2]);
- assert_eq!(7, offset);
-
- close(rd).unwrap();
- close(wr).unwrap();
-}
-
-#[cfg(target_os = "freebsd")]
-#[test]
-fn test_sendfile_freebsd() {
- // Declare the content
- let header_strings = vec!["HTTP/1.1 200 OK\n", "Content-Type: text/plain\n", "\n"];
- let body = "Xabcdef123456";
- let body_offset = 1;
- let trailer_strings = vec!["\n", "Served by Make Believe\n"];
-
- // Write the body to a file
- let mut tmp = tempfile().unwrap();
- tmp.write_all(body.as_bytes()).unwrap();
-
- // Prepare headers and trailers for sendfile
- let headers: Vec<&[u8]> = header_strings.iter().map(|s| s.as_bytes()).collect();
- let trailers: Vec<&[u8]> = trailer_strings.iter().map(|s| s.as_bytes()).collect();
-
- // Prepare socket pair
- let (mut rd, wr) = UnixStream::pair().unwrap();
-
- // Call the test method
- let (res, bytes_written) = sendfile(
- tmp.as_raw_fd(),
- wr.as_raw_fd(),
- body_offset as off_t,
- None,
- Some(headers.as_slice()),
- Some(trailers.as_slice()),
- SfFlags::empty(),
- 0,
- );
- assert!(res.is_ok());
- wr.shutdown(Shutdown::Both).unwrap();
-
- // Prepare the expected result
- let expected_string =
- header_strings.concat() + &body[body_offset..] + &trailer_strings.concat();
-
- // Verify the message that was sent
- assert_eq!(bytes_written as usize, expected_string.as_bytes().len());
-
- let mut read_string = String::new();
- let bytes_read = rd.read_to_string(&mut read_string).unwrap();
- assert_eq!(bytes_written as usize, bytes_read);
- assert_eq!(expected_string, read_string);
-}
-
-#[cfg(any(target_os = "ios", target_os = "macos"))]
-#[test]
-fn test_sendfile_darwin() {
- // Declare the content
- let header_strings = vec!["HTTP/1.1 200 OK\n", "Content-Type: text/plain\n", "\n"];
- let body = "Xabcdef123456";
- let body_offset = 1;
- let trailer_strings = vec!["\n", "Served by Make Believe\n"];
-
- // Write the body to a file
- let mut tmp = tempfile().unwrap();
- tmp.write_all(body.as_bytes()).unwrap();
-
- // Prepare headers and trailers for sendfile
- let headers: Vec<&[u8]> = header_strings.iter().map(|s| s.as_bytes()).collect();
- let trailers: Vec<&[u8]> = trailer_strings.iter().map(|s| s.as_bytes()).collect();
-
- // Prepare socket pair
- let (mut rd, wr) = UnixStream::pair().unwrap();
-
- // Call the test method
- let (res, bytes_written) = sendfile(
- tmp.as_raw_fd(),
- wr.as_raw_fd(),
- body_offset as off_t,
- None,
- Some(headers.as_slice()),
- Some(trailers.as_slice()),
- );
- assert!(res.is_ok());
- wr.shutdown(Shutdown::Both).unwrap();
-
- // Prepare the expected result
- let expected_string =
- header_strings.concat() + &body[body_offset..] + &trailer_strings.concat();
-
- // Verify the message that was sent
- assert_eq!(bytes_written as usize, expected_string.as_bytes().len());
-
- let mut read_string = String::new();
- let bytes_read = rd.read_to_string(&mut read_string).unwrap();
- assert_eq!(bytes_written as usize, bytes_read);
- assert_eq!(expected_string, read_string);
-}
diff --git a/vendor/nix-0.20.0/test/test_stat.rs b/vendor/nix-0.20.0/test/test_stat.rs
deleted file mode 100644
index 0b94666..0000000
--- a/vendor/nix-0.20.0/test/test_stat.rs
+++ /dev/null
@@ -1,319 +0,0 @@
-#[cfg(not(target_os = "redox"))]
-use std::fs;
-use std::fs::File;
-#[cfg(not(target_os = "redox"))]
-use std::os::unix::fs::{symlink, PermissionsExt};
-use std::os::unix::prelude::AsRawFd;
-#[cfg(not(target_os = "redox"))]
-use std::time::{Duration, UNIX_EPOCH};
-#[cfg(not(target_os = "redox"))]
-use std::path::Path;
-
-#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
-use libc::{S_IFMT, S_IFLNK, mode_t};
-
-#[cfg(not(target_os = "redox"))]
-use nix::{fcntl, Error};
-#[cfg(not(target_os = "redox"))]
-use nix::errno::Errno;
-#[cfg(not(target_os = "redox"))]
-use nix::sys::stat::{self, futimens, utimes};
-use nix::sys::stat::{fchmod, stat};
-#[cfg(not(target_os = "redox"))]
-use nix::sys::stat::{fchmodat, utimensat, mkdirat};
-#[cfg(any(target_os = "linux",
- target_os = "haiku",
- target_os = "ios",
- target_os = "macos",
- target_os = "freebsd",
- target_os = "netbsd"))]
-use nix::sys::stat::lutimes;
-#[cfg(not(target_os = "redox"))]
-use nix::sys::stat::{FchmodatFlags, UtimensatFlags};
-use nix::sys::stat::Mode;
-
-#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
-use nix::sys::stat::FileStat;
-
-#[cfg(not(target_os = "redox"))]
-use nix::sys::time::{TimeSpec, TimeVal, TimeValLike};
-#[cfg(not(target_os = "redox"))]
-use nix::unistd::chdir;
-
-#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
-use nix::Result;
-use tempfile;
-
-#[allow(unused_comparisons)]
-// uid and gid are signed on Windows, but not on other platforms. This function
-// allows warning free compiles on all platforms, and can be removed when
-// expression-level #[allow] is available.
-#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
-fn valid_uid_gid(stat: FileStat) -> bool {
- // uid could be 0 for the `root` user. This quite possible when
- // the tests are being run on a rooted Android device.
- stat.st_uid >= 0 && stat.st_gid >= 0
-}
-
-#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
-fn assert_stat_results(stat_result: Result<FileStat>) {
- let stats = stat_result.expect("stat call failed");
- assert!(stats.st_dev > 0); // must be positive integer, exact number machine dependent
- assert!(stats.st_ino > 0); // inode is positive integer, exact number machine dependent
- assert!(stats.st_mode > 0); // must be positive integer
- assert_eq!(stats.st_nlink, 1); // there links created, must be 1
- assert!(valid_uid_gid(stats)); // must be positive integers
- assert_eq!(stats.st_size, 0); // size is 0 because we did not write anything to the file
- assert!(stats.st_blksize > 0); // must be positive integer, exact number machine dependent
- assert!(stats.st_blocks <= 16); // Up to 16 blocks can be allocated for a blank file
-}
-
-#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
-fn assert_lstat_results(stat_result: Result<FileStat>) {
- let stats = stat_result.expect("stat call failed");
- assert!(stats.st_dev > 0); // must be positive integer, exact number machine dependent
- assert!(stats.st_ino > 0); // inode is positive integer, exact number machine dependent
- assert!(stats.st_mode > 0); // must be positive integer
-
- // st_mode is c_uint (u32 on Android) while S_IFMT is mode_t
- // (u16 on Android), and that will be a compile error.
- // On other platforms they are the same (either both are u16 or u32).
- assert_eq!((stats.st_mode as usize) & (S_IFMT as usize), S_IFLNK as usize); // should be a link
- assert_eq!(stats.st_nlink, 1); // there links created, must be 1
- assert!(valid_uid_gid(stats)); // must be positive integers
- assert!(stats.st_size > 0); // size is > 0 because it points to another file
- assert!(stats.st_blksize > 0); // must be positive integer, exact number machine dependent
-
- // st_blocks depends on whether the machine's file system uses fast
- // or slow symlinks, so just make sure it's not negative
- // (Android's st_blocks is ulonglong which is always non-negative.)
- assert!(stats.st_blocks >= 0);
-}
-
-#[test]
-#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
-fn test_stat_and_fstat() {
- use nix::sys::stat::fstat;
-
- let tempdir = tempfile::tempdir().unwrap();
- let filename = tempdir.path().join("foo.txt");
- let file = File::create(&filename).unwrap();
-
- let stat_result = stat(&filename);
- assert_stat_results(stat_result);
-
- let fstat_result = fstat(file.as_raw_fd());
- assert_stat_results(fstat_result);
-}
-
-#[test]
-#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
-fn test_fstatat() {
- let tempdir = tempfile::tempdir().unwrap();
- let filename = tempdir.path().join("foo.txt");
- File::create(&filename).unwrap();
- let dirfd = fcntl::open(tempdir.path(),
- fcntl::OFlag::empty(),
- stat::Mode::empty());
-
- let result = stat::fstatat(dirfd.unwrap(),
- &filename,
- fcntl::AtFlags::empty());
- assert_stat_results(result);
-}
-
-#[test]
-#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
-fn test_stat_fstat_lstat() {
- use nix::sys::stat::{fstat, lstat};
-
- let tempdir = tempfile::tempdir().unwrap();
- let filename = tempdir.path().join("bar.txt");
- let linkname = tempdir.path().join("barlink");
-
- File::create(&filename).unwrap();
- symlink("bar.txt", &linkname).unwrap();
- let link = File::open(&linkname).unwrap();
-
- // should be the same result as calling stat,
- // since it's a regular file
- let stat_result = stat(&filename);
- assert_stat_results(stat_result);
-
- let lstat_result = lstat(&linkname);
- assert_lstat_results(lstat_result);
-
- let fstat_result = fstat(link.as_raw_fd());
- assert_stat_results(fstat_result);
-}
-
-#[test]
-fn test_fchmod() {
- let tempdir = tempfile::tempdir().unwrap();
- let filename = tempdir.path().join("foo.txt");
- let file = File::create(&filename).unwrap();
-
- let mut mode1 = Mode::empty();
- mode1.insert(Mode::S_IRUSR);
- mode1.insert(Mode::S_IWUSR);
- fchmod(file.as_raw_fd(), mode1).unwrap();
-
- let file_stat1 = stat(&filename).unwrap();
- assert_eq!(file_stat1.st_mode & 0o7777, mode1.bits());
-
- let mut mode2 = Mode::empty();
- mode2.insert(Mode::S_IROTH);
- fchmod(file.as_raw_fd(), mode2).unwrap();
-
- let file_stat2 = stat(&filename).unwrap();
- assert_eq!(file_stat2.st_mode & 0o7777, mode2.bits());
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_fchmodat() {
- let _dr = crate::DirRestore::new();
- let tempdir = tempfile::tempdir().unwrap();
- let filename = "foo.txt";
- let fullpath = tempdir.path().join(filename);
- File::create(&fullpath).unwrap();
-
- let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-
- let mut mode1 = Mode::empty();
- mode1.insert(Mode::S_IRUSR);
- mode1.insert(Mode::S_IWUSR);
- fchmodat(Some(dirfd), filename, mode1, FchmodatFlags::FollowSymlink).unwrap();
-
- let file_stat1 = stat(&fullpath).unwrap();
- assert_eq!(file_stat1.st_mode & 0o7777, mode1.bits());
-
- chdir(tempdir.path()).unwrap();
-
- let mut mode2 = Mode::empty();
- mode2.insert(Mode::S_IROTH);
- fchmodat(None, filename, mode2, FchmodatFlags::FollowSymlink).unwrap();
-
- let file_stat2 = stat(&fullpath).unwrap();
- assert_eq!(file_stat2.st_mode & 0o7777, mode2.bits());
-}
-
-/// Asserts that the atime and mtime in a file's metadata match expected values.
-///
-/// The atime and mtime are expressed with a resolution of seconds because some file systems
-/// (like macOS's HFS+) do not have higher granularity.
-#[cfg(not(target_os = "redox"))]
-fn assert_times_eq(exp_atime_sec: u64, exp_mtime_sec: u64, attr: &fs::Metadata) {
- assert_eq!(
- Duration::new(exp_atime_sec, 0),
- attr.accessed().unwrap().duration_since(UNIX_EPOCH).unwrap());
- assert_eq!(
- Duration::new(exp_mtime_sec, 0),
- attr.modified().unwrap().duration_since(UNIX_EPOCH).unwrap());
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_utimes() {
- let tempdir = tempfile::tempdir().unwrap();
- let fullpath = tempdir.path().join("file");
- drop(File::create(&fullpath).unwrap());
-
- utimes(&fullpath, &TimeVal::seconds(9990), &TimeVal::seconds(5550)).unwrap();
- assert_times_eq(9990, 5550, &fs::metadata(&fullpath).unwrap());
-}
-
-#[test]
-#[cfg(any(target_os = "linux",
- target_os = "haiku",
- target_os = "ios",
- target_os = "macos",
- target_os = "freebsd",
- target_os = "netbsd"))]
-fn test_lutimes() {
- let tempdir = tempfile::tempdir().unwrap();
- let target = tempdir.path().join("target");
- let fullpath = tempdir.path().join("symlink");
- drop(File::create(&target).unwrap());
- symlink(&target, &fullpath).unwrap();
-
- let exp_target_metadata = fs::symlink_metadata(&target).unwrap();
- lutimes(&fullpath, &TimeVal::seconds(4560), &TimeVal::seconds(1230)).unwrap();
- assert_times_eq(4560, 1230, &fs::symlink_metadata(&fullpath).unwrap());
-
- let target_metadata = fs::symlink_metadata(&target).unwrap();
- assert_eq!(exp_target_metadata.accessed().unwrap(), target_metadata.accessed().unwrap(),
- "atime of symlink target was unexpectedly modified");
- assert_eq!(exp_target_metadata.modified().unwrap(), target_metadata.modified().unwrap(),
- "mtime of symlink target was unexpectedly modified");
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_futimens() {
- let tempdir = tempfile::tempdir().unwrap();
- let fullpath = tempdir.path().join("file");
- drop(File::create(&fullpath).unwrap());
-
- let fd = fcntl::open(&fullpath, fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-
- futimens(fd, &TimeSpec::seconds(10), &TimeSpec::seconds(20)).unwrap();
- assert_times_eq(10, 20, &fs::metadata(&fullpath).unwrap());
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_utimensat() {
- let _dr = crate::DirRestore::new();
- let tempdir = tempfile::tempdir().unwrap();
- let filename = "foo.txt";
- let fullpath = tempdir.path().join(filename);
- drop(File::create(&fullpath).unwrap());
-
- let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-
- utimensat(Some(dirfd), filename, &TimeSpec::seconds(12345), &TimeSpec::seconds(678),
- UtimensatFlags::FollowSymlink).unwrap();
- assert_times_eq(12345, 678, &fs::metadata(&fullpath).unwrap());
-
- chdir(tempdir.path()).unwrap();
-
- utimensat(None, filename, &TimeSpec::seconds(500), &TimeSpec::seconds(800),
- UtimensatFlags::FollowSymlink).unwrap();
- assert_times_eq(500, 800, &fs::metadata(&fullpath).unwrap());
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_mkdirat_success_path() {
- let tempdir = tempfile::tempdir().unwrap();
- let filename = "example_subdir";
- let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
- assert!((mkdirat(dirfd, filename, Mode::S_IRWXU)).is_ok());
- assert!(Path::exists(&tempdir.path().join(filename)));
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_mkdirat_success_mode() {
- let expected_bits = stat::SFlag::S_IFDIR.bits() | stat::Mode::S_IRWXU.bits();
- let tempdir = tempfile::tempdir().unwrap();
- let filename = "example_subdir";
- let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
- assert!((mkdirat(dirfd, filename, Mode::S_IRWXU)).is_ok());
- let permissions = fs::metadata(tempdir.path().join(filename)).unwrap().permissions();
- let mode = permissions.mode();
- assert_eq!(mode as mode_t, expected_bits)
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_mkdirat_fail() {
- let tempdir = tempfile::tempdir().unwrap();
- let not_dir_filename= "example_not_dir";
- let filename = "example_subdir_dir";
- let dirfd = fcntl::open(&tempdir.path().join(not_dir_filename), fcntl::OFlag::O_CREAT,
- stat::Mode::empty()).unwrap();
- let result = mkdirat(dirfd, filename, Mode::S_IRWXU).unwrap_err();
- assert_eq!(result, Error::Sys(Errno::ENOTDIR));
-}
diff --git a/vendor/nix-0.20.0/test/test_time.rs b/vendor/nix-0.20.0/test/test_time.rs
deleted file mode 100644
index c321352..0000000
--- a/vendor/nix-0.20.0/test/test_time.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-#[cfg(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
-))]
-use nix::time::clock_getcpuclockid;
-use nix::time::{clock_getres, clock_gettime, ClockId};
-
-#[test]
-pub fn test_clock_getres() {
- assert!(clock_getres(ClockId::CLOCK_REALTIME).is_ok());
-}
-
-#[test]
-pub fn test_clock_gettime() {
- assert!(clock_gettime(ClockId::CLOCK_REALTIME).is_ok());
-}
-
-#[cfg(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
-))]
-#[test]
-pub fn test_clock_getcpuclockid() {
- let clock_id = clock_getcpuclockid(nix::unistd::Pid::this()).unwrap();
- assert!(clock_gettime(clock_id).is_ok());
-}
-
-#[test]
-pub fn test_clock_id_res() {
- assert!(ClockId::CLOCK_REALTIME.res().is_ok());
-}
-
-#[test]
-pub fn test_clock_id_now() {
- assert!(ClockId::CLOCK_REALTIME.now().is_ok());
-}
-
-#[cfg(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
-))]
-#[test]
-pub fn test_clock_id_pid_cpu_clock_id() {
- assert!(ClockId::pid_cpu_clock_id(nix::unistd::Pid::this())
- .map(ClockId::now)
- .is_ok());
-}
diff --git a/vendor/nix-0.20.0/test/test_unistd.rs b/vendor/nix-0.20.0/test/test_unistd.rs
deleted file mode 100644
index 16a8a05..0000000
--- a/vendor/nix-0.20.0/test/test_unistd.rs
+++ /dev/null
@@ -1,1110 +0,0 @@
-#[cfg(not(target_os = "redox"))]
-use nix::fcntl::{self, open, readlink};
-use nix::fcntl::{fcntl, FcntlArg, FdFlag, OFlag};
-use nix::unistd::*;
-use nix::unistd::ForkResult::*;
-#[cfg(not(target_os = "redox"))]
-use nix::sys::signal::{SaFlags, SigAction, SigHandler, SigSet, Signal, sigaction};
-use nix::sys::wait::*;
-use nix::sys::stat::{self, Mode, SFlag};
-#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-use nix::pty::{posix_openpt, grantpt, unlockpt, ptsname};
-use nix::errno::Errno;
-#[cfg(not(target_os = "redox"))]
-use nix::Error;
-use std::{env, iter};
-#[cfg(not(target_os = "redox"))]
-use std::ffi::CString;
-#[cfg(not(target_os = "redox"))]
-use std::fs::DirBuilder;
-use std::fs::{self, File};
-use std::io::Write;
-use std::os::unix::prelude::*;
-#[cfg(not(target_os = "redox"))]
-use std::path::Path;
-use tempfile::{tempdir, tempfile};
-use libc::{_exit, off_t};
-
-use crate::*;
-
-#[test]
-#[cfg(not(any(target_os = "netbsd")))]
-fn test_fork_and_waitpid() {
- let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-
- // Safe: Child only calls `_exit`, which is signal-safe
- match unsafe{fork()}.expect("Error: Fork Failed") {
- Child => unsafe { _exit(0) },
- Parent { child } => {
- // assert that child was created and pid > 0
- let child_raw: ::libc::pid_t = child.into();
- assert!(child_raw > 0);
- let wait_status = waitpid(child, None);
- match wait_status {
- // assert that waitpid returned correct status and the pid is the one of the child
- Ok(WaitStatus::Exited(pid_t, _)) => assert_eq!(pid_t, child),
-
- // panic, must never happen
- s @ Ok(_) => panic!("Child exited {:?}, should never happen", s),
-
- // panic, waitpid should never fail
- Err(s) => panic!("Error: waitpid returned Err({:?}", s)
- }
-
- },
- }
-}
-
-#[test]
-fn test_wait() {
- // Grab FORK_MTX so wait doesn't reap a different test's child process
- let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-
- // Safe: Child only calls `_exit`, which is signal-safe
- match unsafe{fork()}.expect("Error: Fork Failed") {
- Child => unsafe { _exit(0) },
- Parent { child } => {
- let wait_status = wait();
-
- // just assert that (any) one child returns with WaitStatus::Exited
- assert_eq!(wait_status, Ok(WaitStatus::Exited(child, 0)));
- },
- }
-}
-
-#[test]
-fn test_mkstemp() {
- let mut path = env::temp_dir();
- path.push("nix_tempfile.XXXXXX");
-
- let result = mkstemp(&path);
- match result {
- Ok((fd, path)) => {
- close(fd).unwrap();
- unlink(path.as_path()).unwrap();
- },
- Err(e) => panic!("mkstemp failed: {}", e)
- }
-}
-
-#[test]
-fn test_mkstemp_directory() {
- // mkstemp should fail if a directory is given
- assert!(mkstemp(&env::temp_dir()).is_err());
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_mkfifo() {
- let tempdir = tempdir().unwrap();
- let mkfifo_fifo = tempdir.path().join("mkfifo_fifo");
-
- mkfifo(&mkfifo_fifo, Mode::S_IRUSR).unwrap();
-
- let stats = stat::stat(&mkfifo_fifo).unwrap();
- let typ = stat::SFlag::from_bits_truncate(stats.st_mode);
- assert!(typ == SFlag::S_IFIFO);
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_mkfifo_directory() {
- // mkfifo should fail if a directory is given
- assert!(mkfifo(&env::temp_dir(), Mode::S_IRUSR).is_err());
-}
-
-#[test]
-#[cfg(not(any(
- target_os = "macos", target_os = "ios",
- target_os = "android", target_os = "redox")))]
-fn test_mkfifoat_none() {
- let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-
- let tempdir = tempdir().unwrap();
- let mkfifoat_fifo = tempdir.path().join("mkfifoat_fifo");
-
- mkfifoat(None, &mkfifoat_fifo, Mode::S_IRUSR).unwrap();
-
- let stats = stat::stat(&mkfifoat_fifo).unwrap();
- let typ = stat::SFlag::from_bits_truncate(stats.st_mode);
- assert_eq!(typ, SFlag::S_IFIFO);
-}
-
-#[test]
-#[cfg(not(any(
- target_os = "macos", target_os = "ios",
- target_os = "android", target_os = "redox")))]
-fn test_mkfifoat() {
- let tempdir = tempdir().unwrap();
- let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
- let mkfifoat_name = "mkfifoat_name";
-
- mkfifoat(Some(dirfd), mkfifoat_name, Mode::S_IRUSR).unwrap();
-
- let stats = stat::fstatat(dirfd, mkfifoat_name, fcntl::AtFlags::empty()).unwrap();
- let typ = stat::SFlag::from_bits_truncate(stats.st_mode);
- assert_eq!(typ, SFlag::S_IFIFO);
-}
-
-#[test]
-#[cfg(not(any(
- target_os = "macos", target_os = "ios",
- target_os = "android", target_os = "redox")))]
-fn test_mkfifoat_directory_none() {
- let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-
- // mkfifoat should fail if a directory is given
- assert!(!mkfifoat(None, &env::temp_dir(), Mode::S_IRUSR).is_ok());
-}
-
-#[test]
-#[cfg(not(any(
- target_os = "macos", target_os = "ios",
- target_os = "android", target_os = "redox")))]
-fn test_mkfifoat_directory() {
- // mkfifoat should fail if a directory is given
- let tempdir = tempdir().unwrap();
- let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
- let mkfifoat_dir = "mkfifoat_dir";
- stat::mkdirat(dirfd, mkfifoat_dir, Mode::S_IRUSR).unwrap();
-
- assert!(!mkfifoat(Some(dirfd), mkfifoat_dir, Mode::S_IRUSR).is_ok());
-}
-
-#[test]
-fn test_getpid() {
- let pid: ::libc::pid_t = getpid().into();
- let ppid: ::libc::pid_t = getppid().into();
- assert!(pid > 0);
- assert!(ppid > 0);
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_getsid() {
- let none_sid: ::libc::pid_t = getsid(None).unwrap().into();
- let pid_sid: ::libc::pid_t = getsid(Some(getpid())).unwrap().into();
- assert!(none_sid > 0);
- assert_eq!(none_sid, pid_sid);
-}
-
-#[cfg(any(target_os = "linux", target_os = "android"))]
-mod linux_android {
- use nix::unistd::gettid;
-
- #[test]
- fn test_gettid() {
- let tid: ::libc::pid_t = gettid().into();
- assert!(tid > 0);
- }
-}
-
-#[test]
-// `getgroups()` and `setgroups()` do not behave as expected on Apple platforms
-#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox", target_os = "fuchsia")))]
-fn test_setgroups() {
- // Skip this test when not run as root as `setgroups()` requires root.
- skip_if_not_root!("test_setgroups");
-
- let _m = crate::GROUPS_MTX.lock().expect("Mutex got poisoned by another test");
-
- // Save the existing groups
- let old_groups = getgroups().unwrap();
-
- // Set some new made up groups
- let groups = [Gid::from_raw(123), Gid::from_raw(456)];
- setgroups(&groups).unwrap();
-
- let new_groups = getgroups().unwrap();
- assert_eq!(new_groups, groups);
-
- // Revert back to the old groups
- setgroups(&old_groups).unwrap();
-}
-
-#[test]
-// `getgroups()` and `setgroups()` do not behave as expected on Apple platforms
-#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox", target_os = "fuchsia")))]
-fn test_initgroups() {
- // Skip this test when not run as root as `initgroups()` and `setgroups()`
- // require root.
- skip_if_not_root!("test_initgroups");
-
- let _m = crate::GROUPS_MTX.lock().expect("Mutex got poisoned by another test");
-
- // Save the existing groups
- let old_groups = getgroups().unwrap();
-
- // It doesn't matter if the root user is not called "root" or if a user
- // called "root" doesn't exist. We are just checking that the extra,
- // made-up group, `123`, is set.
- // FIXME: Test the other half of initgroups' functionality: whether the
- // groups that the user belongs to are also set.
- let user = CString::new("root").unwrap();
- let group = Gid::from_raw(123);
- let group_list = getgrouplist(&user, group).unwrap();
- assert!(group_list.contains(&group));
-
- initgroups(&user, group).unwrap();
-
- let new_groups = getgroups().unwrap();
- assert_eq!(new_groups, group_list);
-
- // Revert back to the old groups
- setgroups(&old_groups).unwrap();
-}
-
-#[cfg(not(target_os = "redox"))]
-macro_rules! execve_test_factory(
- ($test_name:ident, $syscall:ident, $exe: expr $(, $pathname:expr, $flags:expr)*) => (
-
- #[cfg(test)]
- mod $test_name {
- use std::ffi::CStr;
- use super::*;
-
- const EMPTY: &'static [u8] = b"\0";
- const DASH_C: &'static [u8] = b"-c\0";
- const BIGARG: &'static [u8] = b"echo nix!!! && echo foo=$foo && echo baz=$baz\0";
- const FOO: &'static [u8] = b"foo=bar\0";
- const BAZ: &'static [u8] = b"baz=quux\0";
-
- fn syscall_cstr_ref() -> Result<std::convert::Infallible, nix::Error> {
- $syscall(
- $exe,
- $(CString::new($pathname).unwrap().as_c_str(), )*
- &[CStr::from_bytes_with_nul(EMPTY).unwrap(),
- CStr::from_bytes_with_nul(DASH_C).unwrap(),
- CStr::from_bytes_with_nul(BIGARG).unwrap()],
- &[CStr::from_bytes_with_nul(FOO).unwrap(),
- CStr::from_bytes_with_nul(BAZ).unwrap()]
- $(, $flags)*)
- }
-
- fn syscall_cstring() -> Result<std::convert::Infallible, nix::Error> {
- $syscall(
- $exe,
- $(CString::new($pathname).unwrap().as_c_str(), )*
- &[CString::from(CStr::from_bytes_with_nul(EMPTY).unwrap()),
- CString::from(CStr::from_bytes_with_nul(DASH_C).unwrap()),
- CString::from(CStr::from_bytes_with_nul(BIGARG).unwrap())],
- &[CString::from(CStr::from_bytes_with_nul(FOO).unwrap()),
- CString::from(CStr::from_bytes_with_nul(BAZ).unwrap())]
- $(, $flags)*)
- }
-
- fn common_test(syscall: fn() -> Result<std::convert::Infallible, nix::Error>) {
- if "execveat" == stringify!($syscall) {
- // Though undocumented, Docker's default seccomp profile seems to
- // block this syscall. https://github.com/nix-rust/nix/issues/1122
- skip_if_seccomp!($test_name);
- }
-
- let m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
- // The `exec`d process will write to `writer`, and we'll read that
- // data from `reader`.
- let (reader, writer) = pipe().unwrap();
-
- // Safe: Child calls `exit`, `dup`, `close` and the provided `exec*` family function.
- // NOTE: Technically, this makes the macro unsafe to use because you could pass anything.
- // The tests make sure not to do that, though.
- match unsafe{fork()}.unwrap() {
- Child => {
- // Make `writer` be the stdout of the new process.
- dup2(writer, 1).unwrap();
- let r = syscall();
- let _ = std::io::stderr()
- .write_all(format!("{:?}", r).as_bytes());
- // Should only get here in event of error
- unsafe{ _exit(1) };
- },
- Parent { child } => {
- // Wait for the child to exit.
- let ws = waitpid(child, None);
- drop(m);
- assert_eq!(ws, Ok(WaitStatus::Exited(child, 0)));
- // Read 1024 bytes.
- let mut buf = [0u8; 1024];
- read(reader, &mut buf).unwrap();
- // It should contain the things we printed using `/bin/sh`.
- let string = String::from_utf8_lossy(&buf);
- assert!(string.contains("nix!!!"));
- assert!(string.contains("foo=bar"));
- assert!(string.contains("baz=quux"));
- }
- }
- }
-
- // These tests frequently fail on musl, probably due to
- // https://github.com/nix-rust/nix/issues/555
- #[cfg_attr(target_env = "musl", ignore)]
- #[test]
- fn test_cstr_ref() {
- common_test(syscall_cstr_ref);
- }
-
- // These tests frequently fail on musl, probably due to
- // https://github.com/nix-rust/nix/issues/555
- #[cfg_attr(target_env = "musl", ignore)]
- #[test]
- fn test_cstring() {
- common_test(syscall_cstring);
- }
- }
-
- )
-);
-
-cfg_if!{
- if #[cfg(target_os = "android")] {
- execve_test_factory!(test_execve, execve, CString::new("/system/bin/sh").unwrap().as_c_str());
- execve_test_factory!(test_fexecve, fexecve, File::open("/system/bin/sh").unwrap().into_raw_fd());
- } else if #[cfg(any(target_os = "freebsd",
- target_os = "linux"))] {
- // These tests frequently fail on musl, probably due to
- // https://github.com/nix-rust/nix/issues/555
- execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str());
- execve_test_factory!(test_fexecve, fexecve, File::open("/bin/sh").unwrap().into_raw_fd());
- } else if #[cfg(any(target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))] {
- execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str());
- // No fexecve() on DragonFly, ios, macos, NetBSD, OpenBSD.
- //
- // Note for NetBSD and OpenBSD: although rust-lang/libc includes it
- // (under unix/bsd/netbsdlike/) fexecve is not currently implemented on
- // NetBSD nor on OpenBSD.
- }
-}
-
-#[cfg(any(target_os = "haiku", target_os = "linux", target_os = "openbsd"))]
-execve_test_factory!(test_execvpe, execvpe, &CString::new("sh").unwrap());
-
-cfg_if!{
- if #[cfg(target_os = "android")] {
- use nix::fcntl::AtFlags;
- execve_test_factory!(test_execveat_empty, execveat,
- File::open("/system/bin/sh").unwrap().into_raw_fd(),
- "", AtFlags::AT_EMPTY_PATH);
- execve_test_factory!(test_execveat_relative, execveat,
- File::open("/system/bin/").unwrap().into_raw_fd(),
- "./sh", AtFlags::empty());
- execve_test_factory!(test_execveat_absolute, execveat,
- File::open("/").unwrap().into_raw_fd(),
- "/system/bin/sh", AtFlags::empty());
- } else if #[cfg(all(target_os = "linux", any(target_arch ="x86_64", target_arch ="x86")))] {
- use nix::fcntl::AtFlags;
- execve_test_factory!(test_execveat_empty, execveat, File::open("/bin/sh").unwrap().into_raw_fd(),
- "", AtFlags::AT_EMPTY_PATH);
- execve_test_factory!(test_execveat_relative, execveat, File::open("/bin/").unwrap().into_raw_fd(),
- "./sh", AtFlags::empty());
- execve_test_factory!(test_execveat_absolute, execveat, File::open("/").unwrap().into_raw_fd(),
- "/bin/sh", AtFlags::empty());
- }
-}
-
-#[test]
-#[cfg(not(target_os = "fuchsia"))]
-fn test_fchdir() {
- // fchdir changes the process's cwd
- let _dr = crate::DirRestore::new();
-
- let tmpdir = tempdir().unwrap();
- let tmpdir_path = tmpdir.path().canonicalize().unwrap();
- let tmpdir_fd = File::open(&tmpdir_path).unwrap().into_raw_fd();
-
- assert!(fchdir(tmpdir_fd).is_ok());
- assert_eq!(getcwd().unwrap(), tmpdir_path);
-
- assert!(close(tmpdir_fd).is_ok());
-}
-
-#[test]
-fn test_getcwd() {
- // chdir changes the process's cwd
- let _dr = crate::DirRestore::new();
-
- let tmpdir = tempdir().unwrap();
- let tmpdir_path = tmpdir.path().canonicalize().unwrap();
- assert!(chdir(&tmpdir_path).is_ok());
- assert_eq!(getcwd().unwrap(), tmpdir_path);
-
- // make path 500 chars longer so that buffer doubling in getcwd
- // kicks in. Note: One path cannot be longer than 255 bytes
- // (NAME_MAX) whole path cannot be longer than PATH_MAX (usually
- // 4096 on linux, 1024 on macos)
- let mut inner_tmp_dir = tmpdir_path.to_path_buf();
- for _ in 0..5 {
- let newdir = iter::repeat("a").take(100).collect::<String>();
- inner_tmp_dir.push(newdir);
- assert!(mkdir(inner_tmp_dir.as_path(), Mode::S_IRWXU).is_ok());
- }
- assert!(chdir(inner_tmp_dir.as_path()).is_ok());
- assert_eq!(getcwd().unwrap(), inner_tmp_dir.as_path());
-}
-
-#[test]
-fn test_chown() {
- // Testing for anything other than our own UID/GID is hard.
- let uid = Some(getuid());
- let gid = Some(getgid());
-
- let tempdir = tempdir().unwrap();
- let path = tempdir.path().join("file");
- {
- File::create(&path).unwrap();
- }
-
- chown(&path, uid, gid).unwrap();
- chown(&path, uid, None).unwrap();
- chown(&path, None, gid).unwrap();
-
- fs::remove_file(&path).unwrap();
- chown(&path, uid, gid).unwrap_err();
-}
-
-#[test]
-fn test_fchown() {
- // Testing for anything other than our own UID/GID is hard.
- let uid = Some(getuid());
- let gid = Some(getgid());
-
- let path = tempfile().unwrap();
- let fd = path.as_raw_fd();
-
- fchown(fd, uid, gid).unwrap();
- fchown(fd, uid, None).unwrap();
- fchown(fd, None, gid).unwrap();
- fchown(999999999, uid, gid).unwrap_err();
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_fchownat() {
- let _dr = crate::DirRestore::new();
- // Testing for anything other than our own UID/GID is hard.
- let uid = Some(getuid());
- let gid = Some(getgid());
-
- let tempdir = tempdir().unwrap();
- let path = tempdir.path().join("file");
- {
- File::create(&path).unwrap();
- }
-
- let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
-
- fchownat(Some(dirfd), "file", uid, gid, FchownatFlags::FollowSymlink).unwrap();
-
- chdir(tempdir.path()).unwrap();
- fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap();
-
- fs::remove_file(&path).unwrap();
- fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap_err();
-}
-
-#[test]
-fn test_lseek() {
- const CONTENTS: &[u8] = b"abcdef123456";
- let mut tmp = tempfile().unwrap();
- tmp.write_all(CONTENTS).unwrap();
- let tmpfd = tmp.into_raw_fd();
-
- let offset: off_t = 5;
- lseek(tmpfd, offset, Whence::SeekSet).unwrap();
-
- let mut buf = [0u8; 7];
- crate::read_exact(tmpfd, &mut buf);
- assert_eq!(b"f123456", &buf);
-
- close(tmpfd).unwrap();
-}
-
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[test]
-fn test_lseek64() {
- const CONTENTS: &[u8] = b"abcdef123456";
- let mut tmp = tempfile().unwrap();
- tmp.write_all(CONTENTS).unwrap();
- let tmpfd = tmp.into_raw_fd();
-
- lseek64(tmpfd, 5, Whence::SeekSet).unwrap();
-
- let mut buf = [0u8; 7];
- crate::read_exact(tmpfd, &mut buf);
- assert_eq!(b"f123456", &buf);
-
- close(tmpfd).unwrap();
-}
-
-cfg_if!{
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
- macro_rules! require_acct{
- () => {
- require_capability!(CAP_SYS_PACCT);
- }
- }
- } else if #[cfg(target_os = "freebsd")] {
- macro_rules! require_acct{
- () => {
- skip_if_not_root!("test_acct");
- skip_if_jailed!("test_acct");
- }
- }
- } else if #[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] {
- macro_rules! require_acct{
- () => {
- skip_if_not_root!("test_acct");
- }
- }
- }
-}
-
-#[test]
-#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-fn test_acct() {
- use tempfile::NamedTempFile;
- use std::process::Command;
- use std::{thread, time};
-
- let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
- require_acct!();
-
- let file = NamedTempFile::new().unwrap();
- let path = file.path().to_str().unwrap();
-
- acct::enable(path).unwrap();
-
- loop {
- Command::new("echo").arg("Hello world");
- let len = fs::metadata(path).unwrap().len();
- if len > 0 { break; }
- thread::sleep(time::Duration::from_millis(10));
- }
- acct::disable().unwrap();
-}
-
-#[test]
-fn test_fpathconf_limited() {
- let f = tempfile().unwrap();
- // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test
- let path_max = fpathconf(f.as_raw_fd(), PathconfVar::PATH_MAX);
- assert!(path_max.expect("fpathconf failed").expect("PATH_MAX is unlimited") > 0);
-}
-
-#[test]
-fn test_pathconf_limited() {
- // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test
- let path_max = pathconf("/", PathconfVar::PATH_MAX);
- assert!(path_max.expect("pathconf failed").expect("PATH_MAX is unlimited") > 0);
-}
-
-#[test]
-fn test_sysconf_limited() {
- // AFAIK, OPEN_MAX is limited on all platforms, so it makes a good test
- let open_max = sysconf(SysconfVar::OPEN_MAX);
- assert!(open_max.expect("sysconf failed").expect("OPEN_MAX is unlimited") > 0);
-}
-
-#[cfg(target_os = "freebsd")]
-#[test]
-fn test_sysconf_unsupported() {
- // I know of no sysconf variables that are unsupported everywhere, but
- // _XOPEN_CRYPT is unsupported on FreeBSD 11.0, which is one of the platforms
- // we test.
- let open_max = sysconf(SysconfVar::_XOPEN_CRYPT);
- assert!(open_max.expect("sysconf failed").is_none())
-}
-
-// Test that we can create a pair of pipes. No need to verify that they pass
-// data; that's the domain of the OS, not nix.
-#[test]
-fn test_pipe() {
- let (fd0, fd1) = pipe().unwrap();
- let m0 = stat::SFlag::from_bits_truncate(stat::fstat(fd0).unwrap().st_mode);
- // S_IFIFO means it's a pipe
- assert_eq!(m0, SFlag::S_IFIFO);
- let m1 = stat::SFlag::from_bits_truncate(stat::fstat(fd1).unwrap().st_mode);
- assert_eq!(m1, SFlag::S_IFIFO);
-}
-
-// pipe2(2) is the same as pipe(2), except it allows setting some flags. Check
-// that we can set a flag.
-#[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "emscripten",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "redox"))]
-#[test]
-fn test_pipe2() {
- let (fd0, fd1) = pipe2(OFlag::O_CLOEXEC).unwrap();
- let f0 = FdFlag::from_bits_truncate(fcntl(fd0, FcntlArg::F_GETFD).unwrap());
- assert!(f0.contains(FdFlag::FD_CLOEXEC));
- let f1 = FdFlag::from_bits_truncate(fcntl(fd1, FcntlArg::F_GETFD).unwrap());
- assert!(f1.contains(FdFlag::FD_CLOEXEC));
-}
-
-#[test]
-#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-fn test_truncate() {
- let tempdir = tempdir().unwrap();
- let path = tempdir.path().join("file");
-
- {
- let mut tmp = File::create(&path).unwrap();
- const CONTENTS: &[u8] = b"12345678";
- tmp.write_all(CONTENTS).unwrap();
- }
-
- truncate(&path, 4).unwrap();
-
- let metadata = fs::metadata(&path).unwrap();
- assert_eq!(4, metadata.len());
-}
-
-#[test]
-fn test_ftruncate() {
- let tempdir = tempdir().unwrap();
- let path = tempdir.path().join("file");
-
- let tmpfd = {
- let mut tmp = File::create(&path).unwrap();
- const CONTENTS: &[u8] = b"12345678";
- tmp.write_all(CONTENTS).unwrap();
- tmp.into_raw_fd()
- };
-
- ftruncate(tmpfd, 2).unwrap();
- close(tmpfd).unwrap();
-
- let metadata = fs::metadata(&path).unwrap();
- assert_eq!(2, metadata.len());
-}
-
-// Used in `test_alarm`.
-#[cfg(not(target_os = "redox"))]
-static mut ALARM_CALLED: bool = false;
-
-// Used in `test_alarm`.
-#[cfg(not(target_os = "redox"))]
-pub extern fn alarm_signal_handler(raw_signal: libc::c_int) {
- assert_eq!(raw_signal, libc::SIGALRM, "unexpected signal: {}", raw_signal);
- unsafe { ALARM_CALLED = true };
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_alarm() {
- use std::{
- time::{Duration, Instant,},
- thread
- };
-
- // Maybe other tests that fork interfere with this one?
- let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-
- let handler = SigHandler::Handler(alarm_signal_handler);
- let signal_action = SigAction::new(handler, SaFlags::SA_RESTART, SigSet::empty());
- let old_handler = unsafe {
- sigaction(Signal::SIGALRM, &signal_action)
- .expect("unable to set signal handler for alarm")
- };
-
- // Set an alarm.
- assert_eq!(alarm::set(60), None);
-
- // Overwriting an alarm should return the old alarm.
- assert_eq!(alarm::set(1), Some(60));
-
- // We should be woken up after 1 second by the alarm, so we'll sleep for 2
- // seconds to be sure.
- let starttime = Instant::now();
- loop {
- thread::sleep(Duration::from_millis(100));
- if unsafe { ALARM_CALLED} {
- break;
- }
- if starttime.elapsed() > Duration::from_secs(3) {
- panic!("Timeout waiting for SIGALRM");
- }
- }
-
- // Reset the signal.
- unsafe {
- sigaction(Signal::SIGALRM, &old_handler)
- .expect("unable to set signal handler for alarm");
- }
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_canceling_alarm() {
- let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-
- assert_eq!(alarm::cancel(), None);
-
- assert_eq!(alarm::set(60), None);
- assert_eq!(alarm::cancel(), Some(60));
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_symlinkat() {
- let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-
- let tempdir = tempdir().unwrap();
-
- let target = tempdir.path().join("a");
- let linkpath = tempdir.path().join("b");
- symlinkat(&target, None, &linkpath).unwrap();
- assert_eq!(
- readlink(&linkpath).unwrap().to_str().unwrap(),
- target.to_str().unwrap()
- );
-
- let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
- let target = "c";
- let linkpath = "d";
- symlinkat(target, Some(dirfd), linkpath).unwrap();
- assert_eq!(
- readlink(&tempdir.path().join(linkpath))
- .unwrap()
- .to_str()
- .unwrap(),
- target
- );
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_linkat_file() {
- let tempdir = tempdir().unwrap();
- let oldfilename = "foo.txt";
- let oldfilepath = tempdir.path().join(oldfilename);
-
- let newfilename = "bar.txt";
- let newfilepath = tempdir.path().join(newfilename);
-
- // Create file
- File::create(&oldfilepath).unwrap();
-
- // Get file descriptor for base directory
- let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-
- // Attempt hard link file at relative path
- linkat(Some(dirfd), oldfilename, Some(dirfd), newfilename, LinkatFlags::SymlinkFollow).unwrap();
- assert!(newfilepath.exists());
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_linkat_olddirfd_none() {
- let _dr = crate::DirRestore::new();
-
- let tempdir_oldfile = tempdir().unwrap();
- let oldfilename = "foo.txt";
- let oldfilepath = tempdir_oldfile.path().join(oldfilename);
-
- let tempdir_newfile = tempdir().unwrap();
- let newfilename = "bar.txt";
- let newfilepath = tempdir_newfile.path().join(newfilename);
-
- // Create file
- File::create(&oldfilepath).unwrap();
-
- // Get file descriptor for base directory of new file
- let dirfd = fcntl::open(tempdir_newfile.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-
- // Attempt hard link file using curent working directory as relative path for old file path
- chdir(tempdir_oldfile.path()).unwrap();
- linkat(None, oldfilename, Some(dirfd), newfilename, LinkatFlags::SymlinkFollow).unwrap();
- assert!(newfilepath.exists());
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_linkat_newdirfd_none() {
- let _dr = crate::DirRestore::new();
-
- let tempdir_oldfile = tempdir().unwrap();
- let oldfilename = "foo.txt";
- let oldfilepath = tempdir_oldfile.path().join(oldfilename);
-
- let tempdir_newfile = tempdir().unwrap();
- let newfilename = "bar.txt";
- let newfilepath = tempdir_newfile.path().join(newfilename);
-
- // Create file
- File::create(&oldfilepath).unwrap();
-
- // Get file descriptor for base directory of old file
- let dirfd = fcntl::open(tempdir_oldfile.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-
- // Attempt hard link file using current working directory as relative path for new file path
- chdir(tempdir_newfile.path()).unwrap();
- linkat(Some(dirfd), oldfilename, None, newfilename, LinkatFlags::SymlinkFollow).unwrap();
- assert!(newfilepath.exists());
-}
-
-#[test]
-#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
-fn test_linkat_no_follow_symlink() {
- let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-
- let tempdir = tempdir().unwrap();
- let oldfilename = "foo.txt";
- let oldfilepath = tempdir.path().join(oldfilename);
-
- let symoldfilename = "symfoo.txt";
- let symoldfilepath = tempdir.path().join(symoldfilename);
-
- let newfilename = "nofollowsymbar.txt";
- let newfilepath = tempdir.path().join(newfilename);
-
- // Create file
- File::create(&oldfilepath).unwrap();
-
- // Create symlink to file
- symlinkat(&oldfilepath, None, &symoldfilepath).unwrap();
-
- // Get file descriptor for base directory
- let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-
- // Attempt link symlink of file at relative path
- linkat(Some(dirfd), symoldfilename, Some(dirfd), newfilename, LinkatFlags::NoSymlinkFollow).unwrap();
-
- // Assert newfile is actually a symlink to oldfile.
- assert_eq!(
- readlink(&newfilepath)
- .unwrap()
- .to_str()
- .unwrap(),
- oldfilepath.to_str().unwrap()
- );
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_linkat_follow_symlink() {
- let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-
- let tempdir = tempdir().unwrap();
- let oldfilename = "foo.txt";
- let oldfilepath = tempdir.path().join(oldfilename);
-
- let symoldfilename = "symfoo.txt";
- let symoldfilepath = tempdir.path().join(symoldfilename);
-
- let newfilename = "nofollowsymbar.txt";
- let newfilepath = tempdir.path().join(newfilename);
-
- // Create file
- File::create(&oldfilepath).unwrap();
-
- // Create symlink to file
- symlinkat(&oldfilepath, None, &symoldfilepath).unwrap();
-
- // Get file descriptor for base directory
- let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-
- // Attempt link target of symlink of file at relative path
- linkat(Some(dirfd), symoldfilename, Some(dirfd), newfilename, LinkatFlags::SymlinkFollow).unwrap();
-
- let newfilestat = stat::stat(&newfilepath).unwrap();
-
- // Check the file type of the new link
- assert!((stat::SFlag::from_bits_truncate(newfilestat.st_mode) & SFlag::S_IFMT) == SFlag::S_IFREG);
-
- // Check the number of hard links to the original file
- assert_eq!(newfilestat.st_nlink, 2);
-}
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_unlinkat_dir_noremovedir() {
- let tempdir = tempdir().unwrap();
- let dirname = "foo_dir";
- let dirpath = tempdir.path().join(dirname);
-
- // Create dir
- DirBuilder::new().recursive(true).create(&dirpath).unwrap();
-
- // Get file descriptor for base directory
- let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-
- // Attempt unlink dir at relative path without proper flag
- let err_result = unlinkat(Some(dirfd), dirname, UnlinkatFlags::NoRemoveDir).unwrap_err();
- assert!(err_result == Error::Sys(Errno::EISDIR) || err_result == Error::Sys(Errno::EPERM));
- }
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_unlinkat_dir_removedir() {
- let tempdir = tempdir().unwrap();
- let dirname = "foo_dir";
- let dirpath = tempdir.path().join(dirname);
-
- // Create dir
- DirBuilder::new().recursive(true).create(&dirpath).unwrap();
-
- // Get file descriptor for base directory
- let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-
- // Attempt unlink dir at relative path with proper flag
- unlinkat(Some(dirfd), dirname, UnlinkatFlags::RemoveDir).unwrap();
- assert!(!dirpath.exists());
- }
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_unlinkat_file() {
- let tempdir = tempdir().unwrap();
- let filename = "foo.txt";
- let filepath = tempdir.path().join(filename);
-
- // Create file
- File::create(&filepath).unwrap();
-
- // Get file descriptor for base directory
- let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-
- // Attempt unlink file at relative path
- unlinkat(Some(dirfd), filename, UnlinkatFlags::NoRemoveDir).unwrap();
- assert!(!filepath.exists());
- }
-
-#[test]
-fn test_access_not_existing() {
- let tempdir = tempdir().unwrap();
- let dir = tempdir.path().join("does_not_exist.txt");
- assert_eq!(access(&dir, AccessFlags::F_OK).err().unwrap().as_errno().unwrap(),
- Errno::ENOENT);
-}
-
-#[test]
-fn test_access_file_exists() {
- let tempdir = tempdir().unwrap();
- let path = tempdir.path().join("does_exist.txt");
- let _file = File::create(path.clone()).unwrap();
- assert!(access(&path, AccessFlags::R_OK | AccessFlags::W_OK).is_ok());
-}
-
-/// Tests setting the filesystem UID with `setfsuid`.
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[test]
-fn test_setfsuid() {
- use std::os::unix::fs::PermissionsExt;
- use std::{fs, io, thread};
- require_capability!(CAP_SETUID);
-
- // get the UID of the "nobody" user
- let nobody = User::from_name("nobody").unwrap().unwrap();
-
- // create a temporary file with permissions '-rw-r-----'
- let file = tempfile::NamedTempFile::new_in("/var/tmp").unwrap();
- let temp_path = file.into_temp_path();
- dbg!(&temp_path);
- let temp_path_2 = (&temp_path).to_path_buf();
- let mut permissions = fs::metadata(&temp_path).unwrap().permissions();
- permissions.set_mode(640);
-
- // spawn a new thread where to test setfsuid
- thread::spawn(move || {
- // set filesystem UID
- let fuid = setfsuid(nobody.uid);
- // trying to open the temporary file should fail with EACCES
- let res = fs::File::open(&temp_path);
- assert!(res.is_err());
- assert_eq!(res.err().unwrap().kind(), io::ErrorKind::PermissionDenied);
-
- // assert fuid actually changes
- let prev_fuid = setfsuid(Uid::from_raw(-1i32 as u32));
- assert_ne!(prev_fuid, fuid);
- })
- .join()
- .unwrap();
-
- // open the temporary file with the current thread filesystem UID
- fs::File::open(temp_path_2).unwrap();
-}
-
-#[test]
-#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-fn test_ttyname() {
- let fd = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed");
- assert!(fd.as_raw_fd() > 0);
-
- // on linux, we can just call ttyname on the pty master directly, but
- // apparently osx requires that ttyname is called on a slave pty (can't
- // find this documented anywhere, but it seems to empirically be the case)
- grantpt(&fd).expect("grantpt failed");
- unlockpt(&fd).expect("unlockpt failed");
- let sname = unsafe { ptsname(&fd) }.expect("ptsname failed");
- let fds = open(
- Path::new(&sname),
- OFlag::O_RDWR,
- stat::Mode::empty(),
- ).expect("open failed");
- assert!(fds > 0);
-
- let name = ttyname(fds).expect("ttyname failed");
- assert!(name.starts_with("/dev"));
-}
-
-#[test]
-#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-fn test_ttyname_not_pty() {
- let fd = File::open("/dev/zero").unwrap();
- assert!(fd.as_raw_fd() > 0);
- assert_eq!(ttyname(fd.as_raw_fd()), Err(Error::Sys(Errno::ENOTTY)));
-}
-
-#[test]
-#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-fn test_ttyname_invalid_fd() {
- assert_eq!(ttyname(-1), Err(Error::Sys(Errno::EBADF)));
-}
-
-#[test]
-#[cfg(any(
- target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "dragonfly",
-))]
-fn test_getpeereid() {
- use std::os::unix::net::UnixStream;
- let (sock_a, sock_b) = UnixStream::pair().unwrap();
-
- let (uid_a, gid_a) = getpeereid(sock_a.as_raw_fd()).unwrap();
- let (uid_b, gid_b) = getpeereid(sock_b.as_raw_fd()).unwrap();
-
- let uid = geteuid();
- let gid = getegid();
-
- assert_eq!(uid, uid_a);
- assert_eq!(gid, gid_a);
- assert_eq!(uid_a, uid_b);
- assert_eq!(gid_a, gid_b);
-}
-
-#[test]
-#[cfg(any(
- target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "dragonfly",
-))]
-fn test_getpeereid_invalid_fd() {
- // getpeereid is not POSIX, so error codes are inconsistent between different Unices.
- assert!(getpeereid(-1).is_err());
-}
diff --git a/vendor/rustyline-8.2.0/.cargo-checksum.json b/vendor/rustyline-8.2.0/.cargo-checksum.json
deleted file mode 100644
index 457abfa..0000000
--- a/vendor/rustyline-8.2.0/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"BUGS.md":"f0656705142c49b82ca333923f0b099d28259f9354e7f5a963dbeb6e5f1c679b","Cargo.lock":"de9f4128005ebbf56723e933ce301cbbad8b463c3c24265fea0c8a1314c233c1","Cargo.toml":"c31c3c4dc54ad2247cb4c1fbd061be7831c3d44a093d42000645d61c97d405ff","CustomBinding.md":"0a9d0634b8a4706096d46ee0656e6db742c75e30ad0878aeab95ee771fc26f0d","History.md":"aaefe620686fa358bff0f6ae5e87715533e329d3f056f5a8aee873f1eb4baecb","Incremental.md":"42fd96e9d50f6c5ae6980acf667aa0ba24402d029c9922d5f740e35b46b9f7a4","LICENSE":"c660c3a1ca6c7c0d736f249dbc7ca5bdf1cbc7bf4d57bc867d3b47ec1ba8374e","README.md":"0c91015560d44560ff0d525b203a31cdc4887cc73f2d77020a4a915269ec4c68","TODO.md":"b971148c46093ebc5b46cb424de49f5d8cc363cc688c9dc9795e6be72081f2e6","examples/custom_key_bindings.rs":"e079a0527bb571c99d8956a99e2f3fbe21518dc41cbce26f038f91e33112201a","examples/diy_hints.rs":"dd1bd0135d3d7a4cbbf71c1b1335909116e89fd1d7d12163888bf913765baa43","examples/example.rs":"ac4ae9e95c79334b66f2c9afb8425e667afee6f9d013b78b0cae197691c53084","examples/input_validation.rs":"4eba6320d88aae4f9db9c2bd71c6c4a1271db8e92f701e8107170fd932a6ff36","examples/minimal.rs":"0e53f20b16a45af3f4b399e7e2df1064542f90b46770961840c4fcdde8dbb497","examples/numeric_input.rs":"4e3ed14b3a095b9d222802b6290bfb08592642748bd2e9b74d846686108f5bf7","examples/read_password.rs":"52dec10a4196b248706c61cd094215098887ea9fea43addfe909d4f694b594df","rustfmt.toml":"5cf2fe8c17e60938454d864eaf442d878dbaa03e0339dbd59fafa2a26ebf080e","src/binding.rs":"8de37eaf43cdf5dd2818650508b97f64992795cffc76a10c2fbdbb0a183abc3b","src/command.rs":"b6b8e50b36dc447f19315d33e8f9ce575a31c4cfed29c0402f913d58d4a328f2","src/completion.rs":"c1df2a36b1161ebce0987e8414b3a575321cc4a596c91306569615fc522014b0","src/config.rs":"5b8ba0ddca8d4456c308c11ecec058f6bc00fa80b1bd25dea2bcd38df4b01d4a","src/edit.rs":"a4d036238159aca7528ec7b997a0ac9350c34233616f2147403bafe68ee5c65d","src/error.rs":"a2115683431e5fe8217875dd6c6b281c37133cd8797ff9a28f3d854f07452360","src/highlight.rs":"cb4457077a77e13086f46cc6e06d624459b09ed920d573ac0096d9df9f3a45cc","src/hint.rs":"c91e5e54d6fd06b2bd35338f555bb616859768f39e6ac14265e316bc25bf9569","src/history.rs":"c738660d5781d36696ebd0ce0f2cd9e062390f28b35c4fa3a41437705915977d","src/keymap.rs":"309001e42f3902aa11d05e0b82534007778e404b740f6522fc3fa248310df759","src/keys.rs":"c71107c99eed41fdf2264b876fa532a2875ca83dbcbea5d6ded4347aac75cce4","src/kill_ring.rs":"50499767a773a19f96efbdffaf21948751edff730585dc605775405039220361","src/layout.rs":"553a914138b02bc5d5780793b443039f797db0cef8e893ed883f86c5ef6d40d5","src/lib.rs":"196b3f6d6356458a9c2615dc58719d3a271d1ed26a71613aaf2c53cb525f284b","src/line_buffer.rs":"cb8d6b12f5030db0766de92a72f37ddebb1ae39caa14054b138ae64eaf50d0b2","src/test/common.rs":"bf6e9f0ba8024daeaa1d4b50ff288c58d90f3e31b2365c3767e2e3ecc6676a21","src/test/emacs.rs":"2096e6b60814d84484439c78fb8cedf911cc9f80e3f4d50126c2795357f33abb","src/test/history.rs":"c50155700945e0a82d32b5ea28854c1ba6aa6e6cca8262359bb2919176037ae3","src/test/mod.rs":"a23b55b7318f29152e4dc9f94ac07b0f8034c0fb9ae2840697a52675e2f1756f","src/test/vi_cmd.rs":"5fdd1f0fc44b47153fe42364e2b3e959579cf5e4de8617f6c5db059a19c29830","src/test/vi_insert.rs":"ceb7a43afb77c5349258fcc6d548b4e7eedfaaad7f054094d506568b6908c520","src/tty/mod.rs":"4cb28abf1fef00bc3a42b2abb13a980a1e1bd2ce6ca8900b8c5b3325f30aefb4","src/tty/test.rs":"f0ecc0f44a86a4f18c2ced50ba60890ba7c1127d84c3d0552f86ebd57247aaf8","src/tty/unix.rs":"010bab23af3f0c9a9a2b7b5fbec1af54c0bf32131245c3db476bd0554a35d2ee","src/tty/windows.rs":"8366669ec7483be63821780dc4851e66fe08d1933e41c36770aa34143049ad7b","src/undo.rs":"248c66f996fc92122774420319d35bb21e895c6de3559ed1a9eb38482e70341f","src/validate.rs":"45542a909be005da9b8b371a9afc11a2d902b2733b37f3f16dfcfc11b7955e99"},"package":"fbd4eaf7a7738f76c98e4f0395253ae853be3eb018f7b0bb57fe1b6c17e31874"}
\ No newline at end of file
diff --git a/vendor/rustyline-8.2.0/BUGS.md b/vendor/rustyline-8.2.0/BUGS.md
deleted file mode 100644
index a74c67a..0000000
--- a/vendor/rustyline-8.2.0/BUGS.md
+++ /dev/null
@@ -1,45 +0,0 @@
-Know issues
-
-## Document / Syntax
-
-We would like to introduce an incremental parsing phase (see `tree-sitter`).
-Because, when you have tokens (which may be as simple as words) or an AST,
-completion / suggestion / highlighting / validation become easy.
-So we need to send events to a lexer/parser, update `Document` accordingly.
-And fix `Completer` / `Hinter` / `Highlighter` API such as they have access to `Document`.
-
-See [lex_document](https://python-prompt-toolkit.readthedocs.io/en/master/pages/advanced_topics/rendering_flow.html#the-rendering-flow).
-
-## Repaint / Refresh
-
-Currently, performance is poor because, most of the time, we refresh the whole line (and prompt).
-We would like to transform events on prompt/line/hint into partial repaint.
-
-See `termwiz` design (`Surface`).
-See `replxx` refresh delay (`_lastRefreshTime`)
-https://docs.rs/xi-unicode/0.3.0/xi_unicode/struct.LineBreakIterator.html
-https://github.com/xi-editor/xi-editor/blob/master/rust/core-lib/src/linewrap.rs
-
-## Action / Command
-
-We would like to support user defined actions that interact nicely with undo manager and kill-ring.
-To do so, we need to refactor current key event dispatch.
-
-See `replxx` design (`ACTION_RESULT`, `action_trait_t`).
-
-## Line wrapping (should be fixed with verions >= 6.1.2)
-
-On Unix platform, we assume that `auto_right_margin` (`am`) is enabled.
-And on Windows, we activate `ENABLE_WRAP_AT_EOL_OUTPUT`.
-But on Windows 10, `ENABLE_WRAP_AT_EOL_OUTPUT` and `ENABLE_VIRTUAL_TERMINAL_PROCESSING` seems to be incompatible.
-
-## Colors
-
-We assume that ANSI colors are supported.
-Which is not the case on Windows (except on Windows 10)!
-
-## Emoji
-
-https://github.com/kkawakam/rustyline/issues/184
-https://docs.rs/xi-unicode/0.3.0/xi_unicode/trait.EmojiExt.html
-https://docs.rs/termwiz/0.11.0/termwiz/cell/fn.grapheme_column_width.html
\ No newline at end of file
diff --git a/vendor/rustyline-8.2.0/Cargo.lock b/vendor/rustyline-8.2.0/Cargo.lock
deleted file mode 100644
index d2c0c8e..0000000
--- a/vendor/rustyline-8.2.0/Cargo.lock
+++ /dev/null
@@ -1,1234 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "aho-corasick"
-version = "0.7.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "ansi_term"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "arrayvec"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
-
-[[package]]
-name = "assert_matches"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9"
-
-[[package]]
-name = "atty"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
-dependencies = [
- "hermit-abi",
- "libc",
- "winapi",
-]
-
-[[package]]
-name = "autocfg"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
-
-[[package]]
-name = "base-x"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b"
-
-[[package]]
-name = "beef"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6736e2428df2ca2848d846c43e88745121a6654696e349ce0054a420815a7409"
-
-[[package]]
-name = "bitflags"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
-
-[[package]]
-name = "bumpalo"
-version = "3.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
-
-[[package]]
-name = "cc"
-version = "1.0.67"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
-
-[[package]]
-name = "cfg-if"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "chrono"
-version = "0.4.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
-dependencies = [
- "libc",
- "num-integer",
- "num-traits",
- "time 0.1.43",
- "winapi",
-]
-
-[[package]]
-name = "clap"
-version = "2.33.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
-dependencies = [
- "ansi_term",
- "atty",
- "bitflags",
- "strsim 0.8.0",
- "textwrap",
- "unicode-width",
- "vec_map",
-]
-
-[[package]]
-name = "clipboard-win"
-version = "4.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e4ea1881992efc993e4dc50a324cdbd03216e41bdc8385720ff47efc9bd2ca8"
-dependencies = [
- "error-code",
- "str-buf",
- "winapi",
-]
-
-[[package]]
-name = "const_fn"
-version = "0.4.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f92cfa0fd5690b3cf8c1ef2cabbd9b7ef22fa53cf5e1f92b05103f6d5d1cf6e7"
-
-[[package]]
-name = "crossbeam"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd01a6eb3daaafa260f6fc94c3a6c36390abc2080e38e3e34ced87393fb77d80"
-dependencies = [
- "cfg-if 1.0.0",
- "crossbeam-channel 0.5.1",
- "crossbeam-deque",
- "crossbeam-epoch",
- "crossbeam-queue",
- "crossbeam-utils 0.8.4",
-]
-
-[[package]]
-name = "crossbeam-channel"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87"
-dependencies = [
- "crossbeam-utils 0.7.2",
- "maybe-uninit",
-]
-
-[[package]]
-name = "crossbeam-channel"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
-dependencies = [
- "cfg-if 1.0.0",
- "crossbeam-utils 0.8.4",
-]
-
-[[package]]
-name = "crossbeam-deque"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
-dependencies = [
- "cfg-if 1.0.0",
- "crossbeam-epoch",
- "crossbeam-utils 0.8.4",
-]
-
-[[package]]
-name = "crossbeam-epoch"
-version = "0.9.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52fb27eab85b17fbb9f6fd667089e07d6a2eb8743d02639ee7f6a7a7729c9c94"
-dependencies = [
- "cfg-if 1.0.0",
- "crossbeam-utils 0.8.4",
- "lazy_static",
- "memoffset",
- "scopeguard",
-]
-
-[[package]]
-name = "crossbeam-queue"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f6cb3c7f5b8e51bc3ebb73a2327ad4abdbd119dc13223f14f961d2f38486756"
-dependencies = [
- "cfg-if 1.0.0",
- "crossbeam-utils 0.8.4",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
-dependencies = [
- "autocfg",
- "cfg-if 0.1.10",
- "lazy_static",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4feb231f0d4d6af81aed15928e58ecf5816aa62a2393e2c82f46973e92a9a278"
-dependencies = [
- "autocfg",
- "cfg-if 1.0.0",
- "lazy_static",
-]
-
-[[package]]
-name = "darling"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858"
-dependencies = [
- "darling_core",
- "darling_macro",
-]
-
-[[package]]
-name = "darling_core"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
-dependencies = [
- "fnv",
- "ident_case",
- "proc-macro2",
- "quote",
- "strsim 0.9.3",
- "syn",
-]
-
-[[package]]
-name = "darling_macro"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
-dependencies = [
- "darling_core",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "defer-drop"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18ae055245e14ed411f56dddf2a78caae87c25d9d6a18fb61f398a596cad77b4"
-dependencies = [
- "crossbeam-channel 0.4.4",
- "once_cell",
-]
-
-[[package]]
-name = "derive_builder"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0"
-dependencies = [
- "darling",
- "derive_builder_core",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "derive_builder_core"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef"
-dependencies = [
- "darling",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "dirs"
-version = "2.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
-dependencies = [
- "cfg-if 0.1.10",
- "dirs-sys",
-]
-
-[[package]]
-name = "dirs-next"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
-dependencies = [
- "cfg-if 1.0.0",
- "dirs-sys-next",
-]
-
-[[package]]
-name = "dirs-sys"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
-dependencies = [
- "libc",
- "redox_users",
- "winapi",
-]
-
-[[package]]
-name = "dirs-sys-next"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
-dependencies = [
- "libc",
- "redox_users",
- "winapi",
-]
-
-[[package]]
-name = "discard"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
-
-[[package]]
-name = "doc-comment"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
-
-[[package]]
-name = "either"
-version = "1.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
-
-[[package]]
-name = "endian-type"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
-
-[[package]]
-name = "env_logger"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f"
-dependencies = [
- "atty",
- "humantime",
- "log",
- "regex",
- "termcolor",
-]
-
-[[package]]
-name = "error-code"
-version = "2.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5115567ac25674e0043e472be13d14e537f37ea8aa4bdc4aef0c89add1db1ff"
-dependencies = [
- "libc",
- "str-buf",
-]
-
-[[package]]
-name = "fd-lock"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0010f02effd88c702318c5dde0463206be67495d0b4d906ba7c0a8f166cc7f06"
-dependencies = [
- "libc",
- "winapi",
-]
-
-[[package]]
-name = "fnv"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
-
-[[package]]
-name = "fuzzy-matcher"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94"
-dependencies = [
- "thread_local",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
-dependencies = [
- "cfg-if 1.0.0",
- "libc",
- "wasi",
-]
-
-[[package]]
-name = "hermit-abi"
-version = "0.1.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "humantime"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
-
-[[package]]
-name = "ident_case"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
-
-[[package]]
-name = "itoa"
-version = "0.4.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
-
-[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
-[[package]]
-name = "libc"
-version = "0.2.94"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
-
-[[package]]
-name = "log"
-version = "0.4.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
-dependencies = [
- "cfg-if 1.0.0",
-]
-
-[[package]]
-name = "maybe-uninit"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
-
-[[package]]
-name = "memchr"
-version = "2.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
-
-[[package]]
-name = "memoffset"
-version = "0.6.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "nibble_vec"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43"
-dependencies = [
- "smallvec",
-]
-
-[[package]]
-name = "nix"
-version = "0.14.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
-dependencies = [
- "bitflags",
- "cc",
- "cfg-if 0.1.10",
- "libc",
- "void",
-]
-
-[[package]]
-name = "nix"
-version = "0.19.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2"
-dependencies = [
- "bitflags",
- "cc",
- "cfg-if 1.0.0",
- "libc",
-]
-
-[[package]]
-name = "nix"
-version = "0.20.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a"
-dependencies = [
- "bitflags",
- "cc",
- "cfg-if 1.0.0",
- "libc",
-]
-
-[[package]]
-name = "num-integer"
-version = "0.1.44"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
-dependencies = [
- "autocfg",
- "num-traits",
-]
-
-[[package]]
-name = "num-traits"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "num_cpus"
-version = "1.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
-dependencies = [
- "hermit-abi",
- "libc",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
-
-[[package]]
-name = "proc-macro-hack"
-version = "0.5.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
-dependencies = [
- "unicode-xid",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "radix_trie"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd"
-dependencies = [
- "endian-type",
- "nibble_vec",
-]
-
-[[package]]
-name = "rand"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
-dependencies = [
- "libc",
- "rand_chacha",
- "rand_core",
- "rand_hc",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "rand_hc"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
-name = "rayon"
-version = "1.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
-dependencies = [
- "autocfg",
- "crossbeam-deque",
- "either",
- "rayon-core",
-]
-
-[[package]]
-name = "rayon-core"
-version = "1.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
-dependencies = [
- "crossbeam-channel 0.5.1",
- "crossbeam-deque",
- "crossbeam-utils 0.8.4",
- "lazy_static",
- "num_cpus",
-]
-
-[[package]]
-name = "redox_syscall"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "redox_users"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
-dependencies = [
- "getrandom",
- "redox_syscall",
-]
-
-[[package]]
-name = "regex"
-version = "1.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
-
-[[package]]
-name = "remove_dir_all"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "rustc_version"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
-dependencies = [
- "semver",
-]
-
-[[package]]
-name = "rustyline"
-version = "8.2.0"
-dependencies = [
- "assert_matches",
- "bitflags",
- "cfg-if 1.0.0",
- "clipboard-win",
- "dirs-next",
- "doc-comment",
- "env_logger",
- "fd-lock",
- "libc",
- "log",
- "memchr",
- "nix 0.20.0",
- "radix_trie",
- "rustyline-derive",
- "scopeguard",
- "skim",
- "smallvec",
- "tempfile",
- "unicode-segmentation",
- "unicode-width",
- "utf8parse",
- "winapi",
-]
-
-[[package]]
-name = "rustyline-derive"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db9dfbf470021de34cfaf6983067f460ea19164934a7c2d4b92eec0968eb95f1"
-dependencies = [
- "quote",
- "syn",
-]
-
-[[package]]
-name = "ryu"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
-
-[[package]]
-name = "scopeguard"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
-
-[[package]]
-name = "semver"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
-dependencies = [
- "semver-parser",
-]
-
-[[package]]
-name = "semver-parser"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-
-[[package]]
-name = "serde"
-version = "1.0.126"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
-
-[[package]]
-name = "serde_derive"
-version = "1.0.126"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.64"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
-dependencies = [
- "itoa",
- "ryu",
- "serde",
-]
-
-[[package]]
-name = "sha1"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
-
-[[package]]
-name = "shlex"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
-
-[[package]]
-name = "skim"
-version = "0.9.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b9d19f904221fab15163486d2ce116cb86e60296470bb4e956d6687f04ebbb4"
-dependencies = [
- "atty",
- "beef",
- "bitflags",
- "chrono",
- "clap",
- "crossbeam",
- "defer-drop",
- "derive_builder",
- "env_logger",
- "fuzzy-matcher",
- "lazy_static",
- "log",
- "nix 0.19.1",
- "rayon",
- "regex",
- "shlex",
- "time 0.2.26",
- "timer",
- "tuikit",
- "unicode-width",
- "vte",
-]
-
-[[package]]
-name = "smallvec"
-version = "1.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
-
-[[package]]
-name = "standback"
-version = "0.2.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff"
-dependencies = [
- "version_check",
-]
-
-[[package]]
-name = "stdweb"
-version = "0.4.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
-dependencies = [
- "discard",
- "rustc_version",
- "stdweb-derive",
- "stdweb-internal-macros",
- "stdweb-internal-runtime",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "stdweb-derive"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
-dependencies = [
- "proc-macro2",
- "quote",
- "serde",
- "serde_derive",
- "syn",
-]
-
-[[package]]
-name = "stdweb-internal-macros"
-version = "0.2.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
-dependencies = [
- "base-x",
- "proc-macro2",
- "quote",
- "serde",
- "serde_derive",
- "serde_json",
- "sha1",
- "syn",
-]
-
-[[package]]
-name = "stdweb-internal-runtime"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
-
-[[package]]
-name = "str-buf"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d44a3643b4ff9caf57abcee9c2c621d6c03d9135e0d8b589bd9afb5992cb176a"
-
-[[package]]
-name = "strsim"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
-
-[[package]]
-name = "strsim"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
-
-[[package]]
-name = "syn"
-version = "1.0.72"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-xid",
-]
-
-[[package]]
-name = "tempfile"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
-dependencies = [
- "cfg-if 1.0.0",
- "libc",
- "rand",
- "redox_syscall",
- "remove_dir_all",
- "winapi",
-]
-
-[[package]]
-name = "term"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5"
-dependencies = [
- "dirs",
- "winapi",
-]
-
-[[package]]
-name = "termcolor"
-version = "1.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "textwrap"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
-dependencies = [
- "unicode-width",
-]
-
-[[package]]
-name = "thread_local"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
-dependencies = [
- "once_cell",
-]
-
-[[package]]
-name = "time"
-version = "0.1.43"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
-dependencies = [
- "libc",
- "winapi",
-]
-
-[[package]]
-name = "time"
-version = "0.2.26"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08a8cbfbf47955132d0202d1662f49b2423ae35862aee471f3ba4b133358f372"
-dependencies = [
- "const_fn",
- "libc",
- "standback",
- "stdweb",
- "time-macros",
- "version_check",
- "winapi",
-]
-
-[[package]]
-name = "time-macros"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1"
-dependencies = [
- "proc-macro-hack",
- "time-macros-impl",
-]
-
-[[package]]
-name = "time-macros-impl"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa"
-dependencies = [
- "proc-macro-hack",
- "proc-macro2",
- "quote",
- "standback",
- "syn",
-]
-
-[[package]]
-name = "timer"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31d42176308937165701f50638db1c31586f183f1aab416268216577aec7306b"
-dependencies = [
- "chrono",
-]
-
-[[package]]
-name = "tuikit"
-version = "0.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c628cfc5752254a33ebccf73eb79ef6508fab77de5d5ef76246b5e45010a51f"
-dependencies = [
- "bitflags",
- "lazy_static",
- "log",
- "nix 0.14.1",
- "term",
- "unicode-width",
-]
-
-[[package]]
-name = "unicode-segmentation"
-version = "1.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
-
-[[package]]
-name = "unicode-width"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
-
-[[package]]
-name = "utf8parse"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372"
-
-[[package]]
-name = "vec_map"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
-
-[[package]]
-name = "version_check"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
-
-[[package]]
-name = "void"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
-
-[[package]]
-name = "vte"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e7745610024d50ab1ebfa41f8f8ee361c567f7ab51032f93cc1cc4cbf0c547a"
-dependencies = [
- "arrayvec",
- "utf8parse",
- "vte_generate_state_changes",
-]
-
-[[package]]
-name = "vte_generate_state_changes"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff"
-dependencies = [
- "proc-macro2",
- "quote",
-]
-
-[[package]]
-name = "wasi"
-version = "0.10.2+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
-
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.74"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd"
-dependencies = [
- "cfg-if 1.0.0",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.74"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900"
-dependencies = [
- "bumpalo",
- "lazy_static",
- "log",
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.74"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.74"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.74"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f"
-
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-util"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/vendor/rustyline-8.2.0/Cargo.toml b/vendor/rustyline-8.2.0/Cargo.toml
deleted file mode 100644
index 9f96a35..0000000
--- a/vendor/rustyline-8.2.0/Cargo.toml
+++ /dev/null
@@ -1,102 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
-#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
-
-[package]
-edition = "2018"
-name = "rustyline"
-version = "8.2.0"
-authors = ["Katsu Kawakami <kkawa1570@gmail.com>"]
-description = "Rustyline, a readline implementation based on Antirez's Linenoise"
-documentation = "http://docs.rs/rustyline"
-readme = "README.md"
-keywords = ["readline"]
-categories = ["command-line-interface"]
-license = "MIT"
-repository = "https://github.com/kkawakam/rustyline"
-[package.metadata.docs.rs]
-all-features = false
-default-target = "x86_64-unknown-linux-gnu"
-features = ["with-dirs", "with-fuzzy"]
-no-default-features = true
-[dependencies.bitflags]
-version = "1.2"
-
-[dependencies.cfg-if]
-version = "1.0"
-
-[dependencies.dirs-next]
-version = "2.0"
-optional = true
-
-[dependencies.fd-lock]
-version = "2.0.0"
-
-[dependencies.libc]
-version = "0.2"
-
-[dependencies.log]
-version = "0.4"
-
-[dependencies.memchr]
-version = "2.0"
-
-[dependencies.radix_trie]
-version = "0.2"
-
-[dependencies.smallvec]
-version = "1.6.1"
-
-[dependencies.unicode-segmentation]
-version = "1.0"
-
-[dependencies.unicode-width]
-version = "0.1"
-[dev-dependencies.assert_matches]
-version = "1.2"
-
-[dev-dependencies.doc-comment]
-version = "0.3"
-
-[dev-dependencies.env_logger]
-version = "0.8"
-default-features = false
-
-[dev-dependencies.rustyline-derive]
-version = "0.4.0"
-
-[dev-dependencies.tempfile]
-version = "3.1.0"
-
-[features]
-default = ["with-dirs"]
-with-dirs = ["dirs-next"]
-with-fuzzy = ["skim"]
-[target."cfg(unix)".dependencies.nix]
-version = "0.20"
-
-[target."cfg(unix)".dependencies.skim]
-version = "0.9"
-optional = true
-
-[target."cfg(unix)".dependencies.utf8parse]
-version = "0.2"
-[target."cfg(windows)".dependencies.clipboard-win]
-version = "4.2.1"
-
-[target."cfg(windows)".dependencies.scopeguard]
-version = "1.1"
-
-[target."cfg(windows)".dependencies.winapi]
-version = "0.3"
-features = ["consoleapi", "handleapi", "minwindef", "processenv", "std", "winbase", "wincon", "winuser"]
-[badges.maintenance]
-status = "actively-developed"
diff --git a/vendor/rustyline-8.2.0/CustomBinding.md b/vendor/rustyline-8.2.0/CustomBinding.md
deleted file mode 100644
index c5a4d07..0000000
--- a/vendor/rustyline-8.2.0/CustomBinding.md
+++ /dev/null
@@ -1,68 +0,0 @@
-## Related topics
-
-* [Multiple commands for a keybinding](https://github.com/kkawakam/rustyline/issues/306) and
- [Conditional Bind Sequences](https://github.com/kkawakam/rustyline/issues/269) : original issues
-* [Conditional Bind Sequences](https://github.com/kkawakam/rustyline/pull/293) : incomplete proposal
-* [Add `Cmd::Yield` for complex custom bindings](https://github.com/kkawakam/rustyline/pull/342) : another proposal
-* [Initial invoke trait and auto-indent example](https://github.com/kkawakam/rustyline/pull/466) : a validator is like a custom action triggered indirectly.
-
-And other issues that should be solved if our design is good:
-* [Extend Meta-F,Alt+Right feature for hint partial completion](https://github.com/kkawakam/rustyline/pull/430)
-* [Use Arrow-Up to search history with prefix](https://github.com/kkawakam/rustyline/issues/423)
-* [Execute Arbitrary Command Via Keybinding](https://github.com/kkawakam/rustyline/issues/418)
-* [Use Ctrl-E for hint completion](https://github.com/kkawakam/rustyline/pull/407)
-* [Add History Search Behaviour](https://github.com/kkawakam/rustyline/pull/424)
-* ...
-
-## Conditions / Filters
-See https://python-prompt-toolkit.readthedocs.io/en/master/pages/advanced_topics/key_bindings.html?highlight=filter#attaching-a-filter-condition
-
-Some keys/commands may behave differently depending on:
- * edit mode (emacs vs vi)
- * vi input mode (insert vs replace vs command modes)
- * empty line
- * cursor position
- * repeat count
- * original key pressed (when same command is bound to different key)
- * hint
- * ...
-
-## More input
-Some keys/commands may ask for more input.
-I am not sure this point should be tackle here.
-
-## Multiple / complex actions
-For one key/command, we may want to perfom multiple actions.
-We should ask the undo manager to start a "transaction" before first action and commit it after the last action.
-Should we do something specific with the kill ring ?
-We should refresh / repaint only when all actions are performed (or if ask explictly?) depending on cumulated action impacts.
-...
-
-## Misc
-
-```rust
-/// Command / action result
-#[derive(Debug, Clone, PartialEq, Copy)]
-#[non_exhaustive]
-pub enum ActionResult {
- // Interrupt / reject user input
- // => Err should be fine
- //Bail,
- ///
- Continue,
- /// Accept user input (except if `Validator` disagrees)
- Return,
-}
-```
-```rust
-bitflags::bitflags! {
- #[doc = "Action invocation impacts"]
- pub struct Impacts: u8 {
- const PUSH_CHAR = 0b0000_0001;
- const BEEP = 0b0000_0010;
- const MOVE_CURSOR = 0b0000_0100; // State::move_cursor
- const REFRESH = 0b0000_1000; // State::refresh_line
- const CLEAR_SREEN = 0b0001_0000; // State::clear_screen
- }
-}
-```
diff --git a/vendor/rustyline-8.2.0/History.md b/vendor/rustyline-8.2.0/History.md
deleted file mode 100644
index 0e9d6f6..0000000
--- a/vendor/rustyline-8.2.0/History.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# Config
- max_history_size
-
-# Current session
-
-* we should remember (index) of the first line inserted by this session.
- - if no line has been inserted => do nothing on save
- - reset this index after saving successfully.
-* we should remember (path and timestamp) of the file used to initialize/`load` history.
- - if path used to save history is the same:
- + if timestamp is still the same => we can append only new lines if history has not been truncated.
- + update timestamp after saving successfully.
-* we should remember (path and timestamp) of the file used to persist/`save` history.
- - reset them if `load` is then called with a different path
- - update them if `load` is then called with same path.
- - update them after saving successfully
- - if path used to save history is the same:
- + if timestamp is still the same => we can append only new lines if history has not been truncated.
-
-HistoryInfo
- first_add_index: Option<usize>, // first line inserted by this session
- truncated: bool //
- path_info: Option<PathInfo>,
-
-PathInfo
- path: Path,
- modified: SystemTime,
-
----
-With `termwiz`, you can define your own `History` backend.
-`termwiz` does not specify anything how the history is persisted.
-Only how to access / search history entry.
\ No newline at end of file
diff --git a/vendor/rustyline-8.2.0/Incremental.md b/vendor/rustyline-8.2.0/Incremental.md
deleted file mode 100644
index 51e3130..0000000
--- a/vendor/rustyline-8.2.0/Incremental.md
+++ /dev/null
@@ -1,52 +0,0 @@
-## Incremental computation
-
-We would like to avoid redrawing all row(s) when an event occurs.
-Currently, we redraw all row(s) except when:
- * a character is inserted at the end of input (and there is no hint and no `highlight_char`),
- * only the cursor is moved (input is not touched and no `highlight_char`).
-
-Ideally, we would like to redraw only impacted row(s) / cell(s).
-
-### Observable values
-
-Currently, we assume that highlighting does not impact layout / rendered text size.
-So only the following observables impact layout:
- * prompt (interactive search, [input mode indicator](https://github.com/kkawakam/rustyline/pull/369)),
- * [input mode](https://github.com/kkawakam/rustyline/pull/369),
- * line(s) buffer,
- * cursor position,
- * hint / input validation message,
- * screen size (line wrapping),
- * [prompt continuation](https://github.com/kkawakam/rustyline/pull/372)s,
- * row/wrap count.
-
-Some other values may impact layout but they are/should be constant:
- * tab stop,
-
-### Line wrapping and highlighting
-
-Currently, there is no word wrapping (only grapheme wrapping).
-But we highlight the whole input at once.
-So there is no issue: for example, even if a keyword is wrapped, style is preserved.
-
-With [prompt continuation](https://github.com/kkawakam/rustyline/pull/372)s,
-we (will) interleave user input with continuations.
-So we need to preserve style.
-
-TODO How prompt_toolkit handle this problem ?
-Maybe using ANSI sequence directly was a bad idea. If `Highlighter` returns style ranges,
-applying style on input slice is easy (and also supporting styles on Windows < 10).
-
-### Impacts
-
-Current granularity:
- * PUSH_CHAR at end of input
- * BEEP
- * MOVE_CURSOR
- * REFRESH whole input / rows
- * CLEAR_SCREEN (+REFRESH)
-
-Wanted additional granurality:
- * PUSH_STRING at end of input
- * REFRESH_DIRTY only rows / cells
-
diff --git a/vendor/rustyline-8.2.0/LICENSE b/vendor/rustyline-8.2.0/LICENSE
deleted file mode 100644
index ddbad23..0000000
--- a/vendor/rustyline-8.2.0/LICENSE
+++ /dev/null
@@ -1,22 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2015 Katsu Kawakami & Rustyline authors
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
diff --git a/vendor/rustyline-8.2.0/README.md b/vendor/rustyline-8.2.0/README.md
deleted file mode 100644
index 7160382..0000000
--- a/vendor/rustyline-8.2.0/README.md
+++ /dev/null
@@ -1,246 +0,0 @@
-# RustyLine
-[](https://github.com/kkawakam/rustyline/actions)
-[](https://deps.rs/repo/github/kkawakam/rustyline)
-[](https://crates.io/crates/rustyline)
-[](https://docs.rs/rustyline)
-
-Readline implementation in Rust that is based on [Antirez' Linenoise](https://github.com/antirez/linenoise)
-
-**Supported Platforms**
-* Unix (tested on FreeBSD, Linux and macOS)
-* Windows
- * cmd.exe
- * Powershell
-
-**Note**:
-* Powershell ISE is not supported, check [issue #56](https://github.com/kkawakam/rustyline/issues/56)
-* Mintty (Cygwin/MinGW) is not supported
-* Highlighting / Colors are not supported on Windows < Windows 10 except with ConEmu and `ColorMode::Forced`.
-
-## Example
-```rust
-use rustyline::error::ReadlineError;
-use rustyline::Editor;
-
-fn main() {
- // `()` can be used when no completer is required
- let mut rl = Editor::<()>::new();
- if rl.load_history("history.txt").is_err() {
- println!("No previous history.");
- }
- loop {
- let readline = rl.readline(">> ");
- match readline {
- Ok(line) => {
- rl.add_history_entry(line.as_str());
- println!("Line: {}", line);
- },
- Err(ReadlineError::Interrupted) => {
- println!("CTRL-C");
- break
- },
- Err(ReadlineError::Eof) => {
- println!("CTRL-D");
- break
- },
- Err(err) => {
- println!("Error: {:?}", err);
- break
- }
- }
- }
- rl.save_history("history.txt").unwrap();
-}
-```
-
-## crates.io
-You can use this package in your project by adding the following
-to your `Cargo.toml`:
-
-```toml
-[dependencies]
-rustyline = "8.2.0"
-```
-
-## Features
-
- - Unicode (UTF-8) (linenoise supports only ASCII)
- - Word completion (linenoise supports only line completion)
- - Filename completion
- - History search ([Searching for Commands in the History](http://tiswww.case.edu/php/chet/readline/readline.html#SEC8))
- - Kill ring ([Killing Commands](http://tiswww.case.edu/php/chet/readline/readline.html#IDX3))
- - Multi line support (line wrapping)
- - Word commands
- - Hints
-
-## Actions
-
-For all modes:
-
-Keystroke | Action
---------- | ------
-Home | Move cursor to the beginning of line
-End | Move cursor to end of line
-Left | Move cursor one character left
-Right | Move cursor one character right
-Ctrl-C | Interrupt/Cancel edition
-Ctrl-D, Del | (if line is *not* empty) Delete character under cursor
-Ctrl-D | (if line *is* empty) End of File
-Ctrl-J, Ctrl-M, Enter | Finish the line entry
-Ctrl-R | Reverse Search history (Ctrl-S forward, Ctrl-G cancel)
-Ctrl-T | Transpose previous character with current character
-Ctrl-U | Delete from start of line to cursor
-Ctrl-V | Insert any special character without performing its associated action (#65)
-Ctrl-W | Delete word leading up to cursor (using white space as a word boundary)
-Ctrl-Y | Paste from Yank buffer
-Ctrl-Z | Suspend (Unix only)
-Ctrl-_ | Undo
-
-### Emacs mode (default mode)
-
-Keystroke | Action
---------- | ------
-Ctrl-A, Home | Move cursor to the beginning of line
-Ctrl-B, Left | Move cursor one character left
-Ctrl-E, End | Move cursor to end of line
-Ctrl-F, Right| Move cursor one character right
-Ctrl-H, Backspace | Delete character before cursor
-Ctrl-I, Tab | Next completion
-Ctrl-K | Delete from cursor to end of line
-Ctrl-L | Clear screen
-Ctrl-N, Down | Next match from history
-Ctrl-P, Up | Previous match from history
-Ctrl-X Ctrl-U | Undo
-Ctrl-Y | Paste from Yank buffer (Meta-Y to paste next yank instead)
-Meta-< | Move to first entry in history
-Meta-> | Move to last entry in history
-Meta-B, Alt-Left | Move cursor to previous word
-Meta-C | Capitalize the current word
-Meta-D | Delete forwards one word
-Meta-F, Alt-Right | Move cursor to next word
-Meta-L | Lower-case the next word
-Meta-T | Transpose words
-Meta-U | Upper-case the next word
-Meta-Y | See Ctrl-Y
-Meta-Backspace | Kill from the start of the current word, or, if between words, to the start of the previous word
-Meta-0, 1, ..., - | Specify the digit to the argument. `–` starts a negative argument.
-
-[Readline Emacs Editing Mode Cheat Sheet](http://www.catonmat.net/download/readline-emacs-editing-mode-cheat-sheet.pdf)
-
-### vi command mode
-
-Keystroke | Action
---------- | ------
-$, End | Move cursor to end of line
-. | Redo the last text modification
-; | Redo the last character finding command
-, | Redo the last character finding command in opposite direction
-0, Home | Move cursor to the beginning of line
-^ | Move to the first non-blank character of line
-a | Insert after cursor
-A | Insert at the end of line
-b | Move one word or token left
-B | Move one non-blank word left
-c<movement> | Change text of a movement command
-C | Change text to the end of line (equivalent to c$)
-d<movement> | Delete text of a movement command
-D, Ctrl-K | Delete to the end of the line
-e | Move to the end of the current word
-E | Move to the end of the current non-blank word
-f<char> | Move right to the next occurrence of `char`
-F<char> | Move left to the previous occurrence of `char`
-h, Ctrl-H, Backspace | Move one character left
-l, Space | Move one character right
-Ctrl-L | Clear screen
-i | Insert before cursor
-I | Insert at the beginning of line
-+, j, Ctrl-N | Move forward one command in history
--, k, Ctrl-P | Move backward one command in history
-p | Insert the yanked text at the cursor (paste)
-P | Insert the yanked text before the cursor
-r | Replaces a single character under the cursor (without leaving command mode)
-s | Delete a single character under the cursor and enter input mode
-S | Change current line (equivalent to 0c$)
-t<char> | Move right to the next occurrence of `char`, then one char backward
-T<char> | Move left to the previous occurrence of `char`, then one char forward
-u | Undo
-w | Move one word or token right
-W | Move one non-blank word right
-x | Delete a single character under the cursor
-X | Delete a character before the cursor
-y<movement> | Yank a movement into buffer (copy)
-
-### vi insert mode
-
-Keystroke | Action
---------- | ------
-Ctrl-H, Backspace | Delete character before cursor
-Ctrl-I, Tab | Next completion
-Esc | Switch to command mode
-
-[Readline vi Editing Mode Cheat Sheet](http://www.catonmat.net/download/bash-vi-editing-mode-cheat-sheet.pdf)
-
-[Terminal codes (ANSI/VT100)](http://wiki.bash-hackers.org/scripting/terminalcodes)
-
-## Wine
-
-```sh
-$ cargo run --example example --target 'x86_64-pc-windows-gnu'
-...
-Error: Io(Error { repr: Os { code: 6, message: "Invalid handle." } })
-$ wineconsole --backend=curses target/x86_64-pc-windows-gnu/debug/examples/example.exe
-...
-```
-
-## Terminal checks
-
-```sh
-$ # current settings of all terminal attributes:
-$ stty -a
-$ # key bindings:
-$ bind -p
-$ # print out a terminfo description:
-$ infocmp
-```
-
-## Similar projects
-
-Library | Lang | OS | Term | Unicode | History | Completion | Keymap | Kill Ring | Undo | Colors | Hint/Auto suggest |
--------- | ---- | -- | ---- | ------- | ------- | ---------- | ------- | --------- | ---- | ------ | ----------------- |
-[go-prompt][] | Go | Ux/win | ANSI | Yes | Yes | any | Emacs/prog | No | No | Yes | Yes |
-[Haskeline][] | Haskell | Ux/Win | Any | Yes | Yes | any | Emacs/vi/conf | Yes | Yes | ? | ? |
-[linefeed][] | Rust | Ux/Win | Any | | Yes | any | Emacs/conf | Yes | No | ? | No |
-[linenoise][] | C | Ux | ANSI | No | Yes | only line | Emacs | No | No | Ux | Yes |
-[linenoise-ng][] | C | Ux/Win | ANSI | Yes | Yes | only line | Emacs | Yes | No | ? | ? |
-[Liner][] | Rust | Ux | ANSI | | No inc search | only word | Emacs/vi/prog | No | Yes | Ux | History based |
-[prompt_toolkit][] | Python | Ux/Win | ANSI | Yes | Yes | any | Emacs/vi/conf | Yes | Yes | Ux/Win | Yes |
-[rb-readline][] | Ruby | Ux/Win | ANSI | Yes | Yes | only word | Emacs/vi/conf | Yes | Yes | ? | No |
-[replxx][] | C/C++ | Ux/Win | ANSI | Yes | Yes | only line | Emacs | Yes | No | Ux/Win | Yes |
-Rustyline | Rust | Ux/Win | ANSI | Yes | Yes | any | Emacs/vi/bind | Yes | Yes | Ux/Win 10+ | Yes |
-[termwiz][] | Rust | Ux/Win | Any | ? | Yes | any | Emacs | No | No | Ux/Win | No |
-
-[go-prompt]: https://github.com/c-bata/go-prompt
-[Haskeline]: https://github.com/judah/haskeline
-[linefeed]: https://github.com/murarth/linefeed
-[linenoise]: https://github.com/antirez/linenoise
-[linenoise-ng]: https://github.com/arangodb/linenoise-ng
-[Liner]: https://github.com/redox-os/liner
-[prompt_toolkit]: https://github.com/jonathanslenders/python-prompt-toolkit
-[rb-readline]: https://github.com/ConnorAtherton/rb-readline
-[replxx]: https://github.com/AmokHuginnsson/replxx
-[termwiz]: https://github.com/wez/wezterm/tree/master/termwiz
-
-## Multi line support
-
-This is a very simple feature that simply causes lines that are longer
-than the current terminal width to be displayed on the next visual
-line instead of horizontally scrolling as more characters are
-typed. Currently this feature is always enabled and there is no
-configuration option to disable it.
-
-This feature does not allow the end user to hit a special key
-sequence and enter a mode where hitting the return key will cause a
-literal newline to be added to the input buffer.
-
-The way to achieve multi-line editing is to implement the `Validator`
-trait.
diff --git a/vendor/rustyline-8.2.0/TODO.md b/vendor/rustyline-8.2.0/TODO.md
deleted file mode 100644
index 0223526..0000000
--- a/vendor/rustyline-8.2.0/TODO.md
+++ /dev/null
@@ -1,94 +0,0 @@
-API
-- [ ] expose an API callable from C
-
-Async (#126)
-
-Bell
-- [X] bell-style
-
-Color
-- [X] ANSI Colors & Windows 10+
-- [ ] ANSI Colors & Windows <10 (https://docs.rs/console/0.6.1/console/fn.strip_ansi_codes.html ?
- https://github.com/mattn/go-colorable/blob/master/colorable_windows.go,
- https://github.com/mattn/ansicolor-w32.c)
-- [ ] Syntax highlighting (https://github.com/trishume/syntect/)
-- [ ] clicolors spec (https://docs.rs/console/0.6.1/console/fn.colors_enabled.html)
-
-Completion
-- [X] Quoted path
-- [X] Windows escape/unescape space in path
-- [ ] file completion & escape/unescape (#106)
-- [ ] file completion & tilde (#62)
-- [X] display versus replacement
-- [ ] composite/alternate completer (if the current completer returns nothing, try the next one)
-
-Config
-- [ ] Maximum buffer size for the line read
-
-Cursor
-- [ ] insert versus overwrite versus command mode
-- [ ] In vi command mode, prevent user from going to end of line. (#94)
-
-Grapheme
-- [ ] grapheme & input auto-wrap are buggy
-
-Hints Callback
-- [X] Not implemented on windows
-- [X] Do an implementation based on previous history
-
-History
-- [ ] Move to the history line n
-- [ ] historyFile: Where to read/write the history at the start and end of
-each line input session.
-- [X] append_history
-- [ ] history_truncate_file
-
-Input
-- [ ] Password input (#58) (https://github.com/conradkdotcom/rpassword) (https://github.com/antirez/linenoise/issues/125)
-- [X] quoted insert (#65)
-- [ ] Overwrite mode (em-toggle-overwrite, vi-replace-mode, rl_insert_mode)
-- [ ] Encoding
-- [X] [Ctrl-][Alt-][Shift-]<Key> (#121)
-
-Layout
-- [ ] Redraw perf (https://crates.io/crates/cassowary)
-
-Misc
-- [ ] fallible iterator (https://docs.rs/fallible-iterator/0.2.1/fallible_iterator/)
-
-Mouse
-- [ ] Mouse support
-
-Movement
-- [ ] Move to the corresponding opening/closing bracket
-
-Redo
-- [X] redo substitute
-
-Repeat
-- [X] dynamic prompt (arg: ?)
-- [ ] transpose chars
-
-Syntax
-- [ ] syntax specific tokenizer/parser
-- [ ] highlighting
-
-Undo
-- [ ] Merge consecutive Replace
-- [X] Undo group
-- [ ] Undo all changes made to this line.
-- [X] Kill+Insert (substitute/replace)
-- [X] Repeated undo `Undo(RepeatCount)`
-
-Unix
-- [ ] Terminfo (https://github.com/Stebalien/term)
-- [ ] [ncurses](https://crates.io/crates/ncurses) alternative backend ?
-- [X] [bracketed paste mode](https://cirw.in/blog/bracketed-paste)
-- [ ] async stdin (https://github.com/Rufflewind/tokio-file-unix)
-
-Windows
-- [ ] is_atty is not working with Cygwin/MSYS (https://github.com/softprops/atty works but then how to make `enable_raw_mode` works ?)
- (https://github.com/mitsuhiko/console/blob/master/src/windows_term.rs#L285)
- (https://github.com/mattn/go-isatty/blob/master/isatty_windows.go, https://github.com/mattn/go-tty/blob/master/tty_windows.go#L143)
-- [X] UTF-16 surrogate pair
-- [ ] handle ANSI escape code (#61) (https://github.com/DanielKeep/rust-ansi-interpreter)
diff --git a/vendor/rustyline-8.2.0/examples/custom_key_bindings.rs b/vendor/rustyline-8.2.0/examples/custom_key_bindings.rs
deleted file mode 100644
index f5a8ee8..0000000
--- a/vendor/rustyline-8.2.0/examples/custom_key_bindings.rs
+++ /dev/null
@@ -1,117 +0,0 @@
-use smallvec::smallvec;
-use std::borrow::Cow::{self, Borrowed, Owned};
-
-use rustyline::highlight::Highlighter;
-use rustyline::hint::{Hinter, HistoryHinter};
-use rustyline::{
- Cmd, ConditionalEventHandler, Context, Editor, Event, EventContext, EventHandler, KeyEvent,
- RepeatCount, Result,
-};
-use rustyline_derive::{Completer, Helper, Validator};
-
-#[derive(Completer, Helper, Validator)]
-struct MyHelper(HistoryHinter);
-
-impl Hinter for MyHelper {
- type Hint = String;
-
- fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<String> {
- self.0.hint(line, pos, ctx)
- }
-}
-
-impl Highlighter for MyHelper {
- fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
- &'s self,
- prompt: &'p str,
- default: bool,
- ) -> Cow<'b, str> {
- if default {
- Owned(format!("\x1b[1;32m{}\x1b[m", prompt))
- } else {
- Borrowed(prompt)
- }
- }
-
- fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
- Owned(format!("\x1b[1m{}\x1b[m", hint))
- }
-}
-
-#[derive(Clone)]
-struct CompleteHintHandler;
-impl ConditionalEventHandler for CompleteHintHandler {
- fn handle(&self, evt: &Event, _: RepeatCount, _: bool, ctx: &EventContext) -> Option<Cmd> {
- if !ctx.has_hint() {
- return None; // default
- }
- if let Some(k) = evt.get(0) {
- #[allow(clippy::if_same_then_else)]
- if *k == KeyEvent::ctrl('E') {
- Some(Cmd::CompleteHint)
- } else if *k == KeyEvent::alt('f') && ctx.line().len() == ctx.pos() {
- let text = ctx.hint_text()?;
- let mut start = 0;
- if let Some(first) = text.chars().next() {
- if !first.is_alphanumeric() {
- start = text.find(|c: char| c.is_alphanumeric()).unwrap_or_default();
- }
- }
-
- let text = text
- .chars()
- .enumerate()
- .take_while(|(i, c)| *i <= start || c.is_alphanumeric())
- .map(|(_, c)| c)
- .collect::<String>();
-
- Some(Cmd::Insert(1, text))
- } else {
- None
- }
- } else {
- unreachable!()
- }
- }
-}
-
-struct TabEventHandler;
-impl ConditionalEventHandler for TabEventHandler {
- fn handle(&self, evt: &Event, n: RepeatCount, _: bool, ctx: &EventContext) -> Option<Cmd> {
- debug_assert_eq!(*evt, Event::from(KeyEvent::from('\t')));
- if ctx.line()[..ctx.pos()]
- .chars()
- .rev()
- .next()
- .filter(|c| c.is_whitespace())
- .is_some()
- {
- Some(Cmd::SelfInsert(n, '\t'))
- } else {
- None // default complete
- }
- }
-}
-
-fn main() -> Result<()> {
- let mut rl = Editor::<MyHelper>::new();
- rl.set_helper(Some(MyHelper(HistoryHinter {})));
-
- let ceh = Box::new(CompleteHintHandler);
- rl.bind_sequence(KeyEvent::ctrl('E'), EventHandler::Conditional(ceh.clone()));
- rl.bind_sequence(KeyEvent::alt('f'), EventHandler::Conditional(ceh));
- rl.bind_sequence(
- KeyEvent::from('\t'),
- EventHandler::Conditional(Box::new(TabEventHandler)),
- );
- rl.bind_sequence(
- Event::KeySeq(smallvec![KeyEvent::ctrl('X'), KeyEvent::ctrl('E')]),
- EventHandler::Simple(Cmd::Suspend), // TODO external editor
- );
-
- loop {
- let line = rl.readline("> ")?;
- rl.add_history_entry(line.as_str());
- println!("Line: {}", line);
- }
-}
diff --git a/vendor/rustyline-8.2.0/examples/diy_hints.rs b/vendor/rustyline-8.2.0/examples/diy_hints.rs
deleted file mode 100644
index 26f58d8..0000000
--- a/vendor/rustyline-8.2.0/examples/diy_hints.rs
+++ /dev/null
@@ -1,95 +0,0 @@
-use std::collections::HashSet;
-
-use rustyline::hint::{Hint, Hinter};
-use rustyline::Context;
-use rustyline::{Editor, Result};
-use rustyline_derive::{Completer, Helper, Highlighter, Validator};
-
-#[derive(Completer, Helper, Validator, Highlighter)]
-struct DIYHinter {
- // It's simple example of rustyline, for more effecient, please use ** radix trie **
- hints: HashSet<CommandHint>,
-}
-
-#[derive(Hash, Debug, PartialEq, Eq)]
-struct CommandHint {
- display: String,
- complete_up_to: usize,
-}
-
-impl Hint for CommandHint {
- fn display(&self) -> &str {
- &self.display
- }
-
- fn completion(&self) -> Option<&str> {
- if self.complete_up_to > 0 {
- Some(&self.display[..self.complete_up_to])
- } else {
- None
- }
- }
-}
-
-impl CommandHint {
- fn new(text: &str, complete_up_to: &str) -> CommandHint {
- assert!(text.starts_with(complete_up_to));
- CommandHint {
- display: text.into(),
- complete_up_to: complete_up_to.len(),
- }
- }
-
- fn suffix(&self, strip_chars: usize) -> CommandHint {
- CommandHint {
- display: self.display[strip_chars..].to_owned(),
- complete_up_to: self.complete_up_to.saturating_sub(strip_chars),
- }
- }
-}
-
-impl Hinter for DIYHinter {
- type Hint = CommandHint;
-
- fn hint(&self, line: &str, pos: usize, _ctx: &Context<'_>) -> Option<CommandHint> {
- if pos < line.len() {
- return None;
- }
-
- self.hints
- .iter()
- .filter_map(|hint| {
- // expect hint after word complete, like redis cli, add condition:
- // line.ends_with(" ")
- if pos > 0 && hint.display.starts_with(&line[..pos]) {
- Some(hint.suffix(pos))
- } else {
- None
- }
- })
- .next()
- }
-}
-
-fn diy_hints() -> HashSet<CommandHint> {
- let mut set = HashSet::new();
- set.insert(CommandHint::new("help", "help"));
- set.insert(CommandHint::new("get key", "get "));
- set.insert(CommandHint::new("set key value", "set "));
- set.insert(CommandHint::new("hget key field", "hget "));
- set.insert(CommandHint::new("hset key field value", "hset "));
- set
-}
-
-fn main() -> Result<()> {
- println!("This is a DIY hint hack of rustyline");
- let h = DIYHinter { hints: diy_hints() };
-
- let mut rl: Editor<DIYHinter> = Editor::new();
- rl.set_helper(Some(h));
-
- loop {
- let input = rl.readline("> ")?;
- println!("input: {}", input);
- }
-}
diff --git a/vendor/rustyline-8.2.0/examples/example.rs b/vendor/rustyline-8.2.0/examples/example.rs
deleted file mode 100644
index 7b3ccc8..0000000
--- a/vendor/rustyline-8.2.0/examples/example.rs
+++ /dev/null
@@ -1,131 +0,0 @@
-use std::borrow::Cow::{self, Borrowed, Owned};
-
-use rustyline::completion::{Completer, FilenameCompleter, Pair};
-use rustyline::config::OutputStreamType;
-use rustyline::error::ReadlineError;
-use rustyline::highlight::{Highlighter, MatchingBracketHighlighter};
-use rustyline::hint::{Hinter, HistoryHinter};
-use rustyline::validate::{self, MatchingBracketValidator, Validator};
-use rustyline::{Cmd, CompletionType, Config, Context, EditMode, Editor, KeyEvent};
-use rustyline_derive::Helper;
-
-#[derive(Helper)]
-struct MyHelper {
- completer: FilenameCompleter,
- highlighter: MatchingBracketHighlighter,
- validator: MatchingBracketValidator,
- hinter: HistoryHinter,
- colored_prompt: String,
-}
-
-impl Completer for MyHelper {
- type Candidate = Pair;
-
- fn complete(
- &self,
- line: &str,
- pos: usize,
- ctx: &Context<'_>,
- ) -> Result<(usize, Vec<Pair>), ReadlineError> {
- self.completer.complete(line, pos, ctx)
- }
-}
-
-impl Hinter for MyHelper {
- type Hint = String;
-
- fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<String> {
- self.hinter.hint(line, pos, ctx)
- }
-}
-
-impl Highlighter for MyHelper {
- fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
- &'s self,
- prompt: &'p str,
- default: bool,
- ) -> Cow<'b, str> {
- if default {
- Borrowed(&self.colored_prompt)
- } else {
- Borrowed(prompt)
- }
- }
-
- fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
- Owned("\x1b[1m".to_owned() + hint + "\x1b[m")
- }
-
- fn highlight<'l>(&self, line: &'l str, pos: usize) -> Cow<'l, str> {
- self.highlighter.highlight(line, pos)
- }
-
- fn highlight_char(&self, line: &str, pos: usize) -> bool {
- self.highlighter.highlight_char(line, pos)
- }
-}
-
-impl Validator for MyHelper {
- fn validate(
- &self,
- ctx: &mut validate::ValidationContext,
- ) -> rustyline::Result<validate::ValidationResult> {
- self.validator.validate(ctx)
- }
-
- fn validate_while_typing(&self) -> bool {
- self.validator.validate_while_typing()
- }
-}
-
-// To debug rustyline:
-// RUST_LOG=rustyline=debug cargo run --example example 2> debug.log
-fn main() -> rustyline::Result<()> {
- env_logger::init();
- let config = Config::builder()
- .history_ignore_space(true)
- .completion_type(CompletionType::List)
- .edit_mode(EditMode::Emacs)
- .output_stream(OutputStreamType::Stdout)
- .build();
- let h = MyHelper {
- completer: FilenameCompleter::new(),
- highlighter: MatchingBracketHighlighter::new(),
- hinter: HistoryHinter {},
- colored_prompt: "".to_owned(),
- validator: MatchingBracketValidator::new(),
- };
- let mut rl = Editor::with_config(config);
- rl.set_helper(Some(h));
- rl.bind_sequence(KeyEvent::alt('n'), Cmd::HistorySearchForward);
- rl.bind_sequence(KeyEvent::alt('p'), Cmd::HistorySearchBackward);
- if rl.load_history("history.txt").is_err() {
- println!("No previous history.");
- }
- let mut count = 1;
- loop {
- let p = format!("{}> ", count);
- rl.helper_mut().expect("No helper").colored_prompt = format!("\x1b[1;32m{}\x1b[0m", p);
- let readline = rl.readline(&p);
- match readline {
- Ok(line) => {
- rl.add_history_entry(line.as_str());
- println!("Line: {}", line);
- }
- Err(ReadlineError::Interrupted) => {
- println!("CTRL-C");
- break;
- }
- Err(ReadlineError::Eof) => {
- println!("CTRL-D");
- break;
- }
- Err(err) => {
- println!("Error: {:?}", err);
- break;
- }
- }
- count += 1;
- }
- rl.append_history("history.txt")
-}
diff --git a/vendor/rustyline-8.2.0/examples/input_validation.rs b/vendor/rustyline-8.2.0/examples/input_validation.rs
deleted file mode 100644
index c80a34d..0000000
--- a/vendor/rustyline-8.2.0/examples/input_validation.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-use rustyline::validate::{ValidationContext, ValidationResult, Validator};
-use rustyline::{Editor, Result};
-use rustyline_derive::{Completer, Helper, Highlighter, Hinter};
-
-#[derive(Completer, Helper, Highlighter, Hinter)]
-struct InputValidator {}
-
-impl Validator for InputValidator {
- fn validate(&self, ctx: &mut ValidationContext) -> Result<ValidationResult> {
- use ValidationResult::{Incomplete, Invalid, Valid};
- let input = ctx.input();
- let result = if !input.starts_with("SELECT") {
- Invalid(Some(" --< Expect: SELECT stmt".to_owned()))
- } else if !input.ends_with(';') {
- Incomplete
- } else {
- Valid(None)
- };
- Ok(result)
- }
-}
-
-fn main() -> Result<()> {
- let h = InputValidator {};
- let mut rl = Editor::new();
- rl.set_helper(Some(h));
-
- let input = rl.readline("> ")?;
- println!("Input: {}", input);
- Ok(())
-}
diff --git a/vendor/rustyline-8.2.0/examples/minimal.rs b/vendor/rustyline-8.2.0/examples/minimal.rs
deleted file mode 100644
index de84a59..0000000
--- a/vendor/rustyline-8.2.0/examples/minimal.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-use rustyline::{Editor, Result};
-
-/// Minimal REPL
-fn main() -> Result<()> {
- let mut rl = Editor::<()>::new();
- loop {
- let line = rl.readline("> ")?; // read
- println!("Line: {}", line); // eval / print
- } // loop
-}
diff --git a/vendor/rustyline-8.2.0/examples/numeric_input.rs b/vendor/rustyline-8.2.0/examples/numeric_input.rs
deleted file mode 100644
index bdb7625..0000000
--- a/vendor/rustyline-8.2.0/examples/numeric_input.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-use rustyline::{
- Cmd, ConditionalEventHandler, Editor, Event, EventContext, EventHandler, KeyCode, KeyEvent,
- Modifiers, RepeatCount, Result,
-};
-
-struct FilteringEventHandler;
-impl ConditionalEventHandler for FilteringEventHandler {
- fn handle(&self, evt: &Event, _: RepeatCount, _: bool, _: &EventContext) -> Option<Cmd> {
- if let Some(KeyEvent(KeyCode::Char(c), m)) = evt.get(0) {
- if m.contains(Modifiers::CTRL) || m.contains(Modifiers::ALT) || c.is_ascii_digit() {
- None
- } else {
- Some(Cmd::Noop) // filter out invalid input
- }
- } else {
- None
- }
- }
-}
-
-fn main() -> Result<()> {
- let mut rl = Editor::<()>::new();
-
- rl.bind_sequence(
- Event::Any,
- EventHandler::Conditional(Box::new(FilteringEventHandler)),
- );
-
- loop {
- let line = rl.readline("> ")?;
- println!("Num: {}", line);
- }
-}
diff --git a/vendor/rustyline-8.2.0/examples/read_password.rs b/vendor/rustyline-8.2.0/examples/read_password.rs
deleted file mode 100644
index 435e6e3..0000000
--- a/vendor/rustyline-8.2.0/examples/read_password.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-use std::borrow::Cow::{self, Borrowed, Owned};
-
-use rustyline::config::Configurer;
-use rustyline::highlight::Highlighter;
-use rustyline::{ColorMode, Editor, Result};
-use rustyline_derive::{Completer, Helper, Hinter, Validator};
-
-#[derive(Completer, Helper, Hinter, Validator)]
-struct MaskingHighlighter {
- masking: bool,
-}
-
-impl Highlighter for MaskingHighlighter {
- fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> {
- use unicode_width::UnicodeWidthStr;
- if self.masking {
- Owned("*".repeat(line.width()))
- } else {
- Borrowed(line)
- }
- }
-
- fn highlight_char(&self, _line: &str, _pos: usize) -> bool {
- self.masking
- }
-}
-
-fn main() -> Result<()> {
- println!("This is just a hack. Reading passwords securely requires more than that.");
- let h = MaskingHighlighter { masking: false };
- let mut rl = Editor::new();
- rl.set_helper(Some(h));
-
- let username = rl.readline("Username:")?;
- println!("Username: {}", username);
-
- rl.helper_mut().expect("No helper").masking = true;
- rl.set_color_mode(ColorMode::Forced); // force masking
- rl.set_auto_add_history(false); // make sure password is not added to history
- let passwd = rl.readline("Password:")?;
- println!("Secret: {}", passwd);
- Ok(())
-}
diff --git a/vendor/rustyline-8.2.0/rustfmt.toml b/vendor/rustyline-8.2.0/rustfmt.toml
deleted file mode 100644
index 4046229..0000000
--- a/vendor/rustyline-8.2.0/rustfmt.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-wrap_comments = true
-format_strings = true
-error_on_unformatted = false
-reorder_impl_items = true
-
-condense_wildcard_suffixes = true
-format_code_in_doc_comments = true
-format_macro_matchers = true
-format_macro_bodies = true
-#merge_imports = true
-normalize_doc_attributes = true
-use_field_init_shorthand = true
-use_try_shorthand = true
\ No newline at end of file
diff --git a/vendor/rustyline-8.2.0/src/binding.rs b/vendor/rustyline-8.2.0/src/binding.rs
deleted file mode 100644
index 9ce395f..0000000
--- a/vendor/rustyline-8.2.0/src/binding.rs
+++ /dev/null
@@ -1,244 +0,0 @@
-/// Custom event handlers
-use crate::{
- Cmd, EditMode, InputMode, InputState, KeyCode, KeyEvent, Modifiers, Refresher, RepeatCount,
-};
-
-use radix_trie::TrieKey;
-use smallvec::{smallvec, SmallVec};
-
-/// Input event
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum Event {
- /// Wildcard.
- /// Useful if you want to filter out some keys.
- Any,
- /// Key sequence
- // TODO Validate 2 ?
- KeySeq(SmallVec<[KeyEvent; 2]>),
- /// TODO Mouse event
- Mouse(),
-}
-
-impl Event {
- /// See [`KeyEvent::normalize`]
- pub(crate) fn normalize(mut self) -> Self {
- if let Event::KeySeq(ref mut keys) = self {
- for key in keys.iter_mut() {
- *key = KeyEvent::normalize(*key);
- }
- }
- self
- }
-
- /// Return `i`th key event
- pub fn get(&self, i: usize) -> Option<&KeyEvent> {
- if let Event::KeySeq(ref ks) = self {
- ks.get(i)
- } else {
- None
- }
- }
-}
-
-impl From<KeyEvent> for Event {
- fn from(k: KeyEvent) -> Event {
- Event::KeySeq(smallvec![k])
- }
-}
-
-const BASE: u32 = 0x0010ffff + 1;
-const BASE_CONTROL: u32 = 0x02000000;
-const BASE_META: u32 = 0x04000000;
-const BASE_SHIFT: u32 = 0x01000000;
-const ESCAPE: u32 = 27;
-const PAGE_UP: u32 = BASE + 1;
-const PAGE_DOWN: u32 = PAGE_UP + 1;
-const DOWN: u32 = PAGE_DOWN + 1;
-const UP: u32 = DOWN + 1;
-const LEFT: u32 = UP + 1;
-const RIGHT: u32 = LEFT + 1;
-const HOME: u32 = RIGHT + 1;
-const END: u32 = HOME + 1;
-const DELETE: u32 = END + 1;
-const INSERT: u32 = DELETE + 1;
-//const F1: u32 = INSERT + 1;
-const MOUSE: u32 = /* F24 + 1 */ INSERT + 25;
-const PASTE_START: u32 = MOUSE + 1;
-const PASTE_FINISH: u32 = PASTE_START + 1;
-const ANY: u32 = PASTE_FINISH + 1;
-
-impl KeyEvent {
- fn encode(&self) -> u32 {
- let mut u = match self.0 {
- KeyCode::UnknownEscSeq => 0,
- KeyCode::Backspace => u32::from('\x7f'),
- KeyCode::BackTab => u32::from('\t') | BASE_SHIFT,
- KeyCode::BracketedPasteStart => PASTE_START,
- KeyCode::BracketedPasteEnd => PASTE_FINISH,
- KeyCode::Char(c) => u32::from(c),
- KeyCode::Delete => DELETE,
- KeyCode::Down => DOWN,
- KeyCode::End => END,
- KeyCode::Enter => u32::from('\r'),
- KeyCode::F(i) => INSERT + i as u32,
- KeyCode::Esc => ESCAPE,
- KeyCode::Home => HOME,
- KeyCode::Insert => INSERT,
- KeyCode::Left => LEFT,
- KeyCode::Null => 0,
- KeyCode::PageDown => PAGE_DOWN,
- KeyCode::PageUp => PAGE_UP,
- KeyCode::Right => RIGHT,
- KeyCode::Tab => u32::from('\t'),
- KeyCode::Up => UP,
- };
- if self.1.contains(Modifiers::CTRL) {
- u |= BASE_CONTROL;
- }
- if self.1.contains(Modifiers::ALT) {
- u |= BASE_META;
- }
- if self.1.contains(Modifiers::SHIFT) {
- u |= BASE_SHIFT;
- }
- u
- }
-}
-
-impl TrieKey for Event {
- fn encode_bytes(&self) -> Vec<u8> {
- match self {
- Event::Any => ANY.to_be_bytes().to_vec(),
- Event::KeySeq(keys) => {
- let mut dst = Vec::with_capacity(keys.len() * 4);
- for key in keys {
- dst.extend_from_slice(&key.encode().to_be_bytes());
- }
- dst
- }
- Event::Mouse() => MOUSE.to_be_bytes().to_vec(),
- }
- }
-}
-
-/// Event handler
-pub enum EventHandler {
- /// unconditional command
- Simple(Cmd),
- /// handler behaviour depends on input state
- Conditional(Box<dyn ConditionalEventHandler>),
- /* invoke multiple actions
- * TODO Macro(), */
-}
-
-impl From<Cmd> for EventHandler {
- fn from(c: Cmd) -> EventHandler {
- EventHandler::Simple(c)
- }
-}
-
-/// Give access to user input.
-pub struct EventContext<'r> {
- mode: EditMode,
- input_mode: InputMode,
- wrt: &'r dyn Refresher,
-}
-
-impl<'r> EventContext<'r> {
- pub(crate) fn new(is: &InputState, wrt: &'r dyn Refresher) -> Self {
- EventContext {
- mode: is.mode,
- input_mode: is.input_mode,
- wrt,
- }
- }
-
- /// emacs or vi mode
- pub fn mode(&self) -> EditMode {
- self.mode
- }
-
- /// vi input mode
- pub fn input_mode(&self) -> InputMode {
- self.input_mode
- }
-
- /// Returns `true` if there is a hint displayed.
- pub fn has_hint(&self) -> bool {
- self.wrt.has_hint()
- }
-
- /// Returns the hint text that is shown after the current cursor position.
- pub fn hint_text(&self) -> Option<&str> {
- self.wrt.hint_text()
- }
-
- /// currently edited line
- pub fn line(&self) -> &str {
- self.wrt.line()
- }
-
- /// Current cursor position (byte position)
- pub fn pos(&self) -> usize {
- self.wrt.pos()
- }
-}
-
-/// May behave differently depending on:
-/// * edit mode (emacs vs vi)
-/// * vi input mode (insert vs replace vs command modes)
-/// * empty line
-/// * cursor position
-/// * repeat count
-/// * original key pressed (when same command is bound to different key)
-/// * hint
-/// * ...
-pub trait ConditionalEventHandler: Send + Sync {
- /// Takes the current input state and
- /// returns the command to be performed or `None` to perform the default
- /// one.
- fn handle(
- &self,
- evt: &Event,
- n: RepeatCount,
- positive: bool,
- ctx: &EventContext,
- ) -> Option<Cmd>;
-}
-
-#[cfg(test)]
-mod test {
- use super::{Event, EventHandler};
- use crate::{Cmd, KeyCode, KeyEvent, Modifiers};
- use radix_trie::Trie;
- use smallvec::smallvec;
-
- #[test]
- fn encode() {
- let mut trie = Trie::new();
- let evt = Event::KeySeq(smallvec![KeyEvent::ctrl('X'), KeyEvent::ctrl('E')]);
- trie.insert(evt.clone(), EventHandler::from(Cmd::Noop));
- let prefix = Event::from(KeyEvent::ctrl('X'));
- let subtrie = trie.get_raw_descendant(&prefix);
- assert!(subtrie.is_some());
- let subtrie = subtrie.unwrap();
- let sub_result = subtrie.get(&evt);
- assert!(sub_result.is_ok());
- assert!(sub_result.unwrap().is_some());
- let prefix = Event::from(KeyEvent::ctrl('O'));
- let subtrie = trie.get_raw_descendant(&prefix);
- assert!(subtrie.is_none())
- }
-
- #[test]
- fn no_collision() {
- use {Event as E, EventHandler as H, KeyCode as C, KeyEvent as K, Modifiers as M};
- let mut trie = Trie::new();
- trie.insert(E::from(K(C::Backspace, M::NONE)), H::from(Cmd::Noop));
- trie.insert(E::from(K(C::Enter, M::NONE)), H::from(Cmd::Noop));
- trie.insert(E::from(K(C::Tab, M::NONE)), H::from(Cmd::Noop));
- trie.insert(E::from(K(C::Backspace, M::CTRL)), H::from(Cmd::Noop));
- trie.insert(E::from(K(C::Enter, M::CTRL)), H::from(Cmd::Noop));
- trie.insert(E::from(K(C::Tab, M::CTRL)), H::from(Cmd::Noop));
- }
-}
diff --git a/vendor/rustyline-8.2.0/src/command.rs b/vendor/rustyline-8.2.0/src/command.rs
deleted file mode 100644
index ab3c91f..0000000
--- a/vendor/rustyline-8.2.0/src/command.rs
+++ /dev/null
@@ -1,237 +0,0 @@
-use std::sync::{Arc, Mutex};
-
-use crate::complete_hint_line;
-use crate::config::Config;
-use crate::edit::State;
-use crate::error;
-use crate::history::Direction;
-use crate::keymap::{Anchor, At, Cmd, Movement, Word};
-use crate::keymap::{InputState, Refresher};
-use crate::kill_ring::{KillRing, Mode};
-use crate::line_buffer::WordAction;
-use crate::{Helper, Result};
-
-pub enum Status {
- Proceed,
- Submit,
-}
-
-pub fn execute<H: Helper>(
- cmd: Cmd,
- s: &mut State<'_, '_, H>,
- input_state: &InputState,
- kill_ring: &Arc<Mutex<KillRing>>,
- config: &Config,
-) -> Result<Status> {
- use Status::*;
-
- match cmd {
- Cmd::CompleteHint => {
- complete_hint_line(s)?;
- }
- Cmd::SelfInsert(n, c) => {
- s.edit_insert(c, n)?;
- }
- Cmd::Insert(n, text) => {
- s.edit_yank(&input_state, &text, Anchor::Before, n)?;
- }
- Cmd::Move(Movement::BeginningOfLine) => {
- // Move to the beginning of line.
- s.edit_move_home()?
- }
- Cmd::Move(Movement::ViFirstPrint) => {
- s.edit_move_home()?;
- s.edit_move_to_next_word(At::Start, Word::Big, 1)?
- }
- Cmd::Move(Movement::BackwardChar(n)) => {
- // Move back a character.
- s.edit_move_backward(n)?
- }
- Cmd::ReplaceChar(n, c) => s.edit_replace_char(c, n)?,
- Cmd::Replace(mvt, text) => {
- s.edit_kill(&mvt)?;
- if let Some(text) = text {
- s.edit_insert_text(&text)?
- }
- }
- Cmd::Overwrite(c) => {
- s.edit_overwrite_char(c)?;
- }
- Cmd::EndOfFile => {
- if input_state.is_emacs_mode() && !s.line.is_empty() {
- s.edit_delete(1)?
- } else {
- if s.has_hint() || !s.is_default_prompt() {
- // Force a refresh without hints to leave the previous
- // line as the user typed it after a newline.
- s.refresh_line_with_msg(None)?;
- }
- if s.line.is_empty() {
- return Err(error::ReadlineError::Eof);
- } else if !input_state.is_emacs_mode() {
- return Ok(Submit);
- }
- }
- }
- Cmd::Move(Movement::EndOfLine) => {
- // Move to the end of line.
- s.edit_move_end()?
- }
- Cmd::Move(Movement::ForwardChar(n)) => {
- // Move forward a character.
- s.edit_move_forward(n)?
- }
- Cmd::ClearScreen => {
- // Clear the screen leaving the current line at the top of the screen.
- s.clear_screen()?;
- s.refresh_line()?
- }
- Cmd::NextHistory => {
- // Fetch the next command from the history list.
- s.edit_history_next(false)?
- }
- Cmd::PreviousHistory => {
- // Fetch the previous command from the history list.
- s.edit_history_next(true)?
- }
- Cmd::LineUpOrPreviousHistory(n) => {
- if !s.edit_move_line_up(n)? {
- s.edit_history_next(true)?
- }
- }
- Cmd::LineDownOrNextHistory(n) => {
- if !s.edit_move_line_down(n)? {
- s.edit_history_next(false)?
- }
- }
- Cmd::HistorySearchBackward => s.edit_history_search(Direction::Reverse)?,
- Cmd::HistorySearchForward => s.edit_history_search(Direction::Forward)?,
- Cmd::TransposeChars => {
- // Exchange the char before cursor with the character at cursor.
- s.edit_transpose_chars()?
- }
- Cmd::Yank(n, anchor) => {
- // retrieve (yank) last item killed
- let mut kill_ring = kill_ring.lock().unwrap();
- if let Some(text) = kill_ring.yank() {
- s.edit_yank(&input_state, text, anchor, n)?
- }
- }
- Cmd::ViYankTo(ref mvt) => {
- if let Some(text) = s.line.copy(mvt) {
- let mut kill_ring = kill_ring.lock().unwrap();
- kill_ring.kill(&text, Mode::Append)
- }
- }
- Cmd::AcceptLine | Cmd::AcceptOrInsertLine { .. } | Cmd::Newline => {
- if s.has_hint() || !s.is_default_prompt() {
- // Force a refresh without hints to leave the previous
- // line as the user typed it after a newline.
- s.refresh_line_with_msg(None)?;
- }
- let validation_result = s.validate()?;
- let valid = validation_result.is_valid();
- let end = s.line.is_end_of_input();
- match (cmd, valid, end) {
- (Cmd::AcceptLine, ..)
- | (Cmd::AcceptOrInsertLine { .. }, true, true)
- | (
- Cmd::AcceptOrInsertLine {
- accept_in_the_middle: true,
- },
- true,
- _,
- ) => {
- return Ok(Submit);
- }
- (Cmd::Newline, ..)
- | (Cmd::AcceptOrInsertLine { .. }, false, _)
- | (Cmd::AcceptOrInsertLine { .. }, true, false) => {
- if valid || !validation_result.has_message() {
- s.edit_insert('\n', 1)?;
- }
- }
- _ => unreachable!(),
- }
- }
- Cmd::BeginningOfHistory => {
- // move to first entry in history
- s.edit_history(true)?
- }
- Cmd::EndOfHistory => {
- // move to last entry in history
- s.edit_history(false)?
- }
- Cmd::Move(Movement::BackwardWord(n, word_def)) => {
- // move backwards one word
- s.edit_move_to_prev_word(word_def, n)?
- }
- Cmd::CapitalizeWord => {
- // capitalize word after point
- s.edit_word(WordAction::Capitalize)?
- }
- Cmd::Kill(ref mvt) => {
- s.edit_kill(mvt)?;
- }
- Cmd::Move(Movement::ForwardWord(n, at, word_def)) => {
- // move forwards one word
- s.edit_move_to_next_word(at, word_def, n)?
- }
- Cmd::Move(Movement::LineUp(n)) => {
- s.edit_move_line_up(n)?;
- }
- Cmd::Move(Movement::LineDown(n)) => {
- s.edit_move_line_down(n)?;
- }
- Cmd::Move(Movement::BeginningOfBuffer) => {
- // Move to the start of the buffer.
- s.edit_move_buffer_start()?
- }
- Cmd::Move(Movement::EndOfBuffer) => {
- // Move to the end of the buffer.
- s.edit_move_buffer_end()?
- }
- Cmd::DowncaseWord => {
- // lowercase word after point
- s.edit_word(WordAction::Lowercase)?
- }
- Cmd::TransposeWords(n) => {
- // transpose words
- s.edit_transpose_words(n)?
- }
- Cmd::UpcaseWord => {
- // uppercase word after point
- s.edit_word(WordAction::Uppercase)?
- }
- Cmd::YankPop => {
- // yank-pop
- let mut kill_ring = kill_ring.lock().unwrap();
- if let Some((yank_size, text)) = kill_ring.yank_pop() {
- s.edit_yank_pop(yank_size, text)?
- }
- }
- Cmd::Move(Movement::ViCharSearch(n, cs)) => s.edit_move_to(cs, n)?,
- Cmd::Undo(n) => {
- if s.changes.borrow_mut().undo(&mut s.line, n) {
- s.refresh_line()?;
- }
- }
- Cmd::Dedent(mvt) => {
- s.edit_indent(&mvt, config.indent_size(), true)?;
- }
- Cmd::Indent(mvt) => {
- s.edit_indent(&mvt, config.indent_size(), false)?;
- }
- Cmd::Interrupt => {
- // Move to end, in case cursor was in the middle of the
- // line, so that next thing application prints goes after
- // the input
- s.edit_move_buffer_end()?;
- return Err(error::ReadlineError::Interrupted);
- }
- _ => {
- // Ignore the character typed.
- }
- }
- Ok(Proceed)
-}
diff --git a/vendor/rustyline-8.2.0/src/completion.rs b/vendor/rustyline-8.2.0/src/completion.rs
deleted file mode 100644
index cbbc5f3..0000000
--- a/vendor/rustyline-8.2.0/src/completion.rs
+++ /dev/null
@@ -1,637 +0,0 @@
-//! Completion API
-use std::borrow::Cow::{self, Borrowed, Owned};
-use std::fs;
-use std::path::{self, Path};
-
-use crate::line_buffer::LineBuffer;
-use crate::{Context, Result};
-use memchr::memchr;
-
-// TODO: let the implementers choose/find word boundaries ???
-// (line, pos) is like (rl_line_buffer, rl_point) to make contextual completion
-// ("select t.na| from tbl as t")
-// TODO: make &self &mut self ???
-
-/// A completion candidate.
-pub trait Candidate {
- /// Text to display when listing alternatives.
- fn display(&self) -> &str;
- /// Text to insert in line.
- fn replacement(&self) -> &str;
-}
-
-impl Candidate for String {
- fn display(&self) -> &str {
- self.as_str()
- }
-
- fn replacement(&self) -> &str {
- self.as_str()
- }
-}
-
-/// #[deprecated = "Unusable"]
-impl Candidate for str {
- fn display(&self) -> &str {
- self
- }
-
- fn replacement(&self) -> &str {
- self
- }
-}
-
-impl Candidate for &'_ str {
- fn display(&self) -> &str {
- self
- }
-
- fn replacement(&self) -> &str {
- self
- }
-}
-
-/// Completion candidate pair
-pub struct Pair {
- /// Text to display when listing alternatives.
- pub display: String,
- /// Text to insert in line.
- pub replacement: String,
-}
-
-impl Candidate for Pair {
- fn display(&self) -> &str {
- self.display.as_str()
- }
-
- fn replacement(&self) -> &str {
- self.replacement.as_str()
- }
-}
-
-/// To be called for tab-completion.
-pub trait Completer {
- /// Specific completion candidate.
- type Candidate: Candidate;
-
- /// Takes the currently edited `line` with the cursor `pos`ition and
- /// returns the start position and the completion candidates for the
- /// partial word to be completed.
- ///
- /// ("ls /usr/loc", 11) => Ok((3, vec!["/usr/local/"]))
- fn complete(
- &self,
- line: &str,
- pos: usize,
- ctx: &Context<'_>,
- ) -> Result<(usize, Vec<Self::Candidate>)> {
- let _ = (line, pos, ctx);
- Ok((0, Vec::with_capacity(0)))
- }
- /// Updates the edited `line` with the `elected` candidate.
- fn update(&self, line: &mut LineBuffer, start: usize, elected: &str) {
- let end = line.pos();
- line.replace(start..end, elected)
- }
-}
-
-impl Completer for () {
- type Candidate = String;
-
- fn update(&self, _line: &mut LineBuffer, _start: usize, _elected: &str) {
- unreachable!()
- }
-}
-
-impl<'c, C: ?Sized + Completer> Completer for &'c C {
- type Candidate = C::Candidate;
-
- fn complete(
- &self,
- line: &str,
- pos: usize,
- ctx: &Context<'_>,
- ) -> Result<(usize, Vec<Self::Candidate>)> {
- (**self).complete(line, pos, ctx)
- }
-
- fn update(&self, line: &mut LineBuffer, start: usize, elected: &str) {
- (**self).update(line, start, elected)
- }
-}
-macro_rules! box_completer {
- ($($id: ident)*) => {
- $(
- impl<C: ?Sized + Completer> Completer for $id<C> {
- type Candidate = C::Candidate;
-
- fn complete(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Result<(usize, Vec<Self::Candidate>)> {
- (**self).complete(line, pos, ctx)
- }
- fn update(&self, line: &mut LineBuffer, start: usize, elected: &str) {
- (**self).update(line, start, elected)
- }
- }
- )*
- }
-}
-
-use std::rc::Rc;
-use std::sync::Arc;
-box_completer! { Box Rc Arc }
-
-/// A `Completer` for file and folder names.
-pub struct FilenameCompleter {
- break_chars: &'static [u8],
- double_quotes_special_chars: &'static [u8],
-}
-
-const DOUBLE_QUOTES_ESCAPE_CHAR: Option<char> = Some('\\');
-
-cfg_if::cfg_if! {
- if #[cfg(unix)] {
- // rl_basic_word_break_characters, rl_completer_word_break_characters
- const DEFAULT_BREAK_CHARS: [u8; 18] = [
- b' ', b'\t', b'\n', b'"', b'\\', b'\'', b'`', b'@', b'$', b'>', b'<', b'=', b';', b'|', b'&',
- b'{', b'(', b'\0',
- ];
- const ESCAPE_CHAR: Option<char> = Some('\\');
- // In double quotes, not all break_chars need to be escaped
- // https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html
- const DOUBLE_QUOTES_SPECIAL_CHARS: [u8; 4] = [b'"', b'$', b'\\', b'`'];
- } else if #[cfg(windows)] {
- // Remove \ to make file completion works on windows
- const DEFAULT_BREAK_CHARS: [u8; 17] = [
- b' ', b'\t', b'\n', b'"', b'\'', b'`', b'@', b'$', b'>', b'<', b'=', b';', b'|', b'&', b'{',
- b'(', b'\0',
- ];
- const ESCAPE_CHAR: Option<char> = None;
- const DOUBLE_QUOTES_SPECIAL_CHARS: [u8; 1] = [b'"']; // TODO Validate: only '"' ?
- } else if #[cfg(target_arch = "wasm32")] {
- const DEFAULT_BREAK_CHARS: [u8; 0] = [];
- const ESCAPE_CHAR: Option<char> = None;
- const DOUBLE_QUOTES_SPECIAL_CHARS: [u8; 0] = [];
- }
-}
-
-/// Kind of quote.
-#[derive(Clone, Copy, Debug, PartialEq)]
-pub enum Quote {
- /// Double quote: `"`
- Double,
- /// Single quote: `'`
- Single,
- /// No quote
- None,
-}
-
-impl FilenameCompleter {
- /// Constructor
- pub fn new() -> Self {
- Self {
- break_chars: &DEFAULT_BREAK_CHARS,
- double_quotes_special_chars: &DOUBLE_QUOTES_SPECIAL_CHARS,
- }
- }
-
- /// Takes the currently edited `line` with the cursor `pos`ition and
- /// returns the start position and the completion candidates for the
- /// partial path to be completed.
- pub fn complete_path(&self, line: &str, pos: usize) -> Result<(usize, Vec<Pair>)> {
- let (start, path, esc_char, break_chars, quote) =
- if let Some((idx, quote)) = find_unclosed_quote(&line[..pos]) {
- let start = idx + 1;
- if quote == Quote::Double {
- (
- start,
- unescape(&line[start..pos], DOUBLE_QUOTES_ESCAPE_CHAR),
- DOUBLE_QUOTES_ESCAPE_CHAR,
- &self.double_quotes_special_chars,
- quote,
- )
- } else {
- (
- start,
- Borrowed(&line[start..pos]),
- None,
- &self.break_chars,
- quote,
- )
- }
- } else {
- let (start, path) = extract_word(line, pos, ESCAPE_CHAR, &self.break_chars);
- let path = unescape(path, ESCAPE_CHAR);
- (start, path, ESCAPE_CHAR, &self.break_chars, Quote::None)
- };
- let mut matches = filename_complete(&path, esc_char, break_chars, quote);
- #[allow(clippy::unnecessary_sort_by)]
- matches.sort_by(|a, b| a.display().cmp(b.display()));
- Ok((start, matches))
- }
-}
-
-impl Default for FilenameCompleter {
- fn default() -> Self {
- Self::new()
- }
-}
-
-impl Completer for FilenameCompleter {
- type Candidate = Pair;
-
- fn complete(&self, line: &str, pos: usize, _ctx: &Context<'_>) -> Result<(usize, Vec<Pair>)> {
- self.complete_path(line, pos)
- }
-}
-
-/// Remove escape char
-pub fn unescape(input: &str, esc_char: Option<char>) -> Cow<'_, str> {
- let esc_char = if let Some(c) = esc_char {
- c
- } else {
- return Borrowed(input);
- };
- if !input.chars().any(|c| c == esc_char) {
- return Borrowed(input);
- }
- let mut result = String::with_capacity(input.len());
- let mut chars = input.chars();
- while let Some(ch) = chars.next() {
- if ch == esc_char {
- if let Some(ch) = chars.next() {
- if cfg!(windows) && ch != '"' {
- // TODO Validate: only '"' ?
- result.push(esc_char);
- }
- result.push(ch);
- } else if cfg!(windows) {
- result.push(ch);
- }
- } else {
- result.push(ch);
- }
- }
- Owned(result)
-}
-
-/// Escape any `break_chars` in `input` string with `esc_char`.
-/// For example, '/User Information' becomes '/User\ Information'
-/// when space is a breaking char and '\\' the escape char.
-pub fn escape(
- mut input: String,
- esc_char: Option<char>,
- break_chars: &[u8],
- quote: Quote,
-) -> String {
- if quote == Quote::Single {
- return input; // no escape in single quotes
- }
- let n = input
- .bytes()
- .filter(|b| memchr(*b, break_chars).is_some())
- .count();
- if n == 0 {
- return input; // no need to escape
- }
- let esc_char = if let Some(c) = esc_char {
- c
- } else {
- if cfg!(windows) && quote == Quote::None {
- input.insert(0, '"'); // force double quote
- return input;
- }
- return input;
- };
- let mut result = String::with_capacity(input.len() + n);
-
- for c in input.chars() {
- if c.is_ascii() && memchr(c as u8, break_chars).is_some() {
- result.push(esc_char);
- }
- result.push(c);
- }
- result
-}
-
-fn filename_complete(
- path: &str,
- esc_char: Option<char>,
- break_chars: &[u8],
- quote: Quote,
-) -> Vec<Pair> {
- #[cfg(feature = "with-dirs")]
- use dirs_next::home_dir;
- use std::env::current_dir;
-
- let sep = path::MAIN_SEPARATOR;
- let (dir_name, file_name) = match path.rfind(sep) {
- Some(idx) => path.split_at(idx + sep.len_utf8()),
- None => ("", path),
- };
-
- let dir_path = Path::new(dir_name);
- let dir = if dir_path.starts_with("~") {
- // ~[/...]
- #[cfg(feature = "with-dirs")]
- {
- if let Some(home) = home_dir() {
- match dir_path.strip_prefix("~") {
- Ok(rel_path) => home.join(rel_path),
- _ => home,
- }
- } else {
- dir_path.to_path_buf()
- }
- }
- #[cfg(not(feature = "with-dirs"))]
- {
- dir_path.to_path_buf()
- }
- } else if dir_path.is_relative() {
- // TODO ~user[/...] (https://crates.io/crates/users)
- if let Ok(cwd) = current_dir() {
- cwd.join(dir_path)
- } else {
- dir_path.to_path_buf()
- }
- } else {
- dir_path.to_path_buf()
- };
-
- let mut entries: Vec<Pair> = Vec::new();
-
- // if dir doesn't exist, then don't offer any completions
- if !dir.exists() {
- return entries;
- }
-
- // if any of the below IO operations have errors, just ignore them
- if let Ok(read_dir) = dir.read_dir() {
- let file_name = normalize(file_name);
- for entry in read_dir.flatten() {
- if let Some(s) = entry.file_name().to_str() {
- let ns = normalize(s);
- if ns.starts_with(file_name.as_ref()) {
- if let Ok(metadata) = fs::metadata(entry.path()) {
- let mut path = String::from(dir_name) + s;
- if metadata.is_dir() {
- path.push(sep);
- }
- entries.push(Pair {
- display: String::from(s),
- replacement: escape(path, esc_char, break_chars, quote),
- });
- } // else ignore PermissionDenied
- }
- }
- }
- }
- entries
-}
-
-#[cfg(any(windows, target_os = "macos"))]
-fn normalize(s: &str) -> Cow<str> {
- // case insensitive
- Cow::Owned(s.to_lowercase())
-}
-
-#[cfg(not(any(windows, target_os = "macos")))]
-fn normalize(s: &str) -> Cow<str> {
- Cow::Borrowed(s)
-}
-
-/// Given a `line` and a cursor `pos`ition,
-/// try to find backward the start of a word.
-/// Return (0, `line[..pos]`) if no break char has been found.
-/// Return the word and its start position (idx, `line[idx..pos]`) otherwise.
-pub fn extract_word<'l>(
- line: &'l str,
- pos: usize,
- esc_char: Option<char>,
- break_chars: &[u8],
-) -> (usize, &'l str) {
- let line = &line[..pos];
- if line.is_empty() {
- return (0, line);
- }
- let mut start = None;
- for (i, c) in line.char_indices().rev() {
- if let (Some(esc_char), true) = (esc_char, start.is_some()) {
- if esc_char == c {
- // escaped break char
- start = None;
- continue;
- } else {
- break;
- }
- }
- if c.is_ascii() && memchr(c as u8, break_chars).is_some() {
- start = Some(i + c.len_utf8());
- if esc_char.is_none() {
- break;
- } // else maybe escaped...
- }
- }
-
- match start {
- Some(start) => (start, &line[start..]),
- None => (0, line),
- }
-}
-
-/// Returns the longest common prefix among all `Candidate::replacement()`s.
-pub fn longest_common_prefix<C: Candidate>(candidates: &[C]) -> Option<&str> {
- if candidates.is_empty() {
- return None;
- } else if candidates.len() == 1 {
- return Some(&candidates[0].replacement());
- }
- let mut longest_common_prefix = 0;
- 'o: loop {
- for (i, c1) in candidates.iter().enumerate().take(candidates.len() - 1) {
- let b1 = c1.replacement().as_bytes();
- let b2 = candidates[i + 1].replacement().as_bytes();
- if b1.len() <= longest_common_prefix
- || b2.len() <= longest_common_prefix
- || b1[longest_common_prefix] != b2[longest_common_prefix]
- {
- break 'o;
- }
- }
- longest_common_prefix += 1;
- }
- let candidate = candidates[0].replacement();
- while !candidate.is_char_boundary(longest_common_prefix) {
- longest_common_prefix -= 1;
- }
- if longest_common_prefix == 0 {
- return None;
- }
- Some(&candidate[0..longest_common_prefix])
-}
-
-#[derive(PartialEq)]
-enum ScanMode {
- DoubleQuote,
- Escape,
- EscapeInDoubleQuote,
- Normal,
- SingleQuote,
-}
-
-/// try to find an unclosed single/double quote in `s`.
-/// Return `None` if no unclosed quote is found.
-/// Return the unclosed quote position and if it is a double quote.
-fn find_unclosed_quote(s: &str) -> Option<(usize, Quote)> {
- let char_indices = s.char_indices();
- let mut mode = ScanMode::Normal;
- let mut quote_index = 0;
- for (index, char) in char_indices {
- match mode {
- ScanMode::DoubleQuote => {
- if char == '"' {
- mode = ScanMode::Normal;
- } else if char == '\\' {
- // both windows and unix support escape in double quote
- mode = ScanMode::EscapeInDoubleQuote;
- }
- }
- ScanMode::Escape => {
- mode = ScanMode::Normal;
- }
- ScanMode::EscapeInDoubleQuote => {
- mode = ScanMode::DoubleQuote;
- }
- ScanMode::Normal => {
- if char == '"' {
- mode = ScanMode::DoubleQuote;
- quote_index = index;
- } else if char == '\\' && cfg!(not(windows)) {
- mode = ScanMode::Escape;
- } else if char == '\'' && cfg!(not(windows)) {
- mode = ScanMode::SingleQuote;
- quote_index = index;
- }
- }
- ScanMode::SingleQuote => {
- if char == '\'' {
- mode = ScanMode::Normal;
- } // no escape in single quotes
- }
- };
- }
- if ScanMode::DoubleQuote == mode || ScanMode::EscapeInDoubleQuote == mode {
- return Some((quote_index, Quote::Double));
- } else if ScanMode::SingleQuote == mode {
- return Some((quote_index, Quote::Single));
- }
- None
-}
-
-#[cfg(test)]
-mod tests {
- #[test]
- pub fn extract_word() {
- let break_chars: &[u8] = &super::DEFAULT_BREAK_CHARS;
- let line = "ls '/usr/local/b";
- assert_eq!(
- (4, "/usr/local/b"),
- super::extract_word(line, line.len(), Some('\\'), &break_chars)
- );
- let line = "ls /User\\ Information";
- assert_eq!(
- (3, "/User\\ Information"),
- super::extract_word(line, line.len(), Some('\\'), &break_chars)
- );
- }
-
- #[test]
- pub fn unescape() {
- use std::borrow::Cow::{self, Borrowed, Owned};
- let input = "/usr/local/b";
- assert_eq!(Borrowed(input), super::unescape(input, Some('\\')));
- if cfg!(windows) {
- let input = "c:\\users\\All Users\\";
- let result: Cow<'_, str> = Borrowed(input);
- assert_eq!(result, super::unescape(input, Some('\\')));
- } else {
- let input = "/User\\ Information";
- let result: Cow<'_, str> = Owned(String::from("/User Information"));
- assert_eq!(result, super::unescape(input, Some('\\')));
- }
- }
-
- #[test]
- pub fn escape() {
- let break_chars: &[u8] = &super::DEFAULT_BREAK_CHARS;
- let input = String::from("/usr/local/b");
- assert_eq!(
- input.clone(),
- super::escape(input, Some('\\'), &break_chars, super::Quote::None)
- );
- let input = String::from("/User Information");
- let result = String::from("/User\\ Information");
- assert_eq!(
- result,
- super::escape(input, Some('\\'), &break_chars, super::Quote::None)
- );
- }
-
- #[test]
- pub fn longest_common_prefix() {
- let mut candidates = vec![];
- {
- let lcp = super::longest_common_prefix(&candidates);
- assert!(lcp.is_none());
- }
-
- let s = "User";
- let c1 = String::from(s);
- candidates.push(c1);
- {
- let lcp = super::longest_common_prefix(&candidates);
- assert_eq!(Some(s), lcp);
- }
-
- let c2 = String::from("Users");
- candidates.push(c2);
- {
- let lcp = super::longest_common_prefix(&candidates);
- assert_eq!(Some(s), lcp);
- }
-
- let c3 = String::from("");
- candidates.push(c3);
- {
- let lcp = super::longest_common_prefix(&candidates);
- assert!(lcp.is_none());
- }
-
- let candidates = vec![String::from("fée"), String::from("fête")];
- let lcp = super::longest_common_prefix(&candidates);
- assert_eq!(Some("f"), lcp);
- }
-
- #[test]
- pub fn find_unclosed_quote() {
- assert_eq!(None, super::find_unclosed_quote("ls /etc"));
- assert_eq!(
- Some((3, super::Quote::Double)),
- super::find_unclosed_quote("ls \"User Information")
- );
- assert_eq!(
- None,
- super::find_unclosed_quote("ls \"/User Information\" /etc")
- );
- assert_eq!(
- Some((0, super::Quote::Double)),
- super::find_unclosed_quote("\"c:\\users\\All Users\\")
- )
- }
-
- #[cfg(windows)]
- #[test]
- pub fn normalize() {
- assert_eq!(super::normalize("Windows"), "windows")
- }
-}
diff --git a/vendor/rustyline-8.2.0/src/config.rs b/vendor/rustyline-8.2.0/src/config.rs
deleted file mode 100644
index ead493d..0000000
--- a/vendor/rustyline-8.2.0/src/config.rs
+++ /dev/null
@@ -1,532 +0,0 @@
-//! Customize line editor
-use std::default::Default;
-
-/// User preferences
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub struct Config {
- /// Maximum number of entries in History.
- max_history_size: usize, // history_max_entries
- history_duplicates: HistoryDuplicates,
- history_ignore_space: bool,
- completion_type: CompletionType,
- /// When listing completion alternatives, only display
- /// one screen of possibilities at a time.
- completion_prompt_limit: usize,
- /// Duration (milliseconds) Rustyline will wait for a character when
- /// reading an ambiguous key sequence.
- keyseq_timeout: i32,
- /// Emacs or Vi mode
- edit_mode: EditMode,
- /// If true, each nonblank line returned by `readline` will be
- /// automatically added to the history.
- auto_add_history: bool,
- /// Beep or Flash or nothing
- bell_style: BellStyle,
- /// if colors should be enabled.
- color_mode: ColorMode,
- /// Whether to use stdout or stderr
- output_stream: OutputStreamType,
- /// Horizontal space taken by a tab.
- tab_stop: usize,
- /// Indentation size for indent/dedent commands
- indent_size: usize,
- /// Check if cursor position is at leftmost before displaying prompt
- check_cursor_position: bool,
- /// Bracketed paste on unix platform
- enable_bracketed_paste: bool,
-}
-
-impl Config {
- /// Returns a `Config` builder.
- pub fn builder() -> Builder {
- Builder::new()
- }
-
- /// Tell the maximum length (i.e. number of entries) for the history.
- pub fn max_history_size(&self) -> usize {
- self.max_history_size
- }
-
- pub(crate) fn set_max_history_size(&mut self, max_size: usize) {
- self.max_history_size = max_size;
- }
-
- /// Tell if lines which match the previous history entry are saved or not
- /// in the history list.
- ///
- /// By default, they are ignored.
- pub fn history_duplicates(&self) -> HistoryDuplicates {
- self.history_duplicates
- }
-
- pub(crate) fn set_history_ignore_dups(&mut self, yes: bool) {
- self.history_duplicates = if yes {
- HistoryDuplicates::IgnoreConsecutive
- } else {
- HistoryDuplicates::AlwaysAdd
- };
- }
-
- /// Tell if lines which begin with a space character are saved or not in
- /// the history list.
- ///
- /// By default, they are saved.
- pub fn history_ignore_space(&self) -> bool {
- self.history_ignore_space
- }
-
- pub(crate) fn set_history_ignore_space(&mut self, yes: bool) {
- self.history_ignore_space = yes;
- }
-
- /// Completion behaviour.
- ///
- /// By default, `CompletionType::Circular`.
- pub fn completion_type(&self) -> CompletionType {
- self.completion_type
- }
-
- /// When listing completion alternatives, only display
- /// one screen of possibilities at a time (used for `CompletionType::List`
- /// mode).
- pub fn completion_prompt_limit(&self) -> usize {
- self.completion_prompt_limit
- }
-
- /// Duration (milliseconds) Rustyline will wait for a character when
- /// reading an ambiguous key sequence (used for `EditMode::Vi` mode on unix
- /// platform).
- ///
- /// By default, no timeout (-1) or 500ms if `EditMode::Vi` is activated.
- pub fn keyseq_timeout(&self) -> i32 {
- self.keyseq_timeout
- }
-
- /// Emacs or Vi mode
- pub fn edit_mode(&self) -> EditMode {
- self.edit_mode
- }
-
- /// Tell if lines are automatically added to the history.
- ///
- /// By default, they are not.
- pub fn auto_add_history(&self) -> bool {
- self.auto_add_history
- }
-
- /// Bell style: beep, flash or nothing.
- pub fn bell_style(&self) -> BellStyle {
- self.bell_style
- }
-
- /// Tell if colors should be enabled.
- ///
- /// By default, they are except if stdout is not a TTY.
- pub fn color_mode(&self) -> ColorMode {
- self.color_mode
- }
-
- pub(crate) fn set_color_mode(&mut self, color_mode: ColorMode) {
- self.color_mode = color_mode;
- }
-
- /// Tell which output stream should be used: stdout or stderr.
- ///
- /// By default, stdout is used.
- pub fn output_stream(&self) -> OutputStreamType {
- self.output_stream
- }
-
- pub(crate) fn set_output_stream(&mut self, stream: OutputStreamType) {
- self.output_stream = stream;
- }
-
- /// Horizontal space taken by a tab.
- ///
- /// By default, 8.
- pub fn tab_stop(&self) -> usize {
- self.tab_stop
- }
-
- pub(crate) fn set_tab_stop(&mut self, tab_stop: usize) {
- self.tab_stop = tab_stop;
- }
-
- /// Check if cursor position is at leftmost before displaying prompt.
- ///
- /// By default, we don't check.
- pub fn check_cursor_position(&self) -> bool {
- self.check_cursor_position
- }
-
- /// Indentation size used by indentation commands
- ///
- /// By default, 2.
- pub fn indent_size(&self) -> usize {
- self.indent_size
- }
-
- pub(crate) fn set_indent_size(&mut self, indent_size: usize) {
- self.indent_size = indent_size;
- }
-
- /// Bracketed paste on unix platform
- ///
- /// By default, it's enabled.
- pub fn enable_bracketed_paste(&self) -> bool {
- self.enable_bracketed_paste
- }
-}
-
-impl Default for Config {
- fn default() -> Self {
- Self {
- max_history_size: 100,
- history_duplicates: HistoryDuplicates::IgnoreConsecutive,
- history_ignore_space: false,
- completion_type: CompletionType::Circular, // TODO Validate
- completion_prompt_limit: 100,
- keyseq_timeout: -1,
- edit_mode: EditMode::Emacs,
- auto_add_history: false,
- bell_style: BellStyle::default(),
- color_mode: ColorMode::Enabled,
- output_stream: OutputStreamType::Stdout,
- tab_stop: 8,
- indent_size: 2,
- check_cursor_position: false,
- enable_bracketed_paste: true,
- }
- }
-}
-
-/// Beep or flash or nothing
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum BellStyle {
- /// Beep
- Audible,
- /// Silent
- None,
- /// Flash screen (not supported)
- Visible,
-}
-
-/// `Audible` by default on unix (overriden by current Terminal settings).
-/// `None` on windows.
-impl Default for BellStyle {
- #[cfg(any(windows, target_arch = "wasm32"))]
- fn default() -> Self {
- BellStyle::None
- }
-
- #[cfg(unix)]
- fn default() -> Self {
- BellStyle::Audible
- }
-}
-
-/// History filter
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum HistoryDuplicates {
- /// No filter
- AlwaysAdd,
- /// a line will not be added to the history if it matches the previous entry
- IgnoreConsecutive,
-}
-
-/// Tab completion style
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-#[non_exhaustive]
-pub enum CompletionType {
- /// Complete the next full match (like in Vim by default)
- Circular,
- /// Complete till longest match.
- /// When more than one match, list all matches
- /// (like in Bash/Readline).
- List,
-
- /// Complete the match using fuzzy search and selection
- /// (like fzf and plugins)
- /// Currently only available for unix platforms as dependency on
- /// skim->tuikit Compile with `--features=fuzzy` to enable
- #[cfg(all(unix, feature = "with-fuzzy"))]
- Fuzzy,
-}
-
-/// Style of editing / Standard keymaps
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-#[non_exhaustive]
-pub enum EditMode {
- /// Emacs keymap
- Emacs,
- /// Vi keymap
- Vi,
-}
-
-/// Colorization mode
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-#[non_exhaustive]
-pub enum ColorMode {
- /// Activate highlighting if platform/terminal is supported.
- Enabled,
- /// Activate highlighting even if platform is not supported (windows < 10).
- Forced,
- /// Deactivate highlighting even if platform/terminal is supported.
- Disabled,
-}
-
-/// Should the editor use stdout or stderr
-// TODO console term::TermTarget
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-#[non_exhaustive]
-pub enum OutputStreamType {
- /// Use stderr
- Stderr,
- /// Use stdout
- Stdout,
-}
-
-/// Configuration builder
-#[derive(Clone, Debug, Default)]
-pub struct Builder {
- p: Config,
-}
-
-impl Builder {
- /// Returns a `Config` builder.
- pub fn new() -> Self {
- Self {
- p: Config::default(),
- }
- }
-
- /// Set the maximum length for the history.
- pub fn max_history_size(mut self, max_size: usize) -> Self {
- self.set_max_history_size(max_size);
- self
- }
-
- /// Tell if lines which match the previous history entry are saved or not
- /// in the history list.
- ///
- /// By default, they are ignored.
- pub fn history_ignore_dups(mut self, yes: bool) -> Self {
- self.set_history_ignore_dups(yes);
- self
- }
-
- /// Tell if lines which begin with a space character are saved or not in
- /// the history list.
- ///
- /// By default, they are saved.
- pub fn history_ignore_space(mut self, yes: bool) -> Self {
- self.set_history_ignore_space(yes);
- self
- }
-
- /// Set `completion_type`.
- pub fn completion_type(mut self, completion_type: CompletionType) -> Self {
- self.set_completion_type(completion_type);
- self
- }
-
- /// The number of possible completions that determines when the user is
- /// asked whether the list of possibilities should be displayed.
- pub fn completion_prompt_limit(mut self, completion_prompt_limit: usize) -> Self {
- self.set_completion_prompt_limit(completion_prompt_limit);
- self
- }
-
- /// Timeout for ambiguous key sequences in milliseconds.
- /// Currently, it is used only to distinguish a single ESC from an ESC
- /// sequence.
- /// After seeing an ESC key, wait at most `keyseq_timeout_ms` for another
- /// byte.
- pub fn keyseq_timeout(mut self, keyseq_timeout_ms: i32) -> Self {
- self.set_keyseq_timeout(keyseq_timeout_ms);
- self
- }
-
- /// Choose between Emacs or Vi mode.
- pub fn edit_mode(mut self, edit_mode: EditMode) -> Self {
- self.set_edit_mode(edit_mode);
- self
- }
-
- /// Tell if lines are automatically added to the history.
- ///
- /// By default, they are not.
- pub fn auto_add_history(mut self, yes: bool) -> Self {
- self.set_auto_add_history(yes);
- self
- }
-
- /// Set bell style: beep, flash or nothing.
- pub fn bell_style(mut self, bell_style: BellStyle) -> Self {
- self.set_bell_style(bell_style);
- self
- }
-
- /// Forces colorization on or off.
- ///
- /// By default, colorization is on except if stdout is not a TTY.
- pub fn color_mode(mut self, color_mode: ColorMode) -> Self {
- self.set_color_mode(color_mode);
- self
- }
-
- /// Whether to use stdout or stderr.
- ///
- /// Be default, use stdout
- pub fn output_stream(mut self, stream: OutputStreamType) -> Self {
- self.set_output_stream(stream);
- self
- }
-
- /// Horizontal space taken by a tab.
- ///
- /// By default, `8`
- pub fn tab_stop(mut self, tab_stop: usize) -> Self {
- self.set_tab_stop(tab_stop);
- self
- }
-
- /// Check if cursor position is at leftmost before displaying prompt.
- ///
- /// By default, we don't check.
- pub fn check_cursor_position(mut self, yes: bool) -> Self {
- self.set_check_cursor_position(yes);
- self
- }
-
- /// Indentation size
- ///
- /// By default, `2`
- pub fn indent_size(mut self, indent_size: usize) -> Self {
- self.set_indent_size(indent_size);
- self
- }
-
- /// Enable or disable bracketed paste on unix platform
- ///
- /// By default, it's enabled.
- pub fn bracketed_paste(mut self, enabled: bool) -> Self {
- self.enable_bracketed_paste(enabled);
- self
- }
-
- /// Builds a `Config` with the settings specified so far.
- pub fn build(self) -> Config {
- self.p
- }
-}
-
-impl Configurer for Builder {
- fn config_mut(&mut self) -> &mut Config {
- &mut self.p
- }
-}
-
-/// Trait for component that holds a `Config`.
-pub trait Configurer {
- /// `Config` accessor.
- fn config_mut(&mut self) -> &mut Config;
-
- /// Set the maximum length for the history.
- fn set_max_history_size(&mut self, max_size: usize) {
- self.config_mut().set_max_history_size(max_size);
- }
-
- /// Tell if lines which match the previous history entry are saved or not
- /// in the history list.
- ///
- /// By default, they are ignored.
- fn set_history_ignore_dups(&mut self, yes: bool) {
- self.config_mut().set_history_ignore_dups(yes);
- }
-
- /// Tell if lines which begin with a space character are saved or not in
- /// the history list.
- ///
- /// By default, they are saved.
- fn set_history_ignore_space(&mut self, yes: bool) {
- self.config_mut().set_history_ignore_space(yes);
- }
- /// Set `completion_type`.
- fn set_completion_type(&mut self, completion_type: CompletionType) {
- self.config_mut().completion_type = completion_type;
- }
-
- /// The number of possible completions that determines when the user is
- /// asked whether the list of possibilities should be displayed.
- fn set_completion_prompt_limit(&mut self, completion_prompt_limit: usize) {
- self.config_mut().completion_prompt_limit = completion_prompt_limit;
- }
-
- /// Timeout for ambiguous key sequences in milliseconds.
- fn set_keyseq_timeout(&mut self, keyseq_timeout_ms: i32) {
- self.config_mut().keyseq_timeout = keyseq_timeout_ms;
- }
-
- /// Choose between Emacs or Vi mode.
- fn set_edit_mode(&mut self, edit_mode: EditMode) {
- self.config_mut().edit_mode = edit_mode;
- match edit_mode {
- EditMode::Emacs => self.set_keyseq_timeout(-1), // no timeout
- EditMode::Vi => self.set_keyseq_timeout(500),
- }
- }
-
- /// Tell if lines are automatically added to the history.
- ///
- /// By default, they are not.
- fn set_auto_add_history(&mut self, yes: bool) {
- self.config_mut().auto_add_history = yes;
- }
-
- /// Set bell style: beep, flash or nothing.
- fn set_bell_style(&mut self, bell_style: BellStyle) {
- self.config_mut().bell_style = bell_style;
- }
-
- /// Forces colorization on or off.
- ///
- /// By default, colorization is on except if stdout is not a TTY.
- fn set_color_mode(&mut self, color_mode: ColorMode) {
- self.config_mut().set_color_mode(color_mode);
- }
-
- /// Whether to use stdout or stderr
- ///
- /// By default, use stdout
- fn set_output_stream(&mut self, stream: OutputStreamType) {
- self.config_mut().set_output_stream(stream);
- }
-
- /// Horizontal space taken by a tab.
- ///
- /// By default, `8`
- fn set_tab_stop(&mut self, tab_stop: usize) {
- self.config_mut().set_tab_stop(tab_stop);
- }
-
- /// Check if cursor position is at leftmost before displaying prompt.
- ///
- /// By default, we don't check.
- fn set_check_cursor_position(&mut self, yes: bool) {
- self.config_mut().check_cursor_position = yes;
- }
- /// Indentation size for indent/dedent commands
- ///
- /// By default, `2`
- fn set_indent_size(&mut self, size: usize) {
- self.config_mut().set_indent_size(size);
- }
-
- /// Enable or disable bracketed paste on unix platform
- ///
- /// By default, it's enabled.
- fn enable_bracketed_paste(&mut self, enabled: bool) {
- self.config_mut().enable_bracketed_paste = enabled;
- }
-}
diff --git a/vendor/rustyline-8.2.0/src/edit.rs b/vendor/rustyline-8.2.0/src/edit.rs
deleted file mode 100644
index 5f2d0e9..0000000
--- a/vendor/rustyline-8.2.0/src/edit.rs
+++ /dev/null
@@ -1,745 +0,0 @@
-//! Command processor
-
-use log::debug;
-use std::cell::RefCell;
-use std::fmt;
-use std::rc::Rc;
-use unicode_segmentation::UnicodeSegmentation;
-use unicode_width::UnicodeWidthChar;
-
-use super::{Context, Helper, Result};
-use crate::highlight::Highlighter;
-use crate::hint::Hint;
-use crate::history::Direction;
-use crate::keymap::{Anchor, At, CharSearch, Cmd, Movement, RepeatCount, Word};
-use crate::keymap::{InputState, Invoke, Refresher};
-use crate::layout::{Layout, Position};
-use crate::line_buffer::{LineBuffer, WordAction, MAX_LINE};
-use crate::tty::{Renderer, Term, Terminal};
-use crate::undo::Changeset;
-use crate::validate::{ValidationContext, ValidationResult};
-
-/// Represent the state during line editing.
-/// Implement rendering.
-pub struct State<'out, 'prompt, H: Helper> {
- pub out: &'out mut <Terminal as Term>::Writer,
- prompt: &'prompt str, // Prompt to display (rl_prompt)
- prompt_size: Position, // Prompt Unicode/visible width and height
- pub line: LineBuffer, // Edited line buffer
- pub layout: Layout,
- saved_line_for_history: LineBuffer, // Current edited line before history browsing
- byte_buffer: [u8; 4],
- pub changes: Rc<RefCell<Changeset>>, // changes to line, for undo/redo
- pub helper: Option<&'out H>,
- pub ctx: Context<'out>, // Give access to history for `hinter`
- pub hint: Option<Box<dyn Hint>>, // last hint displayed
- highlight_char: bool, // `true` if a char has been highlighted
-}
-
-enum Info<'m> {
- NoHint,
- Hint,
- Msg(Option<&'m str>),
-}
-
-impl<'out, 'prompt, H: Helper> State<'out, 'prompt, H> {
- pub fn new(
- out: &'out mut <Terminal as Term>::Writer,
- prompt: &'prompt str,
- helper: Option<&'out H>,
- ctx: Context<'out>,
- ) -> State<'out, 'prompt, H> {
- let prompt_size = out.calculate_position(prompt, Position::default());
- State {
- out,
- prompt,
- prompt_size,
- line: LineBuffer::with_capacity(MAX_LINE).can_growth(true),
- layout: Layout::default(),
- saved_line_for_history: LineBuffer::with_capacity(MAX_LINE).can_growth(true),
- byte_buffer: [0; 4],
- changes: Rc::new(RefCell::new(Changeset::new())),
- helper,
- ctx,
- hint: None,
- highlight_char: false,
- }
- }
-
- pub fn highlighter(&self) -> Option<&dyn Highlighter> {
- if self.out.colors_enabled() {
- self.helper.map(|h| h as &dyn Highlighter)
- } else {
- None
- }
- }
-
- pub fn next_cmd(
- &mut self,
- input_state: &mut InputState,
- rdr: &mut <Terminal as Term>::Reader,
- single_esc_abort: bool,
- ) -> Result<Cmd> {
- loop {
- let rc = input_state.next_cmd(rdr, self, single_esc_abort);
- if rc.is_err() && self.out.sigwinch() {
- self.out.update_size();
- self.prompt_size = self
- .out
- .calculate_position(self.prompt, Position::default());
- self.refresh_line()?;
- continue;
- }
- if let Ok(Cmd::Replace(..)) = rc {
- self.changes.borrow_mut().begin();
- }
- return rc;
- }
- }
-
- pub fn backup(&mut self) {
- self.saved_line_for_history
- .update(self.line.as_str(), self.line.pos());
- }
-
- pub fn restore(&mut self) {
- self.line.update(
- self.saved_line_for_history.as_str(),
- self.saved_line_for_history.pos(),
- );
- }
-
- pub fn move_cursor(&mut self) -> Result<()> {
- // calculate the desired position of the cursor
- let cursor = self
- .out
- .calculate_position(&self.line[..self.line.pos()], self.prompt_size);
- if self.layout.cursor == cursor {
- return Ok(());
- }
- if self.highlight_char() {
- let prompt_size = self.prompt_size;
- self.refresh(self.prompt, prompt_size, true, Info::NoHint)?;
- } else {
- self.out.move_cursor(self.layout.cursor, cursor)?;
- self.layout.prompt_size = self.prompt_size;
- self.layout.cursor = cursor;
- debug_assert!(self.layout.prompt_size <= self.layout.cursor);
- debug_assert!(self.layout.cursor <= self.layout.end);
- }
- Ok(())
- }
-
- pub fn move_cursor_at_leftmost(&mut self, rdr: &mut <Terminal as Term>::Reader) -> Result<()> {
- self.out.move_cursor_at_leftmost(rdr)
- }
-
- fn refresh(
- &mut self,
- prompt: &str,
- prompt_size: Position,
- default_prompt: bool,
- info: Info<'_>,
- ) -> Result<()> {
- let info = match info {
- Info::NoHint => None,
- Info::Hint => self.hint.as_ref().map(|h| h.display()),
- Info::Msg(msg) => msg,
- };
- let highlighter = if self.out.colors_enabled() {
- self.helper.map(|h| h as &dyn Highlighter)
- } else {
- None
- };
-
- let new_layout = self
- .out
- .compute_layout(prompt_size, default_prompt, &self.line, info);
-
- debug!(target: "rustyline", "old layout: {:?}", self.layout);
- debug!(target: "rustyline", "new layout: {:?}", new_layout);
- self.out.refresh_line(
- prompt,
- &self.line,
- info,
- &self.layout,
- &new_layout,
- highlighter,
- )?;
- self.layout = new_layout;
-
- Ok(())
- }
-
- pub fn hint(&mut self) {
- if let Some(hinter) = self.helper {
- let hint = hinter.hint(self.line.as_str(), self.line.pos(), &self.ctx);
- self.hint = hint.map(|val| Box::new(val) as Box<dyn Hint>)
- } else {
- self.hint = None
- }
- }
-
- fn highlight_char(&mut self) -> bool {
- if let Some(highlighter) = self.highlighter() {
- let highlight_char = highlighter.highlight_char(&self.line, self.line.pos());
- if highlight_char {
- self.highlight_char = true;
- true
- } else if self.highlight_char {
- // previously highlighted => force a full refresh
- self.highlight_char = false;
- true
- } else {
- false
- }
- } else {
- false
- }
- }
-
- pub fn is_default_prompt(&self) -> bool {
- self.layout.default_prompt
- }
-
- pub fn validate(&mut self) -> Result<ValidationResult> {
- if let Some(validator) = self.helper {
- self.changes.borrow_mut().begin();
- let result = validator.validate(&mut ValidationContext::new(self))?;
- let corrected = self.changes.borrow_mut().end();
- match result {
- ValidationResult::Incomplete => {}
- ValidationResult::Valid(ref msg) => {
- // Accept the line regardless of where the cursor is.
- if corrected || self.has_hint() || msg.is_some() {
- // Force a refresh without hints to leave the previous
- // line as the user typed it after a newline.
- self.refresh_line_with_msg(msg.as_deref())?;
- }
- }
- ValidationResult::Invalid(ref msg) => {
- if corrected || self.has_hint() || msg.is_some() {
- self.refresh_line_with_msg(msg.as_deref())?;
- }
- }
- }
- Ok(result)
- } else {
- Ok(ValidationResult::Valid(None))
- }
- }
-}
-
-impl<'out, 'prompt, H: Helper> Invoke for State<'out, 'prompt, H> {
- fn input(&self) -> &str {
- self.line.as_str()
- }
-}
-
-impl<'out, 'prompt, H: Helper> Refresher for State<'out, 'prompt, H> {
- fn refresh_line(&mut self) -> Result<()> {
- let prompt_size = self.prompt_size;
- self.hint();
- self.highlight_char();
- self.refresh(self.prompt, prompt_size, true, Info::Hint)
- }
-
- fn refresh_line_with_msg(&mut self, msg: Option<&str>) -> Result<()> {
- let prompt_size = self.prompt_size;
- self.hint = None;
- self.highlight_char();
- self.refresh(self.prompt, prompt_size, true, Info::Msg(msg))
- }
-
- fn refresh_prompt_and_line(&mut self, prompt: &str) -> Result<()> {
- let prompt_size = self.out.calculate_position(prompt, Position::default());
- self.hint();
- self.highlight_char();
- self.refresh(prompt, prompt_size, false, Info::Hint)
- }
-
- fn doing_insert(&mut self) {
- self.changes.borrow_mut().begin();
- }
-
- fn done_inserting(&mut self) {
- self.changes.borrow_mut().end();
- }
-
- fn last_insert(&self) -> Option<String> {
- self.changes.borrow().last_insert()
- }
-
- fn is_cursor_at_end(&self) -> bool {
- self.line.pos() == self.line.len()
- }
-
- fn has_hint(&self) -> bool {
- self.hint.is_some()
- }
-
- fn hint_text(&self) -> Option<&str> {
- self.hint.as_ref().map(|hint| hint.completion()).flatten()
- }
-
- fn line(&self) -> &str {
- self.line.as_str()
- }
-
- fn pos(&self) -> usize {
- self.line.pos()
- }
-}
-
-impl<'out, 'prompt, H: Helper> fmt::Debug for State<'out, 'prompt, H> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("State")
- .field("prompt", &self.prompt)
- .field("prompt_size", &self.prompt_size)
- .field("buf", &self.line)
- .field("cols", &self.out.get_columns())
- .field("layout", &self.layout)
- .field("saved_line_for_history", &self.saved_line_for_history)
- .finish()
- }
-}
-
-impl<'out, 'prompt, H: Helper> State<'out, 'prompt, H> {
- pub fn clear_screen(&mut self) -> Result<()> {
- self.out.clear_screen()?;
- self.layout.cursor = Position::default();
- self.layout.end = Position::default();
- Ok(())
- }
-
- /// Insert the character `ch` at cursor current position.
- pub fn edit_insert(&mut self, ch: char, n: RepeatCount) -> Result<()> {
- if let Some(push) = self.line.insert(ch, n) {
- if push {
- let prompt_size = self.prompt_size;
- let no_previous_hint = self.hint.is_none();
- self.hint();
- let width = ch.width().unwrap_or(0);
- if n == 1
- && width != 0 // Ctrl-V + \t or \n ...
- && self.layout.cursor.col + width < self.out.get_columns()
- && (self.hint.is_none() && no_previous_hint) // TODO refresh only current line
- && !self.highlight_char()
- {
- // Avoid a full update of the line in the trivial case.
- self.layout.cursor.col += width;
- self.layout.end.col += width;
- debug_assert!(self.layout.prompt_size <= self.layout.cursor);
- debug_assert!(self.layout.cursor <= self.layout.end);
- let bits = ch.encode_utf8(&mut self.byte_buffer);
- let bits = bits.as_bytes();
- self.out.write_and_flush(bits)
- } else {
- self.refresh(self.prompt, prompt_size, true, Info::Hint)
- }
- } else {
- self.refresh_line()
- }
- } else {
- Ok(())
- }
- }
-
- /// Replace a single (or n) character(s) under the cursor (Vi mode)
- pub fn edit_replace_char(&mut self, ch: char, n: RepeatCount) -> Result<()> {
- self.changes.borrow_mut().begin();
- let succeed = if let Some(chars) = self.line.delete(n) {
- let count = chars.graphemes(true).count();
- self.line.insert(ch, count);
- self.line.move_backward(1);
- true
- } else {
- false
- };
- self.changes.borrow_mut().end();
- if succeed {
- self.refresh_line()
- } else {
- Ok(())
- }
- }
-
- /// Overwrite the character under the cursor (Vi mode)
- pub fn edit_overwrite_char(&mut self, ch: char) -> Result<()> {
- if let Some(end) = self.line.next_pos(1) {
- {
- let text = ch.encode_utf8(&mut self.byte_buffer);
- let start = self.line.pos();
- self.line.replace(start..end, text);
- }
- self.refresh_line()
- } else {
- Ok(())
- }
- }
-
- // Yank/paste `text` at current position.
- pub fn edit_yank(
- &mut self,
- input_state: &InputState,
- text: &str,
- anchor: Anchor,
- n: RepeatCount,
- ) -> Result<()> {
- if let Anchor::After = anchor {
- self.line.move_forward(1);
- }
- if self.line.yank(text, n).is_some() {
- if !input_state.is_emacs_mode() {
- self.line.move_backward(1);
- }
- self.refresh_line()
- } else {
- Ok(())
- }
- }
-
- // Delete previously yanked text and yank/paste `text` at current position.
- pub fn edit_yank_pop(&mut self, yank_size: usize, text: &str) -> Result<()> {
- self.changes.borrow_mut().begin();
- let result = if self.line.yank_pop(yank_size, text).is_some() {
- self.refresh_line()
- } else {
- Ok(())
- };
- self.changes.borrow_mut().end();
- result
- }
-
- /// Move cursor on the left.
- pub fn edit_move_backward(&mut self, n: RepeatCount) -> Result<()> {
- if self.line.move_backward(n) {
- self.move_cursor()
- } else {
- Ok(())
- }
- }
-
- /// Move cursor on the right.
- pub fn edit_move_forward(&mut self, n: RepeatCount) -> Result<()> {
- if self.line.move_forward(n) {
- self.move_cursor()
- } else {
- Ok(())
- }
- }
-
- /// Move cursor to the start of the line.
- pub fn edit_move_home(&mut self) -> Result<()> {
- if self.line.move_home() {
- self.move_cursor()
- } else {
- Ok(())
- }
- }
-
- /// Move cursor to the end of the line.
- pub fn edit_move_end(&mut self) -> Result<()> {
- if self.line.move_end() {
- self.move_cursor()
- } else {
- Ok(())
- }
- }
-
- /// Move cursor to the start of the buffer.
- pub fn edit_move_buffer_start(&mut self) -> Result<()> {
- if self.line.move_buffer_start() {
- self.move_cursor()
- } else {
- Ok(())
- }
- }
-
- /// Move cursor to the end of the buffer.
- pub fn edit_move_buffer_end(&mut self) -> Result<()> {
- if self.line.move_buffer_end() {
- self.move_cursor()
- } else {
- Ok(())
- }
- }
-
- pub fn edit_kill(&mut self, mvt: &Movement) -> Result<()> {
- if self.line.kill(mvt) {
- self.refresh_line()
- } else {
- Ok(())
- }
- }
-
- pub fn edit_insert_text(&mut self, text: &str) -> Result<()> {
- if text.is_empty() {
- return Ok(());
- }
- let cursor = self.line.pos();
- self.line.insert_str(cursor, text);
- self.refresh_line()
- }
-
- pub fn edit_delete(&mut self, n: RepeatCount) -> Result<()> {
- if self.line.delete(n).is_some() {
- self.refresh_line()
- } else {
- Ok(())
- }
- }
-
- /// Exchange the char before cursor with the character at cursor.
- pub fn edit_transpose_chars(&mut self) -> Result<()> {
- self.changes.borrow_mut().begin();
- let succeed = self.line.transpose_chars();
- self.changes.borrow_mut().end();
- if succeed {
- self.refresh_line()
- } else {
- Ok(())
- }
- }
-
- pub fn edit_move_to_prev_word(&mut self, word_def: Word, n: RepeatCount) -> Result<()> {
- if self.line.move_to_prev_word(word_def, n) {
- self.move_cursor()
- } else {
- Ok(())
- }
- }
-
- pub fn edit_move_to_next_word(&mut self, at: At, word_def: Word, n: RepeatCount) -> Result<()> {
- if self.line.move_to_next_word(at, word_def, n) {
- self.move_cursor()
- } else {
- Ok(())
- }
- }
-
- /// Moves the cursor to the same column in the line above
- pub fn edit_move_line_up(&mut self, n: RepeatCount) -> Result<bool> {
- if self.line.move_to_line_up(n) {
- self.move_cursor()?;
- Ok(true)
- } else {
- Ok(false)
- }
- }
-
- /// Moves the cursor to the same column in the line above
- pub fn edit_move_line_down(&mut self, n: RepeatCount) -> Result<bool> {
- if self.line.move_to_line_down(n) {
- self.move_cursor()?;
- Ok(true)
- } else {
- Ok(false)
- }
- }
-
- pub fn edit_move_to(&mut self, cs: CharSearch, n: RepeatCount) -> Result<()> {
- if self.line.move_to(cs, n) {
- self.move_cursor()
- } else {
- Ok(())
- }
- }
-
- pub fn edit_word(&mut self, a: WordAction) -> Result<()> {
- self.changes.borrow_mut().begin();
- let succeed = self.line.edit_word(a);
- self.changes.borrow_mut().end();
- if succeed {
- self.refresh_line()
- } else {
- Ok(())
- }
- }
-
- pub fn edit_transpose_words(&mut self, n: RepeatCount) -> Result<()> {
- self.changes.borrow_mut().begin();
- let succeed = self.line.transpose_words(n);
- self.changes.borrow_mut().end();
- if succeed {
- self.refresh_line()
- } else {
- Ok(())
- }
- }
-
- /// Substitute the currently edited line with the next or previous history
- /// entry.
- pub fn edit_history_next(&mut self, prev: bool) -> Result<()> {
- let history = self.ctx.history;
- if history.is_empty() {
- return Ok(());
- }
- if self.ctx.history_index == history.len() {
- if prev {
- // Save the current edited line before overwriting it
- self.backup();
- } else {
- return Ok(());
- }
- } else if self.ctx.history_index == 0 && prev {
- return Ok(());
- }
- if prev {
- self.ctx.history_index -= 1;
- } else {
- self.ctx.history_index += 1;
- }
- if self.ctx.history_index < history.len() {
- let buf = history.get(self.ctx.history_index).unwrap();
- self.changes.borrow_mut().begin();
- self.line.update(buf, buf.len());
- self.changes.borrow_mut().end();
- } else {
- // Restore current edited line
- self.restore();
- }
- self.refresh_line()
- }
-
- // Non-incremental, anchored search
- pub fn edit_history_search(&mut self, dir: Direction) -> Result<()> {
- let history = self.ctx.history;
- if history.is_empty() {
- return self.out.beep();
- }
- if self.ctx.history_index == history.len() && dir == Direction::Forward
- || self.ctx.history_index == 0 && dir == Direction::Reverse
- {
- return self.out.beep();
- }
- if dir == Direction::Reverse {
- self.ctx.history_index -= 1;
- } else {
- self.ctx.history_index += 1;
- }
- if let Some(history_index) = history.starts_with(
- &self.line.as_str()[..self.line.pos()],
- self.ctx.history_index,
- dir,
- ) {
- self.ctx.history_index = history_index;
- let buf = history.get(history_index).unwrap();
- self.changes.borrow_mut().begin();
- self.line.update(buf, buf.len());
- self.changes.borrow_mut().end();
- self.refresh_line()
- } else {
- self.out.beep()
- }
- }
-
- /// Substitute the currently edited line with the first/last history entry.
- pub fn edit_history(&mut self, first: bool) -> Result<()> {
- let history = self.ctx.history;
- if history.is_empty() {
- return Ok(());
- }
- if self.ctx.history_index == history.len() {
- if first {
- // Save the current edited line before overwriting it
- self.backup();
- } else {
- return Ok(());
- }
- } else if self.ctx.history_index == 0 && first {
- return Ok(());
- }
- if first {
- self.ctx.history_index = 0;
- let buf = history.get(self.ctx.history_index).unwrap();
- self.changes.borrow_mut().begin();
- self.line.update(buf, buf.len());
- self.changes.borrow_mut().end();
- } else {
- self.ctx.history_index = history.len();
- // Restore current edited line
- self.restore();
- }
- self.refresh_line()
- }
-
- /// Change the indentation of the lines covered by movement
- pub fn edit_indent(&mut self, mvt: &Movement, amount: usize, dedent: bool) -> Result<()> {
- if self.line.indent(mvt, amount, dedent) {
- self.refresh_line()
- } else {
- Ok(())
- }
- }
-}
-
-#[cfg(test)]
-pub fn init_state<'out, H: Helper>(
- out: &'out mut <Terminal as Term>::Writer,
- line: &str,
- pos: usize,
- helper: Option<&'out H>,
- history: &'out crate::history::History,
-) -> State<'out, 'static, H> {
- State {
- out,
- prompt: "",
- prompt_size: Position::default(),
- line: LineBuffer::init(line, pos, None),
- layout: Layout::default(),
- saved_line_for_history: LineBuffer::with_capacity(100),
- byte_buffer: [0; 4],
- changes: Rc::new(RefCell::new(Changeset::new())),
- helper,
- ctx: Context::new(history),
- hint: Some(Box::new("hint".to_owned())),
- highlight_char: false,
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::init_state;
- use crate::history::History;
- use crate::tty::Sink;
-
- #[test]
- fn edit_history_next() {
- let mut out = Sink::new();
- let mut history = History::new();
- history.add("line0");
- history.add("line1");
- let line = "current edited line";
- let helper: Option<()> = None;
- let mut s = init_state(&mut out, line, 6, helper.as_ref(), &history);
- s.ctx.history_index = history.len();
-
- for _ in 0..2 {
- s.edit_history_next(false).unwrap();
- assert_eq!(line, s.line.as_str());
- }
-
- s.edit_history_next(true).unwrap();
- assert_eq!(line, s.saved_line_for_history.as_str());
- assert_eq!(1, s.ctx.history_index);
- assert_eq!("line1", s.line.as_str());
-
- for _ in 0..2 {
- s.edit_history_next(true).unwrap();
- assert_eq!(line, s.saved_line_for_history.as_str());
- assert_eq!(0, s.ctx.history_index);
- assert_eq!("line0", s.line.as_str());
- }
-
- s.edit_history_next(false).unwrap();
- assert_eq!(line, s.saved_line_for_history.as_str());
- assert_eq!(1, s.ctx.history_index);
- assert_eq!("line1", s.line.as_str());
-
- s.edit_history_next(false).unwrap();
- // assert_eq!(line, s.saved_line_for_history);
- assert_eq!(2, s.ctx.history_index);
- assert_eq!(line, s.line.as_str());
- }
-}
diff --git a/vendor/rustyline-8.2.0/src/error.rs b/vendor/rustyline-8.2.0/src/error.rs
deleted file mode 100644
index b4d365f..0000000
--- a/vendor/rustyline-8.2.0/src/error.rs
+++ /dev/null
@@ -1,92 +0,0 @@
-//! Contains error type for handling I/O and Errno errors
-#[cfg(windows)]
-use std::char;
-use std::error;
-use std::fmt;
-use std::io;
-
-/// The error type for Rustyline errors that can arise from
-/// I/O related errors or Errno when using the nix-rust library
-// #[non_exhaustive]
-#[allow(clippy::module_name_repetitions)]
-#[derive(Debug)]
-#[non_exhaustive]
-pub enum ReadlineError {
- /// I/O Error
- Io(io::Error),
- /// EOF (Ctrl-D)
- Eof,
- /// Ctrl-C
- Interrupted,
- /// Chars Error
- #[cfg(unix)]
- Utf8Error,
- /// Unix Error from syscall
- #[cfg(unix)]
- Errno(nix::Error),
- /// Error generated on WINDOW_BUFFER_SIZE_EVENT to mimic unix SIGWINCH
- /// signal
- #[cfg(windows)]
- WindowResize,
- /// Like Utf8Error on unix
- #[cfg(windows)]
- Decode(char::DecodeUtf16Error),
- /// Something went wrong calling a Windows API
- #[cfg(windows)]
- SystemError(clipboard_win::SystemError),
-}
-
-impl fmt::Display for ReadlineError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match *self {
- ReadlineError::Io(ref err) => err.fmt(f),
- ReadlineError::Eof => write!(f, "EOF"),
- ReadlineError::Interrupted => write!(f, "Interrupted"),
- #[cfg(unix)]
- ReadlineError::Utf8Error => write!(f, "invalid utf-8: corrupt contents"),
- #[cfg(unix)]
- ReadlineError::Errno(ref err) => err.fmt(f),
- #[cfg(windows)]
- ReadlineError::WindowResize => write!(f, "WindowResize"),
- #[cfg(windows)]
- ReadlineError::Decode(ref err) => err.fmt(f),
- #[cfg(windows)]
- ReadlineError::SystemError(ref err) => err.fmt(f),
- }
- }
-}
-
-impl error::Error for ReadlineError {}
-
-impl From<io::Error> for ReadlineError {
- fn from(err: io::Error) -> Self {
- ReadlineError::Io(err)
- }
-}
-
-impl From<io::ErrorKind> for ReadlineError {
- fn from(kind: io::ErrorKind) -> Self {
- ReadlineError::Io(io::Error::from(kind))
- }
-}
-
-#[cfg(unix)]
-impl From<nix::Error> for ReadlineError {
- fn from(err: nix::Error) -> Self {
- ReadlineError::Errno(err)
- }
-}
-
-#[cfg(windows)]
-impl From<char::DecodeUtf16Error> for ReadlineError {
- fn from(err: char::DecodeUtf16Error) -> Self {
- ReadlineError::Decode(err)
- }
-}
-
-#[cfg(windows)]
-impl From<clipboard_win::SystemError> for ReadlineError {
- fn from(err: clipboard_win::SystemError) -> Self {
- ReadlineError::SystemError(err)
- }
-}
diff --git a/vendor/rustyline-8.2.0/src/highlight.rs b/vendor/rustyline-8.2.0/src/highlight.rs
deleted file mode 100644
index 4d62a63..0000000
--- a/vendor/rustyline-8.2.0/src/highlight.rs
+++ /dev/null
@@ -1,280 +0,0 @@
-//! Syntax highlighting
-
-use crate::config::CompletionType;
-use memchr::memchr;
-use std::borrow::Cow::{self, Borrowed, Owned};
-use std::cell::Cell;
-
-/// Syntax highlighter with [ANSI color](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters).
-/// Rustyline will try to handle escape sequence for ANSI color on windows
-/// when not supported natively (windows <10).
-///
-/// Currently, the highlighted version *must* have the same display width as
-/// the original input.
-pub trait Highlighter {
- /// Takes the currently edited `line` with the cursor `pos`ition and
- /// returns the highlighted version (with ANSI color).
- ///
- /// For example, you can implement
- /// [blink-matching-paren](https://www.gnu.org/software/bash/manual/html_node/Readline-Init-File-Syntax.html).
- fn highlight<'l>(&self, line: &'l str, pos: usize) -> Cow<'l, str> {
- let _ = pos;
- Borrowed(line)
- }
- /// Takes the `prompt` and
- /// returns the highlighted version (with ANSI color).
- fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
- &'s self,
- prompt: &'p str,
- default: bool,
- ) -> Cow<'b, str> {
- let _ = default;
- Borrowed(prompt)
- }
- /// Takes the `hint` and
- /// returns the highlighted version (with ANSI color).
- fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
- Borrowed(hint)
- }
- /// Takes the completion `candidate` and
- /// returns the highlighted version (with ANSI color).
- ///
- /// Currently, used only with `CompletionType::List`.
- fn highlight_candidate<'c>(
- &self,
- candidate: &'c str,
- completion: CompletionType,
- ) -> Cow<'c, str> {
- let _ = completion;
- Borrowed(candidate)
- }
- /// Tells if `line` needs to be highlighted when a specific char is typed or
- /// when cursor is moved under a specific char.
- ///
- /// Used to optimize refresh when a character is inserted or the cursor is
- /// moved.
- fn highlight_char(&self, line: &str, pos: usize) -> bool {
- let _ = (line, pos);
- false
- }
-}
-
-impl Highlighter for () {}
-
-impl<'r, H: ?Sized + Highlighter> Highlighter for &'r H {
- fn highlight<'l>(&self, line: &'l str, pos: usize) -> Cow<'l, str> {
- (**self).highlight(line, pos)
- }
-
- fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
- &'s self,
- prompt: &'p str,
- default: bool,
- ) -> Cow<'b, str> {
- (**self).highlight_prompt(prompt, default)
- }
-
- fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
- (**self).highlight_hint(hint)
- }
-
- fn highlight_candidate<'c>(
- &self,
- candidate: &'c str,
- completion: CompletionType,
- ) -> Cow<'c, str> {
- (**self).highlight_candidate(candidate, completion)
- }
-
- fn highlight_char(&self, line: &str, pos: usize) -> bool {
- (**self).highlight_char(line, pos)
- }
-}
-
-const OPENS: &[u8; 3] = b"{[(";
-const CLOSES: &[u8; 3] = b"}])";
-
-/// Highlight matching bracket when typed or cursor moved on.
-#[derive(Default)]
-pub struct MatchingBracketHighlighter {
- bracket: Cell<Option<(u8, usize)>>, // memorize the character to search...
-}
-
-impl MatchingBracketHighlighter {
- /// Constructor
- pub fn new() -> Self {
- Self {
- bracket: Cell::new(None),
- }
- }
-}
-
-impl Highlighter for MatchingBracketHighlighter {
- fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> {
- if line.len() <= 1 {
- return Borrowed(line);
- }
- // highlight matching brace/bracket/parenthesis if it exists
- if let Some((bracket, pos)) = self.bracket.get() {
- if let Some((matching, idx)) = find_matching_bracket(line, pos, bracket) {
- let mut copy = line.to_owned();
- copy.replace_range(idx..=idx, &format!("\x1b[1;34m{}\x1b[0m", matching as char));
- return Owned(copy);
- }
- }
- Borrowed(line)
- }
-
- fn highlight_char(&self, line: &str, pos: usize) -> bool {
- // will highlight matching brace/bracket/parenthesis if it exists
- self.bracket.set(check_bracket(line, pos));
- self.bracket.get().is_some()
- }
-}
-
-fn find_matching_bracket(line: &str, pos: usize, bracket: u8) -> Option<(u8, usize)> {
- let matching = matching_bracket(bracket);
- let mut idx;
- let mut unmatched = 1;
- if is_open_bracket(bracket) {
- // forward search
- idx = pos + 1;
- let bytes = &line.as_bytes()[idx..];
- for b in bytes {
- if *b == matching {
- unmatched -= 1;
- if unmatched == 0 {
- debug_assert_eq!(matching, line.as_bytes()[idx]);
- return Some((matching, idx));
- }
- } else if *b == bracket {
- unmatched += 1;
- }
- idx += 1;
- }
- debug_assert_eq!(idx, line.len());
- } else {
- // backward search
- idx = pos;
- let bytes = &line.as_bytes()[..idx];
- for b in bytes.iter().rev() {
- if *b == matching {
- unmatched -= 1;
- if unmatched == 0 {
- debug_assert_eq!(matching, line.as_bytes()[idx - 1]);
- return Some((matching, idx - 1));
- }
- } else if *b == bracket {
- unmatched += 1;
- }
- idx -= 1;
- }
- debug_assert_eq!(idx, 0);
- }
- None
-}
-
-// check under or before the cursor
-fn check_bracket(line: &str, pos: usize) -> Option<(u8, usize)> {
- if line.is_empty() {
- return None;
- }
- let mut pos = pos;
- if pos >= line.len() {
- pos = line.len() - 1; // before cursor
- let b = line.as_bytes()[pos]; // previous byte
- if is_close_bracket(b) {
- Some((b, pos))
- } else {
- None
- }
- } else {
- let mut under_cursor = true;
- loop {
- let b = line.as_bytes()[pos];
- if is_close_bracket(b) {
- if pos == 0 {
- return None;
- } else {
- return Some((b, pos));
- }
- } else if is_open_bracket(b) {
- if pos + 1 == line.len() {
- return None;
- } else {
- return Some((b, pos));
- }
- } else if under_cursor && pos > 0 {
- under_cursor = false;
- pos -= 1; // or before cursor
- } else {
- return None;
- }
- }
- }
-}
-
-fn matching_bracket(bracket: u8) -> u8 {
- match bracket {
- b'{' => b'}',
- b'}' => b'{',
- b'[' => b']',
- b']' => b'[',
- b'(' => b')',
- b')' => b'(',
- b => b,
- }
-}
-fn is_open_bracket(bracket: u8) -> bool {
- memchr(bracket, OPENS).is_some()
-}
-fn is_close_bracket(bracket: u8) -> bool {
- memchr(bracket, CLOSES).is_some()
-}
-
-#[cfg(test)]
-mod tests {
- #[test]
- pub fn find_matching_bracket() {
- use super::find_matching_bracket;
- assert_eq!(find_matching_bracket("(...", 0, b'('), None);
- assert_eq!(find_matching_bracket("...)", 3, b')'), None);
-
- assert_eq!(find_matching_bracket("()..", 0, b'('), Some((b')', 1)));
- assert_eq!(find_matching_bracket("(..)", 0, b'('), Some((b')', 3)));
-
- assert_eq!(find_matching_bracket("..()", 3, b')'), Some((b'(', 2)));
- assert_eq!(find_matching_bracket("(..)", 3, b')'), Some((b'(', 0)));
-
- assert_eq!(find_matching_bracket("(())", 0, b'('), Some((b')', 3)));
- assert_eq!(find_matching_bracket("(())", 3, b')'), Some((b'(', 0)));
- }
- #[test]
- pub fn check_bracket() {
- use super::check_bracket;
- assert_eq!(check_bracket(")...", 0), None);
- assert_eq!(check_bracket("(...", 2), None);
- assert_eq!(check_bracket("...(", 3), None);
- assert_eq!(check_bracket("...(", 4), None);
- assert_eq!(check_bracket("..).", 4), None);
-
- assert_eq!(check_bracket("(...", 0), Some((b'(', 0)));
- assert_eq!(check_bracket("(...", 1), Some((b'(', 0)));
- assert_eq!(check_bracket("...)", 3), Some((b')', 3)));
- assert_eq!(check_bracket("...)", 4), Some((b')', 3)));
- }
- #[test]
- pub fn matching_bracket() {
- use super::matching_bracket;
- assert_eq!(matching_bracket(b'('), b')');
- assert_eq!(matching_bracket(b')'), b'(');
- }
-
- #[test]
- pub fn is_open_bracket() {
- use super::is_close_bracket;
- use super::is_open_bracket;
- assert!(is_open_bracket(b'('));
- assert!(is_close_bracket(b')'));
- }
-}
diff --git a/vendor/rustyline-8.2.0/src/hint.rs b/vendor/rustyline-8.2.0/src/hint.rs
deleted file mode 100644
index fd0aa3a..0000000
--- a/vendor/rustyline-8.2.0/src/hint.rs
+++ /dev/null
@@ -1,97 +0,0 @@
-//! Hints (suggestions at the right of the prompt as you type).
-
-use crate::history::Direction;
-use crate::Context;
-
-/// A hint returned by Hinter
-pub trait Hint {
- /// Text to display when hint is active
- fn display(&self) -> &str;
- /// Text to insert in line when right arrow is pressed
- fn completion(&self) -> Option<&str>;
-}
-
-impl Hint for String {
- fn display(&self) -> &str {
- self.as_str()
- }
-
- fn completion(&self) -> Option<&str> {
- Some(self.as_str())
- }
-}
-
-/// Hints provider
-pub trait Hinter {
- /// Specific hint type
- type Hint: Hint + 'static;
-
- /// Takes the currently edited `line` with the cursor `pos`ition and
- /// returns the string that should be displayed or `None`
- /// if no hint is available for the text the user currently typed.
- // TODO Validate: called while editing line but not while moving cursor.
- fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<Self::Hint> {
- let _ = (line, pos, ctx);
- None
- }
-}
-
-impl Hinter for () {
- type Hint = String;
-}
-
-impl<'r, H: ?Sized + Hinter> Hinter for &'r H {
- type Hint = H::Hint;
-
- fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<Self::Hint> {
- (**self).hint(line, pos, ctx)
- }
-}
-
-/// Add suggestion based on previous history entries matching current user
-/// input.
-pub struct HistoryHinter {}
-
-impl Hinter for HistoryHinter {
- type Hint = String;
-
- fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<String> {
- if pos < line.len() {
- return None;
- }
- let start = if ctx.history_index() == ctx.history().len() {
- ctx.history_index().saturating_sub(1)
- } else {
- ctx.history_index()
- };
- if let Some(history_index) =
- ctx.history
- .starts_with(&line[..pos], start, Direction::Reverse)
- {
- let entry = ctx.history.get(history_index);
- if let Some(entry) = entry {
- if entry == line || entry == &line[..pos] {
- return None;
- }
- }
- return entry.map(|s| s[pos..].to_owned());
- }
- None
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::{Hinter, HistoryHinter};
- use crate::history::History;
- use crate::Context;
-
- #[test]
- pub fn empty_history() {
- let history = History::new();
- let ctx = Context::new(&history);
- let hinter = HistoryHinter {};
- let hint = hinter.hint("test", 4, &ctx);
- assert_eq!(None, hint);
- }
-}
diff --git a/vendor/rustyline-8.2.0/src/history.rs b/vendor/rustyline-8.2.0/src/history.rs
deleted file mode 100644
index 1d4ae7e..0000000
--- a/vendor/rustyline-8.2.0/src/history.rs
+++ /dev/null
@@ -1,613 +0,0 @@
-//! History API
-
-use log::{debug, warn};
-use std::collections::vec_deque;
-use std::collections::VecDeque;
-use std::fs::{File, OpenOptions};
-use std::io::SeekFrom;
-use std::iter::DoubleEndedIterator;
-use std::ops::Index;
-use std::path::{Path, PathBuf};
-use std::time::SystemTime;
-
-use super::Result;
-use crate::config::{Config, HistoryDuplicates};
-
-/// Search direction
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum Direction {
- /// Search history forward
- Forward,
- /// Search history backward
- Reverse,
-}
-
-/// Current state of the history.
-#[derive(Default)]
-pub struct History {
- entries: VecDeque<String>,
- max_len: usize,
- pub(crate) ignore_space: bool,
- pub(crate) ignore_dups: bool,
- /// Number of entries inputed by user and not saved yet
- new_entries: usize,
- /// last path used by either `load` or `save`
- path_info: Option<PathInfo>,
-}
-
-/// Last histo path, modified timestamp and size
-struct PathInfo(PathBuf, SystemTime, usize);
-
-impl History {
- // New multiline-aware history files start with `#V2\n` and have newlines
- // and backslashes escaped in them.
- const FILE_VERSION_V2: &'static str = "#V2";
-
- /// Default constructor
- pub fn new() -> Self {
- Self::with_config(Config::default())
- }
-
- /// Customized constructor with:
- /// - `Config::max_history_size()`,
- /// - `Config::history_ignore_space()`,
- /// - `Config::history_duplicates()`.
- pub fn with_config(config: Config) -> Self {
- Self {
- entries: VecDeque::new(),
- max_len: config.max_history_size(),
- ignore_space: config.history_ignore_space(),
- ignore_dups: config.history_duplicates() == HistoryDuplicates::IgnoreConsecutive,
- new_entries: 0,
- path_info: None,
- }
- }
-
- /// Return the history entry at position `index`, starting from 0.
- pub fn get(&self, index: usize) -> Option<&String> {
- self.entries.get(index)
- }
-
- /// Return the last history entry (i.e. previous command)
- pub fn last(&self) -> Option<&String> {
- self.entries.back()
- }
-
- /// Add a new entry in the history.
- pub fn add<S: AsRef<str> + Into<String>>(&mut self, line: S) -> bool {
- if self.max_len == 0 {
- return false;
- }
- if line.as_ref().is_empty()
- || (self.ignore_space
- && line
- .as_ref()
- .chars()
- .next()
- .map_or(true, char::is_whitespace))
- {
- return false;
- }
- if self.ignore_dups {
- if let Some(s) = self.entries.back() {
- if s == line.as_ref() {
- return false;
- }
- }
- }
- if self.entries.len() == self.max_len {
- self.entries.pop_front();
- }
- self.entries.push_back(line.into());
- self.new_entries = self.new_entries.saturating_add(1).min(self.len());
- true
- }
-
- /// Return the number of entries in the history.
- pub fn len(&self) -> usize {
- self.entries.len()
- }
-
- /// Return true if the history has no entry.
- pub fn is_empty(&self) -> bool {
- self.entries.is_empty()
- }
-
- /// Set the maximum length for the history. This function can be called even
- /// if there is already some history, the function will make sure to retain
- /// just the latest `len` elements if the new history length value is
- /// smaller than the amount of items already inside the history.
- ///
- /// Like [stifle_history](http://tiswww.case.edu/php/chet/readline/history.html#IDX11).
- pub fn set_max_len(&mut self, len: usize) {
- self.max_len = len;
- if self.len() > len {
- self.entries.drain(..self.len() - len);
- self.new_entries = self.new_entries.min(len);
- }
- }
-
- /// Save the history in the specified file.
- // TODO history_truncate_file
- // https://tiswww.case.edu/php/chet/readline/history.html#IDX31
- pub fn save<P: AsRef<Path> + ?Sized>(&mut self, path: &P) -> Result<()> {
- if self.is_empty() || self.new_entries == 0 {
- return Ok(());
- }
- let path = path.as_ref();
- let old_umask = umask();
- let f = File::create(path);
- restore_umask(old_umask);
- let file = f?;
- self.save_to(&file, false)?;
- self.new_entries = 0;
- self.update_path(path, self.len())
- }
-
- fn save_to(&mut self, file: &File, append: bool) -> Result<()> {
- use std::io::{BufWriter, Write};
-
- fix_perm(file);
- let mut wtr = BufWriter::new(file);
- let first_new_entry = if append {
- self.entries.len().saturating_sub(self.new_entries)
- } else {
- wtr.write_all(Self::FILE_VERSION_V2.as_bytes())?;
- wtr.write_all(b"\n")?;
- 0
- };
- for entry in self.entries.iter().skip(first_new_entry) {
- let mut bytes = entry.as_bytes();
- while let Some(i) = memchr::memchr2(b'\\', b'\n', bytes) {
- wtr.write_all(&bytes[..i])?;
- if bytes[i] == b'\n' {
- wtr.write_all(b"\\n")?; // escaped line feed
- } else {
- debug_assert_eq!(bytes[i], b'\\');
- wtr.write_all(b"\\\\")?; // escaped backslash
- }
- bytes = &bytes[i + 1..];
- }
- wtr.write_all(bytes)?; // remaining bytes with no \n or \
- wtr.write_all(b"\n")?;
- }
- // https://github.com/rust-lang/rust/issues/32677#issuecomment-204833485
- wtr.flush()?;
- Ok(())
- }
-
- /// Append new entries in the specified file.
- // Like [append_history](http://tiswww.case.edu/php/chet/readline/history.html#IDX30).
- pub fn append<P: AsRef<Path> + ?Sized>(&mut self, path: &P) -> Result<()> {
- use fd_lock::FdLock;
- use std::io::Seek;
-
- if self.is_empty() || self.new_entries == 0 {
- return Ok(());
- }
- let path = path.as_ref();
- if !path.exists() || self.new_entries == self.max_len {
- return self.save(path);
- } else if self.can_just_append(path)? {
- let file = OpenOptions::new().append(true).open(path)?;
- self.save_to(&file, true)?;
- let size = self
- .path_info
- .as_ref()
- .unwrap()
- .2
- .saturating_add(self.new_entries);
- self.new_entries = 0;
- return self.update_path(path, size);
- }
- let file = OpenOptions::new().write(true).read(true).open(path)?;
- let mut lock = FdLock::new(file);
- let mut lock_guard = lock.lock()?;
- // we may need to truncate file before appending new entries
- let mut other = Self {
- entries: VecDeque::new(),
- max_len: self.max_len,
- ignore_space: self.ignore_space,
- ignore_dups: self.ignore_dups,
- new_entries: 0,
- path_info: None,
- };
- other.load_from(&lock_guard)?;
- let first_new_entry = self.entries.len().saturating_sub(self.new_entries);
- for entry in self.entries.iter().skip(first_new_entry) {
- other.add(entry);
- }
- lock_guard.seek(SeekFrom::Start(0))?;
- other.save_to(&lock_guard, false)?;
- drop(lock_guard);
- self.update_path(path, other.len())?;
- self.new_entries = 0;
- Ok(())
- }
-
- /// Load the history from the specified file.
- ///
- /// # Errors
- /// Will return `Err` if path does not already exist or could not be read.
- pub fn load<P: AsRef<Path> + ?Sized>(&mut self, path: &P) -> Result<()> {
- let path = path.as_ref();
- let file = File::open(path)?;
- let len = self.len();
- if self.load_from(&file)? {
- self.update_path(path, self.len() - len)
- } else {
- // discard old version on next save
- self.path_info = None;
- Ok(())
- }
- }
-
- fn load_from(&mut self, file: &File) -> Result<bool> {
- use std::io::{BufRead, BufReader};
-
- let rdr = BufReader::new(file);
- let mut lines = rdr.lines();
- let mut v2 = false;
- if let Some(first) = lines.next() {
- let line = first?;
- if line == Self::FILE_VERSION_V2 {
- v2 = true;
- } else {
- self.add(line);
- }
- }
- for line in lines {
- let mut line = line?;
- if line.is_empty() {
- continue;
- }
- if v2 {
- let mut copy = None; // lazily copy line if unescaping is needed
- let mut str = line.as_str();
- while let Some(i) = str.find('\\') {
- if copy.is_none() {
- copy = Some(String::with_capacity(line.len()));
- }
- let s = copy.as_mut().unwrap();
- s.push_str(&str[..i]);
- let j = i + 1; // escaped char idx
- let b = if j < str.len() {
- str.as_bytes()[j]
- } else {
- 0 // unexpected if History::save works properly
- };
- match b {
- b'n' => {
- s.push('\n'); // unescaped line feed
- }
- b'\\' => {
- s.push('\\'); // unescaped back slash
- }
- _ => {
- // only line feed and back slash should have been escaped
- warn!(target: "rustyline", "bad escaped line: {}", line);
- copy = None;
- break;
- }
- }
- str = &str[j + 1..];
- }
- if let Some(mut s) = copy {
- s.push_str(str); // remaining bytes with no escaped char
- line = s;
- }
- }
- self.add(line); // TODO truncate to MAX_LINE
- }
- self.new_entries = 0; // TODO we may lost new entries if loaded lines < max_len
- Ok(v2)
- }
-
- fn update_path(&mut self, path: &Path, size: usize) -> Result<()> {
- let modified = File::open(&path)?.metadata()?.modified()?;
- if let Some(PathInfo(
- ref mut previous_path,
- ref mut previous_modified,
- ref mut previous_size,
- )) = self.path_info
- {
- if previous_path.as_path() != path {
- *previous_path = path.to_owned();
- }
- *previous_modified = modified;
- *previous_size = size;
- } else {
- self.path_info = Some(PathInfo(path.to_owned(), modified, size));
- }
- debug!(target: "rustyline", "PathInfo({:?}, {:?}, {})", path, modified, size);
- Ok(())
- }
-
- fn can_just_append(&self, path: &Path) -> Result<bool> {
- if let Some(PathInfo(ref previous_path, ref previous_modified, ref previous_size)) =
- self.path_info
- {
- if previous_path.as_path() != path {
- debug!(target: "rustyline", "cannot append: {:?} <> {:?}", previous_path, path);
- return Ok(false);
- }
- let modified = File::open(&path)?.metadata()?.modified()?;
- if *previous_modified != modified
- || self.max_len <= *previous_size
- || self.max_len < (*previous_size).saturating_add(self.new_entries)
- {
- debug!(target: "rustyline", "cannot append: {:?} < {:?} or {} < {} + {}",
- previous_modified, modified, self.max_len, previous_size, self.new_entries);
- Ok(false)
- } else {
- Ok(true)
- }
- } else {
- Ok(false)
- }
- }
-
- /// Clear history
- pub fn clear(&mut self) {
- self.entries.clear();
- self.new_entries = 0;
- }
-
- /// Search history (start position inclusive [0, len-1]).
- ///
- /// Return the absolute index of the nearest history entry that matches
- /// `term`.
- ///
- /// Return None if no entry contains `term` between [start, len -1] for
- /// forward search
- /// or between [0, start] for reverse search.
- pub fn search(&self, term: &str, start: usize, dir: Direction) -> Option<usize> {
- let test = |entry: &String| entry.contains(term);
- self.search_match(term, start, dir, test)
- }
-
- /// Anchored search
- pub fn starts_with(&self, term: &str, start: usize, dir: Direction) -> Option<usize> {
- let test = |entry: &String| entry.starts_with(term);
- self.search_match(term, start, dir, test)
- }
-
- fn search_match<F>(&self, term: &str, start: usize, dir: Direction, test: F) -> Option<usize>
- where
- F: Fn(&String) -> bool,
- {
- if term.is_empty() || start >= self.len() {
- return None;
- }
- match dir {
- Direction::Reverse => {
- let index = self
- .entries
- .iter()
- .rev()
- .skip(self.entries.len() - 1 - start)
- .position(test);
- index.map(|index| start - index)
- }
- Direction::Forward => {
- let index = self.entries.iter().skip(start).position(test);
- index.map(|index| index + start)
- }
- }
- }
-
- /// Return a forward iterator.
- pub fn iter(&self) -> Iter<'_> {
- Iter(self.entries.iter())
- }
-}
-
-impl Index<usize> for History {
- type Output = String;
-
- fn index(&self, index: usize) -> &String {
- &self.entries[index]
- }
-}
-
-impl<'a> IntoIterator for &'a History {
- type IntoIter = Iter<'a>;
- type Item = &'a String;
-
- fn into_iter(self) -> Iter<'a> {
- self.iter()
- }
-}
-
-/// History iterator.
-pub struct Iter<'a>(vec_deque::Iter<'a, String>);
-
-impl<'a> Iterator for Iter<'a> {
- type Item = &'a String;
-
- fn next(&mut self) -> Option<&'a String> {
- self.0.next()
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.0.size_hint()
- }
-}
-
-impl<'a> DoubleEndedIterator for Iter<'a> {
- fn next_back(&mut self) -> Option<&'a String> {
- self.0.next_back()
- }
-}
-
-cfg_if::cfg_if! {
- if #[cfg(any(windows, target_arch = "wasm32"))] {
- fn umask() -> u16 {
- 0
- }
-
- fn restore_umask(_: u16) {}
-
- fn fix_perm(_: &File) {}
- } else if #[cfg(unix)] {
- fn umask() -> libc::mode_t {
- unsafe { libc::umask(libc::S_IXUSR | libc::S_IRWXG | libc::S_IRWXO) }
- }
-
- fn restore_umask(old_umask: libc::mode_t) {
- unsafe {
- libc::umask(old_umask);
- }
- }
-
- fn fix_perm(file: &File) {
- use std::os::unix::io::AsRawFd;
- unsafe {
- libc::fchmod(file.as_raw_fd(), libc::S_IRUSR | libc::S_IWUSR);
- }
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::{Direction, History};
- use crate::config::Config;
- use crate::Result;
-
- fn init() -> History {
- let mut history = History::new();
- assert!(history.add("line1"));
- assert!(history.add("line2"));
- assert!(history.add("line3"));
- history
- }
-
- #[test]
- fn new() {
- let history = History::new();
- assert_eq!(0, history.entries.len());
- }
-
- #[test]
- fn add() {
- let config = Config::builder().history_ignore_space(true).build();
- let mut history = History::with_config(config);
- assert_eq!(config.max_history_size(), history.max_len);
- assert!(history.add("line1"));
- assert!(history.add("line2"));
- assert!(!history.add("line2"));
- assert!(!history.add(""));
- assert!(!history.add(" line3"));
- }
-
- #[test]
- fn set_max_len() {
- let mut history = init();
- history.set_max_len(1);
- assert_eq!(1, history.entries.len());
- assert_eq!(Some(&"line3".to_owned()), history.last());
- }
-
- #[test]
- #[cfg_attr(miri, ignore)] // unsupported operation: `getcwd` not available when isolation is enabled
- fn save() -> Result<()> {
- check_save("line\nfour \\ abc")
- }
-
- #[test]
- fn save_windows_path() -> Result<()> {
- let path = "cd source\\repos\\forks\\nushell\\";
- check_save(path)
- }
-
- #[cfg_attr(miri, ignore)] // unsupported operation: `getcwd` not available when isolation is enabled
- fn check_save(line: &str) -> Result<()> {
- let mut history = init();
- assert!(history.add(line));
- let tf = tempfile::NamedTempFile::new()?;
-
- history.save(tf.path())?;
- let mut history2 = History::new();
- history2.load(tf.path())?;
- for (a, b) in history.entries.iter().zip(history2.entries.iter()) {
- assert_eq!(a, b);
- }
- tf.close()?;
- Ok(())
- }
-
- #[test]
- #[cfg_attr(miri, ignore)] // unsupported operation: `getcwd` not available when isolation is enabled
- fn load_legacy() -> Result<()> {
- use std::io::Write;
- let tf = tempfile::NamedTempFile::new()?;
- {
- let mut legacy = std::fs::File::create(tf.path())?;
- // Some data we'd accidentally corrupt if we got the version wrong
- let data = b"\
- test\\n \\abc \\123\n\
- 123\\n\\\\n\n\
- abcde
- ";
- legacy.write_all(data)?;
- legacy.flush()?;
- }
- let mut history = History::new();
- history.load(tf.path())?;
- assert_eq!(history.entries[0], "test\\n \\abc \\123");
- assert_eq!(history.entries[1], "123\\n\\\\n");
- assert_eq!(history.entries[2], "abcde");
-
- tf.close()?;
- Ok(())
- }
-
- #[test]
- #[cfg_attr(miri, ignore)] // unsupported operation: `getcwd` not available when isolation is enabled
- fn append() -> Result<()> {
- let mut history = init();
- let tf = tempfile::NamedTempFile::new()?;
-
- history.append(tf.path())?;
-
- let mut history2 = History::new();
- history2.load(tf.path())?;
- history2.add("line4");
- history2.append(tf.path())?;
-
- history.add("line5");
- history.append(tf.path())?;
-
- let mut history3 = History::new();
- history3.load(tf.path())?;
- assert_eq!(history3.len(), 5);
-
- tf.close()?;
- Ok(())
- }
-
- #[test]
- fn search() {
- let history = init();
- assert_eq!(None, history.search("", 0, Direction::Forward));
- assert_eq!(None, history.search("none", 0, Direction::Forward));
- assert_eq!(None, history.search("line", 3, Direction::Forward));
-
- assert_eq!(Some(0), history.search("line", 0, Direction::Forward));
- assert_eq!(Some(1), history.search("line", 1, Direction::Forward));
- assert_eq!(Some(2), history.search("line3", 1, Direction::Forward));
- }
-
- #[test]
- fn reverse_search() {
- let history = init();
- assert_eq!(None, history.search("", 2, Direction::Reverse));
- assert_eq!(None, history.search("none", 2, Direction::Reverse));
- assert_eq!(None, history.search("line", 3, Direction::Reverse));
-
- assert_eq!(Some(2), history.search("line", 2, Direction::Reverse));
- assert_eq!(Some(1), history.search("line", 1, Direction::Reverse));
- assert_eq!(Some(0), history.search("line1", 1, Direction::Reverse));
- }
-}
diff --git a/vendor/rustyline-8.2.0/src/keymap.rs b/vendor/rustyline-8.2.0/src/keymap.rs
deleted file mode 100644
index 4eb5cb1..0000000
--- a/vendor/rustyline-8.2.0/src/keymap.rs
+++ /dev/null
@@ -1,1124 +0,0 @@
-//! Bindings from keys to command for Emacs and Vi modes
-use std::sync::{Arc, RwLock};
-
-use log::debug;
-use radix_trie::Trie;
-
-use super::Result;
-use crate::keys::{KeyCode as K, KeyEvent, KeyEvent as E, Modifiers as M};
-use crate::tty::{RawReader, Term, Terminal};
-use crate::{Config, EditMode, Event, EventContext, EventHandler};
-
-/// The number of times one command should be repeated.
-pub type RepeatCount = usize;
-
-/// Commands
-#[derive(Debug, Clone, PartialEq)]
-#[non_exhaustive]
-pub enum Cmd {
- /// abort
- Abort, // Miscellaneous Command
- /// accept-line
- ///
- /// See also AcceptOrInsertLine
- AcceptLine,
- /// beginning-of-history
- BeginningOfHistory,
- /// capitalize-word
- CapitalizeWord,
- /// clear-screen
- ClearScreen,
- /// Paste from the clipboard
- #[cfg(windows)]
- PasteFromClipboard,
- /// complete
- Complete,
- /// complete-backward
- CompleteBackward,
- /// complete-hint
- CompleteHint,
- /// Dedent current line
- Dedent(Movement),
- /// downcase-word
- DowncaseWord,
- /// vi-eof-maybe
- EndOfFile,
- /// end-of-history
- EndOfHistory,
- /// forward-search-history
- ForwardSearchHistory,
- /// history-search-backward
- HistorySearchBackward,
- /// history-search-forward
- HistorySearchForward,
- /// Indent current line
- Indent(Movement),
- /// Insert text
- Insert(RepeatCount, String),
- /// Interrupt signal (Ctrl-C)
- Interrupt,
- /// backward-delete-char, backward-kill-line, backward-kill-word
- /// delete-char, kill-line, kill-word, unix-line-discard, unix-word-rubout,
- /// vi-delete, vi-delete-to, vi-rubout
- Kill(Movement),
- /// backward-char, backward-word, beginning-of-line, end-of-line,
- /// forward-char, forward-word, vi-char-search, vi-end-word, vi-next-word,
- /// vi-prev-word
- Move(Movement),
- /// next-history
- NextHistory,
- /// No action
- Noop,
- /// vi-replace
- Overwrite(char),
- /// previous-history
- PreviousHistory,
- /// quoted-insert
- QuotedInsert,
- /// vi-change-char
- ReplaceChar(RepeatCount, char),
- /// vi-change-to, vi-substitute
- Replace(Movement, Option<String>),
- /// reverse-search-history
- ReverseSearchHistory,
- /// self-insert
- SelfInsert(RepeatCount, char),
- /// Suspend signal (Ctrl-Z on unix platform)
- Suspend,
- /// transpose-chars
- TransposeChars,
- /// transpose-words
- TransposeWords(RepeatCount),
- /// undo
- Undo(RepeatCount),
- /// Unsupported / unexpected
- Unknown,
- /// upcase-word
- UpcaseWord,
- /// vi-yank-to
- ViYankTo(Movement),
- /// yank, vi-put
- Yank(RepeatCount, Anchor),
- /// yank-pop
- YankPop,
- /// moves cursor to the line above or switches to prev history entry if
- /// the cursor is already on the first line
- LineUpOrPreviousHistory(RepeatCount),
- /// moves cursor to the line below or switches to next history entry if
- /// the cursor is already on the last line
- LineDownOrNextHistory(RepeatCount),
- /// Inserts a newline
- Newline,
- /// Either accepts or inserts a newline
- ///
- /// Always inserts newline if input is non-valid. Can also insert newline
- /// if cursor is in the middle of the text
- ///
- /// If you support multi-line input:
- /// * Use `accept_in_the_middle: true` for mostly single-line cases, for
- /// example command-line.
- /// * Use `accept_in_the_middle: false` for mostly multi-line cases, for
- /// example SQL or JSON input.
- AcceptOrInsertLine {
- /// Whether this commands accepts input if the cursor not at the end
- /// of the current input
- accept_in_the_middle: bool,
- },
-}
-
-impl Cmd {
- /// Tells if current command should reset kill ring.
- pub fn should_reset_kill_ring(&self) -> bool {
- #[allow(clippy::match_same_arms)]
- match *self {
- Cmd::Kill(Movement::BackwardChar(_)) | Cmd::Kill(Movement::ForwardChar(_)) => true,
- Cmd::ClearScreen
- | Cmd::Kill(_)
- | Cmd::Replace(..)
- | Cmd::Noop
- | Cmd::Suspend
- | Cmd::Yank(..)
- | Cmd::YankPop => false,
- _ => true,
- }
- }
-
- fn is_repeatable_change(&self) -> bool {
- matches!(
- *self,
- Cmd::Dedent(..)
- | Cmd::Indent(..)
- | Cmd::Insert(..)
- | Cmd::Kill(_)
- | Cmd::ReplaceChar(..)
- | Cmd::Replace(..)
- | Cmd::SelfInsert(..)
- | Cmd::ViYankTo(_)
- | Cmd::Yank(..) // Cmd::TransposeChars | TODO Validate
- )
- }
-
- fn is_repeatable(&self) -> bool {
- match *self {
- Cmd::Move(_) => true,
- _ => self.is_repeatable_change(),
- }
- }
-
- // Replay this command with a possible different `RepeatCount`.
- fn redo(&self, new: Option<RepeatCount>, wrt: &dyn Refresher) -> Self {
- match *self {
- Cmd::Dedent(ref mvt) => Cmd::Dedent(mvt.redo(new)),
- Cmd::Indent(ref mvt) => Cmd::Indent(mvt.redo(new)),
- Cmd::Insert(previous, ref text) => {
- Cmd::Insert(repeat_count(previous, new), text.clone())
- }
- Cmd::Kill(ref mvt) => Cmd::Kill(mvt.redo(new)),
- Cmd::Move(ref mvt) => Cmd::Move(mvt.redo(new)),
- Cmd::ReplaceChar(previous, c) => Cmd::ReplaceChar(repeat_count(previous, new), c),
- Cmd::Replace(ref mvt, ref text) => {
- if text.is_none() {
- let last_insert = wrt.last_insert();
- if let Movement::ForwardChar(0) = mvt {
- Cmd::Replace(
- Movement::ForwardChar(last_insert.as_ref().map_or(0, String::len)),
- last_insert,
- )
- } else {
- Cmd::Replace(mvt.redo(new), last_insert)
- }
- } else {
- Cmd::Replace(mvt.redo(new), text.clone())
- }
- }
- Cmd::SelfInsert(previous, c) => {
- // consecutive char inserts are repeatable not only the last one...
- if let Some(text) = wrt.last_insert() {
- Cmd::Insert(repeat_count(previous, new), text)
- } else {
- Cmd::SelfInsert(repeat_count(previous, new), c)
- }
- }
- // Cmd::TransposeChars => Cmd::TransposeChars,
- Cmd::ViYankTo(ref mvt) => Cmd::ViYankTo(mvt.redo(new)),
- Cmd::Yank(previous, anchor) => Cmd::Yank(repeat_count(previous, new), anchor),
- _ => unreachable!(),
- }
- }
-}
-
-fn repeat_count(previous: RepeatCount, new: Option<RepeatCount>) -> RepeatCount {
- match new {
- Some(n) => n,
- None => previous,
- }
-}
-
-/// Different word definitions
-#[derive(Debug, Clone, PartialEq, Copy)]
-pub enum Word {
- /// non-blanks characters
- Big,
- /// alphanumeric characters
- Emacs,
- /// alphanumeric (and '_') characters
- Vi,
-}
-
-/// Where to move with respect to word boundary
-#[derive(Debug, Clone, PartialEq, Copy)]
-pub enum At {
- /// Start of word.
- Start,
- /// Before end of word.
- BeforeEnd,
- /// After end of word.
- AfterEnd,
-}
-
-/// Where to paste (relative to cursor position)
-#[derive(Debug, Clone, PartialEq, Copy)]
-pub enum Anchor {
- /// After cursor
- After,
- /// Before cursor
- Before,
-}
-
-/// Vi character search
-#[derive(Debug, Clone, PartialEq, Copy)]
-pub enum CharSearch {
- /// Forward search
- Forward(char),
- /// Forward search until
- ForwardBefore(char),
- /// Backward search
- Backward(char),
- /// Backward search until
- BackwardAfter(char),
-}
-
-impl CharSearch {
- fn opposite(self) -> Self {
- match self {
- CharSearch::Forward(c) => CharSearch::Backward(c),
- CharSearch::ForwardBefore(c) => CharSearch::BackwardAfter(c),
- CharSearch::Backward(c) => CharSearch::Forward(c),
- CharSearch::BackwardAfter(c) => CharSearch::ForwardBefore(c),
- }
- }
-}
-
-/// Where to move
-#[derive(Debug, Clone, PartialEq)]
-#[non_exhaustive]
-pub enum Movement {
- /// Whole current line (not really a movement but a range)
- WholeLine,
- /// beginning-of-line
- BeginningOfLine,
- /// end-of-line
- EndOfLine,
- /// backward-word, vi-prev-word
- BackwardWord(RepeatCount, Word), // Backward until start of word
- /// forward-word, vi-end-word, vi-next-word
- ForwardWord(RepeatCount, At, Word), // Forward until start/end of word
- /// vi-char-search
- ViCharSearch(RepeatCount, CharSearch),
- /// vi-first-print
- ViFirstPrint,
- /// backward-char
- BackwardChar(RepeatCount),
- /// forward-char
- ForwardChar(RepeatCount),
- /// move to the same column on the previous line
- LineUp(RepeatCount),
- /// move to the same column on the next line
- LineDown(RepeatCount),
- /// Whole user input (not really a movement but a range)
- WholeBuffer,
- /// beginning-of-buffer
- BeginningOfBuffer,
- /// end-of-buffer
- EndOfBuffer,
-}
-
-impl Movement {
- // Replay this movement with a possible different `RepeatCount`.
- fn redo(&self, new: Option<RepeatCount>) -> Self {
- match *self {
- Movement::WholeLine => Movement::WholeLine,
- Movement::BeginningOfLine => Movement::BeginningOfLine,
- Movement::ViFirstPrint => Movement::ViFirstPrint,
- Movement::EndOfLine => Movement::EndOfLine,
- Movement::BackwardWord(previous, word) => {
- Movement::BackwardWord(repeat_count(previous, new), word)
- }
- Movement::ForwardWord(previous, at, word) => {
- Movement::ForwardWord(repeat_count(previous, new), at, word)
- }
- Movement::ViCharSearch(previous, char_search) => {
- Movement::ViCharSearch(repeat_count(previous, new), char_search)
- }
- Movement::BackwardChar(previous) => Movement::BackwardChar(repeat_count(previous, new)),
- Movement::ForwardChar(previous) => Movement::ForwardChar(repeat_count(previous, new)),
- Movement::LineUp(previous) => Movement::LineUp(repeat_count(previous, new)),
- Movement::LineDown(previous) => Movement::LineDown(repeat_count(previous, new)),
- Movement::WholeBuffer => Movement::WholeBuffer,
- Movement::BeginningOfBuffer => Movement::BeginningOfBuffer,
- Movement::EndOfBuffer => Movement::EndOfBuffer,
- }
- }
-}
-
-/// Vi input modes
-#[derive(Clone, Copy, PartialEq)]
-pub enum InputMode {
- /// Vi Command/Alternate
- Command,
- /// Insert/Input mode
- Insert,
- /// Overwrite mode
- Replace,
-}
-
-/// Transform key(s) to commands based on current input mode
-pub struct InputState {
- pub(crate) mode: EditMode,
- custom_bindings: Arc<RwLock<Trie<Event, EventHandler>>>,
- pub(crate) input_mode: InputMode, // vi only ?
- // numeric arguments: http://web.mit.edu/gnu/doc/html/rlman_1.html#SEC7
- num_args: i16,
- last_cmd: Cmd, // vi only
- last_char_search: Option<CharSearch>, // vi only
-}
-
-/// Provide indirect mutation to user input.
-pub trait Invoke {
- /// currently edited line
- fn input(&self) -> &str;
- // TODO
- //fn invoke(&mut self, cmd: Cmd) -> Result<?>;
-}
-
-pub trait Refresher {
- /// Rewrite the currently edited line accordingly to the buffer content,
- /// cursor position, and number of columns of the terminal.
- fn refresh_line(&mut self) -> Result<()>;
- /// Same as [`refresh_line`] with a specific message instead of hint
- fn refresh_line_with_msg(&mut self, msg: Option<&str>) -> Result<()>;
- /// Same as `refresh_line` but with a dynamic prompt.
- fn refresh_prompt_and_line(&mut self, prompt: &str) -> Result<()>;
- /// Vi only, switch to insert mode.
- fn doing_insert(&mut self);
- /// Vi only, switch to command mode.
- fn done_inserting(&mut self);
- /// Vi only, last text inserted.
- fn last_insert(&self) -> Option<String>;
- /// Returns `true` if the cursor is currently at the end of the line.
- fn is_cursor_at_end(&self) -> bool;
- /// Returns `true` if there is a hint displayed.
- fn has_hint(&self) -> bool;
- /// Returns the hint text that is shown after the current cursor position.
- fn hint_text(&self) -> Option<&str>;
- /// currently edited line
- fn line(&self) -> &str;
- /// Current cursor position (byte position)
- fn pos(&self) -> usize;
-}
-
-impl InputState {
- pub fn new(config: &Config, custom_bindings: Arc<RwLock<Trie<Event, EventHandler>>>) -> Self {
- Self {
- mode: config.edit_mode(),
- custom_bindings,
- input_mode: InputMode::Insert,
- num_args: 0,
- last_cmd: Cmd::Noop,
- last_char_search: None,
- }
- }
-
- pub fn is_emacs_mode(&self) -> bool {
- self.mode == EditMode::Emacs
- }
-
- /// Parse user input into one command
- /// `single_esc_abort` is used in emacs mode on unix platform when a single
- /// esc key is expected to abort current action.
- pub fn next_cmd(
- &mut self,
- rdr: &mut <Terminal as Term>::Reader,
- wrt: &mut dyn Refresher,
- single_esc_abort: bool,
- ) -> Result<Cmd> {
- match self.mode {
- EditMode::Emacs => {
- let key = rdr.next_key(single_esc_abort)?;
- self.emacs(rdr, wrt, key)
- }
- EditMode::Vi if self.input_mode != InputMode::Command => {
- let key = rdr.next_key(false)?;
- self.vi_insert(rdr, wrt, key)
- }
- EditMode::Vi => {
- let key = rdr.next_key(false)?;
- self.vi_command(rdr, wrt, key)
- }
- }
- }
-
- fn custom_binding(
- &self,
- wrt: &mut dyn Refresher,
- evt: &Event,
- n: RepeatCount,
- positive: bool,
- ) -> Option<Cmd> {
- let bindings = self.custom_bindings.read().unwrap();
- let handler = bindings.get(&evt).or_else(|| bindings.get(&Event::Any));
- if let Some(handler) = handler {
- match handler {
- EventHandler::Simple(cmd) => Some(cmd.clone()),
- EventHandler::Conditional(handler) => {
- let ctx = EventContext::new(self, wrt);
- handler.handle(&evt, n, positive, &ctx)
- }
- }
- } else {
- None
- }
- }
-
- fn custom_seq_binding<R: RawReader>(
- &self,
- rdr: &mut R,
- wrt: &mut dyn Refresher,
- evt: &mut Event,
- n: RepeatCount,
- positive: bool,
- ) -> Result<Option<Cmd>> {
- let bindings = self.custom_bindings.read().unwrap();
- while let Some(subtrie) = bindings.get_raw_descendant(&evt) {
- let snd_key = rdr.next_key(true)?;
- if let Event::KeySeq(ref mut key_seq) = evt {
- key_seq.push(snd_key);
- } else {
- break;
- }
- let handler = subtrie.get(&evt).unwrap();
- if let Some(handler) = handler {
- let cmd = match handler {
- EventHandler::Simple(cmd) => Some(cmd.clone()),
- EventHandler::Conditional(handler) => {
- let ctx = EventContext::new(self, wrt);
- handler.handle(&evt, n, positive, &ctx)
- }
- };
- if cmd.is_some() {
- return Ok(cmd);
- }
- }
- }
- Ok(None)
- }
-
- fn emacs_digit_argument<R: RawReader>(
- &mut self,
- rdr: &mut R,
- wrt: &mut dyn Refresher,
- digit: char,
- ) -> Result<KeyEvent> {
- #[allow(clippy::cast_possible_truncation)]
- match digit {
- '0'..='9' => {
- self.num_args = digit.to_digit(10).unwrap() as i16;
- }
- '-' => {
- self.num_args = -1;
- }
- _ => unreachable!(),
- }
- loop {
- wrt.refresh_prompt_and_line(&format!("(arg: {}) ", self.num_args))?;
- let key = rdr.next_key(true)?;
- #[allow(clippy::cast_possible_truncation)]
- match key {
- E(K::Char(digit @ '0'..='9'), m) if m == M::NONE || m == M::ALT => {
- if self.num_args == -1 {
- self.num_args *= digit.to_digit(10).unwrap() as i16;
- } else if self.num_args.abs() < 1000 {
- // shouldn't ever need more than 4 digits
- self.num_args = self
- .num_args
- .saturating_mul(10)
- .saturating_add(digit.to_digit(10).unwrap() as i16);
- }
- }
- E(K::Char('-'), m) if m == M::NONE || m == M::ALT => {}
- _ => {
- wrt.refresh_line()?;
- return Ok(key);
- }
- };
- }
- }
-
- fn emacs<R: RawReader>(
- &mut self,
- rdr: &mut R,
- wrt: &mut dyn Refresher,
- mut key: KeyEvent,
- ) -> Result<Cmd> {
- if let E(K::Char(digit @ '-'), M::ALT) = key {
- key = self.emacs_digit_argument(rdr, wrt, digit)?;
- } else if let E(K::Char(digit @ '0'..='9'), M::ALT) = key {
- key = self.emacs_digit_argument(rdr, wrt, digit)?;
- }
- let (n, positive) = self.emacs_num_args(); // consume them in all cases
-
- let mut evt = key.into();
- if let Some(cmd) = self.custom_binding(wrt, &evt, n, positive) {
- return Ok(if cmd.is_repeatable() {
- cmd.redo(Some(n), wrt)
- } else {
- cmd
- });
- }
- let cmd = match key {
- E(K::Char(c), M::NONE) => {
- if positive {
- Cmd::SelfInsert(n, c)
- } else {
- Cmd::Unknown
- }
- }
- E(K::Char('A'), M::CTRL) => Cmd::Move(Movement::BeginningOfLine),
- E(K::Char('B'), M::CTRL) => {
- if positive {
- Cmd::Move(Movement::BackwardChar(n))
- } else {
- Cmd::Move(Movement::ForwardChar(n))
- }
- }
- E(K::Char('E'), M::CTRL) => Cmd::Move(Movement::EndOfLine),
- E(K::Char('F'), M::CTRL) => {
- if positive {
- Cmd::Move(Movement::ForwardChar(n))
- } else {
- Cmd::Move(Movement::BackwardChar(n))
- }
- }
- E(K::Char('G'), M::CTRL) | E::ESC | E(K::Char('G'), M::CTRL_ALT) => Cmd::Abort,
- E(K::Char('H'), M::CTRL) | E::BACKSPACE => {
- if positive {
- Cmd::Kill(Movement::BackwardChar(n))
- } else {
- Cmd::Kill(Movement::ForwardChar(n))
- }
- }
- E(K::BackTab, M::NONE) => Cmd::CompleteBackward,
- E(K::Tab, M::NONE) => {
- if positive {
- Cmd::Complete
- } else {
- Cmd::CompleteBackward
- }
- }
- // Don't complete hints when the cursor is not at the end of a line
- E(K::Right, M::NONE) if wrt.has_hint() && wrt.is_cursor_at_end() => Cmd::CompleteHint,
- E(K::Char('K'), M::CTRL) => {
- if positive {
- Cmd::Kill(Movement::EndOfLine)
- } else {
- Cmd::Kill(Movement::BeginningOfLine)
- }
- }
- E(K::Char('L'), M::CTRL) => Cmd::ClearScreen,
- E(K::Char('N'), M::CTRL) => Cmd::NextHistory,
- E(K::Char('P'), M::CTRL) => Cmd::PreviousHistory,
- E(K::Char('X'), M::CTRL) => {
- if let Some(cmd) = self.custom_seq_binding(rdr, wrt, &mut evt, n, positive)? {
- cmd
- } else {
- let snd_key = match evt {
- // we may have already read the second key in custom_seq_binding
- Event::KeySeq(ref key_seq) if key_seq.len() > 1 => key_seq[1],
- _ => rdr.next_key(true)?,
- };
- match snd_key {
- E(K::Char('G'), M::CTRL) | E::ESC => Cmd::Abort,
- E(K::Char('U'), M::CTRL) => Cmd::Undo(n),
- _ => Cmd::Unknown,
- }
- }
- }
- E(K::Backspace, M::ALT) => {
- if positive {
- Cmd::Kill(Movement::BackwardWord(n, Word::Emacs))
- } else {
- Cmd::Kill(Movement::ForwardWord(n, At::AfterEnd, Word::Emacs))
- }
- }
- E(K::Char('<'), M::ALT) => Cmd::BeginningOfHistory,
- E(K::Char('>'), M::ALT) => Cmd::EndOfHistory,
- E(K::Char('B'), M::ALT)
- | E(K::Char('b'), M::ALT)
- | E(K::Left, M::CTRL)
- | E(K::Left, M::ALT) => {
- if positive {
- Cmd::Move(Movement::BackwardWord(n, Word::Emacs))
- } else {
- Cmd::Move(Movement::ForwardWord(n, At::AfterEnd, Word::Emacs))
- }
- }
- E(K::Char('C'), M::ALT) | E(K::Char('c'), M::ALT) => Cmd::CapitalizeWord,
- E(K::Char('D'), M::ALT) | E(K::Char('d'), M::ALT) => {
- if positive {
- Cmd::Kill(Movement::ForwardWord(n, At::AfterEnd, Word::Emacs))
- } else {
- Cmd::Kill(Movement::BackwardWord(n, Word::Emacs))
- }
- }
- E(K::Char('F'), M::ALT)
- | E(K::Char('f'), M::ALT)
- | E(K::Right, M::CTRL)
- | E(K::Right, M::ALT) => {
- if positive {
- Cmd::Move(Movement::ForwardWord(n, At::AfterEnd, Word::Emacs))
- } else {
- Cmd::Move(Movement::BackwardWord(n, Word::Emacs))
- }
- }
- E(K::Char('L'), M::ALT) | E(K::Char('l'), M::ALT) => Cmd::DowncaseWord,
- E(K::Char('T'), M::ALT) | E(K::Char('t'), M::ALT) => Cmd::TransposeWords(n),
- // TODO ESC-R (r): Undo all changes made to this line.
- E(K::Char('U'), M::ALT) | E(K::Char('u'), M::ALT) => Cmd::UpcaseWord,
- E(K::Char('Y'), M::ALT) | E(K::Char('y'), M::ALT) => Cmd::YankPop,
- _ => self.common(rdr, wrt, evt, key, n, positive)?,
- };
- debug!(target: "rustyline", "Emacs command: {:?}", cmd);
- Ok(cmd)
- }
-
- #[allow(clippy::cast_possible_truncation)]
- fn vi_arg_digit<R: RawReader>(
- &mut self,
- rdr: &mut R,
- wrt: &mut dyn Refresher,
- digit: char,
- ) -> Result<KeyEvent> {
- self.num_args = digit.to_digit(10).unwrap() as i16;
- loop {
- wrt.refresh_prompt_and_line(&format!("(arg: {}) ", self.num_args))?;
- let key = rdr.next_key(false)?;
- if let E(K::Char(digit @ '0'..='9'), M::NONE) = key {
- if self.num_args.abs() < 1000 {
- // shouldn't ever need more than 4 digits
- self.num_args = self
- .num_args
- .saturating_mul(10)
- .saturating_add(digit.to_digit(10).unwrap() as i16);
- }
- } else {
- wrt.refresh_line()?;
- return Ok(key);
- };
- }
- }
-
- fn vi_command<R: RawReader>(
- &mut self,
- rdr: &mut R,
- wrt: &mut dyn Refresher,
- mut key: KeyEvent,
- ) -> Result<Cmd> {
- if let E(K::Char(digit @ '1'..='9'), M::NONE) = key {
- key = self.vi_arg_digit(rdr, wrt, digit)?;
- }
- let no_num_args = self.num_args == 0;
- let n = self.vi_num_args(); // consume them in all cases
- let evt = key.into();
- if let Some(cmd) = self.custom_binding(wrt, &evt, n, true) {
- return Ok(if cmd.is_repeatable() {
- if no_num_args {
- cmd.redo(None, wrt)
- } else {
- cmd.redo(Some(n), wrt)
- }
- } else {
- cmd
- });
- }
- let cmd = match key {
- E(K::Char('$'), M::NONE) | E(K::End, M::NONE) => Cmd::Move(Movement::EndOfLine),
- E(K::Char('.'), M::NONE) => {
- // vi-redo (repeat last command)
- if no_num_args {
- self.last_cmd.redo(None, wrt)
- } else {
- self.last_cmd.redo(Some(n), wrt)
- }
- }
- // TODO E(K::Char('%'), M::NONE) => Cmd::???, Move to the corresponding opening/closing
- // bracket
- E(K::Char('0'), M::NONE) => Cmd::Move(Movement::BeginningOfLine),
- E(K::Char('^'), M::NONE) => Cmd::Move(Movement::ViFirstPrint),
- E(K::Char('a'), M::NONE) => {
- // vi-append-mode
- self.input_mode = InputMode::Insert;
- wrt.doing_insert();
- Cmd::Move(Movement::ForwardChar(n))
- }
- E(K::Char('A'), M::NONE) => {
- // vi-append-eol
- self.input_mode = InputMode::Insert;
- wrt.doing_insert();
- Cmd::Move(Movement::EndOfLine)
- }
- E(K::Char('b'), M::NONE) => Cmd::Move(Movement::BackwardWord(n, Word::Vi)), /* vi-prev-word */
- E(K::Char('B'), M::NONE) => Cmd::Move(Movement::BackwardWord(n, Word::Big)),
- E(K::Char('c'), M::NONE) => {
- self.input_mode = InputMode::Insert;
- match self.vi_cmd_motion(rdr, wrt, key, n)? {
- Some(mvt) => Cmd::Replace(mvt, None),
- None => Cmd::Unknown,
- }
- }
- E(K::Char('C'), M::NONE) => {
- self.input_mode = InputMode::Insert;
- Cmd::Replace(Movement::EndOfLine, None)
- }
- E(K::Char('d'), M::NONE) => match self.vi_cmd_motion(rdr, wrt, key, n)? {
- Some(mvt) => Cmd::Kill(mvt),
- None => Cmd::Unknown,
- },
- E(K::Char('D'), M::NONE) | E(K::Char('K'), M::CTRL) => Cmd::Kill(Movement::EndOfLine),
- E(K::Char('e'), M::NONE) => {
- Cmd::Move(Movement::ForwardWord(n, At::BeforeEnd, Word::Vi))
- }
- E(K::Char('E'), M::NONE) => {
- Cmd::Move(Movement::ForwardWord(n, At::BeforeEnd, Word::Big))
- }
- E(K::Char('i'), M::NONE) => {
- // vi-insertion-mode
- self.input_mode = InputMode::Insert;
- wrt.doing_insert();
- Cmd::Noop
- }
- E(K::Char('I'), M::NONE) => {
- // vi-insert-beg
- self.input_mode = InputMode::Insert;
- wrt.doing_insert();
- Cmd::Move(Movement::BeginningOfLine)
- }
- E(K::Char(c), M::NONE) if c == 'f' || c == 'F' || c == 't' || c == 'T' => {
- // vi-char-search
- let cs = self.vi_char_search(rdr, c)?;
- match cs {
- Some(cs) => Cmd::Move(Movement::ViCharSearch(n, cs)),
- None => Cmd::Unknown,
- }
- }
- E(K::Char(';'), M::NONE) => match self.last_char_search {
- Some(cs) => Cmd::Move(Movement::ViCharSearch(n, cs)),
- None => Cmd::Noop,
- },
- E(K::Char(','), M::NONE) => match self.last_char_search {
- Some(ref cs) => Cmd::Move(Movement::ViCharSearch(n, cs.opposite())),
- None => Cmd::Noop,
- },
- // TODO E(K::Char('G'), M::NONE) => Cmd::???, Move to the history line n
- E(K::Char('p'), M::NONE) => Cmd::Yank(n, Anchor::After), // vi-put
- E(K::Char('P'), M::NONE) => Cmd::Yank(n, Anchor::Before), // vi-put
- E(K::Char('r'), M::NONE) => {
- // vi-replace-char:
- let ch = rdr.next_key(false)?;
- match ch {
- E(K::Char(c), M::NONE) => Cmd::ReplaceChar(n, c),
- E::ESC => Cmd::Noop,
- _ => Cmd::Unknown,
- }
- }
- E(K::Char('R'), M::NONE) => {
- // vi-replace-mode (overwrite-mode)
- self.input_mode = InputMode::Replace;
- Cmd::Replace(Movement::ForwardChar(0), None)
- }
- E(K::Char('s'), M::NONE) => {
- // vi-substitute-char:
- self.input_mode = InputMode::Insert;
- Cmd::Replace(Movement::ForwardChar(n), None)
- }
- E(K::Char('S'), M::NONE) => {
- // vi-substitute-line:
- self.input_mode = InputMode::Insert;
- Cmd::Replace(Movement::WholeLine, None)
- }
- E(K::Char('u'), M::NONE) => Cmd::Undo(n),
- // E(K::Char('U'), M::NONE) => Cmd::???, // revert-line
- E(K::Char('w'), M::NONE) => Cmd::Move(Movement::ForwardWord(n, At::Start, Word::Vi)), /* vi-next-word */
- E(K::Char('W'), M::NONE) => Cmd::Move(Movement::ForwardWord(n, At::Start, Word::Big)), /* vi-next-word */
- // TODO move backward if eol
- E(K::Char('x'), M::NONE) => Cmd::Kill(Movement::ForwardChar(n)), // vi-delete
- E(K::Char('X'), M::NONE) => Cmd::Kill(Movement::BackwardChar(n)), // vi-rubout
- E(K::Char('y'), M::NONE) => match self.vi_cmd_motion(rdr, wrt, key, n)? {
- Some(mvt) => Cmd::ViYankTo(mvt),
- None => Cmd::Unknown,
- },
- // E(K::Char('Y'), M::NONE) => Cmd::???, // vi-yank-to
- E(K::Char('h'), M::NONE) | E(K::Char('H'), M::CTRL) | E::BACKSPACE => {
- Cmd::Move(Movement::BackwardChar(n))
- }
- E(K::Char('G'), M::CTRL) => Cmd::Abort,
- E(K::Char('l'), M::NONE) | E(K::Char(' '), M::NONE) => {
- Cmd::Move(Movement::ForwardChar(n))
- }
- E(K::Char('L'), M::CTRL) => Cmd::ClearScreen,
- E(K::Char('+'), M::NONE) | E(K::Char('j'), M::NONE) => Cmd::LineDownOrNextHistory(n),
- // TODO: move to the start of the line.
- E(K::Char('N'), M::CTRL) => Cmd::NextHistory,
- E(K::Char('-'), M::NONE) | E(K::Char('k'), M::NONE) => Cmd::LineUpOrPreviousHistory(n),
- // TODO: move to the start of the line.
- E(K::Char('P'), M::CTRL) => Cmd::PreviousHistory,
- E(K::Char('R'), M::CTRL) => {
- self.input_mode = InputMode::Insert; // TODO Validate
- Cmd::ReverseSearchHistory
- }
- E(K::Char('S'), M::CTRL) => {
- self.input_mode = InputMode::Insert; // TODO Validate
- Cmd::ForwardSearchHistory
- }
- E(K::Char('<'), M::NONE) => match self.vi_cmd_motion(rdr, wrt, key, n)? {
- Some(mvt) => Cmd::Dedent(mvt),
- None => Cmd::Unknown,
- },
- E(K::Char('>'), M::NONE) => match self.vi_cmd_motion(rdr, wrt, key, n)? {
- Some(mvt) => Cmd::Indent(mvt),
- None => Cmd::Unknown,
- },
- E::ESC => Cmd::Noop,
- _ => self.common(rdr, wrt, evt, key, n, true)?,
- };
- debug!(target: "rustyline", "Vi command: {:?}", cmd);
- if cmd.is_repeatable_change() {
- self.last_cmd = cmd.clone();
- }
- Ok(cmd)
- }
-
- fn vi_insert<R: RawReader>(
- &mut self,
- rdr: &mut R,
- wrt: &mut dyn Refresher,
- key: KeyEvent,
- ) -> Result<Cmd> {
- let evt = key.into();
- if let Some(cmd) = self.custom_binding(wrt, &evt, 0, true) {
- return Ok(if cmd.is_repeatable() {
- cmd.redo(None, wrt)
- } else {
- cmd
- });
- }
- let cmd = match key {
- E(K::Char(c), M::NONE) => {
- if self.input_mode == InputMode::Replace {
- Cmd::Overwrite(c)
- } else {
- Cmd::SelfInsert(1, c)
- }
- }
- E(K::Char('H'), M::CTRL) | E::BACKSPACE => Cmd::Kill(Movement::BackwardChar(1)),
- E(K::BackTab, M::NONE) => Cmd::CompleteBackward,
- E(K::Tab, M::NONE) => Cmd::Complete,
- // Don't complete hints when the cursor is not at the end of a line
- E(K::Right, M::NONE) if wrt.has_hint() && wrt.is_cursor_at_end() => Cmd::CompleteHint,
- E(K::Char(k), M::ALT) => {
- debug!(target: "rustyline", "Vi fast command mode: {}", k);
- self.input_mode = InputMode::Command;
- wrt.done_inserting();
-
- self.vi_command(rdr, wrt, E(K::Char(k), M::NONE))?
- }
- E::ESC => {
- // vi-movement-mode/vi-command-mode
- self.input_mode = InputMode::Command;
- wrt.done_inserting();
- Cmd::Move(Movement::BackwardChar(1))
- }
- _ => self.common(rdr, wrt, evt, key, 1, true)?,
- };
- debug!(target: "rustyline", "Vi insert: {:?}", cmd);
- if cmd.is_repeatable_change() {
- if let (Cmd::Replace(..), Cmd::SelfInsert(..)) = (&self.last_cmd, &cmd) {
- // replacing...
- } else if let (Cmd::SelfInsert(..), Cmd::SelfInsert(..)) = (&self.last_cmd, &cmd) {
- // inserting...
- } else {
- self.last_cmd = cmd.clone();
- }
- }
- Ok(cmd)
- }
-
- fn vi_cmd_motion<R: RawReader>(
- &mut self,
- rdr: &mut R,
- wrt: &mut dyn Refresher,
- key: KeyEvent,
- n: RepeatCount,
- ) -> Result<Option<Movement>> {
- let mut mvt = rdr.next_key(false)?;
- if mvt == key {
- return Ok(Some(Movement::WholeLine));
- }
- let mut n = n;
- if let E(K::Char(digit @ '1'..='9'), M::NONE) = mvt {
- // vi-arg-digit
- mvt = self.vi_arg_digit(rdr, wrt, digit)?;
- n = self.vi_num_args().saturating_mul(n);
- }
- Ok(match mvt {
- E(K::Char('$'), M::NONE) => Some(Movement::EndOfLine),
- E(K::Char('0'), M::NONE) => Some(Movement::BeginningOfLine),
- E(K::Char('^'), M::NONE) => Some(Movement::ViFirstPrint),
- E(K::Char('b'), M::NONE) => Some(Movement::BackwardWord(n, Word::Vi)),
- E(K::Char('B'), M::NONE) => Some(Movement::BackwardWord(n, Word::Big)),
- E(K::Char('e'), M::NONE) => Some(Movement::ForwardWord(n, At::AfterEnd, Word::Vi)),
- E(K::Char('E'), M::NONE) => Some(Movement::ForwardWord(n, At::AfterEnd, Word::Big)),
- E(K::Char(c), M::NONE) if c == 'f' || c == 'F' || c == 't' || c == 'T' => {
- let cs = self.vi_char_search(rdr, c)?;
- cs.map(|cs| Movement::ViCharSearch(n, cs))
- }
- E(K::Char(';'), M::NONE) => self
- .last_char_search
- .map(|cs| Movement::ViCharSearch(n, cs)),
- E(K::Char(','), M::NONE) => self
- .last_char_search
- .map(|cs| Movement::ViCharSearch(n, cs.opposite())),
- E(K::Char('h'), M::NONE) | E(K::Char('H'), M::CTRL) | E::BACKSPACE => {
- Some(Movement::BackwardChar(n))
- }
- E(K::Char('l'), M::NONE) | E(K::Char(' '), M::NONE) => Some(Movement::ForwardChar(n)),
- E(K::Char('j'), M::NONE) | E(K::Char('+'), M::NONE) => Some(Movement::LineDown(n)),
- E(K::Char('k'), M::NONE) | E(K::Char('-'), M::NONE) => Some(Movement::LineUp(n)),
- E(K::Char('w'), M::NONE) => {
- // 'cw' is 'ce'
- if key == E(K::Char('c'), M::NONE) {
- Some(Movement::ForwardWord(n, At::AfterEnd, Word::Vi))
- } else {
- Some(Movement::ForwardWord(n, At::Start, Word::Vi))
- }
- }
- E(K::Char('W'), M::NONE) => {
- // 'cW' is 'cE'
- if key == E(K::Char('c'), M::NONE) {
- Some(Movement::ForwardWord(n, At::AfterEnd, Word::Big))
- } else {
- Some(Movement::ForwardWord(n, At::Start, Word::Big))
- }
- }
- _ => None,
- })
- }
-
- fn vi_char_search<R: RawReader>(
- &mut self,
- rdr: &mut R,
- cmd: char,
- ) -> Result<Option<CharSearch>> {
- let ch = rdr.next_key(false)?;
- Ok(match ch {
- E(K::Char(ch), M::NONE) => {
- let cs = match cmd {
- 'f' => CharSearch::Forward(ch),
- 't' => CharSearch::ForwardBefore(ch),
- 'F' => CharSearch::Backward(ch),
- 'T' => CharSearch::BackwardAfter(ch),
- _ => unreachable!(),
- };
- self.last_char_search = Some(cs);
- Some(cs)
- }
- _ => None,
- })
- }
-
- fn common<R: RawReader>(
- &mut self,
- rdr: &mut R,
- wrt: &mut dyn Refresher,
- mut evt: Event,
- key: KeyEvent,
- n: RepeatCount,
- positive: bool,
- ) -> Result<Cmd> {
- Ok(match key {
- E(K::Home, M::NONE) => Cmd::Move(Movement::BeginningOfLine),
- E(K::Left, M::NONE) => {
- if positive {
- Cmd::Move(Movement::BackwardChar(n))
- } else {
- Cmd::Move(Movement::ForwardChar(n))
- }
- }
- E(K::Char('C'), M::CTRL) => Cmd::Interrupt,
- E(K::Char('D'), M::CTRL) => Cmd::EndOfFile,
- E(K::Delete, M::NONE) => {
- if positive {
- Cmd::Kill(Movement::ForwardChar(n))
- } else {
- Cmd::Kill(Movement::BackwardChar(n))
- }
- }
- E(K::End, M::NONE) => Cmd::Move(Movement::EndOfLine),
- E(K::Right, M::NONE) => {
- if positive {
- Cmd::Move(Movement::ForwardChar(n))
- } else {
- Cmd::Move(Movement::BackwardChar(n))
- }
- }
- E(K::Char('J'), M::CTRL) | E::ENTER => Cmd::AcceptOrInsertLine {
- accept_in_the_middle: true,
- },
- E(K::Down, M::NONE) => Cmd::LineDownOrNextHistory(1),
- E(K::Up, M::NONE) => Cmd::LineUpOrPreviousHistory(1),
- E(K::Char('R'), M::CTRL) => Cmd::ReverseSearchHistory,
- // most terminals override Ctrl+S to suspend execution
- E(K::Char('S'), M::CTRL) => Cmd::ForwardSearchHistory,
- E(K::Char('T'), M::CTRL) => Cmd::TransposeChars,
- E(K::Char('U'), M::CTRL) => {
- if positive {
- Cmd::Kill(Movement::BeginningOfLine)
- } else {
- Cmd::Kill(Movement::EndOfLine)
- }
- }
- // most terminals override Ctrl+Q to resume execution
- E(K::Char('Q'), M::CTRL) => Cmd::QuotedInsert,
- #[cfg(not(windows))]
- E(K::Char('V'), M::CTRL) => Cmd::QuotedInsert,
- #[cfg(windows)]
- E(K::Char('V'), M::CTRL) => Cmd::PasteFromClipboard,
- E(K::Char('W'), M::CTRL) => {
- if positive {
- Cmd::Kill(Movement::BackwardWord(n, Word::Big))
- } else {
- Cmd::Kill(Movement::ForwardWord(n, At::AfterEnd, Word::Big))
- }
- }
- E(K::Char('Y'), M::CTRL) => {
- if positive {
- Cmd::Yank(n, Anchor::Before)
- } else {
- Cmd::Unknown // TODO Validate
- }
- }
- E(K::Char('Z'), M::CTRL) => Cmd::Suspend,
- E(K::Char('_'), M::CTRL) => Cmd::Undo(n),
- E(K::UnknownEscSeq, M::NONE) => Cmd::Noop,
- E(K::BracketedPasteStart, M::NONE) => {
- let paste = rdr.read_pasted_text()?;
- Cmd::Insert(1, paste)
- }
- _ => self
- .custom_seq_binding(rdr, wrt, &mut evt, n, positive)?
- .unwrap_or(Cmd::Unknown),
- })
- }
-
- fn num_args(&mut self) -> i16 {
- let num_args = match self.num_args {
- 0 => 1,
- _ => self.num_args,
- };
- self.num_args = 0;
- num_args
- }
-
- #[allow(clippy::cast_sign_loss)]
- fn emacs_num_args(&mut self) -> (RepeatCount, bool) {
- let num_args = self.num_args();
- if num_args < 0 {
- if let (n, false) = num_args.overflowing_abs() {
- (n as RepeatCount, false)
- } else {
- (RepeatCount::max_value(), false)
- }
- } else {
- (num_args as RepeatCount, true)
- }
- }
-
- #[allow(clippy::cast_sign_loss)]
- fn vi_num_args(&mut self) -> RepeatCount {
- let num_args = self.num_args();
- if num_args < 0 {
- unreachable!()
- } else {
- num_args.abs() as RepeatCount
- }
- }
-}
diff --git a/vendor/rustyline-8.2.0/src/keys.rs b/vendor/rustyline-8.2.0/src/keys.rs
deleted file mode 100644
index 6a250ae..0000000
--- a/vendor/rustyline-8.2.0/src/keys.rs
+++ /dev/null
@@ -1,202 +0,0 @@
-//! Key constants
-
-/// Input key pressed and modifiers
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct KeyEvent(pub KeyCode, pub Modifiers);
-
-impl KeyEvent {
- /// Constant value representing an unmodified press of `KeyCode::Backspace`.
- pub(crate) const BACKSPACE: Self = Self(KeyCode::Backspace, Modifiers::NONE);
- /// Constant value representing an unmodified press of `KeyCode::Enter`.
- pub(crate) const ENTER: Self = Self(KeyCode::Enter, Modifiers::NONE);
- /// Constant value representing an unmodified press of `KeyCode::Esc`.
- pub(crate) const ESC: Self = Self(KeyCode::Esc, Modifiers::NONE);
-
- /// Constructor from `char` and modifiers
- pub fn new(c: char, mut mods: Modifiers) -> Self {
- use {KeyCode as K, KeyEvent as E, Modifiers as M};
-
- if !c.is_control() {
- if !mods.is_empty() {
- mods.remove(M::SHIFT); // TODO Validate: no SHIFT even if
- // `c` is uppercase
- }
- return E(K::Char(c), mods);
- }
- #[allow(clippy::match_same_arms)]
- match c {
- '\x00' => E(K::Char(' '), mods | M::CTRL),
- '\x01' => E(K::Char('A'), mods | M::CTRL),
- '\x02' => E(K::Char('B'), mods | M::CTRL),
- '\x03' => E(K::Char('C'), mods | M::CTRL),
- '\x04' => E(K::Char('D'), mods | M::CTRL),
- '\x05' => E(K::Char('E'), mods | M::CTRL),
- '\x06' => E(K::Char('F'), mods | M::CTRL),
- '\x07' => E(K::Char('G'), mods | M::CTRL),
- '\x08' => E(K::Backspace, mods), // '\b'
- '\x09' => {
- // '\t'
- if mods.contains(M::SHIFT) {
- mods.remove(M::SHIFT);
- E(K::BackTab, mods)
- } else {
- E(K::Tab, mods)
- }
- }
- '\x0a' => E(K::Char('J'), mods | M::CTRL), // '\n' (10)
- '\x0b' => E(K::Char('K'), mods | M::CTRL),
- '\x0c' => E(K::Char('L'), mods | M::CTRL),
- '\x0d' => E(K::Enter, mods), // '\r' (13)
- '\x0e' => E(K::Char('N'), mods | M::CTRL),
- '\x0f' => E(K::Char('O'), mods | M::CTRL),
- '\x10' => E(K::Char('P'), mods | M::CTRL),
- '\x11' => E(K::Char('Q'), mods | M::CTRL),
- '\x12' => E(K::Char('R'), mods | M::CTRL),
- '\x13' => E(K::Char('S'), mods | M::CTRL),
- '\x14' => E(K::Char('T'), mods | M::CTRL),
- '\x15' => E(K::Char('U'), mods | M::CTRL),
- '\x16' => E(K::Char('V'), mods | M::CTRL),
- '\x17' => E(K::Char('W'), mods | M::CTRL),
- '\x18' => E(K::Char('X'), mods | M::CTRL),
- '\x19' => E(K::Char('Y'), mods | M::CTRL),
- '\x1a' => E(K::Char('Z'), mods | M::CTRL),
- '\x1b' => E(K::Esc, mods), // Ctrl-[
- '\x1c' => E(K::Char('\\'), mods | M::CTRL),
- '\x1d' => E(K::Char(']'), mods | M::CTRL),
- '\x1e' => E(K::Char('^'), mods | M::CTRL),
- '\x1f' => E(K::Char('_'), mods | M::CTRL),
- '\x7f' => E(K::Backspace, mods), // Rubout
- '\u{9b}' => E(K::Esc, mods | M::SHIFT),
- _ => E(K::Null, mods),
- }
- }
-
- /// Constructor from `char` with Ctrl modifier
- pub fn ctrl(c: char) -> Self {
- Self::new(c, Modifiers::CTRL)
- }
-
- /// Constructor from `char` with Alt modifier
- pub fn alt(c: char) -> Self {
- Self::new(c, Modifiers::ALT)
- }
-
- /// ctrl-a => ctrl-A (uppercase)
- /// shift-A => A (no SHIFT modifier)
- /// shift-Tab => BackTab
- pub fn normalize(e: Self) -> Self {
- use {KeyCode as K, KeyEvent as E, Modifiers as M};
-
- match e {
- E(K::Char(c), m) if c.is_ascii_control() => Self::new(c, m),
- E(K::Char(c), m) if c.is_ascii_lowercase() && m.contains(M::CTRL) => {
- E(K::Char(c.to_ascii_uppercase()), m)
- }
- E(K::Char(c), m) if c.is_ascii_uppercase() && m.contains(M::SHIFT) => {
- E(K::Char(c), m ^ M::SHIFT)
- }
- E(K::Tab, m) if m.contains(M::SHIFT) => E(K::BackTab, m ^ M::SHIFT),
- _ => e,
- }
- }
-}
-
-impl From<char> for KeyEvent {
- fn from(c: char) -> Self {
- Self::new(c, Modifiers::NONE)
- }
-}
-
-/// Input key pressed
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-#[non_exhaustive]
-pub enum KeyCode {
- /// Unsupported escape sequence (on unix platform)
- UnknownEscSeq,
- /// ⌫ or Ctrl-H
- Backspace,
- /// ⇤ (usually Shift-Tab)
- BackTab,
- /// Paste (on unix platform)
- BracketedPasteStart,
- /// Paste (on unix platform)
- BracketedPasteEnd,
- /// Single char
- Char(char),
- /// ⌦
- Delete,
- /// ↓ arrow key
- Down,
- /// ⇲
- End,
- /// ↵ or Ctrl-M
- Enter,
- /// Escape or Ctrl-[
- Esc,
- /// Function key
- F(u8),
- /// ⇱
- Home,
- /// Insert key
- Insert,
- /// ← arrow key
- Left,
- /// \0
- Null,
- /// ⇟
- PageDown,
- /// ⇞
- PageUp,
- /// → arrow key
- Right,
- /// ⇥ or Ctrl-I
- Tab,
- /// ↑ arrow key
- Up,
-}
-
-bitflags::bitflags! {
- /// The set of modifier keys that were triggered along with a key press.
- pub struct Modifiers: u8 {
- /// Control modifier
- const CTRL = 1<<3;
- /// Escape or Alt modifier
- const ALT = 1<<2;
- /// Shift modifier
- const SHIFT = 1<<1;
-
- /// No modifier
- const NONE = 0;
- /// Ctrl + Shift
- const CTRL_SHIFT = Self::CTRL.bits | Self::SHIFT.bits;
- /// Alt + Shift
- const ALT_SHIFT = Self::ALT.bits | Self::SHIFT.bits;
- /// Ctrl + Alt
- const CTRL_ALT = Self::CTRL.bits | Self::ALT.bits;
- /// Ctrl + Alt + Shift
- const CTRL_ALT_SHIFT = Self::CTRL.bits | Self::ALT.bits | Self::SHIFT.bits;
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::{KeyCode as K, KeyEvent as E, Modifiers as M};
-
- #[test]
- fn new() {
- assert_eq!(E::ESC, E::new('\x1b', M::NONE));
- }
-
- #[test]
- fn from() {
- assert_eq!(E(K::Tab, M::NONE), E::from('\t'));
- }
-
- #[test]
- fn normalize() {
- assert_eq!(E::ctrl('A'), E::normalize(E(K::Char('\x01'), M::NONE)));
- assert_eq!(E::ctrl('A'), E::normalize(E::ctrl('a')));
- assert_eq!(E::from('A'), E::normalize(E(K::Char('A'), M::SHIFT)));
- assert_eq!(E(K::BackTab, M::NONE), E::normalize(E(K::Tab, M::SHIFT)));
- }
-}
diff --git a/vendor/rustyline-8.2.0/src/kill_ring.rs b/vendor/rustyline-8.2.0/src/kill_ring.rs
deleted file mode 100644
index 71899f1..0000000
--- a/vendor/rustyline-8.2.0/src/kill_ring.rs
+++ /dev/null
@@ -1,230 +0,0 @@
-//! Kill Ring management
-use crate::line_buffer::{DeleteListener, Direction};
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-enum Action {
- Kill,
- Yank(usize),
- Other,
-}
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum Mode {
- Append,
- Prepend,
-}
-
-pub struct KillRing {
- slots: Vec<String>,
- // where we are in the kill ring
- index: usize,
- // whether or not the last command was a kill or a yank
- last_action: Action,
- killing: bool,
-}
-
-impl KillRing {
- /// Create a new kill-ring of the given `size`.
- pub fn new(size: usize) -> Self {
- Self {
- slots: Vec::with_capacity(size),
- index: 0,
- last_action: Action::Other,
- killing: false,
- }
- }
-
- /// Reset `last_action` state.
- pub fn reset(&mut self) {
- self.last_action = Action::Other;
- }
-
- /// Add `text` to the kill-ring.
- pub fn kill(&mut self, text: &str, dir: Mode) {
- if let Action::Kill = self.last_action {
- if self.slots.capacity() == 0 {
- // disabled
- return;
- }
- match dir {
- Mode::Append => self.slots[self.index].push_str(text),
- Mode::Prepend => self.slots[self.index].insert_str(0, text),
- };
- } else {
- self.last_action = Action::Kill;
- if self.slots.capacity() == 0 {
- // disabled
- return;
- }
- if self.index == self.slots.capacity() - 1 {
- // full
- self.index = 0;
- } else if !self.slots.is_empty() {
- self.index += 1;
- }
- if self.index == self.slots.len() {
- self.slots.push(String::from(text))
- } else {
- self.slots[self.index] = String::from(text);
- }
- }
- }
-
- /// Yank previously killed text.
- /// Return `None` when kill-ring is empty.
- pub fn yank(&mut self) -> Option<&String> {
- if self.slots.is_empty() {
- None
- } else {
- self.last_action = Action::Yank(self.slots[self.index].len());
- Some(&self.slots[self.index])
- }
- }
-
- /// Yank killed text stored in previous slot.
- /// Return `None` when the previous command was not a yank.
- pub fn yank_pop(&mut self) -> Option<(usize, &String)> {
- match self.last_action {
- Action::Yank(yank_size) => {
- if self.slots.is_empty() {
- return None;
- }
- if self.index == 0 {
- self.index = self.slots.len() - 1;
- } else {
- self.index -= 1;
- }
- self.last_action = Action::Yank(self.slots[self.index].len());
- Some((yank_size, &self.slots[self.index]))
- }
- _ => None,
- }
- }
-}
-
-impl DeleteListener for KillRing {
- fn start_killing(&mut self) {
- self.killing = true;
- }
-
- fn delete(&mut self, _: usize, string: &str, dir: Direction) {
- if !self.killing {
- return;
- }
- let mode = match dir {
- Direction::Forward => Mode::Append,
- Direction::Backward => Mode::Prepend,
- };
- self.kill(string, mode);
- }
-
- fn stop_killing(&mut self) {
- self.killing = false;
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::{Action, KillRing, Mode};
-
- #[test]
- fn disabled() {
- let mut kill_ring = KillRing::new(0);
- kill_ring.kill("text", Mode::Append);
- assert!(kill_ring.slots.is_empty());
- assert_eq!(0, kill_ring.index);
- assert_eq!(Action::Kill, kill_ring.last_action);
-
- assert_eq!(None, kill_ring.yank());
- assert_eq!(Action::Kill, kill_ring.last_action);
- }
-
- #[test]
- fn one_kill() {
- let mut kill_ring = KillRing::new(2);
- kill_ring.kill("word1", Mode::Append);
- assert_eq!(0, kill_ring.index);
- assert_eq!(1, kill_ring.slots.len());
- assert_eq!("word1", kill_ring.slots[0]);
- assert_eq!(Action::Kill, kill_ring.last_action);
- }
-
- #[test]
- fn kill_append() {
- let mut kill_ring = KillRing::new(2);
- kill_ring.kill("word1", Mode::Append);
- kill_ring.kill(" word2", Mode::Append);
- assert_eq!(0, kill_ring.index);
- assert_eq!(1, kill_ring.slots.len());
- assert_eq!("word1 word2", kill_ring.slots[0]);
- assert_eq!(Action::Kill, kill_ring.last_action);
- }
-
- #[test]
- fn kill_backward() {
- let mut kill_ring = KillRing::new(2);
- kill_ring.kill("word1", Mode::Prepend);
- kill_ring.kill("word2 ", Mode::Prepend);
- assert_eq!(0, kill_ring.index);
- assert_eq!(1, kill_ring.slots.len());
- assert_eq!("word2 word1", kill_ring.slots[0]);
- assert_eq!(Action::Kill, kill_ring.last_action);
- }
-
- #[test]
- fn kill_other_kill() {
- let mut kill_ring = KillRing::new(2);
- kill_ring.kill("word1", Mode::Append);
- kill_ring.reset();
- kill_ring.kill("word2", Mode::Append);
- assert_eq!(1, kill_ring.index);
- assert_eq!(2, kill_ring.slots.len());
- assert_eq!("word1", kill_ring.slots[0]);
- assert_eq!("word2", kill_ring.slots[1]);
- assert_eq!(Action::Kill, kill_ring.last_action);
- }
-
- #[test]
- fn many_kill() {
- let mut kill_ring = KillRing::new(2);
- kill_ring.kill("word1", Mode::Append);
- kill_ring.reset();
- kill_ring.kill("word2", Mode::Append);
- kill_ring.reset();
- kill_ring.kill("word3", Mode::Append);
- kill_ring.reset();
- kill_ring.kill("word4", Mode::Append);
- assert_eq!(1, kill_ring.index);
- assert_eq!(2, kill_ring.slots.len());
- assert_eq!("word3", kill_ring.slots[0]);
- assert_eq!("word4", kill_ring.slots[1]);
- assert_eq!(Action::Kill, kill_ring.last_action);
- }
-
- #[test]
- fn yank() {
- let mut kill_ring = KillRing::new(2);
- kill_ring.kill("word1", Mode::Append);
- kill_ring.reset();
- kill_ring.kill("word2", Mode::Append);
-
- assert_eq!(Some(&"word2".to_owned()), kill_ring.yank());
- assert_eq!(Action::Yank(5), kill_ring.last_action);
- assert_eq!(Some(&"word2".to_owned()), kill_ring.yank());
- assert_eq!(Action::Yank(5), kill_ring.last_action);
- }
-
- #[test]
- fn yank_pop() {
- let mut kill_ring = KillRing::new(2);
- kill_ring.kill("word1", Mode::Append);
- kill_ring.reset();
- kill_ring.kill("longword2", Mode::Append);
-
- assert_eq!(None, kill_ring.yank_pop());
- kill_ring.yank();
- assert_eq!(Some((9, &"word1".to_owned())), kill_ring.yank_pop());
- assert_eq!(Some((5, &"longword2".to_owned())), kill_ring.yank_pop());
- assert_eq!(Some((9, &"word1".to_owned())), kill_ring.yank_pop());
- }
-}
diff --git a/vendor/rustyline-8.2.0/src/layout.rs b/vendor/rustyline-8.2.0/src/layout.rs
deleted file mode 100644
index 5679ec1..0000000
--- a/vendor/rustyline-8.2.0/src/layout.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-use std::cmp::{Ord, Ordering, PartialOrd};
-
-#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
-pub struct Position {
- pub col: usize, // The leftmost column is number 0.
- pub row: usize, // The highest row is number 0.
-}
-
-impl PartialOrd for Position {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- Some(self.cmp(other))
- }
-}
-
-impl Ord for Position {
- fn cmp(&self, other: &Self) -> Ordering {
- match self.row.cmp(&other.row) {
- Ordering::Equal => self.col.cmp(&other.col),
- o => o,
- }
- }
-}
-
-#[derive(Debug, Default)]
-pub struct Layout {
- /// Prompt Unicode/visible width and height
- pub prompt_size: Position,
- pub default_prompt: bool,
- /// Cursor position (relative to the start of the prompt)
- pub cursor: Position,
- /// Number of rows used so far (from start of prompt to end of input)
- pub end: Position,
-}
diff --git a/vendor/rustyline-8.2.0/src/lib.rs b/vendor/rustyline-8.2.0/src/lib.rs
deleted file mode 100644
index 843a7b8..0000000
--- a/vendor/rustyline-8.2.0/src/lib.rs
+++ /dev/null
@@ -1,884 +0,0 @@
-//! Readline for Rust
-//!
-//! This implementation is based on [Antirez's
-//! Linenoise](https://github.com/antirez/linenoise)
-//!
-//! # Example
-//!
-//! Usage
-//!
-//! ```
-//! let mut rl = rustyline::Editor::<()>::new();
-//! let readline = rl.readline(">> ");
-//! match readline {
-//! Ok(line) => println!("Line: {:?}", line),
-//! Err(_) => println!("No input"),
-//! }
-//! ```
-#![warn(missing_docs)]
-
-mod binding;
-mod command;
-pub mod completion;
-pub mod config;
-mod edit;
-pub mod error;
-pub mod highlight;
-pub mod hint;
-pub mod history;
-mod keymap;
-mod keys;
-mod kill_ring;
-mod layout;
-pub mod line_buffer;
-mod tty;
-mod undo;
-pub mod validate;
-
-use std::fmt;
-use std::io::{self, Write};
-use std::path::Path;
-use std::result;
-use std::sync::{Arc, Mutex, RwLock};
-
-use log::debug;
-use radix_trie::Trie;
-use unicode_width::UnicodeWidthStr;
-
-use crate::tty::{RawMode, Renderer, Term, Terminal};
-
-pub use crate::binding::{ConditionalEventHandler, Event, EventContext, EventHandler};
-use crate::completion::{longest_common_prefix, Candidate, Completer};
-pub use crate::config::{
- ColorMode, CompletionType, Config, EditMode, HistoryDuplicates, OutputStreamType,
-};
-use crate::edit::State;
-use crate::highlight::Highlighter;
-use crate::hint::Hinter;
-use crate::history::{Direction, History};
-pub use crate::keymap::{Anchor, At, CharSearch, Cmd, InputMode, Movement, RepeatCount, Word};
-use crate::keymap::{InputState, Refresher};
-pub use crate::keys::{KeyCode, KeyEvent, Modifiers};
-use crate::kill_ring::KillRing;
-
-use crate::validate::Validator;
-
-/// The error type for I/O and Linux Syscalls (Errno)
-pub type Result<T> = result::Result<T, error::ReadlineError>;
-
-/// Completes the line/word
-fn complete_line<H: Helper>(
- rdr: &mut <Terminal as Term>::Reader,
- s: &mut State<'_, '_, H>,
- input_state: &mut InputState,
- config: &Config,
-) -> Result<Option<Cmd>> {
- #[cfg(all(unix, feature = "with-fuzzy"))]
- use skim::prelude::{
- unbounded, Skim, SkimItem, SkimItemReceiver, SkimItemSender, SkimOptionsBuilder,
- };
-
- let completer = s.helper.unwrap();
- // get a list of completions
- let (start, candidates) = completer.complete(&s.line, s.line.pos(), &s.ctx)?;
- // if no completions, we are done
- if candidates.is_empty() {
- s.out.beep()?;
- Ok(None)
- } else if CompletionType::Circular == config.completion_type() {
- let mark = s.changes.borrow_mut().begin();
- // Save the current edited line before overwriting it
- let backup = s.line.as_str().to_owned();
- let backup_pos = s.line.pos();
- let mut cmd;
- let mut i = 0;
- loop {
- // Show completion or original buffer
- if i < candidates.len() {
- let candidate = candidates[i].replacement();
- // TODO we can't highlight the line buffer directly
- /*let candidate = if let Some(highlighter) = s.highlighter {
- highlighter.highlight_candidate(candidate, CompletionType::Circular)
- } else {
- Borrowed(candidate)
- };*/
- completer.update(&mut s.line, start, candidate);
- } else {
- // Restore current edited line
- s.line.update(&backup, backup_pos);
- }
- s.refresh_line()?;
-
- cmd = s.next_cmd(input_state, rdr, true)?;
- match cmd {
- Cmd::Complete => {
- i = (i + 1) % (candidates.len() + 1); // Circular
- if i == candidates.len() {
- s.out.beep()?;
- }
- }
- Cmd::CompleteBackward => {
- if i == 0 {
- i = candidates.len(); // Circular
- s.out.beep()?;
- } else {
- i = (i - 1) % (candidates.len() + 1); // Circular
- }
- }
- Cmd::Abort => {
- // Re-show original buffer
- if i < candidates.len() {
- s.line.update(&backup, backup_pos);
- s.refresh_line()?;
- }
- s.changes.borrow_mut().truncate(mark);
- return Ok(None);
- }
- _ => {
- s.changes.borrow_mut().end();
- break;
- }
- }
- }
- Ok(Some(cmd))
- } else if CompletionType::List == config.completion_type() {
- if let Some(lcp) = longest_common_prefix(&candidates) {
- // if we can extend the item, extend it
- if lcp.len() > s.line.pos() - start {
- completer.update(&mut s.line, start, lcp);
- s.refresh_line()?;
- }
- }
- // beep if ambiguous
- if candidates.len() > 1 {
- s.out.beep()?;
- } else {
- return Ok(None);
- }
- // we can't complete any further, wait for second tab
- let mut cmd = s.next_cmd(input_state, rdr, true)?;
- // if any character other than tab, pass it to the main loop
- if cmd != Cmd::Complete {
- return Ok(Some(cmd));
- }
- // move cursor to EOL to avoid overwriting the command line
- let save_pos = s.line.pos();
- s.edit_move_end()?;
- s.line.set_pos(save_pos);
- // we got a second tab, maybe show list of possible completions
- let show_completions = if candidates.len() > config.completion_prompt_limit() {
- let msg = format!("\nDisplay all {} possibilities? (y or n)", candidates.len());
- s.out.write_and_flush(msg.as_bytes())?;
- s.layout.end.row += 1;
- while cmd != Cmd::SelfInsert(1, 'y')
- && cmd != Cmd::SelfInsert(1, 'Y')
- && cmd != Cmd::SelfInsert(1, 'n')
- && cmd != Cmd::SelfInsert(1, 'N')
- && cmd != Cmd::Kill(Movement::BackwardChar(1))
- {
- cmd = s.next_cmd(input_state, rdr, false)?;
- }
- matches!(cmd, Cmd::SelfInsert(1, 'y') | Cmd::SelfInsert(1, 'Y'))
- } else {
- true
- };
- if show_completions {
- page_completions(rdr, s, input_state, &candidates)
- } else {
- s.refresh_line()?;
- Ok(None)
- }
- } else {
- // if fuzzy feature is enabled and on unix based systems check for the
- // corresponding completion_type
- #[cfg(all(unix, feature = "with-fuzzy"))]
- {
- use std::borrow::Cow;
- if CompletionType::Fuzzy == config.completion_type() {
- struct Candidate {
- index: usize,
- text: String,
- }
- impl SkimItem for Candidate {
- fn text(&self) -> Cow<str> {
- Cow::Borrowed(&self.text)
- }
- }
-
- let (tx_item, rx_item): (SkimItemSender, SkimItemReceiver) = unbounded();
-
- candidates
- .iter()
- .enumerate()
- .map(|(i, c)| Candidate {
- index: i,
- text: c.display().to_owned(),
- })
- .for_each(|c| {
- let _ = tx_item.send(Arc::new(c));
- });
- drop(tx_item); // so that skim could know when to stop waiting for more items.
-
- // setup skim and run with input options
- // will display UI for fuzzy search and return selected results
- // by default skim multi select is off so only expect one selection
-
- let options = SkimOptionsBuilder::default()
- .height(Some("20%"))
- .prompt(Some("? "))
- .reverse(true)
- .build()
- .unwrap();
-
- let selected_items = Skim::run_with(&options, Some(rx_item))
- .map(|out| out.selected_items)
- .unwrap_or_else(Vec::new);
-
- // match the first (and only) returned option with the candidate and update the
- // line otherwise only refresh line to clear the skim UI changes
- if let Some(item) = selected_items.first() {
- let item: &Candidate = (*item).as_any() // cast to Any
- .downcast_ref::<Candidate>() // downcast to concrete type
- .expect("something wrong with downcast");
- if let Some(candidate) = candidates.get(item.index) {
- completer.update(&mut s.line, start, candidate.replacement());
- }
- }
- s.refresh_line()?;
- }
- };
- Ok(None)
- }
-}
-
-/// Completes the current hint
-fn complete_hint_line<H: Helper>(s: &mut State<'_, '_, H>) -> Result<()> {
- let hint = match s.hint.as_ref() {
- Some(hint) => hint,
- None => return Ok(()),
- };
- s.line.move_end();
- if let Some(text) = hint.completion() {
- if s.line.yank(text, 1).is_none() {
- s.out.beep()?;
- }
- } else {
- s.out.beep()?;
- }
- s.refresh_line_with_msg(None)?;
- Ok(())
-}
-
-fn page_completions<C: Candidate, H: Helper>(
- rdr: &mut <Terminal as Term>::Reader,
- s: &mut State<'_, '_, H>,
- input_state: &mut InputState,
- candidates: &[C],
-) -> Result<Option<Cmd>> {
- use std::cmp;
-
- let min_col_pad = 2;
- let cols = s.out.get_columns();
- let max_width = cmp::min(
- cols,
- candidates
- .iter()
- .map(|s| s.display().width())
- .max()
- .unwrap()
- + min_col_pad,
- );
- let num_cols = cols / max_width;
-
- let mut pause_row = s.out.get_rows() - 1;
- let num_rows = (candidates.len() + num_cols - 1) / num_cols;
- let mut ab = String::new();
- for row in 0..num_rows {
- if row == pause_row {
- s.out.write_and_flush(b"\n--More--")?;
- let mut cmd = Cmd::Noop;
- while cmd != Cmd::SelfInsert(1, 'y')
- && cmd != Cmd::SelfInsert(1, 'Y')
- && cmd != Cmd::SelfInsert(1, 'n')
- && cmd != Cmd::SelfInsert(1, 'N')
- && cmd != Cmd::SelfInsert(1, 'q')
- && cmd != Cmd::SelfInsert(1, 'Q')
- && cmd != Cmd::SelfInsert(1, ' ')
- && cmd != Cmd::Kill(Movement::BackwardChar(1))
- && cmd != Cmd::AcceptLine
- && cmd != Cmd::Newline
- && !matches!(cmd, Cmd::AcceptOrInsertLine { .. })
- {
- cmd = s.next_cmd(input_state, rdr, false)?;
- }
- match cmd {
- Cmd::SelfInsert(1, 'y') | Cmd::SelfInsert(1, 'Y') | Cmd::SelfInsert(1, ' ') => {
- pause_row += s.out.get_rows() - 1;
- }
- Cmd::AcceptLine | Cmd::Newline | Cmd::AcceptOrInsertLine { .. } => {
- pause_row += 1;
- }
- _ => break,
- }
- }
- s.out.write_and_flush(b"\n")?;
- ab.clear();
- for col in 0..num_cols {
- let i = (col * num_rows) + row;
- if i < candidates.len() {
- let candidate = &candidates[i].display();
- let width = candidate.width();
- if let Some(highlighter) = s.highlighter() {
- ab.push_str(&highlighter.highlight_candidate(candidate, CompletionType::List));
- } else {
- ab.push_str(candidate);
- }
- if ((col + 1) * num_rows) + row < candidates.len() {
- for _ in width..max_width {
- ab.push(' ');
- }
- }
- }
- }
- s.out.write_and_flush(ab.as_bytes())?;
- }
- s.out.write_and_flush(b"\n")?;
- s.layout.end.row = 0; // dirty way to make clear_old_rows do nothing
- s.layout.cursor.row = 0;
- s.refresh_line()?;
- Ok(None)
-}
-
-/// Incremental search
-fn reverse_incremental_search<H: Helper>(
- rdr: &mut <Terminal as Term>::Reader,
- s: &mut State<'_, '_, H>,
- input_state: &mut InputState,
- history: &History,
-) -> Result<Option<Cmd>> {
- if history.is_empty() {
- return Ok(None);
- }
- let mark = s.changes.borrow_mut().begin();
- // Save the current edited line (and cursor position) before overwriting it
- let backup = s.line.as_str().to_owned();
- let backup_pos = s.line.pos();
-
- let mut search_buf = String::new();
- let mut history_idx = history.len() - 1;
- let mut direction = Direction::Reverse;
- let mut success = true;
-
- let mut cmd;
- // Display the reverse-i-search prompt and process chars
- loop {
- let prompt = if success {
- format!("(reverse-i-search)`{}': ", search_buf)
- } else {
- format!("(failed reverse-i-search)`{}': ", search_buf)
- };
- s.refresh_prompt_and_line(&prompt)?;
-
- cmd = s.next_cmd(input_state, rdr, true)?;
- if let Cmd::SelfInsert(_, c) = cmd {
- search_buf.push(c);
- } else {
- match cmd {
- Cmd::Kill(Movement::BackwardChar(_)) => {
- search_buf.pop();
- continue;
- }
- Cmd::ReverseSearchHistory => {
- direction = Direction::Reverse;
- if history_idx > 0 {
- history_idx -= 1;
- } else {
- success = false;
- continue;
- }
- }
- Cmd::ForwardSearchHistory => {
- direction = Direction::Forward;
- if history_idx < history.len() - 1 {
- history_idx += 1;
- } else {
- success = false;
- continue;
- }
- }
- Cmd::Abort => {
- // Restore current edited line (before search)
- s.line.update(&backup, backup_pos);
- s.refresh_line()?;
- s.changes.borrow_mut().truncate(mark);
- return Ok(None);
- }
- Cmd::Move(_) => {
- s.refresh_line()?; // restore prompt
- break;
- }
- _ => break,
- }
- }
- success = match history.search(&search_buf, history_idx, direction) {
- Some(idx) => {
- history_idx = idx;
- let entry = history.get(idx).unwrap();
- let pos = entry.find(&search_buf).unwrap();
- s.line.update(entry, pos);
- true
- }
- _ => false,
- };
- }
- s.changes.borrow_mut().end();
- Ok(Some(cmd))
-}
-
-/// Handles reading and editing the readline buffer.
-/// It will also handle special inputs in an appropriate fashion
-/// (e.g., C-c will exit readline)
-fn readline_edit<H: Helper>(
- prompt: &str,
- initial: Option<(&str, &str)>,
- editor: &mut Editor<H>,
- original_mode: &tty::Mode,
-) -> Result<String> {
- let mut stdout = editor.term.create_writer();
-
- editor.reset_kill_ring(); // TODO recreate a new kill ring vs Arc<Mutex<KillRing>>
- let ctx = Context::new(&editor.history);
- let mut s = State::new(&mut stdout, prompt, editor.helper.as_ref(), ctx);
-
- let mut input_state = InputState::new(&editor.config, Arc::clone(&editor.custom_bindings));
-
- s.line.set_delete_listener(editor.kill_ring.clone());
- s.line.set_change_listener(s.changes.clone());
-
- if let Some((left, right)) = initial {
- s.line
- .update((left.to_owned() + right).as_ref(), left.len());
- }
-
- let mut rdr = editor.term.create_reader(&editor.config)?;
- if editor.term.is_output_tty() && editor.config.check_cursor_position() {
- if let Err(e) = s.move_cursor_at_leftmost(&mut rdr) {
- if s.out.sigwinch() {
- s.out.update_size();
- } else {
- return Err(e);
- }
- }
- }
- s.refresh_line()?;
-
- loop {
- let mut cmd = s.next_cmd(&mut input_state, &mut rdr, false)?;
-
- if cmd.should_reset_kill_ring() {
- editor.reset_kill_ring();
- }
-
- // First trigger commands that need extra input
-
- if cmd == Cmd::Complete && s.helper.is_some() {
- let next = complete_line(&mut rdr, &mut s, &mut input_state, &editor.config)?;
- if let Some(next) = next {
- cmd = next;
- } else {
- continue;
- }
- }
-
- if cmd == Cmd::ReverseSearchHistory {
- // Search history backward
- let next =
- reverse_incremental_search(&mut rdr, &mut s, &mut input_state, &editor.history)?;
- if let Some(next) = next {
- cmd = next;
- } else {
- continue;
- }
- }
-
- #[cfg(unix)]
- if cmd == Cmd::Suspend {
- original_mode.disable_raw_mode()?;
- tty::suspend()?;
- let _ = editor.term.enable_raw_mode()?; // TODO original_mode may have changed
- s.refresh_line()?;
- continue;
- }
-
- #[cfg(unix)]
- if cmd == Cmd::QuotedInsert {
- // Quoted insert
- use crate::tty::RawReader;
- let c = rdr.next_char()?;
- s.edit_insert(c, 1)?;
- continue;
- }
-
- #[cfg(windows)]
- if cmd == Cmd::PasteFromClipboard {
- use crate::tty::RawReader;
- let clipboard = rdr.read_pasted_text()?;
- s.edit_yank(&input_state, &clipboard[..], Anchor::Before, 1)?;
- }
-
- // Tiny test quirk
- #[cfg(test)]
- if matches!(
- cmd,
- Cmd::AcceptLine | Cmd::Newline | Cmd::AcceptOrInsertLine { .. }
- ) {
- editor.term.cursor = s.layout.cursor.col;
- }
-
- // Execute things can be done solely on a state object
- match command::execute(cmd, &mut s, &input_state, &editor.kill_ring, &editor.config)? {
- command::Status::Proceed => continue,
- command::Status::Submit => break,
- }
- }
-
- // Move to end, in case cursor was in the middle of the line, so that
- // next thing application prints goes after the input
- s.edit_move_buffer_end()?;
-
- if cfg!(windows) {
- let _ = original_mode; // silent warning
- }
- Ok(s.line.into_string())
-}
-
-struct Guard<'m>(&'m tty::Mode);
-
-#[allow(unused_must_use)]
-impl Drop for Guard<'_> {
- fn drop(&mut self) {
- let Guard(mode) = *self;
- mode.disable_raw_mode();
- }
-}
-
-/// Readline method that will enable RAW mode, call the `readline_edit()`
-/// method and disable raw mode
-fn readline_raw<H: Helper>(
- prompt: &str,
- initial: Option<(&str, &str)>,
- editor: &mut Editor<H>,
-) -> Result<String> {
- let original_mode = editor.term.enable_raw_mode()?;
- let guard = Guard(&original_mode);
- let user_input = readline_edit(prompt, initial, editor, &original_mode);
- if editor.config.auto_add_history() {
- if let Ok(ref line) = user_input {
- editor.add_history_entry(line.as_str());
- }
- }
- drop(guard); // disable_raw_mode(original_mode)?;
- match editor.config.output_stream() {
- OutputStreamType::Stdout => writeln!(io::stdout())?,
- OutputStreamType::Stderr => writeln!(io::stderr())?,
- };
- user_input
-}
-
-fn readline_direct() -> Result<String> {
- let mut line = String::new();
- if io::stdin().read_line(&mut line)? > 0 {
- Ok(line)
- } else {
- Err(error::ReadlineError::Eof)
- }
-}
-
-/// Syntax specific helper.
-///
-/// TODO Tokenizer/parser used for both completion, suggestion, highlighting.
-/// (parse current line once)
-pub trait Helper
-where
- Self: Completer + Hinter + Highlighter + Validator,
-{
-}
-
-impl Helper for () {}
-
-impl<'h, H: ?Sized + Helper> Helper for &'h H {}
-
-/// Completion/suggestion context
-pub struct Context<'h> {
- history: &'h History,
- history_index: usize,
-}
-
-impl<'h> Context<'h> {
- /// Constructor. Visible for testing.
- pub fn new(history: &'h History) -> Self {
- Context {
- history,
- history_index: history.len(),
- }
- }
-
- /// Return an immutable reference to the history object.
- pub fn history(&self) -> &History {
- &self.history
- }
-
- /// The history index we are currently editing
- pub fn history_index(&self) -> usize {
- self.history_index
- }
-}
-
-/// Line editor
-pub struct Editor<H: Helper> {
- term: Terminal,
- history: History,
- helper: Option<H>,
- kill_ring: Arc<Mutex<KillRing>>,
- config: Config,
- custom_bindings: Arc<RwLock<Trie<Event, EventHandler>>>,
-}
-
-#[allow(clippy::new_without_default)]
-impl<H: Helper> Editor<H> {
- /// Create an editor with the default configuration
- pub fn new() -> Self {
- Self::with_config(Config::default())
- }
-
- /// Create an editor with a specific configuration.
- pub fn with_config(config: Config) -> Self {
- let term = Terminal::new(
- config.color_mode(),
- config.output_stream(),
- config.tab_stop(),
- config.bell_style(),
- config.enable_bracketed_paste(),
- );
- Self {
- term,
- history: History::with_config(config),
- helper: None,
- kill_ring: Arc::new(Mutex::new(KillRing::new(60))),
- config,
- custom_bindings: Arc::new(RwLock::new(Trie::new())),
- }
- }
-
- /// This method will read a line from STDIN and will display a `prompt`.
- ///
- /// It uses terminal-style interaction if `stdin` is connected to a
- /// terminal.
- /// Otherwise (e.g., if `stdin` is a pipe or the terminal is not supported),
- /// it uses file-style interaction.
- pub fn readline(&mut self, prompt: &str) -> Result<String> {
- self.readline_with(prompt, None)
- }
-
- /// This function behaves in the exact same manner as `readline`, except
- /// that it pre-populates the input area.
- ///
- /// The text that resides in the input area is given as a 2-tuple.
- /// The string on the left of the tuple is what will appear to the left of
- /// the cursor and the string on the right is what will appear to the
- /// right of the cursor.
- pub fn readline_with_initial(&mut self, prompt: &str, initial: (&str, &str)) -> Result<String> {
- self.readline_with(prompt, Some(initial))
- }
-
- fn readline_with(&mut self, prompt: &str, initial: Option<(&str, &str)>) -> Result<String> {
- if self.term.is_unsupported() {
- debug!(target: "rustyline", "unsupported terminal");
- // Write prompt and flush it to stdout
- let mut stdout = io::stdout();
- stdout.write_all(prompt.as_bytes())?;
- stdout.flush()?;
-
- readline_direct()
- } else if self.term.is_stdin_tty() {
- readline_raw(prompt, initial, self)
- } else {
- debug!(target: "rustyline", "stdin is not a tty");
- // Not a tty: read from file / pipe.
- readline_direct()
- }
- }
-
- /// Load the history from the specified file.
- pub fn load_history<P: AsRef<Path> + ?Sized>(&mut self, path: &P) -> Result<()> {
- self.history.load(path)
- }
-
- /// Save the history in the specified file.
- pub fn save_history<P: AsRef<Path> + ?Sized>(&mut self, path: &P) -> Result<()> {
- self.history.save(path)
- }
-
- /// Append new entries in the specified file.
- pub fn append_history<P: AsRef<Path> + ?Sized>(&mut self, path: &P) -> Result<()> {
- self.history.append(path)
- }
-
- /// Add a new entry in the history.
- pub fn add_history_entry<S: AsRef<str> + Into<String>>(&mut self, line: S) -> bool {
- self.history.add(line)
- }
-
- /// Clear history.
- pub fn clear_history(&mut self) {
- self.history.clear()
- }
-
- /// Return a mutable reference to the history object.
- pub fn history_mut(&mut self) -> &mut History {
- &mut self.history
- }
-
- /// Return an immutable reference to the history object.
- pub fn history(&self) -> &History {
- &self.history
- }
-
- /// Register a callback function to be called for tab-completion
- /// or to show hints to the user at the right of the prompt.
- pub fn set_helper(&mut self, helper: Option<H>) {
- self.helper = helper;
- }
-
- /// Return a mutable reference to the helper.
- pub fn helper_mut(&mut self) -> Option<&mut H> {
- self.helper.as_mut()
- }
-
- /// Return an immutable reference to the helper.
- pub fn helper(&self) -> Option<&H> {
- self.helper.as_ref()
- }
-
- /// Bind a sequence to a command.
- pub fn bind_sequence<E: Into<Event>, R: Into<EventHandler>>(
- &mut self,
- key_seq: E,
- handler: R,
- ) -> Option<EventHandler> {
- if let Ok(mut bindings) = self.custom_bindings.write() {
- bindings.insert(Event::normalize(key_seq.into()), handler.into())
- } else {
- None
- }
- }
-
- /// Remove a binding for the given sequence.
- pub fn unbind_sequence<E: Into<Event>>(&mut self, key_seq: E) -> Option<EventHandler> {
- if let Ok(mut bindings) = self.custom_bindings.write() {
- bindings.remove(&Event::normalize(key_seq.into()))
- } else {
- None
- }
- }
-
- /// Returns an iterator over edited lines
- /// ```
- /// let mut rl = rustyline::Editor::<()>::new();
- /// for readline in rl.iter("> ") {
- /// match readline {
- /// Ok(line) => {
- /// println!("Line: {}", line);
- /// }
- /// Err(err) => {
- /// println!("Error: {:?}", err);
- /// break;
- /// }
- /// }
- /// }
- /// ```
- pub fn iter<'a>(&'a mut self, prompt: &'a str) -> impl Iterator<Item = Result<String>> + 'a {
- Iter {
- editor: self,
- prompt,
- }
- }
-
- fn reset_kill_ring(&self) {
- let mut kill_ring = self.kill_ring.lock().unwrap();
- kill_ring.reset();
- }
-
- /// If output stream is a tty, this function returns its width and height as
- /// a number of characters.
- pub fn dimensions(&mut self) -> Option<(usize, usize)> {
- if self.term.is_output_tty() {
- let out = self.term.create_writer();
- Some((out.get_columns(), out.get_rows()))
- } else {
- None
- }
- }
-}
-
-impl<H: Helper> config::Configurer for Editor<H> {
- fn config_mut(&mut self) -> &mut Config {
- &mut self.config
- }
-
- fn set_max_history_size(&mut self, max_size: usize) {
- self.config_mut().set_max_history_size(max_size);
- self.history.set_max_len(max_size);
- }
-
- fn set_history_ignore_dups(&mut self, yes: bool) {
- self.config_mut().set_history_ignore_dups(yes);
- self.history.ignore_dups = yes;
- }
-
- fn set_history_ignore_space(&mut self, yes: bool) {
- self.config_mut().set_history_ignore_space(yes);
- self.history.ignore_space = yes;
- }
-
- fn set_color_mode(&mut self, color_mode: ColorMode) {
- self.config_mut().set_color_mode(color_mode);
- self.term.color_mode = color_mode;
- }
-}
-
-impl<H: Helper> fmt::Debug for Editor<H> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("Editor")
- .field("term", &self.term)
- .field("config", &self.config)
- .finish()
- }
-}
-
-struct Iter<'a, H: Helper> {
- editor: &'a mut Editor<H>,
- prompt: &'a str,
-}
-
-impl<'a, H: Helper> Iterator for Iter<'a, H> {
- type Item = Result<String>;
-
- fn next(&mut self) -> Option<Result<String>> {
- let readline = self.editor.readline(self.prompt);
- match readline {
- Ok(l) => Some(Ok(l)),
- Err(error::ReadlineError::Eof) => None,
- e @ Err(_) => Some(e),
- }
- }
-}
-
-#[cfg(test)]
-#[macro_use]
-extern crate assert_matches;
-#[cfg(test)]
-mod test;
-
-#[cfg(doctest)]
-doc_comment::doctest!("../README.md");
diff --git a/vendor/rustyline-8.2.0/src/line_buffer.rs b/vendor/rustyline-8.2.0/src/line_buffer.rs
deleted file mode 100644
index 8799da2..0000000
--- a/vendor/rustyline-8.2.0/src/line_buffer.rs
+++ /dev/null
@@ -1,1854 +0,0 @@
-//! Line buffer with current cursor position
-use crate::keymap::{At, CharSearch, Movement, RepeatCount, Word};
-use std::cell::RefCell;
-use std::cmp::min;
-use std::fmt;
-use std::iter;
-use std::ops::{Deref, Index, Range};
-use std::rc::Rc;
-use std::string::Drain;
-use std::sync::{Arc, Mutex};
-use unicode_segmentation::UnicodeSegmentation;
-
-/// Default maximum buffer size for the line read
-pub(crate) const MAX_LINE: usize = 4096;
-pub(crate) const INDENT: &str = " ";
-
-/// Word's case change
-#[derive(Clone, Copy)]
-pub enum WordAction {
- /// Capitalize word
- Capitalize,
- /// lowercase word
- Lowercase,
- /// uppercase word
- Uppercase,
-}
-
-/// Delete (kill) direction
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub(crate) enum Direction {
- Forward,
- Backward,
-}
-
-impl Default for Direction {
- fn default() -> Self {
- Direction::Forward
- }
-}
-
-/// Listener to be notified when some text is deleted.
-pub(crate) trait DeleteListener {
- fn start_killing(&mut self);
- fn delete(&mut self, idx: usize, string: &str, dir: Direction);
- fn stop_killing(&mut self);
-}
-
-/// Listener to be notified when the line is modified.
-pub(crate) trait ChangeListener: DeleteListener {
- fn insert_char(&mut self, idx: usize, c: char);
- fn insert_str(&mut self, idx: usize, string: &str);
- fn replace(&mut self, idx: usize, old: &str, new: &str);
-}
-
-/// Represent the current input (text and cursor position).
-///
-/// The methods do text manipulations or/and cursor movements.
-pub struct LineBuffer {
- buf: String, // Edited line buffer (rl_line_buffer)
- pos: usize, // Current cursor position (byte position) (rl_point)
- can_growth: bool, // Whether to allow dynamic growth
- dl: Option<Arc<Mutex<dyn DeleteListener>>>,
- cl: Option<Rc<RefCell<dyn ChangeListener>>>,
-}
-
-impl fmt::Debug for LineBuffer {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("LineBuffer")
- .field("buf", &self.buf)
- .field("pos", &self.pos)
- .finish()
- }
-}
-
-impl LineBuffer {
- /// Create a new line buffer with the given maximum `capacity`.
- pub fn with_capacity(capacity: usize) -> Self {
- Self {
- buf: String::with_capacity(capacity),
- pos: 0,
- can_growth: false,
- dl: None,
- cl: None,
- }
- }
-
- /// Set whether to allow dynamic allocation
- pub(crate) fn can_growth(mut self, can_growth: bool) -> Self {
- self.can_growth = can_growth;
- self
- }
-
- fn must_truncate(&self, new_len: usize) -> bool {
- !self.can_growth && new_len > self.buf.capacity()
- }
-
- #[cfg(test)]
- pub(crate) fn init(
- line: &str,
- pos: usize,
- cl: Option<Rc<RefCell<dyn ChangeListener>>>,
- ) -> Self {
- let mut lb = Self::with_capacity(MAX_LINE);
- assert!(lb.insert_str(0, line));
- lb.set_pos(pos);
- lb.cl = cl;
- lb
- }
-
- pub(crate) fn set_delete_listener(&mut self, dl: Arc<Mutex<dyn DeleteListener>>) {
- self.dl = Some(dl);
- }
-
- pub(crate) fn set_change_listener(&mut self, dl: Rc<RefCell<dyn ChangeListener>>) {
- self.cl = Some(dl);
- }
-
- /// Extracts a string slice containing the entire buffer.
- pub fn as_str(&self) -> &str {
- &self.buf
- }
-
- /// Converts a buffer into a `String` without copying or allocating.
- pub fn into_string(self) -> String {
- self.buf
- }
-
- /// Current cursor position (byte position)
- pub fn pos(&self) -> usize {
- self.pos
- }
-
- /// Set cursor position (byte position)
- pub fn set_pos(&mut self, pos: usize) {
- assert!(pos <= self.buf.len());
- self.pos = pos;
- }
-
- /// Returns the length of this buffer, in bytes.
- pub fn len(&self) -> usize {
- self.buf.len()
- }
-
- /// Returns `true` if this buffer has a length of zero.
- pub fn is_empty(&self) -> bool {
- self.buf.is_empty()
- }
-
- /// Set line content (`buf`) and cursor position (`pos`).
- pub fn update(&mut self, buf: &str, pos: usize) {
- assert!(pos <= buf.len());
- let end = self.len();
- self.drain(0..end, Direction::default());
- let max = self.buf.capacity();
- if self.must_truncate(buf.len()) {
- self.insert_str(0, &buf[..max]);
- if pos > max {
- self.pos = max;
- } else {
- self.pos = pos;
- }
- } else {
- self.insert_str(0, buf);
- self.pos = pos;
- }
- }
-
- fn end_of_line(&self) -> usize {
- if let Some(n) = self.buf[self.pos..].find('\n') {
- n + self.pos
- } else {
- self.buf.len()
- }
- }
-
- fn start_of_line(&self) -> usize {
- if let Some(i) = self.buf[..self.pos].rfind('\n') {
- // `i` is before the new line, e.g. at the end of the previous one.
- i + 1
- } else {
- 0
- }
- }
-
- /// Returns the character at current cursor position.
- pub(crate) fn grapheme_at_cursor(&self) -> Option<&str> {
- if self.pos == self.buf.len() {
- None
- } else {
- self.buf[self.pos..].graphemes(true).next()
- }
- }
-
- /// Returns the position of the character just after the current cursor
- /// position.
- pub fn next_pos(&self, n: RepeatCount) -> Option<usize> {
- if self.pos == self.buf.len() {
- return None;
- }
- self.buf[self.pos..]
- .grapheme_indices(true)
- .take(n)
- .last()
- .map(|(i, s)| i + self.pos + s.len())
- }
-
- /// Returns the position of the character just before the current cursor
- /// position.
- fn prev_pos(&self, n: RepeatCount) -> Option<usize> {
- if self.pos == 0 {
- return None;
- }
- self.buf[..self.pos]
- .grapheme_indices(true)
- .rev()
- .take(n)
- .last()
- .map(|(i, _)| i)
- }
-
- /// Insert the character `ch` at current cursor position
- /// and advance cursor position accordingly.
- /// Return `None` when maximum buffer size has been reached,
- /// `true` when the character has been appended to the end of the line.
- pub fn insert(&mut self, ch: char, n: RepeatCount) -> Option<bool> {
- let shift = ch.len_utf8() * n;
- if self.must_truncate(self.buf.len() + shift) {
- return None;
- }
- let push = self.pos == self.buf.len();
- if n == 1 {
- self.buf.insert(self.pos, ch);
- for cl in &self.cl {
- if let Ok(mut cl) = cl.try_borrow_mut() {
- cl.insert_char(self.pos, ch);
- } // Ok: while undoing, cl is borrowed. And we want to ignore
- // changes while undoing.
- }
- } else {
- let text = iter::repeat(ch).take(n).collect::<String>();
- let pos = self.pos;
- self.insert_str(pos, &text);
- }
- self.pos += shift;
- Some(push)
- }
-
- /// Yank/paste `text` at current position.
- /// Return `None` when maximum buffer size has been reached or is empty,
- /// `true` when the character has been appended to the end of the line.
- pub fn yank(&mut self, text: &str, n: RepeatCount) -> Option<bool> {
- let shift = text.len() * n;
- if text.is_empty() || self.must_truncate(self.buf.len() + shift) {
- return None;
- }
- let push = self.pos == self.buf.len();
- let pos = self.pos;
- if n == 1 {
- self.insert_str(pos, text);
- } else {
- let text = iter::repeat(text).take(n).collect::<String>();
- self.insert_str(pos, &text);
- }
- self.pos += shift;
- Some(push)
- }
-
- /// Delete previously yanked text and yank/paste `text` at current position.
- pub fn yank_pop(&mut self, yank_size: usize, text: &str) -> Option<bool> {
- let end = self.pos;
- let start = end - yank_size;
- self.drain(start..end, Direction::default());
- self.pos -= yank_size;
- self.yank(text, 1)
- }
-
- /// Move cursor on the left.
- pub fn move_backward(&mut self, n: RepeatCount) -> bool {
- match self.prev_pos(n) {
- Some(pos) => {
- self.pos = pos;
- true
- }
- None => false,
- }
- }
-
- /// Move cursor on the right.
- pub fn move_forward(&mut self, n: RepeatCount) -> bool {
- match self.next_pos(n) {
- Some(pos) => {
- self.pos = pos;
- true
- }
- None => false,
- }
- }
-
- /// Move cursor to the start of the buffer.
- pub fn move_buffer_start(&mut self) -> bool {
- if self.pos > 0 {
- self.pos = 0;
- true
- } else {
- false
- }
- }
-
- /// Move cursor to the end of the buffer.
- pub fn move_buffer_end(&mut self) -> bool {
- if self.pos == self.buf.len() {
- false
- } else {
- self.pos = self.buf.len();
- true
- }
- }
-
- /// Move cursor to the start of the line.
- pub fn move_home(&mut self) -> bool {
- let start = self.start_of_line();
- if self.pos > start {
- self.pos = start;
- true
- } else {
- false
- }
- }
-
- /// Move cursor to the end of the line.
- pub fn move_end(&mut self) -> bool {
- let end = self.end_of_line();
- if self.pos == end {
- false
- } else {
- self.pos = end;
- true
- }
- }
-
- /// Is cursor at the end of input (whitespaces after cursor is discarded)
- pub fn is_end_of_input(&self) -> bool {
- self.pos >= self.buf.trim_end().len()
- }
-
- /// Delete the character at the right of the cursor without altering the
- /// cursor position. Basically this is what happens with the "Delete"
- /// keyboard key.
- /// Return the number of characters deleted.
- pub fn delete(&mut self, n: RepeatCount) -> Option<String> {
- match self.next_pos(n) {
- Some(pos) => {
- let start = self.pos;
- let chars = self
- .drain(start..pos, Direction::Forward)
- .collect::<String>();
- Some(chars)
- }
- None => None,
- }
- }
-
- /// Delete the character at the left of the cursor.
- /// Basically that is what happens with the "Backspace" keyboard key.
- pub fn backspace(&mut self, n: RepeatCount) -> bool {
- match self.prev_pos(n) {
- Some(pos) => {
- let end = self.pos;
- self.drain(pos..end, Direction::Backward);
- self.pos = pos;
- true
- }
- None => false,
- }
- }
-
- /// Kill the text from point to the end of the line.
- pub fn kill_line(&mut self) -> bool {
- if !self.buf.is_empty() && self.pos < self.buf.len() {
- let start = self.pos;
- let end = self.end_of_line();
- if start == end {
- self.delete(1);
- } else {
- self.drain(start..end, Direction::Forward);
- }
- true
- } else {
- false
- }
- }
-
- /// Kill the text from point to the end of the buffer.
- pub fn kill_buffer(&mut self) -> bool {
- if !self.buf.is_empty() && self.pos < self.buf.len() {
- let start = self.pos;
- let end = self.buf.len();
- self.drain(start..end, Direction::Forward);
- true
- } else {
- false
- }
- }
-
- /// Kill backward from point to the beginning of the line.
- pub fn discard_line(&mut self) -> bool {
- if self.pos > 0 && !self.buf.is_empty() {
- let start = self.start_of_line();
- let end = self.pos;
- if end == start {
- self.backspace(1)
- } else {
- self.drain(start..end, Direction::Backward);
- self.pos = start;
- true
- }
- } else {
- false
- }
- }
-
- /// Kill backward from point to the beginning of the buffer.
- pub fn discard_buffer(&mut self) -> bool {
- if self.pos > 0 && !self.buf.is_empty() {
- let end = self.pos;
- self.drain(0..end, Direction::Backward);
- self.pos = 0;
- true
- } else {
- false
- }
- }
-
- /// Exchange the char before cursor with the character at cursor.
- pub fn transpose_chars(&mut self) -> bool {
- if self.pos == 0 || self.buf.graphemes(true).count() < 2 {
- return false;
- }
- if self.pos == self.buf.len() {
- self.move_backward(1);
- }
- let chars = self.delete(1).unwrap();
- self.move_backward(1);
- self.yank(&chars, 1);
- self.move_forward(1);
- true
- }
-
- /// Go left until start of word
- fn prev_word_pos(&self, pos: usize, word_def: Word, n: RepeatCount) -> Option<usize> {
- if pos == 0 {
- return None;
- }
- let mut sow = 0;
- let mut gis = self.buf[..pos].grapheme_indices(true).rev();
- 'outer: for _ in 0..n {
- sow = 0;
- let mut gj = gis.next();
- 'inner: loop {
- if let Some((j, y)) = gj {
- let gi = gis.next();
- if let Some((_, x)) = gi {
- if is_start_of_word(word_def, x, y) {
- sow = j;
- break 'inner;
- }
- gj = gi;
- } else {
- break 'outer;
- }
- } else {
- break 'outer;
- }
- }
- }
- Some(sow)
- }
-
- /// Moves the cursor to the beginning of previous word.
- pub fn move_to_prev_word(&mut self, word_def: Word, n: RepeatCount) -> bool {
- if let Some(pos) = self.prev_word_pos(self.pos, word_def, n) {
- self.pos = pos;
- true
- } else {
- false
- }
- }
-
- /// Delete the previous word, maintaining the cursor at the start of the
- /// current word.
- pub fn delete_prev_word(&mut self, word_def: Word, n: RepeatCount) -> bool {
- if let Some(pos) = self.prev_word_pos(self.pos, word_def, n) {
- let end = self.pos;
- self.drain(pos..end, Direction::Backward);
- self.pos = pos;
- true
- } else {
- false
- }
- }
-
- fn next_word_pos(&self, pos: usize, at: At, word_def: Word, n: RepeatCount) -> Option<usize> {
- if pos == self.buf.len() {
- return None;
- }
- let mut wp = 0;
- let mut gis = self.buf[pos..].grapheme_indices(true);
- let mut gi = if at == At::BeforeEnd {
- // TODO Validate
- gis.next()
- } else {
- None
- };
- 'outer: for _ in 0..n {
- wp = 0;
- gi = gis.next();
- 'inner: loop {
- if let Some((i, x)) = gi {
- let gj = gis.next();
- if let Some((j, y)) = gj {
- if at == At::Start && is_start_of_word(word_def, x, y) {
- wp = j;
- break 'inner;
- } else if at != At::Start && is_end_of_word(word_def, x, y) {
- if word_def == Word::Emacs || at == At::AfterEnd {
- wp = j;
- } else {
- wp = i;
- }
- break 'inner;
- }
- gi = gj;
- } else {
- break 'outer;
- }
- } else {
- break 'outer;
- }
- }
- }
- if wp == 0 {
- if word_def == Word::Emacs || at == At::AfterEnd {
- Some(self.buf.len())
- } else {
- match gi {
- Some((i, _)) if i != 0 => Some(i + pos),
- _ => None,
- }
- }
- } else {
- Some(wp + pos)
- }
- }
-
- /// Moves the cursor to the end of next word.
- pub fn move_to_next_word(&mut self, at: At, word_def: Word, n: RepeatCount) -> bool {
- if let Some(pos) = self.next_word_pos(self.pos, at, word_def, n) {
- self.pos = pos;
- true
- } else {
- false
- }
- }
-
- /// Moves the cursor to the same column in the line above
- pub fn move_to_line_up(&mut self, n: RepeatCount) -> bool {
- match self.buf[..self.pos].rfind('\n') {
- Some(off) => {
- let column = self.buf[off + 1..self.pos].graphemes(true).count();
-
- let mut dest_start = self.buf[..off].rfind('\n').map(|n| n + 1).unwrap_or(0);
- let mut dest_end = off;
- for _ in 1..n {
- if dest_start == 0 {
- break;
- }
- dest_end = dest_start - 1;
- dest_start = self.buf[..dest_end].rfind('\n').map(|n| n + 1).unwrap_or(0);
- }
- let gidx = self.buf[dest_start..dest_end]
- .grapheme_indices(true)
- .nth(column);
-
- self.pos = gidx.map(|(idx, _)| dest_start + idx).unwrap_or(off); // if there's no enough columns
- true
- }
- None => false,
- }
- }
-
- /// N lines up starting from the current one
- ///
- /// Fails if the cursor is on the first line
- fn n_lines_up(&self, n: RepeatCount) -> Option<(usize, usize)> {
- let mut start = if let Some(off) = self.buf[..self.pos].rfind('\n') {
- off + 1
- } else {
- return None;
- };
- let end = self.buf[self.pos..]
- .find('\n')
- .map(|x| self.pos + x + 1)
- .unwrap_or_else(|| self.buf.len());
- for _ in 0..n {
- if let Some(off) = self.buf[..start - 1].rfind('\n') {
- start = off + 1
- } else {
- start = 0;
- break;
- }
- }
- Some((start, end))
- }
-
- /// N lines down starting from the current one
- ///
- /// Fails if the cursor is on the last line
- fn n_lines_down(&self, n: RepeatCount) -> Option<(usize, usize)> {
- let mut end = if let Some(off) = self.buf[self.pos..].find('\n') {
- self.pos + off + 1
- } else {
- return None;
- };
- let start = self.buf[..self.pos].rfind('\n').unwrap_or(0);
- for _ in 0..n {
- if let Some(off) = self.buf[end..].find('\n') {
- end = end + off + 1
- } else {
- end = self.buf.len();
- break;
- };
- }
- Some((start, end))
- }
-
- /// Moves the cursor to the same column in the line above
- pub fn move_to_line_down(&mut self, n: RepeatCount) -> bool {
- match self.buf[self.pos..].find('\n') {
- Some(off) => {
- let line_start = self.buf[..self.pos].rfind('\n').map(|n| n + 1).unwrap_or(0);
- let column = self.buf[line_start..self.pos].graphemes(true).count();
- let mut dest_start = self.pos + off + 1;
- let mut dest_end = self.buf[dest_start..]
- .find('\n')
- .map(|v| dest_start + v)
- .unwrap_or_else(|| self.buf.len());
- for _ in 1..n {
- if dest_end == self.buf.len() {
- break;
- }
- dest_start = dest_end + 1;
- dest_end = self.buf[dest_start..]
- .find('\n')
- .map(|v| dest_start + v)
- .unwrap_or_else(|| self.buf.len());
- }
- self.pos = self.buf[dest_start..dest_end]
- .grapheme_indices(true)
- .nth(column)
- .map(|(idx, _)| dest_start + idx)
- .unwrap_or(dest_end); // if there's no enough columns
- debug_assert!(self.pos <= self.buf.len());
- true
- }
- None => false,
- }
- }
-
- fn search_char_pos(&self, cs: CharSearch, n: RepeatCount) -> Option<usize> {
- let mut shift = 0;
- let search_result = match cs {
- CharSearch::Backward(c) | CharSearch::BackwardAfter(c) => self.buf[..self.pos]
- .char_indices()
- .rev()
- .filter(|&(_, ch)| ch == c)
- .take(n)
- .last()
- .map(|(i, _)| i),
- CharSearch::Forward(c) | CharSearch::ForwardBefore(c) => {
- if let Some(cc) = self.grapheme_at_cursor() {
- shift = self.pos + cc.len();
- if shift < self.buf.len() {
- self.buf[shift..]
- .char_indices()
- .filter(|&(_, ch)| ch == c)
- .take(n)
- .last()
- .map(|(i, _)| i)
- } else {
- None
- }
- } else {
- None
- }
- }
- };
- search_result.map(|pos| match cs {
- CharSearch::Backward(_) => pos,
- CharSearch::BackwardAfter(c) => pos + c.len_utf8(),
- CharSearch::Forward(_) => shift + pos,
- CharSearch::ForwardBefore(_) => {
- shift + pos
- - self.buf[..shift + pos]
- .chars()
- .next_back()
- .unwrap()
- .len_utf8()
- }
- })
- }
-
- /// Move cursor to the matching character position.
- /// Return `true` when the search succeeds.
- pub fn move_to(&mut self, cs: CharSearch, n: RepeatCount) -> bool {
- if let Some(pos) = self.search_char_pos(cs, n) {
- self.pos = pos;
- true
- } else {
- false
- }
- }
-
- /// Kill from the cursor to the end of the current word,
- /// or, if between words, to the end of the next word.
- pub fn delete_word(&mut self, at: At, word_def: Word, n: RepeatCount) -> bool {
- if let Some(pos) = self.next_word_pos(self.pos, at, word_def, n) {
- let start = self.pos;
- self.drain(start..pos, Direction::Forward);
- true
- } else {
- false
- }
- }
-
- /// Delete range specified by `cs` search.
- pub fn delete_to(&mut self, cs: CharSearch, n: RepeatCount) -> bool {
- let search_result = match cs {
- CharSearch::ForwardBefore(c) => self.search_char_pos(CharSearch::Forward(c), n),
- _ => self.search_char_pos(cs, n),
- };
- if let Some(pos) = search_result {
- match cs {
- CharSearch::Backward(_) | CharSearch::BackwardAfter(_) => {
- let end = self.pos;
- self.pos = pos;
- self.drain(pos..end, Direction::Backward);
- }
- CharSearch::ForwardBefore(_) => {
- let start = self.pos;
- self.drain(start..pos, Direction::Forward);
- }
- CharSearch::Forward(c) => {
- let start = self.pos;
- self.drain(start..pos + c.len_utf8(), Direction::Forward);
- }
- };
- true
- } else {
- false
- }
- }
-
- fn skip_whitespace(&self) -> Option<usize> {
- if self.pos == self.buf.len() {
- return None;
- }
- self.buf[self.pos..]
- .grapheme_indices(true)
- .filter_map(|(i, ch)| {
- if ch.chars().all(char::is_alphanumeric) {
- Some(i)
- } else {
- None
- }
- })
- .next()
- .map(|i| i + self.pos)
- }
-
- /// Alter the next word.
- pub fn edit_word(&mut self, a: WordAction) -> bool {
- if let Some(start) = self.skip_whitespace() {
- if let Some(end) = self.next_word_pos(start, At::AfterEnd, Word::Emacs, 1) {
- if start == end {
- return false;
- }
- let word = self
- .drain(start..end, Direction::default())
- .collect::<String>();
- let result = match a {
- WordAction::Capitalize => {
- let ch = (&word).graphemes(true).next().unwrap();
- let cap = ch.to_uppercase();
- cap + &word[ch.len()..].to_lowercase()
- }
- WordAction::Lowercase => word.to_lowercase(),
- WordAction::Uppercase => word.to_uppercase(),
- };
- self.insert_str(start, &result);
- self.pos = start + result.len();
- return true;
- }
- }
- false
- }
-
- /// Transpose two words
- pub fn transpose_words(&mut self, n: RepeatCount) -> bool {
- let word_def = Word::Emacs;
- self.move_to_next_word(At::AfterEnd, word_def, n);
- let w2_end = self.pos;
- self.move_to_prev_word(word_def, 1);
- let w2_beg = self.pos;
- self.move_to_prev_word(word_def, n);
- let w1_beg = self.pos;
- self.move_to_next_word(At::AfterEnd, word_def, 1);
- let w1_end = self.pos;
- if w1_beg == w2_beg || w2_beg < w1_end {
- return false;
- }
-
- let w1 = self.buf[w1_beg..w1_end].to_owned();
-
- let w2 = self
- .drain(w2_beg..w2_end, Direction::default())
- .collect::<String>();
- self.insert_str(w2_beg, &w1);
-
- self.drain(w1_beg..w1_end, Direction::default());
- self.insert_str(w1_beg, &w2);
-
- self.pos = w2_end;
- true
- }
-
- /// Replaces the content between [`start`..`end`] with `text`
- /// and positions the cursor to the end of text.
- pub fn replace(&mut self, range: Range<usize>, text: &str) {
- let start = range.start;
- for cl in &self.cl {
- if let Ok(mut cl) = cl.try_borrow_mut() {
- cl.replace(start, self.buf.index(range.clone()), text);
- } // Ok: while undoing, cl is borrowed. And we want to ignore
- // changes while undoing.
- }
- self.buf.drain(range);
- if start == self.buf.len() {
- self.buf.push_str(text);
- } else {
- self.buf.insert_str(start, text);
- }
- self.pos = start + text.len();
- }
-
- /// Insert the `s`tring at the specified position.
- /// Return `true` if the text has been inserted at the end of the line.
- pub fn insert_str(&mut self, idx: usize, s: &str) -> bool {
- for cl in &self.cl {
- if let Ok(mut cl) = cl.try_borrow_mut() {
- cl.insert_str(idx, s);
- } // Ok: while undoing, cl is borrowed. And we want to ignore
- // changes while undoing.
- }
- if idx == self.buf.len() {
- self.buf.push_str(s);
- true
- } else {
- self.buf.insert_str(idx, s);
- false
- }
- }
-
- /// Remove the specified `range` in the line.
- pub fn delete_range(&mut self, range: Range<usize>) {
- self.set_pos(range.start);
- self.drain(range, Direction::default());
- }
-
- fn drain(&mut self, range: Range<usize>, dir: Direction) -> Drain<'_> {
- for dl in &self.dl {
- let lock = dl.try_lock();
- if let Ok(mut dl) = lock {
- dl.delete(range.start, &self.buf[range.start..range.end], dir);
- }
- }
- for cl in &self.cl {
- if let Ok(mut cl) = cl.try_borrow_mut() {
- cl.delete(range.start, &self.buf[range.start..range.end], dir);
- } // Ok: while undoing, cl is borrowed. And we want to ignore
- // changes while undoing.
- }
- self.buf.drain(range)
- }
-
- /// Return the content between current cursor position and `mvt` position.
- /// Return `None` when the buffer is empty or when the movement fails.
- pub fn copy(&self, mvt: &Movement) -> Option<String> {
- if self.is_empty() {
- return None;
- }
- match *mvt {
- Movement::WholeLine => {
- let start = self.start_of_line();
- let end = self.end_of_line();
- if start == end {
- None
- } else {
- Some(self.buf[start..self.pos].to_owned())
- }
- }
- Movement::BeginningOfLine => {
- let start = self.start_of_line();
- if self.pos == start {
- None
- } else {
- Some(self.buf[start..self.pos].to_owned())
- }
- }
- Movement::ViFirstPrint => {
- if self.pos == 0 {
- None
- } else {
- self.next_word_pos(0, At::Start, Word::Big, 1)
- .map(|pos| self.buf[pos..self.pos].to_owned())
- }
- }
- Movement::EndOfLine => {
- let end = self.end_of_line();
- if self.pos == end {
- None
- } else {
- Some(self.buf[self.pos..end].to_owned())
- }
- }
- Movement::EndOfBuffer => {
- if self.pos == self.buf.len() {
- None
- } else {
- Some(self.buf[self.pos..].to_owned())
- }
- }
- Movement::WholeBuffer => {
- if self.buf.is_empty() {
- None
- } else {
- Some(self.buf.clone())
- }
- }
- Movement::BeginningOfBuffer => {
- if self.pos == 0 {
- None
- } else {
- Some(self.buf[..self.pos].to_owned())
- }
- }
- Movement::BackwardWord(n, word_def) => self
- .prev_word_pos(self.pos, word_def, n)
- .map(|pos| self.buf[pos..self.pos].to_owned()),
- Movement::ForwardWord(n, at, word_def) => self
- .next_word_pos(self.pos, at, word_def, n)
- .map(|pos| self.buf[self.pos..pos].to_owned()),
- Movement::ViCharSearch(n, cs) => {
- let search_result = match cs {
- CharSearch::ForwardBefore(c) => self.search_char_pos(CharSearch::Forward(c), n),
- _ => self.search_char_pos(cs, n),
- };
- search_result.map(|pos| match cs {
- CharSearch::Backward(_) | CharSearch::BackwardAfter(_) => {
- self.buf[pos..self.pos].to_owned()
- }
- CharSearch::ForwardBefore(_) => self.buf[self.pos..pos].to_owned(),
- CharSearch::Forward(c) => self.buf[self.pos..pos + c.len_utf8()].to_owned(),
- })
- }
- Movement::BackwardChar(n) => self
- .prev_pos(n)
- .map(|pos| self.buf[pos..self.pos].to_owned()),
- Movement::ForwardChar(n) => self
- .next_pos(n)
- .map(|pos| self.buf[self.pos..pos].to_owned()),
- Movement::LineUp(n) => {
- if let Some((start, end)) = self.n_lines_up(n) {
- Some(self.buf[start..end].to_owned())
- } else {
- None
- }
- }
- Movement::LineDown(n) => {
- if let Some((start, end)) = self.n_lines_down(n) {
- Some(self.buf[start..end].to_owned())
- } else {
- None
- }
- }
- }
- }
-
- /// Kill range specified by `mvt`.
- pub fn kill(&mut self, mvt: &Movement) -> bool {
- let notify = !matches!(*mvt, Movement::ForwardChar(_) | Movement::BackwardChar(_));
- if notify {
- if let Some(dl) = self.dl.as_ref() {
- let mut dl = dl.lock().unwrap();
- dl.start_killing()
- }
- }
- let killed = match *mvt {
- Movement::ForwardChar(n) => {
- // Delete (forward) `n` characters at point.
- self.delete(n).is_some()
- }
- Movement::BackwardChar(n) => {
- // Delete `n` characters backward.
- self.backspace(n)
- }
- Movement::EndOfLine => {
- // Kill the text from point to the end of the line.
- self.kill_line()
- }
- Movement::WholeLine => {
- self.move_home();
- self.kill_line()
- }
- Movement::BeginningOfLine => {
- // Kill backward from point to the beginning of the line.
- self.discard_line()
- }
- Movement::BackwardWord(n, word_def) => {
- // kill `n` words backward (until start of word)
- self.delete_prev_word(word_def, n)
- }
- Movement::ForwardWord(n, at, word_def) => {
- // kill `n` words forward (until start/end of word)
- self.delete_word(at, word_def, n)
- }
- Movement::ViCharSearch(n, cs) => self.delete_to(cs, n),
- Movement::LineUp(n) => {
- if let Some((start, end)) = self.n_lines_up(n) {
- self.delete_range(start..end);
- true
- } else {
- false
- }
- }
- Movement::LineDown(n) => {
- if let Some((start, end)) = self.n_lines_down(n) {
- self.delete_range(start..end);
- true
- } else {
- false
- }
- }
- Movement::ViFirstPrint => {
- false // TODO
- }
- Movement::EndOfBuffer => {
- // Kill the text from point to the end of the buffer.
- self.kill_buffer()
- }
- Movement::BeginningOfBuffer => {
- // Kill backward from point to the beginning of the buffer.
- self.discard_buffer()
- }
- Movement::WholeBuffer => {
- self.move_buffer_start();
- self.kill_buffer()
- }
- };
- if notify {
- if let Some(dl) = self.dl.as_ref() {
- let mut dl = dl.lock().unwrap();
- dl.stop_killing()
- }
- }
- killed
- }
-
- /// Indent range specified by `mvt`.
- pub fn indent(&mut self, mvt: &Movement, amount: usize, dedent: bool) -> bool {
- let pair = match *mvt {
- // All inline operators are the same: indent current line
- Movement::WholeLine
- | Movement::BeginningOfLine
- | Movement::ViFirstPrint
- | Movement::EndOfLine
- | Movement::BackwardChar(..)
- | Movement::ForwardChar(..)
- | Movement::ViCharSearch(..) => Some((self.pos, self.pos)),
- Movement::EndOfBuffer => Some((self.pos, self.buf.len())),
- Movement::WholeBuffer => Some((0, self.buf.len())),
- Movement::BeginningOfBuffer => Some((0, self.pos)),
- Movement::BackwardWord(n, word_def) => self
- .prev_word_pos(self.pos, word_def, n)
- .map(|pos| (pos, self.pos)),
- Movement::ForwardWord(n, at, word_def) => self
- .next_word_pos(self.pos, at, word_def, n)
- .map(|pos| (self.pos, pos)),
- Movement::LineUp(n) => self.n_lines_up(n),
- Movement::LineDown(n) => self.n_lines_down(n),
- };
- let (start, end) = pair.unwrap_or((self.pos, self.pos));
- let start = self.buf[..start]
- .rfind('\n')
- .map(|pos| pos + 1)
- .unwrap_or(0);
- let end = self.buf[end..]
- .rfind('\n')
- .map(|pos| end + pos)
- .unwrap_or_else(|| self.buf.len());
- let mut index = start;
- if dedent {
- for line in self.buf[start..end].to_string().split('\n') {
- let max = line.len() - line.trim_start().len();
- let deleting = min(max, amount);
- self.drain(index..index + deleting, Default::default());
- if self.pos >= index {
- if self.pos.saturating_sub(index) < deleting {
- // don't wrap into the previous line
- self.pos = index;
- } else {
- self.pos -= deleting;
- }
- }
- index += line.len() + 1 - deleting;
- }
- } else {
- for line in self.buf[start..end].to_string().split('\n') {
- for off in (0..amount).step_by(INDENT.len()) {
- self.insert_str(index, &INDENT[..min(amount - off, INDENT.len())]);
- }
- if self.pos >= index {
- self.pos += amount;
- }
- index += amount + line.len() + 1;
- }
- }
- true
- }
-}
-
-impl Deref for LineBuffer {
- type Target = str;
-
- fn deref(&self) -> &str {
- self.as_str()
- }
-}
-
-fn is_start_of_word(word_def: Word, previous: &str, grapheme: &str) -> bool {
- (!is_word_char(word_def, previous) && is_word_char(word_def, grapheme))
- || (word_def == Word::Vi && !is_other_char(previous) && is_other_char(grapheme))
-}
-fn is_end_of_word(word_def: Word, grapheme: &str, next: &str) -> bool {
- (!is_word_char(word_def, next) && is_word_char(word_def, grapheme))
- || (word_def == Word::Vi && !is_other_char(next) && is_other_char(grapheme))
-}
-
-fn is_word_char(word_def: Word, grapheme: &str) -> bool {
- match word_def {
- Word::Emacs => grapheme.chars().all(char::is_alphanumeric),
- Word::Vi => is_vi_word_char(grapheme),
- Word::Big => !grapheme.chars().any(char::is_whitespace),
- }
-}
-fn is_vi_word_char(grapheme: &str) -> bool {
- grapheme.chars().all(char::is_alphanumeric) || grapheme == "_"
-}
-fn is_other_char(grapheme: &str) -> bool {
- !(grapheme.chars().any(char::is_whitespace) || is_vi_word_char(grapheme))
-}
-
-#[cfg(test)]
-mod test {
- use super::{ChangeListener, DeleteListener, Direction, LineBuffer, WordAction, MAX_LINE};
- use crate::keymap::{At, CharSearch, Word};
- use std::cell::RefCell;
- use std::rc::Rc;
-
- struct Listener {
- deleted_str: Option<String>,
- }
-
- impl Listener {
- fn new() -> Rc<RefCell<Listener>> {
- let l = Listener { deleted_str: None };
- Rc::new(RefCell::new(l))
- }
-
- fn assert_deleted_str_eq(&self, expected: &str) {
- let actual = self.deleted_str.as_ref().expect("no deleted string");
- assert_eq!(expected, actual)
- }
- }
-
- impl DeleteListener for Listener {
- fn start_killing(&mut self) {}
-
- fn delete(&mut self, _: usize, string: &str, _: Direction) {
- self.deleted_str = Some(string.to_owned());
- }
-
- fn stop_killing(&mut self) {}
- }
- impl ChangeListener for Listener {
- fn insert_char(&mut self, _: usize, _: char) {}
-
- fn insert_str(&mut self, _: usize, _: &str) {}
-
- fn replace(&mut self, _: usize, _: &str, _: &str) {}
- }
-
- #[test]
- fn next_pos() {
- let s = LineBuffer::init("ö̲g̈", 0, None);
- assert_eq!(7, s.len());
- let pos = s.next_pos(1);
- assert_eq!(Some(4), pos);
-
- let s = LineBuffer::init("ö̲g̈", 4, None);
- let pos = s.next_pos(1);
- assert_eq!(Some(7), pos);
- }
-
- #[test]
- fn prev_pos() {
- let s = LineBuffer::init("ö̲g̈", 4, None);
- assert_eq!(7, s.len());
- let pos = s.prev_pos(1);
- assert_eq!(Some(0), pos);
-
- let s = LineBuffer::init("ö̲g̈", 7, None);
- let pos = s.prev_pos(1);
- assert_eq!(Some(4), pos);
- }
-
- #[test]
- fn insert() {
- let mut s = LineBuffer::with_capacity(MAX_LINE);
- let push = s.insert('α', 1).unwrap();
- assert_eq!("α", s.buf);
- assert_eq!(2, s.pos);
- assert!(push);
-
- let push = s.insert('ß', 1).unwrap();
- assert_eq!("αß", s.buf);
- assert_eq!(4, s.pos);
- assert!(push);
-
- s.pos = 0;
- let push = s.insert('γ', 1).unwrap();
- assert_eq!("γαß", s.buf);
- assert_eq!(2, s.pos);
- assert!(!push);
- }
-
- #[test]
- fn yank_after() {
- let mut s = LineBuffer::init("αß", 2, None);
- s.move_forward(1);
- let ok = s.yank("γδε", 1);
- assert_eq!(Some(true), ok);
- assert_eq!("αßγδε", s.buf);
- assert_eq!(10, s.pos);
- }
-
- #[test]
- fn yank_before() {
- let mut s = LineBuffer::init("αε", 2, None);
- let ok = s.yank("ßγδ", 1);
- assert_eq!(Some(false), ok);
- assert_eq!("αßγδε", s.buf);
- assert_eq!(8, s.pos);
- }
-
- #[test]
- fn moves() {
- let mut s = LineBuffer::init("αß", 4, None);
- let ok = s.move_backward(1);
- assert_eq!("αß", s.buf);
- assert_eq!(2, s.pos);
- assert!(ok);
-
- let ok = s.move_forward(1);
- assert_eq!("αß", s.buf);
- assert_eq!(4, s.pos);
- assert!(ok);
-
- let ok = s.move_home();
- assert_eq!("αß", s.buf);
- assert_eq!(0, s.pos);
- assert!(ok);
-
- let ok = s.move_end();
- assert_eq!("αß", s.buf);
- assert_eq!(4, s.pos);
- assert!(ok);
- }
-
- #[test]
- fn move_home_end_multiline() {
- let text = "αa\nsdf ßc\nasdf";
- let mut s = LineBuffer::init(text, 7, None);
- let ok = s.move_home();
- assert_eq!(text, s.buf);
- assert_eq!(4, s.pos);
- assert!(ok);
-
- let ok = s.move_home();
- assert_eq!(text, s.buf);
- assert_eq!(4, s.pos);
- assert!(!ok);
-
- let ok = s.move_end();
- assert_eq!(text, s.buf);
- assert_eq!(11, s.pos);
- assert!(ok);
-
- let ok = s.move_end();
- assert_eq!(text, s.buf);
- assert_eq!(11, s.pos);
- assert!(!ok);
- }
-
- #[test]
- fn move_buffer_multiline() {
- let text = "αa\nsdf ßc\nasdf";
- let mut s = LineBuffer::init(text, 7, None);
- let ok = s.move_buffer_start();
- assert_eq!(text, s.buf);
- assert_eq!(0, s.pos);
- assert!(ok);
-
- let ok = s.move_buffer_start();
- assert_eq!(text, s.buf);
- assert_eq!(0, s.pos);
- assert!(!ok);
-
- let ok = s.move_buffer_end();
- assert_eq!(text, s.buf);
- assert_eq!(text.len(), s.pos);
- assert!(ok);
-
- let ok = s.move_buffer_end();
- assert_eq!(text, s.buf);
- assert_eq!(text.len(), s.pos);
- assert!(!ok);
- }
-
- #[test]
- fn move_grapheme() {
- let mut s = LineBuffer::init("ag̈", 4, None);
- assert_eq!(4, s.len());
- let ok = s.move_backward(1);
- assert!(ok);
- assert_eq!(1, s.pos);
-
- let ok = s.move_forward(1);
- assert!(ok);
- assert_eq!(4, s.pos);
- }
-
- #[test]
- fn delete() {
- let cl = Listener::new();
- let mut s = LineBuffer::init("αß", 2, Some(cl.clone()));
- let chars = s.delete(1);
- assert_eq!("α", s.buf);
- assert_eq!(2, s.pos);
- assert_eq!(Some("ß".to_owned()), chars);
-
- let ok = s.backspace(1);
- assert_eq!("", s.buf);
- assert_eq!(0, s.pos);
- assert!(ok);
- cl.borrow().assert_deleted_str_eq("α");
- }
-
- #[test]
- fn kill() {
- let cl = Listener::new();
- let mut s = LineBuffer::init("αßγδε", 6, Some(cl.clone()));
- let ok = s.kill_line();
- assert_eq!("αßγ", s.buf);
- assert_eq!(6, s.pos);
- assert!(ok);
- cl.borrow().assert_deleted_str_eq("δε");
-
- s.pos = 4;
- let ok = s.discard_line();
- assert_eq!("γ", s.buf);
- assert_eq!(0, s.pos);
- assert!(ok);
- cl.borrow().assert_deleted_str_eq("αß");
- }
-
- #[test]
- fn kill_multiline() {
- let cl = Listener::new();
- let mut s = LineBuffer::init("αß\nγδ 12\nε f4", 7, Some(cl.clone()));
-
- let ok = s.kill_line();
- assert_eq!("αß\nγ\nε f4", s.buf);
- assert_eq!(7, s.pos);
- assert!(ok);
- cl.borrow().assert_deleted_str_eq("δ 12");
-
- let ok = s.kill_line();
- assert_eq!("αß\nγε f4", s.buf);
- assert_eq!(7, s.pos);
- assert!(ok);
- cl.borrow().assert_deleted_str_eq("\n");
-
- let ok = s.kill_line();
- assert_eq!("αß\nγ", s.buf);
- assert_eq!(7, s.pos);
- assert!(ok);
- cl.borrow().assert_deleted_str_eq("ε f4");
-
- let ok = s.kill_line();
- assert_eq!(7, s.pos);
- assert!(!ok);
- }
-
- #[test]
- fn discard_multiline() {
- let cl = Listener::new();
- let mut s = LineBuffer::init("αß\nc γδε", 9, Some(cl.clone()));
-
- let ok = s.discard_line();
- assert_eq!("αß\nδε", s.buf);
- assert_eq!(5, s.pos);
- assert!(ok);
- cl.borrow().assert_deleted_str_eq("c γ");
-
- let ok = s.discard_line();
- assert_eq!("αßδε", s.buf);
- assert_eq!(4, s.pos);
- assert!(ok);
- cl.borrow().assert_deleted_str_eq("\n");
-
- let ok = s.discard_line();
- assert_eq!("δε", s.buf);
- assert_eq!(0, s.pos);
- assert!(ok);
- cl.borrow().assert_deleted_str_eq("αß");
-
- let ok = s.discard_line();
- assert_eq!(0, s.pos);
- assert!(!ok);
- }
-
- #[test]
- fn transpose() {
- let mut s = LineBuffer::init("aßc", 1, None);
- let ok = s.transpose_chars();
- assert_eq!("ßac", s.buf);
- assert_eq!(3, s.pos);
- assert!(ok);
-
- s.buf = String::from("aßc");
- s.pos = 3;
- let ok = s.transpose_chars();
- assert_eq!("acß", s.buf);
- assert_eq!(4, s.pos);
- assert!(ok);
-
- s.buf = String::from("aßc");
- s.pos = 4;
- let ok = s.transpose_chars();
- assert_eq!("acß", s.buf);
- assert_eq!(4, s.pos);
- assert!(ok);
- }
-
- #[test]
- fn move_to_prev_word() {
- let mut s = LineBuffer::init("a ß c", 6, None); // before 'c'
- let ok = s.move_to_prev_word(Word::Emacs, 1);
- assert_eq!("a ß c", s.buf);
- assert_eq!(2, s.pos); // before 'ß'
- assert!(ok);
-
- assert!(s.move_end()); // after 'c'
- assert_eq!(7, s.pos);
- let ok = s.move_to_prev_word(Word::Emacs, 1);
- assert!(ok);
- assert_eq!(6, s.pos); // before 'c'
-
- let ok = s.move_to_prev_word(Word::Emacs, 2);
- assert!(ok);
- assert_eq!(0, s.pos);
- }
-
- #[test]
- fn move_to_prev_vi_word() {
- let mut s = LineBuffer::init("alpha ,beta/rho; mu", 19, None);
- let ok = s.move_to_prev_word(Word::Vi, 1);
- assert!(ok);
- assert_eq!(17, s.pos);
- let ok = s.move_to_prev_word(Word::Vi, 1);
- assert!(ok);
- assert_eq!(15, s.pos);
- let ok = s.move_to_prev_word(Word::Vi, 1);
- assert!(ok);
- assert_eq!(12, s.pos);
- let ok = s.move_to_prev_word(Word::Vi, 1);
- assert!(ok);
- assert_eq!(11, s.pos);
- let ok = s.move_to_prev_word(Word::Vi, 1);
- assert!(ok);
- assert_eq!(7, s.pos);
- let ok = s.move_to_prev_word(Word::Vi, 1);
- assert!(ok);
- assert_eq!(6, s.pos);
- let ok = s.move_to_prev_word(Word::Vi, 1);
- assert!(ok);
- assert_eq!(0, s.pos);
- let ok = s.move_to_prev_word(Word::Vi, 1);
- assert!(!ok);
- }
-
- #[test]
- fn move_to_prev_big_word() {
- let mut s = LineBuffer::init("alpha ,beta/rho; mu", 19, None);
- let ok = s.move_to_prev_word(Word::Big, 1);
- assert!(ok);
- assert_eq!(17, s.pos);
- let ok = s.move_to_prev_word(Word::Big, 1);
- assert!(ok);
- assert_eq!(6, s.pos);
- let ok = s.move_to_prev_word(Word::Big, 1);
- assert!(ok);
- assert_eq!(0, s.pos);
- let ok = s.move_to_prev_word(Word::Big, 1);
- assert!(!ok);
- }
-
- #[test]
- fn move_to_forward() {
- let mut s = LineBuffer::init("αßγδε", 2, None);
- let ok = s.move_to(CharSearch::ForwardBefore('ε'), 1);
- assert!(ok);
- assert_eq!(6, s.pos);
-
- let mut s = LineBuffer::init("αßγδε", 2, None);
- let ok = s.move_to(CharSearch::Forward('ε'), 1);
- assert!(ok);
- assert_eq!(8, s.pos);
-
- let mut s = LineBuffer::init("αßγδε", 2, None);
- let ok = s.move_to(CharSearch::Forward('ε'), 10);
- assert!(ok);
- assert_eq!(8, s.pos);
- }
-
- #[test]
- fn move_to_backward() {
- let mut s = LineBuffer::init("αßγδε", 8, None);
- let ok = s.move_to(CharSearch::BackwardAfter('ß'), 1);
- assert!(ok);
- assert_eq!(4, s.pos);
-
- let mut s = LineBuffer::init("αßγδε", 8, None);
- let ok = s.move_to(CharSearch::Backward('ß'), 1);
- assert!(ok);
- assert_eq!(2, s.pos);
- }
-
- #[test]
- fn delete_prev_word() {
- let cl = Listener::new();
- let mut s = LineBuffer::init("a ß c", 6, Some(cl.clone()));
- let ok = s.delete_prev_word(Word::Big, 1);
- assert_eq!("a c", s.buf);
- assert_eq!(2, s.pos);
- assert!(ok);
- cl.borrow().assert_deleted_str_eq("ß ");
- }
-
- #[test]
- fn move_to_next_word() {
- let mut s = LineBuffer::init("a ß c", 1, None); // after 'a'
- let ok = s.move_to_next_word(At::AfterEnd, Word::Emacs, 1);
- assert_eq!("a ß c", s.buf);
- assert!(ok);
- assert_eq!(4, s.pos); // after 'ß'
-
- let ok = s.move_to_next_word(At::AfterEnd, Word::Emacs, 1);
- assert!(ok);
- assert_eq!(7, s.pos); // after 'c'
-
- s.move_home();
- let ok = s.move_to_next_word(At::AfterEnd, Word::Emacs, 1);
- assert!(ok);
- assert_eq!(1, s.pos); // after 'a'
-
- let ok = s.move_to_next_word(At::AfterEnd, Word::Emacs, 2);
- assert!(ok);
- assert_eq!(7, s.pos); // after 'c'
- }
-
- #[test]
- fn move_to_end_of_word() {
- let mut s = LineBuffer::init("a ßeta c", 1, None);
- let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
- assert_eq!("a ßeta c", s.buf);
- assert_eq!(6, s.pos);
- assert!(ok);
- }
-
- #[test]
- fn move_to_end_of_vi_word() {
- let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0, None);
- let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
- assert!(ok);
- assert_eq!(4, s.pos);
- let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
- assert!(ok);
- assert_eq!(6, s.pos);
- let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
- assert!(ok);
- assert_eq!(10, s.pos);
- let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
- assert!(ok);
- assert_eq!(11, s.pos);
- let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
- assert!(ok);
- assert_eq!(14, s.pos);
- let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
- assert!(ok);
- assert_eq!(15, s.pos);
- let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
- assert!(ok);
- assert_eq!(18, s.pos);
- let ok = s.move_to_next_word(At::BeforeEnd, Word::Vi, 1);
- assert!(!ok);
- }
-
- #[test]
- fn move_to_end_of_big_word() {
- let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0, None);
- let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
- assert!(ok);
- assert_eq!(4, s.pos);
- let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
- assert!(ok);
- assert_eq!(15, s.pos);
- let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
- assert!(ok);
- assert_eq!(18, s.pos);
- let ok = s.move_to_next_word(At::BeforeEnd, Word::Big, 1);
- assert!(!ok);
- }
-
- #[test]
- fn move_to_start_of_word() {
- let mut s = LineBuffer::init("a ß c", 2, None);
- let ok = s.move_to_next_word(At::Start, Word::Emacs, 1);
- assert_eq!("a ß c", s.buf);
- assert_eq!(6, s.pos);
- assert!(ok);
- }
-
- #[test]
- fn move_to_start_of_vi_word() {
- let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0, None);
- let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
- assert!(ok);
- assert_eq!(6, s.pos);
- let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
- assert!(ok);
- assert_eq!(7, s.pos);
- let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
- assert!(ok);
- assert_eq!(11, s.pos);
- let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
- assert!(ok);
- assert_eq!(12, s.pos);
- let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
- assert!(ok);
- assert_eq!(15, s.pos);
- let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
- assert!(ok);
- assert_eq!(17, s.pos);
- let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
- assert!(ok);
- assert_eq!(18, s.pos);
- let ok = s.move_to_next_word(At::Start, Word::Vi, 1);
- assert!(!ok);
- }
-
- #[test]
- fn move_to_start_of_big_word() {
- let mut s = LineBuffer::init("alpha ,beta/rho; mu", 0, None);
- let ok = s.move_to_next_word(At::Start, Word::Big, 1);
- assert!(ok);
- assert_eq!(6, s.pos);
- let ok = s.move_to_next_word(At::Start, Word::Big, 1);
- assert!(ok);
- assert_eq!(17, s.pos);
- let ok = s.move_to_next_word(At::Start, Word::Big, 1);
- assert!(ok);
- assert_eq!(18, s.pos);
- let ok = s.move_to_next_word(At::Start, Word::Big, 1);
- assert!(!ok);
- }
-
- #[test]
- fn delete_word() {
- let cl = Listener::new();
- let mut s = LineBuffer::init("a ß c", 1, Some(cl.clone()));
- let ok = s.delete_word(At::AfterEnd, Word::Emacs, 1);
- assert_eq!("a c", s.buf);
- assert_eq!(1, s.pos);
- assert!(ok);
- cl.borrow().assert_deleted_str_eq(" ß");
-
- let mut s = LineBuffer::init("test", 0, Some(cl.clone()));
- let ok = s.delete_word(At::AfterEnd, Word::Vi, 1);
- assert_eq!("", s.buf);
- assert_eq!(0, s.pos);
- assert!(ok);
- cl.borrow().assert_deleted_str_eq("test");
- }
-
- #[test]
- fn delete_til_start_of_word() {
- let cl = Listener::new();
- let mut s = LineBuffer::init("a ß c", 2, Some(cl.clone()));
- let ok = s.delete_word(At::Start, Word::Emacs, 1);
- assert_eq!("a c", s.buf);
- assert_eq!(2, s.pos);
- assert!(ok);
- cl.borrow().assert_deleted_str_eq("ß ");
- }
-
- #[test]
- fn delete_to_forward() {
- let cl = Listener::new();
- let mut s = LineBuffer::init("αßγδε", 2, Some(cl.clone()));
- let ok = s.delete_to(CharSearch::ForwardBefore('ε'), 1);
- assert!(ok);
- cl.borrow().assert_deleted_str_eq("ßγδ");
- assert_eq!("αε", s.buf);
- assert_eq!(2, s.pos);
-
- let mut s = LineBuffer::init("αßγδε", 2, Some(cl.clone()));
- let ok = s.delete_to(CharSearch::Forward('ε'), 1);
- assert!(ok);
- cl.borrow().assert_deleted_str_eq("ßγδε");
- assert_eq!("α", s.buf);
- assert_eq!(2, s.pos);
- }
-
- #[test]
- fn delete_to_backward() {
- let cl = Listener::new();
- let mut s = LineBuffer::init("αßγδε", 8, Some(cl.clone()));
- let ok = s.delete_to(CharSearch::BackwardAfter('α'), 1);
- assert!(ok);
- cl.borrow().assert_deleted_str_eq("ßγδ");
- assert_eq!("αε", s.buf);
- assert_eq!(2, s.pos);
-
- let mut s = LineBuffer::init("αßγδε", 8, Some(cl.clone()));
- let ok = s.delete_to(CharSearch::Backward('ß'), 1);
- assert!(ok);
- cl.borrow().assert_deleted_str_eq("ßγδ");
- assert_eq!("αε", s.buf);
- assert_eq!(2, s.pos);
- }
-
- #[test]
- fn edit_word() {
- let mut s = LineBuffer::init("a ßeta c", 1, None);
- assert!(s.edit_word(WordAction::Uppercase));
- assert_eq!("a SSETA c", s.buf);
- assert_eq!(7, s.pos);
-
- let mut s = LineBuffer::init("a ßetA c", 1, None);
- assert!(s.edit_word(WordAction::Lowercase));
- assert_eq!("a ßeta c", s.buf);
- assert_eq!(7, s.pos);
-
- let mut s = LineBuffer::init("a ßETA c", 1, None);
- assert!(s.edit_word(WordAction::Capitalize));
- assert_eq!("a SSeta c", s.buf);
- assert_eq!(7, s.pos);
-
- let mut s = LineBuffer::init("test", 1, None);
- assert!(s.edit_word(WordAction::Capitalize));
- assert_eq!("tEst", s.buf);
- assert_eq!(4, s.pos);
- }
-
- #[test]
- fn transpose_words() {
- let mut s = LineBuffer::init("ßeta / δelta__", 15, None);
- assert!(s.transpose_words(1));
- assert_eq!("δelta__ / ßeta", s.buf);
- assert_eq!(16, s.pos);
-
- let mut s = LineBuffer::init("ßeta / δelta", 14, None);
- assert!(s.transpose_words(1));
- assert_eq!("δelta / ßeta", s.buf);
- assert_eq!(14, s.pos);
-
- let mut s = LineBuffer::init(" / δelta", 8, None);
- assert!(!s.transpose_words(1));
-
- let mut s = LineBuffer::init("ßeta / __", 9, None);
- assert!(!s.transpose_words(1));
- }
-
- #[test]
- fn move_by_line() {
- let text = "aa123\nsdf bc\nasdf";
- let mut s = LineBuffer::init(text, 14, None);
- // move up
- let ok = s.move_to_line_up(1);
- assert_eq!(7, s.pos);
- assert!(ok);
-
- let ok = s.move_to_line_up(1);
- assert_eq!(1, s.pos);
- assert!(ok);
-
- let ok = s.move_to_line_up(1);
- assert_eq!(1, s.pos);
- assert!(!ok);
-
- // move down
- let ok = s.move_to_line_down(1);
- assert_eq!(7, s.pos);
- assert!(ok);
-
- let ok = s.move_to_line_down(1);
- assert_eq!(14, s.pos);
- assert!(ok);
-
- let ok = s.move_to_line_down(1);
- assert_eq!(14, s.pos);
- assert!(!ok);
-
- // move by multiple steps
- let ok = s.move_to_line_up(2);
- assert_eq!(1, s.pos);
- assert!(ok);
-
- let ok = s.move_to_line_down(2);
- assert_eq!(14, s.pos);
- assert!(ok);
- }
-}
diff --git a/vendor/rustyline-8.2.0/src/test/common.rs b/vendor/rustyline-8.2.0/src/test/common.rs
deleted file mode 100644
index 0f31dce..0000000
--- a/vendor/rustyline-8.2.0/src/test/common.rs
+++ /dev/null
@@ -1,340 +0,0 @@
-///! Basic commands tests.
-use super::{assert_cursor, assert_line, assert_line_with_initial, init_editor};
-use crate::config::EditMode;
-use crate::error::ReadlineError;
-use crate::keys::{KeyCode as K, KeyEvent as E, Modifiers as M};
-
-#[test]
-fn home_key() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_cursor(*mode, ("", ""), &[E(K::Home, M::NONE), E::ENTER], ("", ""));
- assert_cursor(
- *mode,
- ("Hi", ""),
- &[E(K::Home, M::NONE), E::ENTER],
- ("", "Hi"),
- );
- if *mode == EditMode::Vi {
- // vi command mode
- assert_cursor(
- *mode,
- ("Hi", ""),
- &[E::ESC, E(K::Home, M::NONE), E::ENTER],
- ("", "Hi"),
- );
- }
- }
-}
-
-#[test]
-fn end_key() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_cursor(*mode, ("", ""), &[E(K::End, M::NONE), E::ENTER], ("", ""));
- assert_cursor(
- *mode,
- ("H", "i"),
- &[E(K::End, M::NONE), E::ENTER],
- ("Hi", ""),
- );
- assert_cursor(
- *mode,
- ("", "Hi"),
- &[E(K::End, M::NONE), E::ENTER],
- ("Hi", ""),
- );
- if *mode == EditMode::Vi {
- // vi command mode
- assert_cursor(
- *mode,
- ("", "Hi"),
- &[E::ESC, E(K::End, M::NONE), E::ENTER],
- ("Hi", ""),
- );
- }
- }
-}
-
-#[test]
-fn left_key() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_cursor(
- *mode,
- ("Hi", ""),
- &[E(K::Left, M::NONE), E::ENTER],
- ("H", "i"),
- );
- assert_cursor(
- *mode,
- ("H", "i"),
- &[E(K::Left, M::NONE), E::ENTER],
- ("", "Hi"),
- );
- assert_cursor(
- *mode,
- ("", "Hi"),
- &[E(K::Left, M::NONE), E::ENTER],
- ("", "Hi"),
- );
- if *mode == EditMode::Vi {
- // vi command mode
- assert_cursor(
- *mode,
- ("Bye", ""),
- &[E::ESC, E(K::Left, M::NONE), E::ENTER],
- ("B", "ye"),
- );
- }
- }
-}
-
-#[test]
-fn right_key() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_cursor(*mode, ("", ""), &[E(K::Right, M::NONE), E::ENTER], ("", ""));
- assert_cursor(
- *mode,
- ("", "Hi"),
- &[E(K::Right, M::NONE), E::ENTER],
- ("H", "i"),
- );
- assert_cursor(
- *mode,
- ("B", "ye"),
- &[E(K::Right, M::NONE), E::ENTER],
- ("By", "e"),
- );
- assert_cursor(
- *mode,
- ("H", "i"),
- &[E(K::Right, M::NONE), E::ENTER],
- ("Hi", ""),
- );
- if *mode == EditMode::Vi {
- // vi command mode
- assert_cursor(
- *mode,
- ("", "Hi"),
- &[E::ESC, E(K::Right, M::NONE), E::ENTER],
- ("H", "i"),
- );
- }
- }
-}
-
-#[test]
-fn enter_key() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_line(*mode, &[E::ENTER], "");
- assert_line(*mode, &[E::from('a'), E::ENTER], "a");
- assert_line_with_initial(*mode, ("Hi", ""), &[E::ENTER], "Hi");
- assert_line_with_initial(*mode, ("", "Hi"), &[E::ENTER], "Hi");
- assert_line_with_initial(*mode, ("H", "i"), &[E::ENTER], "Hi");
- if *mode == EditMode::Vi {
- // vi command mode
- assert_line(*mode, &[E::ESC, E::ENTER], "");
- assert_line(*mode, &[E::from('a'), E::ESC, E::ENTER], "a");
- assert_line_with_initial(*mode, ("Hi", ""), &[E::ESC, E::ENTER], "Hi");
- assert_line_with_initial(*mode, ("", "Hi"), &[E::ESC, E::ENTER], "Hi");
- assert_line_with_initial(*mode, ("H", "i"), &[E::ESC, E::ENTER], "Hi");
- }
- }
-}
-
-#[test]
-fn newline_key() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_line(*mode, &[E::ctrl('J')], "");
- assert_line(*mode, &[E::from('a'), E::ctrl('J')], "a");
- if *mode == EditMode::Vi {
- // vi command mode
- assert_line(*mode, &[E::ESC, E::ctrl('J')], "");
- assert_line(*mode, &[E::from('a'), E::ESC, E::ctrl('J')], "a");
- }
- }
-}
-
-#[test]
-fn eof_key() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- let mut editor = init_editor(*mode, &[E::ctrl('D')]);
- let err = editor.readline(">>");
- assert_matches!(err, Err(ReadlineError::Eof));
- }
- assert_line(
- EditMode::Emacs,
- &[E::from('a'), E::ctrl('D'), E::ENTER],
- "a",
- );
- assert_line(EditMode::Vi, &[E::from('a'), E::ctrl('D')], "a");
- assert_line(EditMode::Vi, &[E::from('a'), E::ESC, E::ctrl('D')], "a");
- assert_line_with_initial(EditMode::Emacs, ("", "Hi"), &[E::ctrl('D'), E::ENTER], "i");
- assert_line_with_initial(EditMode::Vi, ("", "Hi"), &[E::ctrl('D')], "Hi");
- assert_line_with_initial(EditMode::Vi, ("", "Hi"), &[E::ESC, E::ctrl('D')], "Hi");
-}
-
-#[test]
-fn interrupt_key() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- let mut editor = init_editor(*mode, &[E::ctrl('C')]);
- let err = editor.readline(">>");
- assert_matches!(err, Err(ReadlineError::Interrupted));
-
- let mut editor = init_editor(*mode, &[E::ctrl('C')]);
- let err = editor.readline_with_initial(">>", ("Hi", ""));
- assert_matches!(err, Err(ReadlineError::Interrupted));
- if *mode == EditMode::Vi {
- // vi command mode
- let mut editor = init_editor(*mode, &[E::ESC, E::ctrl('C')]);
- let err = editor.readline_with_initial(">>", ("Hi", ""));
- assert_matches!(err, Err(ReadlineError::Interrupted));
- }
- }
-}
-
-#[test]
-fn delete_key() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_cursor(
- *mode,
- ("a", ""),
- &[E(K::Delete, M::NONE), E::ENTER],
- ("a", ""),
- );
- assert_cursor(
- *mode,
- ("", "a"),
- &[E(K::Delete, M::NONE), E::ENTER],
- ("", ""),
- );
- if *mode == EditMode::Vi {
- // vi command mode
- assert_cursor(
- *mode,
- ("", "a"),
- &[E::ESC, E(K::Delete, M::NONE), E::ENTER],
- ("", ""),
- );
- }
- }
-}
-
-#[test]
-fn ctrl_t() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_cursor(*mode, ("a", "b"), &[E::ctrl('T'), E::ENTER], ("ba", ""));
- assert_cursor(*mode, ("ab", "cd"), &[E::ctrl('T'), E::ENTER], ("acb", "d"));
- if *mode == EditMode::Vi {
- // vi command mode
- assert_cursor(
- *mode,
- ("ab", ""),
- &[E::ESC, E::ctrl('T'), E::ENTER],
- ("ba", ""),
- );
- }
- }
-}
-
-#[test]
-fn ctrl_u() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_cursor(
- *mode,
- ("start of line ", "end"),
- &[E::ctrl('U'), E::ENTER],
- ("", "end"),
- );
- assert_cursor(*mode, ("", "end"), &[E::ctrl('U'), E::ENTER], ("", "end"));
- if *mode == EditMode::Vi {
- // vi command mode
- assert_cursor(
- *mode,
- ("start of line ", "end"),
- &[E::ESC, E::ctrl('U'), E::ENTER],
- ("", " end"),
- );
- }
- }
-}
-
-#[cfg(unix)]
-#[test]
-fn ctrl_v() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_cursor(
- *mode,
- ("", ""),
- &[E::ctrl('V'), E(K::Char('\t'), M::NONE), E::ENTER],
- ("\t", ""),
- );
- if *mode == EditMode::Vi {
- // vi command mode
- assert_cursor(
- *mode,
- ("", ""),
- &[E::ESC, E::ctrl('V'), E(K::Char('\t'), M::NONE), E::ENTER],
- ("\t", ""),
- );
- }
- }
-}
-
-#[test]
-fn ctrl_w() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_cursor(
- *mode,
- ("Hello, ", "world"),
- &[E::ctrl('W'), E::ENTER],
- ("", "world"),
- );
- assert_cursor(
- *mode,
- ("Hello, world.", ""),
- &[E::ctrl('W'), E::ENTER],
- ("Hello, ", ""),
- );
- if *mode == EditMode::Vi {
- // vi command mode
- assert_cursor(
- *mode,
- ("Hello, world.", ""),
- &[E::ESC, E::ctrl('W'), E::ENTER],
- ("Hello, ", "."),
- );
- }
- }
-}
-
-#[test]
-fn ctrl_y() {
- for mode in &[EditMode::Emacs /* FIXME, EditMode::Vi */] {
- assert_cursor(
- *mode,
- ("Hello, ", "world"),
- &[E::ctrl('W'), E::ctrl('Y'), E::ENTER],
- ("Hello, ", "world"),
- );
- }
-}
-
-#[test]
-fn ctrl__() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_cursor(
- *mode,
- ("Hello, ", "world"),
- &[E::ctrl('W'), E::ctrl('_'), E::ENTER],
- ("Hello, ", "world"),
- );
- if *mode == EditMode::Vi {
- // vi command mode
- assert_cursor(
- *mode,
- ("Hello, ", "world"),
- &[E::ESC, E::ctrl('W'), E::ctrl('_'), E::ENTER],
- ("Hello,", " world"),
- );
- }
- }
-}
diff --git a/vendor/rustyline-8.2.0/src/test/emacs.rs b/vendor/rustyline-8.2.0/src/test/emacs.rs
deleted file mode 100644
index aa3e0b6..0000000
--- a/vendor/rustyline-8.2.0/src/test/emacs.rs
+++ /dev/null
@@ -1,424 +0,0 @@
-//! Emacs specific key bindings
-use super::{assert_cursor, assert_history};
-use crate::config::EditMode;
-use crate::keys::{KeyCode as K, KeyEvent as E, Modifiers as M};
-
-#[test]
-fn ctrl_a() {
- assert_cursor(
- EditMode::Emacs,
- ("Hi", ""),
- &[E::ctrl('A'), E::ENTER],
- ("", "Hi"),
- );
- assert_cursor(
- EditMode::Emacs,
- ("test test\n123", "foo"),
- &[E::ctrl('A'), E::ENTER],
- ("test test\n", "123foo"),
- );
-}
-
-#[test]
-fn ctrl_e() {
- assert_cursor(
- EditMode::Emacs,
- ("", "Hi"),
- &[E::ctrl('E'), E::ENTER],
- ("Hi", ""),
- );
- assert_cursor(
- EditMode::Emacs,
- ("foo", "test test\n123"),
- &[E::ctrl('E'), E::ENTER],
- ("footest test", "\n123"),
- );
-}
-
-#[test]
-fn ctrl_b() {
- assert_cursor(
- EditMode::Emacs,
- ("Hi", ""),
- &[E::ctrl('B'), E::ENTER],
- ("H", "i"),
- );
- assert_cursor(
- EditMode::Emacs,
- ("Hi", ""),
- &[E::alt('2'), E::ctrl('B'), E::ENTER],
- ("", "Hi"),
- );
- assert_cursor(
- EditMode::Emacs,
- ("", "Hi"),
- &[E::alt('-'), E::alt('2'), E::ctrl('B'), E::ENTER],
- ("Hi", ""),
- );
-}
-
-#[test]
-fn ctrl_f() {
- assert_cursor(
- EditMode::Emacs,
- ("", "Hi"),
- &[E::ctrl('F'), E::ENTER],
- ("H", "i"),
- );
- assert_cursor(
- EditMode::Emacs,
- ("", "Hi"),
- &[E::alt('2'), E::ctrl('F'), E::ENTER],
- ("Hi", ""),
- );
- assert_cursor(
- EditMode::Emacs,
- ("Hi", ""),
- &[E::alt('-'), E::alt('2'), E::ctrl('F'), E::ENTER],
- ("", "Hi"),
- );
-}
-
-#[test]
-fn ctrl_h() {
- assert_cursor(
- EditMode::Emacs,
- ("Hi", ""),
- &[E::ctrl('H'), E::ENTER],
- ("H", ""),
- );
- assert_cursor(
- EditMode::Emacs,
- ("Hi", ""),
- &[E::alt('2'), E::ctrl('H'), E::ENTER],
- ("", ""),
- );
- assert_cursor(
- EditMode::Emacs,
- ("", "Hi"),
- &[E::alt('-'), E::alt('2'), E::ctrl('H'), E::ENTER],
- ("", ""),
- );
-}
-
-#[test]
-fn backspace() {
- assert_cursor(
- EditMode::Emacs,
- ("", ""),
- &[E::BACKSPACE, E::ENTER],
- ("", ""),
- );
- assert_cursor(
- EditMode::Emacs,
- ("Hi", ""),
- &[E::BACKSPACE, E::ENTER],
- ("H", ""),
- );
- assert_cursor(
- EditMode::Emacs,
- ("", "Hi"),
- &[E::BACKSPACE, E::ENTER],
- ("", "Hi"),
- );
-}
-
-#[test]
-fn ctrl_k() {
- assert_cursor(
- EditMode::Emacs,
- ("Hi", ""),
- &[E::ctrl('K'), E::ENTER],
- ("Hi", ""),
- );
- assert_cursor(
- EditMode::Emacs,
- ("", "Hi"),
- &[E::ctrl('K'), E::ENTER],
- ("", ""),
- );
- assert_cursor(
- EditMode::Emacs,
- ("B", "ye"),
- &[E::ctrl('K'), E::ENTER],
- ("B", ""),
- );
- assert_cursor(
- EditMode::Emacs,
- ("Hi", "foo\nbar"),
- &[E::ctrl('K'), E::ENTER],
- ("Hi", "\nbar"),
- );
- assert_cursor(
- EditMode::Emacs,
- ("Hi", "\nbar"),
- &[E::ctrl('K'), E::ENTER],
- ("Hi", "bar"),
- );
- assert_cursor(
- EditMode::Emacs,
- ("Hi", "bar"),
- &[E::ctrl('K'), E::ENTER],
- ("Hi", ""),
- );
-}
-
-#[test]
-fn ctrl_u() {
- assert_cursor(
- EditMode::Emacs,
- ("", "Hi"),
- &[E::ctrl('U'), E::ENTER],
- ("", "Hi"),
- );
- assert_cursor(
- EditMode::Emacs,
- ("Hi", ""),
- &[E::ctrl('U'), E::ENTER],
- ("", ""),
- );
- assert_cursor(
- EditMode::Emacs,
- ("B", "ye"),
- &[E::ctrl('U'), E::ENTER],
- ("", "ye"),
- );
- assert_cursor(
- EditMode::Emacs,
- ("foo\nbar", "Hi"),
- &[E::ctrl('U'), E::ENTER],
- ("foo\n", "Hi"),
- );
- assert_cursor(
- EditMode::Emacs,
- ("foo\n", "Hi"),
- &[E::ctrl('U'), E::ENTER],
- ("foo", "Hi"),
- );
- assert_cursor(
- EditMode::Emacs,
- ("foo", "Hi"),
- &[E::ctrl('U'), E::ENTER],
- ("", "Hi"),
- );
-}
-#[test]
-fn ctrl_n() {
- assert_history(
- EditMode::Emacs,
- &["line1", "line2"],
- &[E::ctrl('P'), E::ctrl('P'), E::ctrl('N'), E::ENTER],
- "",
- ("line2", ""),
- );
-}
-
-#[test]
-fn ctrl_p() {
- assert_history(
- EditMode::Emacs,
- &["line1"],
- &[E::ctrl('P'), E::ENTER],
- "",
- ("line1", ""),
- );
-}
-
-#[test]
-fn ctrl_t() {
- /* FIXME
- assert_cursor(
- ("ab", "cd"),
- &[E::alt('2'), E::ctrl('T'), E::ENTER],
- ("acdb", ""),
- );*/
-}
-
-#[test]
-fn ctrl_x_ctrl_u() {
- assert_cursor(
- EditMode::Emacs,
- ("Hello, ", "world"),
- &[E::ctrl('W'), E::ctrl('X'), E::ctrl('U'), E::ENTER],
- ("Hello, ", "world"),
- );
-}
-
-#[test]
-fn meta_b() {
- assert_cursor(
- EditMode::Emacs,
- ("Hello, world!", ""),
- &[E::alt('B'), E::ENTER],
- ("Hello, ", "world!"),
- );
- assert_cursor(
- EditMode::Emacs,
- ("Hello, world!", ""),
- &[E::alt('2'), E::alt('B'), E::ENTER],
- ("", "Hello, world!"),
- );
- assert_cursor(
- EditMode::Emacs,
- ("", "Hello, world!"),
- &[E::alt('-'), E::alt('B'), E::ENTER],
- ("Hello", ", world!"),
- );
-}
-
-#[test]
-fn meta_f() {
- assert_cursor(
- EditMode::Emacs,
- ("", "Hello, world!"),
- &[E::alt('F'), E::ENTER],
- ("Hello", ", world!"),
- );
- assert_cursor(
- EditMode::Emacs,
- ("", "Hello, world!"),
- &[E::alt('2'), E::alt('F'), E::ENTER],
- ("Hello, world", "!"),
- );
- assert_cursor(
- EditMode::Emacs,
- ("Hello, world!", ""),
- &[E::alt('-'), E::alt('F'), E::ENTER],
- ("Hello, ", "world!"),
- );
-}
-
-#[test]
-fn meta_c() {
- assert_cursor(
- EditMode::Emacs,
- ("hi", ""),
- &[E::alt('C'), E::ENTER],
- ("hi", ""),
- );
- assert_cursor(
- EditMode::Emacs,
- ("", "hi"),
- &[E::alt('C'), E::ENTER],
- ("Hi", ""),
- );
- /* FIXME
- assert_cursor(
- ("", "hi test"),
- &[E::alt('2'), E::alt('C'), E::ENTER],
- ("Hi Test", ""),
- );*/
-}
-
-#[test]
-fn meta_l() {
- assert_cursor(
- EditMode::Emacs,
- ("Hi", ""),
- &[E::alt('L'), E::ENTER],
- ("Hi", ""),
- );
- assert_cursor(
- EditMode::Emacs,
- ("", "HI"),
- &[E::alt('L'), E::ENTER],
- ("hi", ""),
- );
- /* FIXME
- assert_cursor(
- ("", "HI TEST"),
- &[E::alt('2'), E::alt('L'), E::ENTER],
- ("hi test", ""),
- );*/
-}
-
-#[test]
-fn meta_u() {
- assert_cursor(
- EditMode::Emacs,
- ("hi", ""),
- &[E::alt('U'), E::ENTER],
- ("hi", ""),
- );
- assert_cursor(
- EditMode::Emacs,
- ("", "hi"),
- &[E::alt('U'), E::ENTER],
- ("HI", ""),
- );
- /* FIXME
- assert_cursor(
- ("", "hi test"),
- &[E::alt('2'), E::alt('U'), E::ENTER],
- ("HI TEST", ""),
- );*/
-}
-
-#[test]
-fn meta_d() {
- assert_cursor(
- EditMode::Emacs,
- ("Hello", ", world!"),
- &[E::alt('D'), E::ENTER],
- ("Hello", "!"),
- );
- assert_cursor(
- EditMode::Emacs,
- ("Hello", ", world!"),
- &[E::alt('2'), E::alt('D'), E::ENTER],
- ("Hello", ""),
- );
-}
-
-#[test]
-fn meta_t() {
- assert_cursor(
- EditMode::Emacs,
- ("Hello", ", world!"),
- &[E::alt('T'), E::ENTER],
- ("world, Hello", "!"),
- );
- /* FIXME
- assert_cursor(
- ("One Two", " Three Four"),
- &[E::alt('T'), E::ENTER],
- ("One Four Three Two", ""),
- );*/
-}
-
-#[test]
-fn meta_y() {
- assert_cursor(
- EditMode::Emacs,
- ("Hello, world", "!"),
- &[
- E::ctrl('W'),
- E(K::Left, M::NONE),
- E::ctrl('W'),
- E::ctrl('Y'),
- E::alt('Y'),
- E::ENTER,
- ],
- ("world", " !"),
- );
-}
-
-#[test]
-fn meta_backspace() {
- assert_cursor(
- EditMode::Emacs,
- ("Hello, wor", "ld!"),
- &[E(K::Backspace, M::ALT), E::ENTER],
- ("Hello, ", "ld!"),
- );
-}
-
-#[test]
-fn meta_digit() {
- assert_cursor(
- EditMode::Emacs,
- ("", ""),
- &[E::alt('3'), E::from('h'), E::ENTER],
- ("hhh", ""),
- );
-}
diff --git a/vendor/rustyline-8.2.0/src/test/history.rs b/vendor/rustyline-8.2.0/src/test/history.rs
deleted file mode 100644
index ab86924..0000000
--- a/vendor/rustyline-8.2.0/src/test/history.rs
+++ /dev/null
@@ -1,243 +0,0 @@
-//! History related commands tests
-use super::assert_history;
-use crate::config::EditMode;
-use crate::keys::{KeyCode as K, KeyEvent as E, Modifiers as M};
-
-#[test]
-fn down_key() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_history(
- *mode,
- &["line1"],
- &[E(K::Down, M::NONE), E::ENTER],
- "",
- ("", ""),
- );
- assert_history(
- *mode,
- &["line1", "line2"],
- &[
- E(K::Up, M::NONE),
- E(K::Up, M::NONE),
- E(K::Down, M::NONE),
- E::ENTER,
- ],
- "",
- ("line2", ""),
- );
- assert_history(
- *mode,
- &["line1"],
- &[
- E::from('a'),
- E(K::Up, M::NONE),
- E(K::Down, M::NONE), // restore original line
- E::ENTER,
- ],
- "",
- ("a", ""),
- );
- assert_history(
- *mode,
- &["line1"],
- &[
- E::from('a'),
- E(K::Down, M::NONE), // noop
- E::ENTER,
- ],
- "",
- ("a", ""),
- );
- }
-}
-
-#[test]
-fn up_key() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_history(*mode, &[], &[E(K::Up, M::NONE), E::ENTER], "", ("", ""));
- assert_history(
- *mode,
- &["line1"],
- &[E(K::Up, M::NONE), E::ENTER],
- "",
- ("line1", ""),
- );
- assert_history(
- *mode,
- &["line1", "line2"],
- &[E(K::Up, M::NONE), E(K::Up, M::NONE), E::ENTER],
- "",
- ("line1", ""),
- );
- }
-}
-
-#[test]
-fn ctrl_r() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_history(
- *mode,
- &[],
- &[E::ctrl('R'), E::from('o'), E::ENTER],
- "",
- ("o", ""),
- );
- assert_history(
- *mode,
- &["rustc", "cargo"],
- &[
- E::ctrl('R'),
- E::from('o'),
- E(K::Right, M::NONE), // just to assert cursor pos
- E::ENTER,
- ],
- "",
- ("cargo", ""),
- );
- assert_history(
- *mode,
- &["rustc", "cargo"],
- &[
- E::ctrl('R'),
- E::from('u'),
- E(K::Right, M::NONE), // just to assert cursor pos
- E::ENTER,
- ],
- "",
- ("ru", "stc"),
- );
- assert_history(
- *mode,
- &["rustc", "cargo"],
- &[
- E::ctrl('R'),
- E::from('r'),
- E::from('u'),
- E(K::Right, M::NONE), // just to assert cursor pos
- E::ENTER,
- ],
- "",
- ("r", "ustc"),
- );
- assert_history(
- *mode,
- &["rustc", "cargo"],
- &[
- E::ctrl('R'),
- E::from('r'),
- E::ctrl('R'),
- E(K::Right, M::NONE), // just to assert cursor pos
- E::ENTER,
- ],
- "",
- ("r", "ustc"),
- );
- assert_history(
- *mode,
- &["rustc", "cargo"],
- &[
- E::ctrl('R'),
- E::from('r'),
- E::from('z'), // no match
- E(K::Right, M::NONE), // just to assert cursor pos
- E::ENTER,
- ],
- "",
- ("car", "go"),
- );
- assert_history(
- EditMode::Emacs,
- &["rustc", "cargo"],
- &[
- E::from('a'),
- E::ctrl('R'),
- E::from('r'),
- E::ctrl('G'), // abort (FIXME: doesn't work with vi mode)
- E::ENTER,
- ],
- "",
- ("a", ""),
- );
- }
-}
-
-#[test]
-fn ctrl_r_with_long_prompt() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_history(
- *mode,
- &["rustc", "cargo"],
- &[E::ctrl('R'), E::from('o'), E::ENTER],
- ">>>>>>>>>>>>>>>>>>>>>>>>>>> ",
- ("cargo", ""),
- );
- }
-}
-
-#[test]
-fn ctrl_s() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_history(
- *mode,
- &["rustc", "cargo"],
- &[
- E::ctrl('R'),
- E::from('r'),
- E::ctrl('R'),
- E::ctrl('S'),
- E(K::Right, M::NONE), // just to assert cursor pos
- E::ENTER,
- ],
- "",
- ("car", "go"),
- );
- }
-}
-
-#[test]
-fn meta_lt() {
- assert_history(
- EditMode::Emacs,
- &[""],
- &[E::alt('<'), E::ENTER],
- "",
- ("", ""),
- );
- assert_history(
- EditMode::Emacs,
- &["rustc", "cargo"],
- &[E::alt('<'), E::ENTER],
- "",
- ("rustc", ""),
- );
-}
-
-#[test]
-fn meta_gt() {
- assert_history(
- EditMode::Emacs,
- &[""],
- &[E::alt('>'), E::ENTER],
- "",
- ("", ""),
- );
- assert_history(
- EditMode::Emacs,
- &["rustc", "cargo"],
- &[E::alt('<'), E::alt('>'), E::ENTER],
- "",
- ("", ""),
- );
- assert_history(
- EditMode::Emacs,
- &["rustc", "cargo"],
- &[
- E::from('a'),
- E::alt('<'),
- E::alt('>'), // restore original line
- E::ENTER,
- ],
- "",
- ("a", ""),
- );
-}
diff --git a/vendor/rustyline-8.2.0/src/test/mod.rs b/vendor/rustyline-8.2.0/src/test/mod.rs
deleted file mode 100644
index 9b66b83..0000000
--- a/vendor/rustyline-8.2.0/src/test/mod.rs
+++ /dev/null
@@ -1,146 +0,0 @@
-use std::sync::{Arc, RwLock};
-use std::vec::IntoIter;
-
-use radix_trie::Trie;
-
-use crate::completion::Completer;
-use crate::config::{Config, EditMode};
-use crate::edit::init_state;
-use crate::highlight::Highlighter;
-use crate::hint::Hinter;
-use crate::keymap::{Cmd, InputState};
-use crate::keys::{KeyCode as K, KeyEvent, KeyEvent as E, Modifiers as M};
-use crate::tty::Sink;
-use crate::validate::Validator;
-use crate::{Context, Editor, Helper, Result};
-
-mod common;
-mod emacs;
-mod history;
-mod vi_cmd;
-mod vi_insert;
-
-fn init_editor(mode: EditMode, keys: &[KeyEvent]) -> Editor<()> {
- let config = Config::builder().edit_mode(mode).build();
- let mut editor = Editor::<()>::with_config(config);
- editor.term.keys.extend(keys.iter().cloned());
- editor
-}
-
-struct SimpleCompleter;
-impl Completer for SimpleCompleter {
- type Candidate = String;
-
- fn complete(
- &self,
- line: &str,
- _pos: usize,
- _ctx: &Context<'_>,
- ) -> Result<(usize, Vec<String>)> {
- Ok((0, vec![line.to_owned() + "t"]))
- }
-}
-impl Hinter for SimpleCompleter {
- type Hint = String;
-
- fn hint(&self, _line: &str, _pos: usize, _ctx: &Context<'_>) -> Option<Self::Hint> {
- None
- }
-}
-
-impl Helper for SimpleCompleter {}
-impl Highlighter for SimpleCompleter {}
-impl Validator for SimpleCompleter {}
-
-#[test]
-fn complete_line() {
- let mut out = Sink::new();
- let history = crate::history::History::new();
- let helper = Some(SimpleCompleter);
- let mut s = init_state(&mut out, "rus", 3, helper.as_ref(), &history);
- let config = Config::default();
- let mut input_state = InputState::new(&config, Arc::new(RwLock::new(Trie::new())));
- let keys = vec![E::ENTER];
- let mut rdr: IntoIter<KeyEvent> = keys.into_iter();
- let cmd = super::complete_line(&mut rdr, &mut s, &mut input_state, &Config::default()).unwrap();
- assert_eq!(
- Some(Cmd::AcceptOrInsertLine {
- accept_in_the_middle: true
- }),
- cmd
- );
- assert_eq!("rust", s.line.as_str());
- assert_eq!(4, s.line.pos());
-}
-
-// `keys`: keys to press
-// `expected_line`: line after enter key
-fn assert_line(mode: EditMode, keys: &[KeyEvent], expected_line: &str) {
- let mut editor = init_editor(mode, keys);
- let actual_line = editor.readline(">>").unwrap();
- assert_eq!(expected_line, actual_line);
-}
-
-// `initial`: line status before `keys` pressed: strings before and after cursor
-// `keys`: keys to press
-// `expected_line`: line after enter key
-fn assert_line_with_initial(
- mode: EditMode,
- initial: (&str, &str),
- keys: &[KeyEvent],
- expected_line: &str,
-) {
- let mut editor = init_editor(mode, keys);
- let actual_line = editor.readline_with_initial(">>", initial).unwrap();
- assert_eq!(expected_line, actual_line);
-}
-
-// `initial`: line status before `keys` pressed: strings before and after cursor
-// `keys`: keys to press
-// `expected`: line status before enter key: strings before and after cursor
-fn assert_cursor(mode: EditMode, initial: (&str, &str), keys: &[KeyEvent], expected: (&str, &str)) {
- let mut editor = init_editor(mode, keys);
- let actual_line = editor.readline_with_initial("", initial).unwrap();
- assert_eq!(expected.0.to_owned() + expected.1, actual_line);
- assert_eq!(expected.0.len(), editor.term.cursor);
-}
-
-// `entries`: history entries before `keys` pressed
-// `keys`: keys to press
-// `expected`: line status before enter key: strings before and after cursor
-fn assert_history(
- mode: EditMode,
- entries: &[&str],
- keys: &[KeyEvent],
- prompt: &str,
- expected: (&str, &str),
-) {
- let mut editor = init_editor(mode, keys);
- for entry in entries {
- editor.history.add(*entry);
- }
- let actual_line = editor.readline(prompt).unwrap();
- assert_eq!(expected.0.to_owned() + expected.1, actual_line);
- if prompt.is_empty() {
- assert_eq!(expected.0.len(), editor.term.cursor);
- }
-}
-
-#[test]
-fn unknown_esc_key() {
- for mode in &[EditMode::Emacs, EditMode::Vi] {
- assert_line(*mode, &[E(K::UnknownEscSeq, M::NONE), E::ENTER], "");
- }
-}
-
-#[test]
-fn test_send() {
- fn assert_send<T: Send>() {}
- assert_send::<Editor<()>>();
-}
-
-#[test]
-fn test_sync() {
- fn assert_sync<T: Sync>() {}
- assert_sync::<Editor<()>>();
-}
diff --git a/vendor/rustyline-8.2.0/src/test/vi_cmd.rs b/vendor/rustyline-8.2.0/src/test/vi_cmd.rs
deleted file mode 100644
index be8437d..0000000
--- a/vendor/rustyline-8.2.0/src/test/vi_cmd.rs
+++ /dev/null
@@ -1,583 +0,0 @@
-//! Vi command mode specific key bindings
-use super::{assert_cursor, assert_history};
-use crate::config::EditMode;
-use crate::keys::KeyEvent as E;
-
-#[test]
-fn dollar() {
- assert_cursor(
- EditMode::Vi,
- ("", "Hi"),
- &[E::ESC, E::from('$'), E::ENTER],
- ("Hi", ""), // FIXME
- );
-}
-
-/*#[test]
-fn dot() {
- // TODO
-}*/
-
-#[test]
-fn semi_colon() {
- assert_cursor(
- EditMode::Vi,
- ("", "Hello, world!"),
- &[E::ESC, E::from('f'), E::from('o'), E::from(';'), E::ENTER],
- ("Hello, w", "orld!"),
- );
-}
-
-#[test]
-fn comma() {
- assert_cursor(
- EditMode::Vi,
- ("Hello, w", "orld!"),
- &[E::ESC, E::from('f'), E::from('l'), E::from(','), E::ENTER],
- ("Hel", "lo, world!"),
- );
-}
-
-#[test]
-fn zero() {
- assert_cursor(
- EditMode::Vi,
- ("Hi", ""),
- &[E::ESC, E::from('0'), E::ENTER],
- ("", "Hi"),
- );
-}
-
-#[test]
-fn caret() {
- assert_cursor(
- EditMode::Vi,
- (" Hi", ""),
- &[E::ESC, E::from('^'), E::ENTER],
- (" ", "Hi"),
- );
-}
-
-#[test]
-fn a() {
- assert_cursor(
- EditMode::Vi,
- ("B", "e"),
- &[E::ESC, E::from('a'), E::from('y'), E::ENTER],
- ("By", "e"),
- );
-}
-
-#[test]
-fn uppercase_a() {
- assert_cursor(
- EditMode::Vi,
- ("", "By"),
- &[E::ESC, E::from('A'), E::from('e'), E::ENTER],
- ("Bye", ""),
- );
-}
-
-#[test]
-fn b() {
- assert_cursor(
- EditMode::Vi,
- ("Hello, world!", ""),
- &[E::ESC, E::from('b'), E::ENTER],
- ("Hello, ", "world!"),
- );
- assert_cursor(
- EditMode::Vi,
- ("Hello, world!", ""),
- &[E::ESC, E::from('2'), E::from('b'), E::ENTER],
- ("Hello", ", world!"),
- );
-}
-
-#[test]
-fn uppercase_b() {
- assert_cursor(
- EditMode::Vi,
- ("Hello, world!", ""),
- &[E::ESC, E::from('B'), E::ENTER],
- ("Hello, ", "world!"),
- );
- assert_cursor(
- EditMode::Vi,
- ("Hello, world!", ""),
- &[E::ESC, E::from('2'), E::from('B'), E::ENTER],
- ("", "Hello, world!"),
- );
-}
-
-#[test]
-fn uppercase_c() {
- assert_cursor(
- EditMode::Vi,
- ("Hello, w", "orld!"),
- &[E::ESC, E::from('C'), E::from('i'), E::ENTER],
- ("Hello, i", ""),
- );
-}
-
-#[test]
-fn ctrl_k() {
- for key in &[E::from('D'), E::ctrl('K')] {
- assert_cursor(
- EditMode::Vi,
- ("Hi", ""),
- &[E::ESC, *key, E::ENTER],
- ("H", ""),
- );
- assert_cursor(
- EditMode::Vi,
- ("", "Hi"),
- &[E::ESC, *key, E::ENTER],
- ("", ""),
- );
- assert_cursor(
- EditMode::Vi,
- ("By", "e"),
- &[E::ESC, *key, E::ENTER],
- ("B", ""),
- );
- }
-}
-
-#[test]
-fn e() {
- assert_cursor(
- EditMode::Vi,
- ("", "Hello, world!"),
- &[E::ESC, E::from('e'), E::ENTER],
- ("Hell", "o, world!"),
- );
- assert_cursor(
- EditMode::Vi,
- ("", "Hello, world!"),
- &[E::ESC, E::from('2'), E::from('e'), E::ENTER],
- ("Hello, worl", "d!"),
- );
-}
-
-#[test]
-fn uppercase_e() {
- assert_cursor(
- EditMode::Vi,
- ("", "Hello, world!"),
- &[E::ESC, E::from('E'), E::ENTER],
- ("Hello", ", world!"),
- );
- assert_cursor(
- EditMode::Vi,
- ("", "Hello, world!"),
- &[E::ESC, E::from('2'), E::from('E'), E::ENTER],
- ("Hello, world", "!"),
- );
-}
-
-#[test]
-fn f() {
- assert_cursor(
- EditMode::Vi,
- ("", "Hello, world!"),
- &[E::ESC, E::from('f'), E::from('r'), E::ENTER],
- ("Hello, wo", "rld!"),
- );
- assert_cursor(
- EditMode::Vi,
- ("", "Hello, world!"),
- &[E::ESC, E::from('3'), E::from('f'), E::from('l'), E::ENTER],
- ("Hello, wor", "ld!"),
- );
-}
-
-#[test]
-fn uppercase_f() {
- assert_cursor(
- EditMode::Vi,
- ("Hello, world!", ""),
- &[E::ESC, E::from('F'), E::from('r'), E::ENTER],
- ("Hello, wo", "rld!"),
- );
- assert_cursor(
- EditMode::Vi,
- ("Hello, world!", ""),
- &[E::ESC, E::from('3'), E::from('F'), E::from('l'), E::ENTER],
- ("He", "llo, world!"),
- );
-}
-
-#[test]
-fn i() {
- assert_cursor(
- EditMode::Vi,
- ("Be", ""),
- &[E::ESC, E::from('i'), E::from('y'), E::ENTER],
- ("By", "e"),
- );
-}
-
-#[test]
-fn uppercase_i() {
- assert_cursor(
- EditMode::Vi,
- ("Be", ""),
- &[E::ESC, E::from('I'), E::from('y'), E::ENTER],
- ("y", "Be"),
- );
-}
-
-#[test]
-fn u() {
- assert_cursor(
- EditMode::Vi,
- ("Hello, ", "world"),
- &[E::ESC, E::ctrl('W'), E::from('u'), E::ENTER],
- ("Hello,", " world"),
- );
-}
-
-#[test]
-fn w() {
- assert_cursor(
- EditMode::Vi,
- ("", "Hello, world!"),
- &[E::ESC, E::from('w'), E::ENTER],
- ("Hello", ", world!"),
- );
- assert_cursor(
- EditMode::Vi,
- ("", "Hello, world!"),
- &[E::ESC, E::from('2'), E::from('w'), E::ENTER],
- ("Hello, ", "world!"),
- );
-}
-
-#[test]
-fn uppercase_w() {
- assert_cursor(
- EditMode::Vi,
- ("", "Hello, world!"),
- &[E::ESC, E::from('W'), E::ENTER],
- ("Hello, ", "world!"),
- );
- assert_cursor(
- EditMode::Vi,
- ("", "Hello, world!"),
- &[E::ESC, E::from('2'), E::from('W'), E::ENTER],
- ("Hello, world", "!"),
- );
-}
-
-#[test]
-fn x() {
- assert_cursor(
- EditMode::Vi,
- ("", "a"),
- &[E::ESC, E::from('x'), E::ENTER],
- ("", ""),
- );
-}
-
-#[test]
-fn uppercase_x() {
- assert_cursor(
- EditMode::Vi,
- ("Hi", ""),
- &[E::ESC, E::from('X'), E::ENTER],
- ("", "i"),
- );
-}
-
-#[test]
-fn h() {
- for key in &[E::from('h'), E::ctrl('H'), E::BACKSPACE] {
- assert_cursor(
- EditMode::Vi,
- ("Bye", ""),
- &[E::ESC, *key, E::ENTER],
- ("B", "ye"),
- );
- assert_cursor(
- EditMode::Vi,
- ("Bye", ""),
- &[E::ESC, E::from('2'), *key, E::ENTER],
- ("", "Bye"),
- );
- }
-}
-
-#[test]
-fn l() {
- for key in &[E::from('l'), E::from(' ')] {
- assert_cursor(
- EditMode::Vi,
- ("", "Hi"),
- &[E::ESC, *key, E::ENTER],
- ("H", "i"),
- );
- assert_cursor(
- EditMode::Vi,
- ("", "Hi"),
- &[E::ESC, E::from('2'), *key, E::ENTER],
- ("Hi", ""),
- );
- }
-}
-
-#[test]
-fn j() {
- for key in &[E::from('j'), E::from('+')] {
- assert_cursor(
- EditMode::Vi,
- ("Hel", "lo,\nworld!"),
- // NOTE: escape moves backwards on char
- &[E::ESC, *key, E::ENTER],
- ("Hello,\nwo", "rld!"),
- );
- assert_cursor(
- EditMode::Vi,
- ("", "One\nTwo\nThree"),
- &[E::ESC, E::from('2'), *key, E::ENTER],
- ("One\nTwo\n", "Three"),
- );
- assert_cursor(
- EditMode::Vi,
- ("Hel", "lo,\nworld!"),
- // NOTE: escape moves backwards on char
- &[E::ESC, E::from('7'), *key, E::ENTER],
- ("Hello,\nwo", "rld!"),
- );
- }
-}
-
-#[test]
-fn k() {
- for key in &[E::from('k'), E::from('-')] {
- assert_cursor(
- EditMode::Vi,
- ("Hello,\nworl", "d!"),
- // NOTE: escape moves backwards on char
- &[E::ESC, *key, E::ENTER],
- ("Hel", "lo,\nworld!"),
- );
- assert_cursor(
- EditMode::Vi,
- ("One\nTwo\nT", "hree"),
- // NOTE: escape moves backwards on char
- &[E::ESC, E::from('2'), *key, E::ENTER],
- ("", "One\nTwo\nThree"),
- );
- assert_cursor(
- EditMode::Vi,
- ("Hello,\nworl", "d!"),
- // NOTE: escape moves backwards on char
- &[E::ESC, E::from('5'), *key, E::ENTER],
- ("Hel", "lo,\nworld!"),
- );
- assert_cursor(
- EditMode::Vi,
- ("first line\nshort\nlong line", ""),
- &[E::ESC, *key, E::ENTER],
- ("first line\nshort", "\nlong line"),
- );
- }
-}
-
-#[test]
-fn ctrl_n() {
- for key in &[E::ctrl('N')] {
- assert_history(
- EditMode::Vi,
- &["line1", "line2"],
- &[E::ESC, E::ctrl('P'), E::ctrl('P'), *key, E::ENTER],
- "",
- ("line2", ""),
- );
- }
-}
-
-#[test]
-fn ctrl_p() {
- for key in &[E::ctrl('P')] {
- assert_history(
- EditMode::Vi,
- &["line1"],
- &[E::ESC, *key, E::ENTER],
- "",
- ("line1", ""),
- );
- }
-}
-
-#[test]
-fn p() {
- assert_cursor(
- EditMode::Vi,
- ("Hello, ", "world"),
- &[E::ESC, E::ctrl('W'), E::from('p'), E::ENTER],
- (" Hello", ",world"),
- );
-}
-
-#[test]
-fn uppercase_p() {
- assert_cursor(
- EditMode::Vi,
- ("Hello, ", "world"),
- &[E::ESC, E::ctrl('W'), E::from('P'), E::ENTER],
- ("Hello", ", world"),
- );
-}
-
-#[test]
-fn r() {
- assert_cursor(
- EditMode::Vi,
- ("Hi", ", world!"),
- &[E::ESC, E::from('r'), E::from('o'), E::ENTER],
- ("H", "o, world!"),
- );
- assert_cursor(
- EditMode::Vi,
- ("He", "llo, world!"),
- &[E::ESC, E::from('4'), E::from('r'), E::from('i'), E::ENTER],
- ("Hiii", "i, world!"),
- );
-}
-
-#[test]
-fn s() {
- assert_cursor(
- EditMode::Vi,
- ("Hi", ", world!"),
- &[E::ESC, E::from('s'), E::from('o'), E::ENTER],
- ("Ho", ", world!"),
- );
- assert_cursor(
- EditMode::Vi,
- ("He", "llo, world!"),
- &[E::ESC, E::from('4'), E::from('s'), E::from('i'), E::ENTER],
- ("Hi", ", world!"),
- );
-}
-
-#[test]
-fn uppercase_s() {
- assert_cursor(
- EditMode::Vi,
- ("Hello, ", "world"),
- &[E::ESC, E::from('S'), E::ENTER],
- ("", ""),
- );
-}
-
-#[test]
-fn t() {
- assert_cursor(
- EditMode::Vi,
- ("", "Hello, world!"),
- &[E::ESC, E::from('t'), E::from('r'), E::ENTER],
- ("Hello, w", "orld!"),
- );
- assert_cursor(
- EditMode::Vi,
- ("", "Hello, world!"),
- &[E::ESC, E::from('3'), E::from('t'), E::from('l'), E::ENTER],
- ("Hello, wo", "rld!"),
- );
-}
-
-#[test]
-fn uppercase_t() {
- assert_cursor(
- EditMode::Vi,
- ("Hello, world!", ""),
- &[E::ESC, E::from('T'), E::from('r'), E::ENTER],
- ("Hello, wor", "ld!"),
- );
- assert_cursor(
- EditMode::Vi,
- ("Hello, world!", ""),
- &[E::ESC, E::from('3'), E::from('T'), E::from('l'), E::ENTER],
- ("Hel", "lo, world!"),
- );
-}
-
-#[test]
-fn indent() {
- assert_cursor(
- EditMode::Vi,
- ("Hello, world!", ""),
- &[E::ESC, E::from('>'), E::from('>'), E::ENTER],
- (" Hello, world", "!"), // Esc moves to the left
- );
- assert_cursor(
- EditMode::Vi,
- ("line1\nline2", ""),
- &[E::ESC, E::from('>'), E::from('>'), E::ENTER],
- ("line1\n line", "2"), // Esc moves to the left
- );
- assert_cursor(
- EditMode::Vi,
- ("line1\nline2", ""),
- &[E::ESC, E::from('>'), E::from('k'), E::ENTER],
- (" line1\n line", "2"), // Esc moves to the left
- );
- assert_cursor(
- EditMode::Vi,
- (" li", "ne1\n line2"),
- &[E::ESC, E::from('>'), E::from('j'), E::ENTER],
- (" l", "ine1\n line2"), // Esc moves to the left
- );
- assert_cursor(
- EditMode::Vi,
- (" ", "line1\n line2"),
- &[E::ESC, E::from('>'), E::from('j'), E::ENTER],
- (" ", " line1\n line2"), // Esc moves to the left
- );
- assert_cursor(
- EditMode::Vi,
- (" ", "line1\n line2"),
- &[E::ESC, E::from('>'), E::from('j'), E::ENTER],
- (" ", " line1\n line2"), // Esc moves to the left
- );
-}
-
-#[test]
-fn dedent() {
- assert_cursor(
- EditMode::Vi,
- (" line1\n line2", ""),
- &[E::ESC, E::from('<'), E::from('<'), E::ENTER],
- (" line1\nline", "2"),
- );
-
- assert_cursor(
- EditMode::Vi,
- (" line1\n line2", ""),
- &[E::ESC, E::from('<'), E::from('k'), E::ENTER],
- ("line1\nline", "2"),
- );
-
- assert_cursor(
- EditMode::Vi,
- (" li", "ne1\n line2"),
- &[E::ESC, E::from('<'), E::from('j'), E::ENTER],
- ("l", "ine1\nline2"),
- );
-
- assert_cursor(
- EditMode::Vi,
- (" ", "line1\n line2"),
- &[E::ESC, E::from('<'), E::from('j'), E::ENTER],
- ("", "line1\nline2"),
- );
- assert_cursor(
- EditMode::Vi,
- ("line", "1\n line2"),
- &[E::ESC, E::from('<'), E::from('j'), E::ENTER],
- ("lin", "e1\nline2"),
- );
-}
diff --git a/vendor/rustyline-8.2.0/src/test/vi_insert.rs b/vendor/rustyline-8.2.0/src/test/vi_insert.rs
deleted file mode 100644
index 8a18529..0000000
--- a/vendor/rustyline-8.2.0/src/test/vi_insert.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-//! Vi insert mode specific key bindings
-use super::assert_cursor;
-use crate::config::EditMode;
-use crate::keys::KeyEvent as E;
-
-#[test]
-fn insert_mode_by_default() {
- assert_cursor(EditMode::Vi, ("", ""), &[E::from('a'), E::ENTER], ("a", ""));
-}
-
-#[test]
-fn ctrl_h() {
- assert_cursor(
- EditMode::Vi,
- ("Hi", ""),
- &[E::ctrl('H'), E::ENTER],
- ("H", ""),
- );
-}
-
-#[test]
-fn backspace() {
- assert_cursor(EditMode::Vi, ("", ""), &[E::BACKSPACE, E::ENTER], ("", ""));
- assert_cursor(
- EditMode::Vi,
- ("Hi", ""),
- &[E::BACKSPACE, E::ENTER],
- ("H", ""),
- );
- assert_cursor(
- EditMode::Vi,
- ("", "Hi"),
- &[E::BACKSPACE, E::ENTER],
- ("", "Hi"),
- );
-}
-
-#[test]
-fn esc() {
- assert_cursor(
- EditMode::Vi,
- ("", ""),
- &[E::from('a'), E::ESC, E::ENTER],
- ("", "a"),
- );
-}
diff --git a/vendor/rustyline-8.2.0/src/tty/mod.rs b/vendor/rustyline-8.2.0/src/tty/mod.rs
deleted file mode 100644
index b1a44b7..0000000
--- a/vendor/rustyline-8.2.0/src/tty/mod.rs
+++ /dev/null
@@ -1,245 +0,0 @@
-//! This module implements and describes common TTY methods & traits
-
-use unicode_width::UnicodeWidthStr;
-
-use crate::config::{BellStyle, ColorMode, Config, OutputStreamType};
-use crate::highlight::Highlighter;
-use crate::keys::KeyEvent;
-use crate::layout::{Layout, Position};
-use crate::line_buffer::LineBuffer;
-use crate::Result;
-
-/// Terminal state
-pub trait RawMode: Sized {
- /// Disable RAW mode for the terminal.
- fn disable_raw_mode(&self) -> Result<()>;
-}
-
-/// Translate bytes read from stdin to keys.
-pub trait RawReader {
- /// Blocking read of key pressed.
- fn next_key(&mut self, single_esc_abort: bool) -> Result<KeyEvent>;
- /// For CTRL-V support
- #[cfg(unix)]
- fn next_char(&mut self) -> Result<char>;
- /// Bracketed paste
- fn read_pasted_text(&mut self) -> Result<String>;
-}
-
-/// Display prompt, line and cursor in terminal output
-pub trait Renderer {
- type Reader: RawReader;
-
- fn move_cursor(&mut self, old: Position, new: Position) -> Result<()>;
-
- /// Display `prompt`, line and cursor in terminal output
- #[allow(clippy::too_many_arguments)]
- fn refresh_line(
- &mut self,
- prompt: &str,
- line: &LineBuffer,
- hint: Option<&str>,
- old_layout: &Layout,
- new_layout: &Layout,
- highlighter: Option<&dyn Highlighter>,
- ) -> Result<()>;
-
- /// Compute layout for rendering prompt + line + some info (either hint,
- /// validation msg, ...). on the screen. Depending on screen width, line
- /// wrapping may be applied.
- fn compute_layout(
- &self,
- prompt_size: Position,
- default_prompt: bool,
- line: &LineBuffer,
- info: Option<&str>,
- ) -> Layout {
- // calculate the desired position of the cursor
- let pos = line.pos();
- let cursor = self.calculate_position(&line[..pos], prompt_size);
- // calculate the position of the end of the input line
- let mut end = if pos == line.len() {
- cursor
- } else {
- self.calculate_position(&line[pos..], cursor)
- };
- if let Some(info) = info {
- end = self.calculate_position(&info, end);
- }
-
- let new_layout = Layout {
- prompt_size,
- default_prompt,
- cursor,
- end,
- };
- debug_assert!(new_layout.prompt_size <= new_layout.cursor);
- debug_assert!(new_layout.cursor <= new_layout.end);
- new_layout
- }
-
- /// Calculate the number of columns and rows used to display `s` on a
- /// `cols` width terminal starting at `orig`.
- fn calculate_position(&self, s: &str, orig: Position) -> Position;
-
- fn write_and_flush(&self, buf: &[u8]) -> Result<()>;
-
- /// Beep, used for completion when there is nothing to complete or when all
- /// the choices were already shown.
- fn beep(&mut self) -> Result<()>;
-
- /// Clear the screen. Used to handle ctrl+l
- fn clear_screen(&mut self) -> Result<()>;
-
- /// Check if a SIGWINCH signal has been received
- fn sigwinch(&self) -> bool;
- /// Update the number of columns/rows in the current terminal.
- fn update_size(&mut self);
- /// Get the number of columns in the current terminal.
- fn get_columns(&self) -> usize;
- /// Get the number of rows in the current terminal.
- fn get_rows(&self) -> usize;
- /// Check if output supports colors.
- fn colors_enabled(&self) -> bool;
-
- /// Make sure prompt is at the leftmost edge of the screen
- fn move_cursor_at_leftmost(&mut self, rdr: &mut Self::Reader) -> Result<()>;
-}
-
-impl<'a, R: Renderer + ?Sized> Renderer for &'a mut R {
- type Reader = R::Reader;
-
- fn move_cursor(&mut self, old: Position, new: Position) -> Result<()> {
- (**self).move_cursor(old, new)
- }
-
- fn refresh_line(
- &mut self,
- prompt: &str,
- line: &LineBuffer,
- hint: Option<&str>,
- old_layout: &Layout,
- new_layout: &Layout,
- highlighter: Option<&dyn Highlighter>,
- ) -> Result<()> {
- (**self).refresh_line(prompt, line, hint, old_layout, new_layout, highlighter)
- }
-
- fn calculate_position(&self, s: &str, orig: Position) -> Position {
- (**self).calculate_position(s, orig)
- }
-
- fn write_and_flush(&self, buf: &[u8]) -> Result<()> {
- (**self).write_and_flush(buf)
- }
-
- fn beep(&mut self) -> Result<()> {
- (**self).beep()
- }
-
- fn clear_screen(&mut self) -> Result<()> {
- (**self).clear_screen()
- }
-
- fn sigwinch(&self) -> bool {
- (**self).sigwinch()
- }
-
- fn update_size(&mut self) {
- (**self).update_size()
- }
-
- fn get_columns(&self) -> usize {
- (**self).get_columns()
- }
-
- fn get_rows(&self) -> usize {
- (**self).get_rows()
- }
-
- fn colors_enabled(&self) -> bool {
- (**self).colors_enabled()
- }
-
- fn move_cursor_at_leftmost(&mut self, rdr: &mut R::Reader) -> Result<()> {
- (**self).move_cursor_at_leftmost(rdr)
- }
-}
-
-// ignore ANSI escape sequence
-fn width(s: &str, esc_seq: &mut u8) -> usize {
- if *esc_seq == 1 {
- if s == "[" {
- // CSI
- *esc_seq = 2;
- } else {
- // two-character sequence
- *esc_seq = 0;
- }
- 0
- } else if *esc_seq == 2 {
- if s == ";" || (s.as_bytes()[0] >= b'0' && s.as_bytes()[0] <= b'9') {
- /*} else if s == "m" {
- // last
- *esc_seq = 0;*/
- } else {
- // not supported
- *esc_seq = 0;
- }
- 0
- } else if s == "\x1b" {
- *esc_seq = 1;
- 0
- } else if s == "\n" {
- 0
- } else {
- s.width()
- }
-}
-
-/// Terminal contract
-pub trait Term {
- type Reader: RawReader; // rl_instream
- type Writer: Renderer<Reader = Self::Reader>; // rl_outstream
- type Mode: RawMode;
-
- fn new(
- color_mode: ColorMode,
- stream: OutputStreamType,
- tab_stop: usize,
- bell_style: BellStyle,
- enable_bracketed_paste: bool,
- ) -> Self;
- /// Check if current terminal can provide a rich line-editing user
- /// interface.
- fn is_unsupported(&self) -> bool;
- /// check if stdin is connected to a terminal.
- fn is_stdin_tty(&self) -> bool;
- /// check if output stream is connected to a terminal.
- fn is_output_tty(&self) -> bool;
- /// Enable RAW mode for the terminal.
- fn enable_raw_mode(&mut self) -> Result<Self::Mode>;
- /// Create a RAW reader
- fn create_reader(&self, config: &Config) -> Result<Self::Reader>;
- /// Create a writer
- fn create_writer(&self) -> Self::Writer;
-}
-
-// If on Windows platform import Windows TTY module
-// and re-export into mod.rs scope
-#[cfg(all(windows, not(target_arch = "wasm32")))]
-mod windows;
-#[cfg(all(windows, not(target_arch = "wasm32")))]
-pub use self::windows::*;
-
-// If on Unix platform import Unix TTY module
-// and re-export into mod.rs scope
-#[cfg(all(unix, not(target_arch = "wasm32")))]
-mod unix;
-#[cfg(all(unix, not(target_arch = "wasm32")))]
-pub use self::unix::*;
-
-#[cfg(any(test, target_arch = "wasm32"))]
-mod test;
-#[cfg(any(test, target_arch = "wasm32"))]
-pub use self::test::*;
diff --git a/vendor/rustyline-8.2.0/src/tty/test.rs b/vendor/rustyline-8.2.0/src/tty/test.rs
deleted file mode 100644
index d8bed91..0000000
--- a/vendor/rustyline-8.2.0/src/tty/test.rs
+++ /dev/null
@@ -1,200 +0,0 @@
-//! Tests specific definitions
-use std::iter::IntoIterator;
-use std::slice::Iter;
-use std::vec::IntoIter;
-
-use super::{RawMode, RawReader, Renderer, Term};
-use crate::config::{BellStyle, ColorMode, Config, OutputStreamType};
-use crate::error::ReadlineError;
-use crate::highlight::Highlighter;
-use crate::keys::KeyEvent;
-use crate::layout::{Layout, Position};
-use crate::line_buffer::LineBuffer;
-use crate::Result;
-
-pub type Mode = ();
-
-impl RawMode for Mode {
- fn disable_raw_mode(&self) -> Result<()> {
- Ok(())
- }
-}
-
-impl<'a> RawReader for Iter<'a, KeyEvent> {
- fn next_key(&mut self, _: bool) -> Result<KeyEvent> {
- match self.next() {
- Some(key) => Ok(*key),
- None => Err(ReadlineError::Eof),
- }
- }
-
- #[cfg(unix)]
- fn next_char(&mut self) -> Result<char> {
- unimplemented!();
- }
-
- fn read_pasted_text(&mut self) -> Result<String> {
- unimplemented!()
- }
-}
-
-impl RawReader for IntoIter<KeyEvent> {
- fn next_key(&mut self, _: bool) -> Result<KeyEvent> {
- match self.next() {
- Some(key) => Ok(key),
- None => Err(ReadlineError::Eof),
- }
- }
-
- #[cfg(unix)]
- fn next_char(&mut self) -> Result<char> {
- use crate::keys::{KeyCode as K, KeyEvent as E, Modifiers as M};
- match self.next() {
- Some(E(K::Char(c), M::NONE)) => Ok(c),
- None => Err(ReadlineError::Eof),
- _ => unimplemented!(),
- }
- }
-
- fn read_pasted_text(&mut self) -> Result<String> {
- unimplemented!()
- }
-}
-
-pub struct Sink {}
-
-impl Sink {
- pub fn new() -> Sink {
- Sink {}
- }
-}
-
-impl Renderer for Sink {
- type Reader = IntoIter<KeyEvent>;
-
- fn move_cursor(&mut self, _: Position, _: Position) -> Result<()> {
- Ok(())
- }
-
- fn refresh_line(
- &mut self,
- _prompt: &str,
- _line: &LineBuffer,
- _hint: Option<&str>,
- _old_layout: &Layout,
- _new_layout: &Layout,
- _highlighter: Option<&dyn Highlighter>,
- ) -> Result<()> {
- Ok(())
- }
-
- fn calculate_position(&self, s: &str, orig: Position) -> Position {
- let mut pos = orig;
- pos.col += s.len();
- pos
- }
-
- fn write_and_flush(&self, _: &[u8]) -> Result<()> {
- Ok(())
- }
-
- fn beep(&mut self) -> Result<()> {
- Ok(())
- }
-
- fn clear_screen(&mut self) -> Result<()> {
- Ok(())
- }
-
- fn sigwinch(&self) -> bool {
- false
- }
-
- fn update_size(&mut self) {}
-
- fn get_columns(&self) -> usize {
- 80
- }
-
- fn get_rows(&self) -> usize {
- 24
- }
-
- fn colors_enabled(&self) -> bool {
- false
- }
-
- fn move_cursor_at_leftmost(&mut self, _: &mut IntoIter<KeyEvent>) -> Result<()> {
- Ok(())
- }
-}
-
-pub type Terminal = DummyTerminal;
-
-#[derive(Clone, Debug)]
-pub struct DummyTerminal {
- pub keys: Vec<KeyEvent>,
- pub cursor: usize, // cursor position before last command
- pub color_mode: ColorMode,
- pub bell_style: BellStyle,
-}
-
-impl Term for DummyTerminal {
- type Mode = Mode;
- type Reader = IntoIter<KeyEvent>;
- type Writer = Sink;
-
- fn new(
- color_mode: ColorMode,
- _stream: OutputStreamType,
- _tab_stop: usize,
- bell_style: BellStyle,
- _enable_bracketed_paste: bool,
- ) -> DummyTerminal {
- DummyTerminal {
- keys: Vec::new(),
- cursor: 0,
- color_mode,
- bell_style,
- }
- }
-
- // Init checks:
-
- #[cfg(not(target_arch = "wasm32"))]
- fn is_unsupported(&self) -> bool {
- false
- }
-
- #[cfg(target_arch = "wasm32")]
- fn is_unsupported(&self) -> bool {
- true
- }
-
- fn is_stdin_tty(&self) -> bool {
- true
- }
-
- fn is_output_tty(&self) -> bool {
- false
- }
-
- // Interactive loop:
-
- fn enable_raw_mode(&mut self) -> Result<Mode> {
- Ok(())
- }
-
- fn create_reader(&self, _: &Config) -> Result<IntoIter<KeyEvent>> {
- Ok(self.keys.clone().into_iter())
- }
-
- fn create_writer(&self) -> Sink {
- Sink::new()
- }
-}
-
-#[cfg(unix)]
-pub fn suspend() -> Result<()> {
- Ok(())
-}
diff --git a/vendor/rustyline-8.2.0/src/tty/unix.rs b/vendor/rustyline-8.2.0/src/tty/unix.rs
deleted file mode 100644
index b86a5ce..0000000
--- a/vendor/rustyline-8.2.0/src/tty/unix.rs
+++ /dev/null
@@ -1,1244 +0,0 @@
-//! Unix specific definitions
-use std::cmp;
-use std::io::{self, ErrorKind, Read, Write};
-use std::os::unix::io::{AsRawFd, RawFd};
-use std::sync;
-use std::sync::atomic::{AtomicBool, Ordering};
-
-use log::{debug, warn};
-use nix::poll::{self, PollFlags};
-use nix::sys::signal;
-use nix::sys::termios;
-use nix::sys::termios::SetArg;
-use unicode_segmentation::UnicodeSegmentation;
-use utf8parse::{Parser, Receiver};
-
-use super::{width, RawMode, RawReader, Renderer, Term};
-use crate::config::{BellStyle, ColorMode, Config, OutputStreamType};
-use crate::error;
-use crate::highlight::Highlighter;
-use crate::keys::{KeyCode as K, KeyEvent, KeyEvent as E, Modifiers as M};
-use crate::layout::{Layout, Position};
-use crate::line_buffer::LineBuffer;
-use crate::Result;
-
-const STDIN_FILENO: RawFd = libc::STDIN_FILENO;
-
-/// Unsupported Terminals that don't support RAW mode
-const UNSUPPORTED_TERM: [&str; 3] = ["dumb", "cons25", "emacs"];
-
-const BRACKETED_PASTE_ON: &[u8] = b"\x1b[?2004h";
-const BRACKETED_PASTE_OFF: &[u8] = b"\x1b[?2004l";
-
-impl AsRawFd for OutputStreamType {
- fn as_raw_fd(&self) -> RawFd {
- match self {
- OutputStreamType::Stdout => libc::STDOUT_FILENO,
- OutputStreamType::Stderr => libc::STDERR_FILENO,
- }
- }
-}
-
-nix::ioctl_read_bad!(win_size, libc::TIOCGWINSZ, libc::winsize);
-
-#[allow(clippy::useless_conversion)]
-fn get_win_size<T: AsRawFd + ?Sized>(fileno: &T) -> (usize, usize) {
- use std::mem::zeroed;
-
- if cfg!(test) {
- return (80, 24);
- }
-
- unsafe {
- let mut size: libc::winsize = zeroed();
- match win_size(fileno.as_raw_fd(), &mut size) {
- Ok(0) => {
- // In linux pseudo-terminals are created with dimensions of
- // zero. If host application didn't initialize the correct
- // size before start we treat zero size as 80 columns and
- // inifinite rows
- let cols = if size.ws_col == 0 {
- 80
- } else {
- size.ws_col as usize
- };
- let rows = if size.ws_row == 0 {
- usize::max_value()
- } else {
- size.ws_row as usize
- };
- (cols, rows)
- }
- _ => (80, 24),
- }
- }
-}
-
-/// Check TERM environment variable to see if current term is in our
-/// unsupported list
-fn is_unsupported_term() -> bool {
- match std::env::var("TERM") {
- Ok(term) => {
- for iter in &UNSUPPORTED_TERM {
- if (*iter).eq_ignore_ascii_case(&term) {
- return true;
- }
- }
- false
- }
- Err(_) => false,
- }
-}
-
-/// Return whether or not STDIN, STDOUT or STDERR is a TTY
-fn is_a_tty(fd: RawFd) -> bool {
- unsafe { libc::isatty(fd) != 0 }
-}
-
-#[must_use = "You must restore default mode (disable_raw_mode)"]
-pub struct PosixMode {
- termios: termios::Termios,
- out: Option<OutputStreamType>,
-}
-
-#[cfg(not(test))]
-pub type Mode = PosixMode;
-
-impl RawMode for PosixMode {
- /// Disable RAW mode for the terminal.
- fn disable_raw_mode(&self) -> Result<()> {
- termios::tcsetattr(STDIN_FILENO, SetArg::TCSADRAIN, &self.termios)?;
- // disable bracketed paste
- if let Some(out) = self.out {
- write_and_flush(out, BRACKETED_PASTE_OFF)?;
- }
- Ok(())
- }
-}
-
-// Rust std::io::Stdin is buffered with no way to know if bytes are available.
-// So we use low-level stuff instead...
-struct StdinRaw {}
-
-impl Read for StdinRaw {
- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- loop {
- let res = unsafe {
- libc::read(
- STDIN_FILENO,
- buf.as_mut_ptr() as *mut libc::c_void,
- buf.len() as libc::size_t,
- )
- };
- if res == -1 {
- let error = io::Error::last_os_error();
- if error.kind() != ErrorKind::Interrupted || SIGWINCH.load(Ordering::Relaxed) {
- return Err(error);
- }
- } else {
- #[allow(clippy::cast_sign_loss)]
- return Ok(res as usize);
- }
- }
- }
-}
-
-/// Console input reader
-pub struct PosixRawReader {
- stdin: StdinRaw,
- timeout_ms: i32,
- buf: [u8; 1],
- parser: Parser,
- receiver: Utf8,
-}
-
-struct Utf8 {
- c: Option<char>,
- valid: bool,
-}
-
-const UP: char = 'A'; // kcuu1, kUP*
-const DOWN: char = 'B'; // kcud1, kDN*
-const RIGHT: char = 'C'; // kcuf1, kRIT*
-const LEFT: char = 'D'; // kcub1, kLFT*
-const END: char = 'F'; // kend*
-const HOME: char = 'H'; // khom*
-const INSERT: char = '2'; // kic*
-const DELETE: char = '3'; // kdch1, kDC*
-const PAGE_UP: char = '5'; // kpp, kPRV*
-const PAGE_DOWN: char = '6'; // knp, kNXT*
-
-const RXVT_HOME: char = '7';
-const RXVT_END: char = '8';
-
-const SHIFT: char = '2';
-const ALT: char = '3';
-const ALT_SHIFT: char = '4';
-const CTRL: char = '5';
-const CTRL_SHIFT: char = '6';
-const CTRL_ALT: char = '7';
-const CTRL_ALT_SHIFT: char = '8';
-
-const RXVT_SHIFT: char = '$';
-const RXVT_CTRL: char = '\x1e';
-const RXVT_CTRL_SHIFT: char = '@';
-
-impl PosixRawReader {
- fn new(config: &Config) -> Self {
- Self {
- stdin: StdinRaw {},
- timeout_ms: config.keyseq_timeout(),
- buf: [0; 1],
- parser: Parser::new(),
- receiver: Utf8 {
- c: None,
- valid: true,
- },
- }
- }
-
- /// Handle \E <seq1> sequences
- // https://invisible-island.net/xterm/xterm-function-keys.html
- fn escape_sequence(&mut self) -> Result<KeyEvent> {
- self._do_escape_sequence(true)
- }
-
- /// Don't call directly, call `PosixRawReader::escape_sequence` instead
- fn _do_escape_sequence(&mut self, allow_recurse: bool) -> Result<KeyEvent> {
- // Read the next byte representing the escape sequence.
- let seq1 = self.next_char()?;
- if seq1 == '[' {
- // \E[ sequences. (CSI)
- self.escape_csi()
- } else if seq1 == 'O' {
- // xterm
- // \EO sequences. (SS3)
- self.escape_o()
- } else if seq1 == '\x1b' {
- // \E\E — used by rxvt, iTerm (under default config), etc.
- // ```
- // \E\E[A => Alt-Up
- // \E\E[B => Alt-Down
- // \E\E[C => Alt-Right
- // \E\E[D => Alt-Left
- // ```
- //
- // In general this more or less works just adding ALT to an existing
- // key, but has a wrinkle in that `ESC ESC` without anything
- // following should be interpreted as the the escape key.
- //
- // We hanlde this by polling to see if there's anything coming
- // within our timeout, and if so, recursing once, but adding alt to
- // what we read.
- if !allow_recurse {
- return Ok(E::ESC);
- }
- let timeout = if self.timeout_ms < 0 {
- 100
- } else {
- self.timeout_ms
- };
- match self.poll(timeout) {
- // Ignore poll errors, it's very likely we'll pick them up on
- // the next read anyway.
- Ok(0) | Err(_) => Ok(E::ESC),
- Ok(n) => {
- debug_assert!(n > 0, "{}", n);
- // recurse, and add the alt modifier.
- let E(k, m) = self._do_escape_sequence(false)?;
- Ok(E(k, m | M::ALT))
- }
- }
- } else {
- Ok(E::alt(seq1))
- }
- }
-
- /// Handle \E[ <seq2> escape sequences
- fn escape_csi(&mut self) -> Result<KeyEvent> {
- let seq2 = self.next_char()?;
- if seq2.is_digit(10) {
- match seq2 {
- '0' | '9' => {
- debug!(target: "rustyline", "unsupported esc sequence: \\E[{:?}", seq2);
- Ok(E(K::UnknownEscSeq, M::NONE))
- }
- _ => {
- // Extended escape, read additional byte.
- self.extended_escape(seq2)
- }
- }
- } else if seq2 == '[' {
- let seq3 = self.next_char()?;
- // Linux console
- Ok(match seq3 {
- 'A' => E(K::F(1), M::NONE),
- 'B' => E(K::F(2), M::NONE),
- 'C' => E(K::F(3), M::NONE),
- 'D' => E(K::F(4), M::NONE),
- 'E' => E(K::F(5), M::NONE),
- _ => {
- debug!(target: "rustyline", "unsupported esc sequence: \\E[[{:?}", seq3);
- E(K::UnknownEscSeq, M::NONE)
- }
- })
- } else {
- // ANSI
- Ok(match seq2 {
- UP => E(K::Up, M::NONE),
- DOWN => E(K::Down, M::NONE),
- RIGHT => E(K::Right, M::NONE),
- LEFT => E(K::Left, M::NONE),
- //'E' => E(K::, M::), // Ignore
- END => E(K::End, M::NONE),
- //'G' => E(K::, M::), // Ignore
- HOME => E(K::Home, M::NONE), // khome
- //'J' => E(K::, M::), // clr_eos
- //'K' => E(K::, M::), // clr_eol
- //'L' => E(K::, M::), // il1
- //'M' => E(K::, M::), // kmous
- //'P' => E(K::Delete, M::NONE), // dch1
- 'Z' => E(K::BackTab, M::NONE),
- 'a' => E(K::Up, M::SHIFT), // rxvt: kind or kUP
- 'b' => E(K::Down, M::SHIFT), // rxvt: kri or kDN
- 'c' => E(K::Right, M::SHIFT), // rxvt
- 'd' => E(K::Left, M::SHIFT), // rxvt
- _ => {
- debug!(target: "rustyline", "unsupported esc sequence: \\E[{:?}", seq2);
- E(K::UnknownEscSeq, M::NONE)
- }
- })
- }
- }
-
- /// Handle \E[ <seq2:digit> escape sequences
- #[allow(clippy::cognitive_complexity)]
- fn extended_escape(&mut self, seq2: char) -> Result<KeyEvent> {
- let seq3 = self.next_char()?;
- if seq3 == '~' {
- Ok(match seq2 {
- '1' | RXVT_HOME => E(K::Home, M::NONE), // tmux, xrvt
- INSERT => E(K::Insert, M::NONE),
- DELETE => E(K::Delete, M::NONE),
- '4' | RXVT_END => E(K::End, M::NONE), // tmux, xrvt
- PAGE_UP => E(K::PageUp, M::NONE),
- PAGE_DOWN => E(K::PageDown, M::NONE),
- _ => {
- debug!(target: "rustyline",
- "unsupported esc sequence: \\E[{}~", seq2);
- E(K::UnknownEscSeq, M::NONE)
- }
- })
- } else if seq3.is_digit(10) {
- let seq4 = self.next_char()?;
- if seq4 == '~' {
- Ok(match (seq2, seq3) {
- ('1', '1') => E(K::F(1), M::NONE), // rxvt-unicode
- ('1', '2') => E(K::F(2), M::NONE), // rxvt-unicode
- ('1', '3') => E(K::F(3), M::NONE), // rxvt-unicode
- ('1', '4') => E(K::F(4), M::NONE), // rxvt-unicode
- ('1', '5') => E(K::F(5), M::NONE), // kf5
- ('1', '7') => E(K::F(6), M::NONE), // kf6
- ('1', '8') => E(K::F(7), M::NONE), // kf7
- ('1', '9') => E(K::F(8), M::NONE), // kf8
- ('2', '0') => E(K::F(9), M::NONE), // kf9
- ('2', '1') => E(K::F(10), M::NONE), // kf10
- ('2', '3') => E(K::F(11), M::NONE), // kf11
- ('2', '4') => E(K::F(12), M::NONE), // kf12
- //('6', '2') => KeyCode::ScrollUp,
- //('6', '3') => KeyCode::ScrollDown,
- _ => {
- debug!(target: "rustyline",
- "unsupported esc sequence: \\E[{}{}~", seq2, seq3);
- E(K::UnknownEscSeq, M::NONE)
- }
- })
- } else if seq4 == ';' {
- let seq5 = self.next_char()?;
- if seq5.is_digit(10) {
- let seq6 = self.next_char()?;
- if seq6.is_digit(10) {
- self.next_char()?; // 'R' expected
- Ok(E(K::UnknownEscSeq, M::NONE))
- } else if seq6 == 'R' {
- Ok(E(K::UnknownEscSeq, M::NONE))
- } else if seq6 == '~' {
- Ok(match (seq2, seq3, seq5) {
- ('1', '5', CTRL) => E(K::F(5), M::CTRL),
- //('1', '5', '6') => E(K::F(17), M::CTRL),
- ('1', '7', CTRL) => E(K::F(6), M::CTRL),
- //('1', '7', '6') => E(K::F(18), M::CTRL),
- ('1', '8', CTRL) => E(K::F(7), M::CTRL),
- ('1', '9', CTRL) => E(K::F(8), M::CTRL),
- //('1', '9', '6') => E(K::F(19), M::CTRL),
- ('2', '0', CTRL) => E(K::F(9), M::CTRL),
- //('2', '0', '6') => E(K::F(21), M::CTRL),
- ('2', '1', CTRL) => E(K::F(10), M::CTRL),
- //('2', '1', '6') => E(K::F(22), M::CTRL),
- ('2', '3', CTRL) => E(K::F(11), M::CTRL),
- //('2', '3', '6') => E(K::F(23), M::CTRL),
- ('2', '4', CTRL) => E(K::F(12), M::CTRL),
- //('2', '4', '6') => E(K::F(24), M::CTRL),
- _ => {
- debug!(target: "rustyline",
- "unsupported esc sequence: \\E[{}{};{}~", seq2, seq3, seq5);
- E(K::UnknownEscSeq, M::NONE)
- }
- })
- } else {
- debug!(target: "rustyline",
- "unsupported esc sequence: \\E[{}{};{}{}", seq2, seq3, seq5, seq6);
- Ok(E(K::UnknownEscSeq, M::NONE))
- }
- } else {
- debug!(target: "rustyline",
- "unsupported esc sequence: \\E[{}{};{:?}", seq2, seq3, seq5);
- Ok(E(K::UnknownEscSeq, M::NONE))
- }
- } else if seq4.is_digit(10) {
- let seq5 = self.next_char()?;
- if seq5 == '~' {
- Ok(match (seq2, seq3, seq4) {
- ('2', '0', '0') => E(K::BracketedPasteStart, M::NONE),
- ('2', '0', '1') => E(K::BracketedPasteEnd, M::NONE),
- _ => {
- debug!(target: "rustyline",
- "unsupported esc sequence: \\E[{}{}{}~", seq2, seq3, seq4);
- E(K::UnknownEscSeq, M::NONE)
- }
- })
- } else {
- debug!(target: "rustyline",
- "unsupported esc sequence: \\E[{}{}{}{}", seq2, seq3, seq4, seq5);
- Ok(E(K::UnknownEscSeq, M::NONE))
- }
- } else {
- debug!(target: "rustyline",
- "unsupported esc sequence: \\E[{}{}{:?}", seq2, seq3, seq4);
- Ok(E(K::UnknownEscSeq, M::NONE))
- }
- } else if seq3 == ';' {
- let seq4 = self.next_char()?;
- if seq4.is_digit(10) {
- let seq5 = self.next_char()?;
- if seq5.is_digit(10) {
- self.next_char()?; // 'R' expected
- //('1', '0', UP) => E(K::, M::), // Alt + Shift + Up
- Ok(E(K::UnknownEscSeq, M::NONE))
- } else if seq2 == '1' {
- Ok(match (seq4, seq5) {
- (SHIFT, UP) => E(K::Up, M::SHIFT), // ~ key_sr
- (SHIFT, DOWN) => E(K::Down, M::SHIFT), // ~ key_sf
- (SHIFT, RIGHT) => E(K::Right, M::SHIFT),
- (SHIFT, LEFT) => E(K::Left, M::SHIFT),
- (SHIFT, END) => E(K::End, M::SHIFT), // kEND
- (SHIFT, HOME) => E(K::Home, M::SHIFT), // kHOM
- //('2', 'P') => E(K::F(13), M::NONE),
- //('2', 'Q') => E(K::F(14), M::NONE),
- //('2', 'S') => E(K::F(16), M::NONE),
- (ALT, UP) => E(K::Up, M::ALT),
- (ALT, DOWN) => E(K::Down, M::ALT),
- (ALT, RIGHT) => E(K::Right, M::ALT),
- (ALT, LEFT) => E(K::Left, M::ALT),
- (ALT, END) => E(K::End, M::ALT),
- (ALT, HOME) => E(K::Home, M::ALT),
- (ALT_SHIFT, UP) => E(K::Up, M::ALT_SHIFT),
- (ALT_SHIFT, DOWN) => E(K::Down, M::ALT_SHIFT),
- (ALT_SHIFT, RIGHT) => E(K::Right, M::ALT_SHIFT),
- (ALT_SHIFT, LEFT) => E(K::Left, M::ALT_SHIFT),
- (ALT_SHIFT, END) => E(K::End, M::ALT_SHIFT),
- (ALT_SHIFT, HOME) => E(K::Home, M::ALT_SHIFT),
- (CTRL, UP) => E(K::Up, M::CTRL),
- (CTRL, DOWN) => E(K::Down, M::CTRL),
- (CTRL, RIGHT) => E(K::Right, M::CTRL),
- (CTRL, LEFT) => E(K::Left, M::CTRL),
- (CTRL, END) => E(K::End, M::CTRL),
- (CTRL, HOME) => E(K::Home, M::CTRL),
- (CTRL, 'P') => E(K::F(1), M::CTRL),
- (CTRL, 'Q') => E(K::F(2), M::CTRL),
- (CTRL, 'S') => E(K::F(4), M::CTRL),
- (CTRL, 'p') => E(K::Char('0'), M::CTRL),
- (CTRL, 'q') => E(K::Char('1'), M::CTRL),
- (CTRL, 'r') => E(K::Char('2'), M::CTRL),
- (CTRL, 's') => E(K::Char('3'), M::CTRL),
- (CTRL, 't') => E(K::Char('4'), M::CTRL),
- (CTRL, 'u') => E(K::Char('5'), M::CTRL),
- (CTRL, 'v') => E(K::Char('6'), M::CTRL),
- (CTRL, 'w') => E(K::Char('7'), M::CTRL),
- (CTRL, 'x') => E(K::Char('8'), M::CTRL),
- (CTRL, 'y') => E(K::Char('9'), M::CTRL),
- (CTRL_SHIFT, UP) => E(K::Up, M::CTRL_SHIFT),
- (CTRL_SHIFT, DOWN) => E(K::Down, M::CTRL_SHIFT),
- (CTRL_SHIFT, RIGHT) => E(K::Right, M::CTRL_SHIFT),
- (CTRL_SHIFT, LEFT) => E(K::Left, M::CTRL_SHIFT),
- (CTRL_SHIFT, END) => E(K::End, M::CTRL_SHIFT),
- (CTRL_SHIFT, HOME) => E(K::Home, M::CTRL_SHIFT),
- //('6', 'P') => E(K::F(13), M::CTRL),
- //('6', 'Q') => E(K::F(14), M::CTRL),
- //('6', 'S') => E(K::F(16), M::CTRL),
- (CTRL_SHIFT, 'p') => E(K::Char('0'), M::CTRL_SHIFT),
- (CTRL_SHIFT, 'q') => E(K::Char('1'), M::CTRL_SHIFT),
- (CTRL_SHIFT, 'r') => E(K::Char('2'), M::CTRL_SHIFT),
- (CTRL_SHIFT, 's') => E(K::Char('3'), M::CTRL_SHIFT),
- (CTRL_SHIFT, 't') => E(K::Char('4'), M::CTRL_SHIFT),
- (CTRL_SHIFT, 'u') => E(K::Char('5'), M::CTRL_SHIFT),
- (CTRL_SHIFT, 'v') => E(K::Char('6'), M::CTRL_SHIFT),
- (CTRL_SHIFT, 'w') => E(K::Char('7'), M::CTRL_SHIFT),
- (CTRL_SHIFT, 'x') => E(K::Char('8'), M::CTRL_SHIFT),
- (CTRL_SHIFT, 'y') => E(K::Char('9'), M::CTRL_SHIFT),
- (CTRL_ALT, UP) => E(K::Up, M::CTRL_ALT),
- (CTRL_ALT, DOWN) => E(K::Down, M::CTRL_ALT),
- (CTRL_ALT, RIGHT) => E(K::Right, M::CTRL_ALT),
- (CTRL_ALT, LEFT) => E(K::Left, M::CTRL_ALT),
- (CTRL_ALT, END) => E(K::End, M::CTRL_ALT),
- (CTRL_ALT, HOME) => E(K::Home, M::CTRL_ALT),
- (CTRL_ALT, 'p') => E(K::Char('0'), M::CTRL_ALT),
- (CTRL_ALT, 'q') => E(K::Char('1'), M::CTRL_ALT),
- (CTRL_ALT, 'r') => E(K::Char('2'), M::CTRL_ALT),
- (CTRL_ALT, 's') => E(K::Char('3'), M::CTRL_ALT),
- (CTRL_ALT, 't') => E(K::Char('4'), M::CTRL_ALT),
- (CTRL_ALT, 'u') => E(K::Char('5'), M::CTRL_ALT),
- (CTRL_ALT, 'v') => E(K::Char('6'), M::CTRL_ALT),
- (CTRL_ALT, 'w') => E(K::Char('7'), M::CTRL_ALT),
- (CTRL_ALT, 'x') => E(K::Char('8'), M::CTRL_ALT),
- (CTRL_ALT, 'y') => E(K::Char('9'), M::CTRL_ALT),
- (CTRL_ALT_SHIFT, UP) => E(K::Up, M::CTRL_ALT_SHIFT),
- (CTRL_ALT_SHIFT, DOWN) => E(K::Down, M::CTRL_ALT_SHIFT),
- (CTRL_ALT_SHIFT, RIGHT) => E(K::Right, M::CTRL_ALT_SHIFT),
- (CTRL_ALT_SHIFT, LEFT) => E(K::Left, M::CTRL_ALT_SHIFT),
- (CTRL_ALT_SHIFT, END) => E(K::End, M::CTRL_ALT_SHIFT),
- (CTRL_ALT_SHIFT, HOME) => E(K::Home, M::CTRL_ALT_SHIFT),
- (CTRL_ALT_SHIFT, 'p') => E(K::Char('0'), M::CTRL_ALT_SHIFT),
- (CTRL_ALT_SHIFT, 'q') => E(K::Char('1'), M::CTRL_ALT_SHIFT),
- (CTRL_ALT_SHIFT, 'r') => E(K::Char('2'), M::CTRL_ALT_SHIFT),
- (CTRL_ALT_SHIFT, 's') => E(K::Char('3'), M::CTRL_ALT_SHIFT),
- (CTRL_ALT_SHIFT, 't') => E(K::Char('4'), M::CTRL_ALT_SHIFT),
- (CTRL_ALT_SHIFT, 'u') => E(K::Char('5'), M::CTRL_ALT_SHIFT),
- (CTRL_ALT_SHIFT, 'v') => E(K::Char('6'), M::CTRL_ALT_SHIFT),
- (CTRL_ALT_SHIFT, 'w') => E(K::Char('7'), M::CTRL_ALT_SHIFT),
- (CTRL_ALT_SHIFT, 'x') => E(K::Char('8'), M::CTRL_ALT_SHIFT),
- (CTRL_ALT_SHIFT, 'y') => E(K::Char('9'), M::CTRL_ALT_SHIFT),
- // Meta + arrow on (some?) Macs when using iTerm defaults
- ('9', UP) => E(K::Up, M::ALT),
- ('9', DOWN) => E(K::Down, M::ALT),
- ('9', RIGHT) => E(K::Right, M::ALT),
- ('9', LEFT) => E(K::Left, M::ALT),
- _ => {
- debug!(target: "rustyline",
- "unsupported esc sequence: \\E[1;{}{:?}", seq4, seq5);
- E(K::UnknownEscSeq, M::NONE)
- }
- })
- } else if seq5 == '~' {
- Ok(match (seq2, seq4) {
- (INSERT, SHIFT) => E(K::Insert, M::SHIFT),
- (INSERT, ALT) => E(K::Insert, M::ALT),
- (INSERT, ALT_SHIFT) => E(K::Insert, M::ALT_SHIFT),
- (INSERT, CTRL) => E(K::Insert, M::CTRL),
- (INSERT, CTRL_SHIFT) => E(K::Insert, M::CTRL_SHIFT),
- (INSERT, CTRL_ALT) => E(K::Insert, M::CTRL_ALT),
- (INSERT, CTRL_ALT_SHIFT) => E(K::Insert, M::CTRL_ALT_SHIFT),
- (DELETE, SHIFT) => E(K::Delete, M::SHIFT),
- (DELETE, ALT) => E(K::Delete, M::ALT),
- (DELETE, ALT_SHIFT) => E(K::Delete, M::ALT_SHIFT),
- (DELETE, CTRL) => E(K::Delete, M::CTRL),
- (DELETE, CTRL_SHIFT) => E(K::Delete, M::CTRL_SHIFT),
- (DELETE, CTRL_ALT) => E(K::Delete, M::CTRL_ALT),
- (DELETE, CTRL_ALT_SHIFT) => E(K::Delete, M::CTRL_ALT_SHIFT),
- (PAGE_UP, SHIFT) => E(K::PageUp, M::SHIFT),
- (PAGE_UP, ALT) => E(K::PageUp, M::ALT),
- (PAGE_UP, ALT_SHIFT) => E(K::PageUp, M::ALT_SHIFT),
- (PAGE_UP, CTRL) => E(K::PageUp, M::CTRL),
- (PAGE_UP, CTRL_SHIFT) => E(K::PageUp, M::CTRL_SHIFT),
- (PAGE_UP, CTRL_ALT) => E(K::PageUp, M::CTRL_ALT),
- (PAGE_UP, CTRL_ALT_SHIFT) => E(K::PageUp, M::CTRL_ALT_SHIFT),
- (PAGE_DOWN, SHIFT) => E(K::PageDown, M::SHIFT),
- (PAGE_DOWN, ALT) => E(K::PageDown, M::ALT),
- (PAGE_DOWN, ALT_SHIFT) => E(K::PageDown, M::ALT_SHIFT),
- (PAGE_DOWN, CTRL) => E(K::PageDown, M::CTRL),
- (PAGE_DOWN, CTRL_SHIFT) => E(K::PageDown, M::CTRL_SHIFT),
- (PAGE_DOWN, CTRL_ALT) => E(K::PageDown, M::CTRL_ALT),
- (PAGE_DOWN, CTRL_ALT_SHIFT) => E(K::PageDown, M::CTRL_ALT_SHIFT),
- _ => {
- debug!(target: "rustyline",
- "unsupported esc sequence: \\E[{};{:?}~", seq2, seq4);
- E(K::UnknownEscSeq, M::NONE)
- }
- })
- } else {
- debug!(target: "rustyline",
- "unsupported esc sequence: \\E[{};{}{:?}", seq2, seq4, seq5);
- Ok(E(K::UnknownEscSeq, M::NONE))
- }
- } else {
- debug!(target: "rustyline",
- "unsupported esc sequence: \\E[{};{:?}", seq2, seq4);
- Ok(E(K::UnknownEscSeq, M::NONE))
- }
- } else {
- Ok(match (seq2, seq3) {
- (DELETE, RXVT_CTRL) => E(K::Delete, M::CTRL),
- (DELETE, RXVT_CTRL_SHIFT) => E(K::Delete, M::CTRL_SHIFT),
- (CTRL, UP) => E(K::Up, M::CTRL),
- (CTRL, DOWN) => E(K::Down, M::CTRL),
- (CTRL, RIGHT) => E(K::Right, M::CTRL),
- (CTRL, LEFT) => E(K::Left, M::CTRL),
- (PAGE_UP, RXVT_CTRL) => E(K::PageUp, M::CTRL),
- (PAGE_UP, RXVT_SHIFT) => E(K::PageUp, M::SHIFT),
- (PAGE_UP, RXVT_CTRL_SHIFT) => E(K::PageUp, M::CTRL_SHIFT),
- (PAGE_DOWN, RXVT_CTRL) => E(K::PageDown, M::CTRL),
- (PAGE_DOWN, RXVT_SHIFT) => E(K::PageDown, M::SHIFT),
- (PAGE_DOWN, RXVT_CTRL_SHIFT) => E(K::PageDown, M::CTRL_SHIFT),
- (RXVT_HOME, RXVT_CTRL) => E(K::Home, M::CTRL),
- (RXVT_HOME, RXVT_SHIFT) => E(K::Home, M::SHIFT),
- (RXVT_HOME, RXVT_CTRL_SHIFT) => E(K::Home, M::CTRL_SHIFT),
- (RXVT_END, RXVT_CTRL) => E(K::End, M::CTRL), // kEND5 or kel
- (RXVT_END, RXVT_SHIFT) => E(K::End, M::SHIFT),
- (RXVT_END, RXVT_CTRL_SHIFT) => E(K::End, M::CTRL_SHIFT),
- _ => {
- debug!(target: "rustyline",
- "unsupported esc sequence: \\E[{}{:?}", seq2, seq3);
- E(K::UnknownEscSeq, M::NONE)
- }
- })
- }
- }
-
- /// Handle \EO <seq2> escape sequences
- fn escape_o(&mut self) -> Result<KeyEvent> {
- let seq2 = self.next_char()?;
- Ok(match seq2 {
- UP => E(K::Up, M::NONE),
- DOWN => E(K::Down, M::NONE),
- RIGHT => E(K::Right, M::NONE),
- LEFT => E(K::Left, M::NONE),
- //'E' => E(K::, M::),// key_b2, kb2
- END => E(K::End, M::NONE), // kend
- HOME => E(K::Home, M::NONE), // khome
- 'M' => E::ENTER, // kent
- 'P' => E(K::F(1), M::NONE), // kf1
- 'Q' => E(K::F(2), M::NONE), // kf2
- 'R' => E(K::F(3), M::NONE), // kf3
- 'S' => E(K::F(4), M::NONE), // kf4
- 'a' => E(K::Up, M::CTRL),
- 'b' => E(K::Down, M::CTRL),
- 'c' => E(K::Right, M::CTRL), // rxvt
- 'd' => E(K::Left, M::CTRL), // rxvt
- 'l' => E(K::F(8), M::NONE),
- 't' => E(K::F(5), M::NONE), // kf5 or kb1
- 'u' => E(K::F(6), M::NONE), // kf6 or kb2
- 'v' => E(K::F(7), M::NONE), // kf7 or kb3
- 'w' => E(K::F(9), M::NONE), // kf9 or ka1
- 'x' => E(K::F(10), M::NONE), // kf10 or ka2
- _ => {
- debug!(target: "rustyline", "unsupported esc sequence: \\EO{:?}", seq2);
- E(K::UnknownEscSeq, M::NONE)
- }
- })
- }
-
- fn poll(&mut self, timeout_ms: i32) -> ::nix::Result<i32> {
- let mut fds = [poll::PollFd::new(STDIN_FILENO, PollFlags::POLLIN)];
- let r = poll::poll(&mut fds, timeout_ms);
- match r {
- Ok(_) => r,
- Err(nix::Error::Sys(nix::errno::Errno::EINTR)) => {
- if SIGWINCH.load(Ordering::Relaxed) {
- r
- } else {
- Ok(0) // Ignore EINTR while polling
- }
- }
- Err(_) => r,
- }
- }
-}
-
-impl RawReader for PosixRawReader {
- fn next_key(&mut self, single_esc_abort: bool) -> Result<KeyEvent> {
- let c = self.next_char()?;
-
- let mut key = KeyEvent::new(c, M::NONE);
- if key == E::ESC {
- let timeout_ms = if single_esc_abort && self.timeout_ms == -1 {
- 0
- } else {
- self.timeout_ms
- };
- match self.poll(timeout_ms) {
- Ok(n) if n == 0 => {
- // single escape
- }
- Ok(_) => {
- // escape sequence
- key = self.escape_sequence()?
- }
- // Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
- Err(e) => return Err(e.into()),
- }
- }
- debug!(target: "rustyline", "key: {:?}", key);
- Ok(key)
- }
-
- fn next_char(&mut self) -> Result<char> {
- loop {
- let n = self.stdin.read(&mut self.buf)?;
- if n == 0 {
- return Err(error::ReadlineError::Eof);
- }
- let b = self.buf[0];
- self.parser.advance(&mut self.receiver, b);
- if !self.receiver.valid {
- return Err(error::ReadlineError::Utf8Error);
- } else if let Some(c) = self.receiver.c.take() {
- return Ok(c);
- }
- }
- }
-
- fn read_pasted_text(&mut self) -> Result<String> {
- let mut buffer = String::new();
- loop {
- match self.next_char()? {
- '\x1b' => {
- let key = self.escape_sequence()?;
- if key == E(K::BracketedPasteEnd, M::NONE) {
- break;
- } else {
- continue; // TODO validate
- }
- }
- c => buffer.push(c),
- };
- }
- let buffer = buffer.replace("\r\n", "\n");
- let buffer = buffer.replace("\r", "\n");
- Ok(buffer)
- }
-}
-
-impl Receiver for Utf8 {
- /// Called whenever a code point is parsed successfully
- fn codepoint(&mut self, c: char) {
- self.c = Some(c);
- self.valid = true;
- }
-
- /// Called when an invalid_sequence is detected
- fn invalid_sequence(&mut self) {
- self.c = None;
- self.valid = false;
- }
-}
-
-/// Console output writer
-pub struct PosixRenderer {
- out: OutputStreamType,
- cols: usize, // Number of columns in terminal
- buffer: String,
- tab_stop: usize,
- colors_enabled: bool,
- bell_style: BellStyle,
-}
-
-impl PosixRenderer {
- fn new(
- out: OutputStreamType,
- tab_stop: usize,
- colors_enabled: bool,
- bell_style: BellStyle,
- ) -> Self {
- let (cols, _) = get_win_size(&out);
- Self {
- out,
- cols,
- buffer: String::with_capacity(1024),
- tab_stop,
- colors_enabled,
- bell_style,
- }
- }
-
- fn clear_old_rows(&mut self, layout: &Layout) {
- use std::fmt::Write;
- let current_row = layout.cursor.row;
- let old_rows = layout.end.row;
- // old_rows < cursor_row if the prompt spans multiple lines and if
- // this is the default State.
- let cursor_row_movement = old_rows.saturating_sub(current_row);
- // move the cursor down as required
- if cursor_row_movement > 0 {
- write!(self.buffer, "\x1b[{}B", cursor_row_movement).unwrap();
- }
- // clear old rows
- for _ in 0..old_rows {
- self.buffer.push_str("\r\x1b[0K\x1b[A");
- }
- // clear the line
- self.buffer.push_str("\r\x1b[0K");
- }
-}
-
-impl Renderer for PosixRenderer {
- type Reader = PosixRawReader;
-
- fn move_cursor(&mut self, old: Position, new: Position) -> Result<()> {
- use std::fmt::Write;
- self.buffer.clear();
- let row_ordering = new.row.cmp(&old.row);
- if row_ordering == cmp::Ordering::Greater {
- // move down
- let row_shift = new.row - old.row;
- if row_shift == 1 {
- self.buffer.push_str("\x1b[B");
- } else {
- write!(self.buffer, "\x1b[{}B", row_shift).unwrap();
- }
- } else if row_ordering == cmp::Ordering::Less {
- // move up
- let row_shift = old.row - new.row;
- if row_shift == 1 {
- self.buffer.push_str("\x1b[A");
- } else {
- write!(self.buffer, "\x1b[{}A", row_shift).unwrap();
- }
- }
- let col_ordering = new.col.cmp(&old.col);
- if col_ordering == cmp::Ordering::Greater {
- // move right
- let col_shift = new.col - old.col;
- if col_shift == 1 {
- self.buffer.push_str("\x1b[C");
- } else {
- write!(self.buffer, "\x1b[{}C", col_shift).unwrap();
- }
- } else if col_ordering == cmp::Ordering::Less {
- // move left
- let col_shift = old.col - new.col;
- if col_shift == 1 {
- self.buffer.push_str("\x1b[D");
- } else {
- write!(self.buffer, "\x1b[{}D", col_shift).unwrap();
- }
- }
- self.write_and_flush(self.buffer.as_bytes())
- }
-
- fn refresh_line(
- &mut self,
- prompt: &str,
- line: &LineBuffer,
- hint: Option<&str>,
- old_layout: &Layout,
- new_layout: &Layout,
- highlighter: Option<&dyn Highlighter>,
- ) -> Result<()> {
- use std::fmt::Write;
- self.buffer.clear();
-
- let default_prompt = new_layout.default_prompt;
- let cursor = new_layout.cursor;
- let end_pos = new_layout.end;
-
- self.clear_old_rows(old_layout);
-
- if let Some(highlighter) = highlighter {
- // display the prompt
- self.buffer
- .push_str(&highlighter.highlight_prompt(prompt, default_prompt));
- // display the input line
- self.buffer
- .push_str(&highlighter.highlight(line, line.pos()));
- } else {
- // display the prompt
- self.buffer.push_str(prompt);
- // display the input line
- self.buffer.push_str(line);
- }
- // display hint
- if let Some(hint) = hint {
- if let Some(highlighter) = highlighter {
- self.buffer.push_str(&highlighter.highlight_hint(hint));
- } else {
- self.buffer.push_str(hint);
- }
- }
- // we have to generate our own newline on line wrap
- if end_pos.col == 0
- && end_pos.row > 0
- && !hint
- .map(|h| h.ends_with('\n'))
- .unwrap_or_else(|| line.ends_with('\n'))
- {
- self.buffer.push('\n');
- }
- // position the cursor
- let new_cursor_row_movement = end_pos.row - cursor.row;
- // move the cursor up as required
- if new_cursor_row_movement > 0 {
- write!(self.buffer, "\x1b[{}A", new_cursor_row_movement).unwrap();
- }
- // position the cursor within the line
- if cursor.col > 0 {
- write!(self.buffer, "\r\x1b[{}C", cursor.col).unwrap();
- } else {
- self.buffer.push('\r');
- }
-
- self.write_and_flush(self.buffer.as_bytes())?;
-
- Ok(())
- }
-
- fn write_and_flush(&self, buf: &[u8]) -> Result<()> {
- write_and_flush(self.out, buf)
- }
-
- /// Control characters are treated as having zero width.
- /// Characters with 2 column width are correctly handled (not split).
- fn calculate_position(&self, s: &str, orig: Position) -> Position {
- let mut pos = orig;
- let mut esc_seq = 0;
- for c in s.graphemes(true) {
- if c == "\n" {
- pos.row += 1;
- pos.col = 0;
- continue;
- }
- let cw = if c == "\t" {
- self.tab_stop - (pos.col % self.tab_stop)
- } else {
- width(c, &mut esc_seq)
- };
- pos.col += cw;
- if pos.col > self.cols {
- pos.row += 1;
- pos.col = cw;
- }
- }
- if pos.col == self.cols {
- pos.col = 0;
- pos.row += 1;
- }
- pos
- }
-
- fn beep(&mut self) -> Result<()> {
- match self.bell_style {
- BellStyle::Audible => {
- io::stderr().write_all(b"\x07")?;
- io::stderr().flush()?;
- Ok(())
- }
- _ => Ok(()),
- }
- }
-
- /// Clear the screen. Used to handle ctrl+l
- fn clear_screen(&mut self) -> Result<()> {
- self.write_and_flush(b"\x1b[H\x1b[2J")
- }
-
- /// Check if a SIGWINCH signal has been received
- fn sigwinch(&self) -> bool {
- SIGWINCH
- .compare_exchange(true, false, Ordering::SeqCst, Ordering::SeqCst)
- .unwrap_or(false)
- }
-
- /// Try to update the number of columns in the current terminal,
- fn update_size(&mut self) {
- let (cols, _) = get_win_size(&self.out);
- self.cols = cols;
- }
-
- fn get_columns(&self) -> usize {
- self.cols
- }
-
- /// Try to get the number of rows in the current terminal,
- /// or assume 24 if it fails.
- fn get_rows(&self) -> usize {
- let (_, rows) = get_win_size(&self.out);
- rows
- }
-
- fn colors_enabled(&self) -> bool {
- self.colors_enabled
- }
-
- fn move_cursor_at_leftmost(&mut self, rdr: &mut PosixRawReader) -> Result<()> {
- if rdr.poll(0)? != 0 {
- debug!(target: "rustyline", "cannot request cursor location");
- return Ok(());
- }
- /* Report cursor location */
- self.write_and_flush(b"\x1b[6n")?;
- /* Read the response: ESC [ rows ; cols R */
- if rdr.poll(100)? == 0
- || rdr.next_char()? != '\x1b'
- || rdr.next_char()? != '['
- || read_digits_until(rdr, ';')?.is_none()
- {
- warn!(target: "rustyline", "cannot read initial cursor location");
- return Ok(());
- }
- let col = read_digits_until(rdr, 'R')?;
- debug!(target: "rustyline", "initial cursor location: {:?}", col);
- if col.is_some() && col != Some(1) {
- self.write_and_flush(b"\n")?;
- }
- Ok(())
- }
-}
-
-fn read_digits_until(rdr: &mut PosixRawReader, sep: char) -> Result<Option<u32>> {
- let mut num: u32 = 0;
- loop {
- match rdr.next_char()? {
- digit @ '0'..='9' => {
- num = num
- .saturating_mul(10)
- .saturating_add(digit.to_digit(10).unwrap());
- continue;
- }
- c if c == sep => break,
- _ => return Ok(None),
- }
- }
- Ok(Some(num))
-}
-
-static SIGWINCH_ONCE: sync::Once = sync::Once::new();
-static SIGWINCH: AtomicBool = AtomicBool::new(false);
-
-fn install_sigwinch_handler() {
- SIGWINCH_ONCE.call_once(|| unsafe {
- let sigwinch = signal::SigAction::new(
- signal::SigHandler::Handler(sigwinch_handler),
- signal::SaFlags::empty(),
- signal::SigSet::empty(),
- );
- let _ = signal::sigaction(signal::SIGWINCH, &sigwinch);
- });
-}
-
-extern "C" fn sigwinch_handler(_: libc::c_int) {
- SIGWINCH.store(true, Ordering::SeqCst);
- debug!(target: "rustyline", "SIGWINCH");
-}
-
-#[cfg(not(test))]
-pub type Terminal = PosixTerminal;
-
-#[derive(Clone, Debug)]
-pub struct PosixTerminal {
- unsupported: bool,
- stdin_isatty: bool,
- stdstream_isatty: bool,
- pub(crate) color_mode: ColorMode,
- stream_type: OutputStreamType,
- tab_stop: usize,
- bell_style: BellStyle,
- enable_bracketed_paste: bool,
-}
-
-impl PosixTerminal {
- fn colors_enabled(&self) -> bool {
- match self.color_mode {
- ColorMode::Enabled => self.stdstream_isatty,
- ColorMode::Forced => true,
- ColorMode::Disabled => false,
- }
- }
-}
-
-impl Term for PosixTerminal {
- type Mode = PosixMode;
- type Reader = PosixRawReader;
- type Writer = PosixRenderer;
-
- fn new(
- color_mode: ColorMode,
- stream_type: OutputStreamType,
- tab_stop: usize,
- bell_style: BellStyle,
- enable_bracketed_paste: bool,
- ) -> Self {
- let term = Self {
- unsupported: is_unsupported_term(),
- stdin_isatty: is_a_tty(STDIN_FILENO),
- stdstream_isatty: is_a_tty(stream_type.as_raw_fd()),
- color_mode,
- stream_type,
- tab_stop,
- bell_style,
- enable_bracketed_paste,
- };
- if !term.unsupported && term.stdin_isatty && term.stdstream_isatty {
- install_sigwinch_handler();
- }
- term
- }
-
- // Init checks:
-
- /// Check if current terminal can provide a rich line-editing user
- /// interface.
- fn is_unsupported(&self) -> bool {
- self.unsupported
- }
-
- /// check if stdin is connected to a terminal.
- fn is_stdin_tty(&self) -> bool {
- self.stdin_isatty
- }
-
- fn is_output_tty(&self) -> bool {
- self.stdstream_isatty
- }
-
- // Interactive loop:
-
- fn enable_raw_mode(&mut self) -> Result<Self::Mode> {
- use nix::errno::Errno::ENOTTY;
- use nix::sys::termios::{ControlFlags, InputFlags, LocalFlags, SpecialCharacterIndices};
- if !self.stdin_isatty {
- return Err(nix::Error::from_errno(ENOTTY).into());
- }
- let original_mode = termios::tcgetattr(STDIN_FILENO)?;
- let mut raw = original_mode.clone();
- // disable BREAK interrupt, CR to NL conversion on input,
- // input parity check, strip high bit (bit 8), output flow control
- raw.input_flags &= !(InputFlags::BRKINT
- | InputFlags::ICRNL
- | InputFlags::INPCK
- | InputFlags::ISTRIP
- | InputFlags::IXON);
- // we don't want raw output, it turns newlines into straight line feeds
- // disable all output processing
- // raw.c_oflag = raw.c_oflag & !(OutputFlags::OPOST);
-
- // character-size mark (8 bits)
- raw.control_flags |= ControlFlags::CS8;
- // disable echoing, canonical mode, extended input processing and signals
- raw.local_flags &=
- !(LocalFlags::ECHO | LocalFlags::ICANON | LocalFlags::IEXTEN | LocalFlags::ISIG);
- raw.control_chars[SpecialCharacterIndices::VMIN as usize] = 1; // One character-at-a-time input
- raw.control_chars[SpecialCharacterIndices::VTIME as usize] = 0; // with blocking read
- termios::tcsetattr(STDIN_FILENO, SetArg::TCSADRAIN, &raw)?;
-
- // enable bracketed paste
- let out = if !self.enable_bracketed_paste {
- None
- } else if let Err(e) = write_and_flush(self.stream_type, BRACKETED_PASTE_ON) {
- debug!(target: "rustyline", "Cannot enable bracketed paste: {}", e);
- None
- } else {
- Some(self.stream_type)
- };
- Ok(PosixMode {
- termios: original_mode,
- out,
- })
- }
-
- /// Create a RAW reader
- fn create_reader(&self, config: &Config) -> Result<PosixRawReader> {
- Ok(PosixRawReader::new(config))
- }
-
- fn create_writer(&self) -> PosixRenderer {
- PosixRenderer::new(
- self.stream_type,
- self.tab_stop,
- self.colors_enabled(),
- self.bell_style,
- )
- }
-}
-
-#[cfg(not(test))]
-pub fn suspend() -> Result<()> {
- use nix::unistd::Pid;
- // suspend the whole process group
- signal::kill(Pid::from_raw(0), signal::SIGTSTP)?;
- Ok(())
-}
-
-fn write_and_flush(out: OutputStreamType, buf: &[u8]) -> Result<()> {
- match out {
- OutputStreamType::Stdout => {
- io::stdout().write_all(buf)?;
- io::stdout().flush()?;
- }
- OutputStreamType::Stderr => {
- io::stderr().write_all(buf)?;
- io::stderr().flush()?;
- }
- }
- Ok(())
-}
-
-#[cfg(test)]
-mod test {
- use super::{Position, PosixRenderer, PosixTerminal, Renderer};
- use crate::config::{BellStyle, OutputStreamType};
- use crate::line_buffer::LineBuffer;
-
- #[test]
- #[ignore]
- fn prompt_with_ansi_escape_codes() {
- let out = PosixRenderer::new(OutputStreamType::Stdout, 4, true, BellStyle::default());
- let pos = out.calculate_position("\x1b[1;32m>>\x1b[0m ", Position::default());
- assert_eq!(3, pos.col);
- assert_eq!(0, pos.row);
- }
-
- #[test]
- fn test_unsupported_term() {
- ::std::env::set_var("TERM", "xterm");
- assert!(!super::is_unsupported_term());
-
- ::std::env::set_var("TERM", "dumb");
- assert!(super::is_unsupported_term());
- }
-
- #[test]
- fn test_send() {
- fn assert_send<T: Send>() {}
- assert_send::<PosixTerminal>();
- }
-
- #[test]
- fn test_sync() {
- fn assert_sync<T: Sync>() {}
- assert_sync::<PosixTerminal>();
- }
-
- #[test]
- fn test_line_wrap() {
- let mut out = PosixRenderer::new(OutputStreamType::Stdout, 4, true, BellStyle::default());
- let prompt = "> ";
- let default_prompt = true;
- let prompt_size = out.calculate_position(prompt, Position::default());
-
- let mut line = LineBuffer::init("", 0, None);
- let old_layout = out.compute_layout(prompt_size, default_prompt, &line, None);
- assert_eq!(Position { col: 2, row: 0 }, old_layout.cursor);
- assert_eq!(old_layout.cursor, old_layout.end);
-
- assert_eq!(Some(true), line.insert('a', out.cols - prompt_size.col + 1));
- let new_layout = out.compute_layout(prompt_size, default_prompt, &line, None);
- assert_eq!(Position { col: 1, row: 1 }, new_layout.cursor);
- assert_eq!(new_layout.cursor, new_layout.end);
- out.refresh_line(prompt, &line, None, &old_layout, &new_layout, None)
- .unwrap();
- #[rustfmt::skip]
- assert_eq!(
- "\r\u{1b}[0K> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\u{1b}[1C",
- out.buffer
- );
- }
-}
diff --git a/vendor/rustyline-8.2.0/src/tty/windows.rs b/vendor/rustyline-8.2.0/src/tty/windows.rs
deleted file mode 100644
index 067a2b1..0000000
--- a/vendor/rustyline-8.2.0/src/tty/windows.rs
+++ /dev/null
@@ -1,686 +0,0 @@
-//! Windows specific definitions
-#![allow(clippy::try_err)] // suggested fix does not work (cannot infer...)
-
-use std::io::{self, Write};
-use std::mem;
-use std::sync::atomic::{AtomicBool, Ordering};
-
-use log::{debug, warn};
-use unicode_segmentation::UnicodeSegmentation;
-use unicode_width::UnicodeWidthStr;
-use winapi::shared::minwindef::{BOOL, DWORD, FALSE, TRUE, WORD};
-use winapi::shared::winerror;
-use winapi::um::handleapi::INVALID_HANDLE_VALUE;
-use winapi::um::wincon::{self, CONSOLE_SCREEN_BUFFER_INFO, COORD};
-use winapi::um::winnt::{CHAR, HANDLE};
-use winapi::um::{consoleapi, processenv, winbase, winuser};
-
-use super::{width, RawMode, RawReader, Renderer, Term};
-use crate::config::{BellStyle, ColorMode, Config, OutputStreamType};
-use crate::error;
-use crate::highlight::Highlighter;
-use crate::keys::{KeyCode as K, KeyEvent, Modifiers as M};
-use crate::layout::{Layout, Position};
-use crate::line_buffer::LineBuffer;
-use crate::Result;
-
-const STDIN_FILENO: DWORD = winbase::STD_INPUT_HANDLE;
-const STDOUT_FILENO: DWORD = winbase::STD_OUTPUT_HANDLE;
-const STDERR_FILENO: DWORD = winbase::STD_ERROR_HANDLE;
-
-fn get_std_handle(fd: DWORD) -> Result<HANDLE> {
- let handle = unsafe { processenv::GetStdHandle(fd) };
- if handle == INVALID_HANDLE_VALUE {
- Err(io::Error::last_os_error())?;
- } else if handle.is_null() {
- Err(io::Error::new(
- io::ErrorKind::Other,
- "no stdio handle available for this process",
- ))?;
- }
- Ok(handle)
-}
-
-fn check(rc: BOOL) -> Result<()> {
- if rc == FALSE {
- Err(io::Error::last_os_error())?
- } else {
- Ok(())
- }
-}
-
-fn get_win_size(handle: HANDLE) -> (usize, usize) {
- let mut info = unsafe { mem::zeroed() };
- match unsafe { wincon::GetConsoleScreenBufferInfo(handle, &mut info) } {
- FALSE => (80, 24),
- _ => (
- info.dwSize.X as usize,
- (1 + info.srWindow.Bottom - info.srWindow.Top) as usize,
- ), // (info.srWindow.Right - info.srWindow.Left + 1)
- }
-}
-
-fn get_console_mode(handle: HANDLE) -> Result<DWORD> {
- let mut original_mode = 0;
- check(unsafe { consoleapi::GetConsoleMode(handle, &mut original_mode) })?;
- Ok(original_mode)
-}
-
-#[must_use = "You must restore default mode (disable_raw_mode)"]
-#[cfg(not(test))]
-pub type Mode = ConsoleMode;
-
-#[derive(Clone, Copy, Debug)]
-pub struct ConsoleMode {
- original_stdin_mode: DWORD,
- stdin_handle: HANDLE,
- original_stdstream_mode: Option<DWORD>,
- stdstream_handle: HANDLE,
-}
-
-impl RawMode for ConsoleMode {
- /// Disable RAW mode for the terminal.
- fn disable_raw_mode(&self) -> Result<()> {
- check(unsafe { consoleapi::SetConsoleMode(self.stdin_handle, self.original_stdin_mode) })?;
- if let Some(original_stdstream_mode) = self.original_stdstream_mode {
- check(unsafe {
- consoleapi::SetConsoleMode(self.stdstream_handle, original_stdstream_mode)
- })?;
- }
- Ok(())
- }
-}
-
-/// Console input reader
-pub struct ConsoleRawReader {
- handle: HANDLE,
-}
-
-impl ConsoleRawReader {
- pub fn create() -> Result<ConsoleRawReader> {
- let handle = get_std_handle(STDIN_FILENO)?;
- Ok(ConsoleRawReader { handle })
- }
-}
-
-impl RawReader for ConsoleRawReader {
- fn next_key(&mut self, _: bool) -> Result<KeyEvent> {
- use std::char::decode_utf16;
- use winapi::um::wincon::{
- LEFT_ALT_PRESSED, LEFT_CTRL_PRESSED, RIGHT_ALT_PRESSED, RIGHT_CTRL_PRESSED,
- SHIFT_PRESSED,
- };
-
- let mut rec: wincon::INPUT_RECORD = unsafe { mem::zeroed() };
- let mut count = 0;
- let mut surrogate = 0;
- loop {
- // TODO GetNumberOfConsoleInputEvents
- check(unsafe { consoleapi::ReadConsoleInputW(self.handle, &mut rec, 1, &mut count) })?;
-
- if rec.EventType == wincon::WINDOW_BUFFER_SIZE_EVENT {
- SIGWINCH.store(true, Ordering::SeqCst);
- debug!(target: "rustyline", "SIGWINCH");
- return Err(error::ReadlineError::WindowResize); // sigwinch +
- // err => err
- // ignored
- } else if rec.EventType != wincon::KEY_EVENT {
- continue;
- }
- let key_event = unsafe { rec.Event.KeyEvent() };
- // writeln!(io::stderr(), "key_event: {:?}", key_event).unwrap();
- if key_event.bKeyDown == 0 && key_event.wVirtualKeyCode != winuser::VK_MENU as WORD {
- continue;
- }
- // key_event.wRepeatCount seems to be always set to 1 (maybe because we only
- // read one character at a time)
-
- let alt_gr = key_event.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_ALT_PRESSED)
- == (LEFT_CTRL_PRESSED | RIGHT_ALT_PRESSED);
- let alt = key_event.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED) != 0;
- let mut mods = M::NONE;
- if !alt_gr
- && key_event.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) != 0
- {
- mods |= M::CTRL;
- }
- if alt && !alt_gr {
- mods |= M::ALT;
- }
- if key_event.dwControlKeyState & SHIFT_PRESSED != 0 {
- mods |= M::SHIFT;
- }
-
- let utf16 = unsafe { *key_event.uChar.UnicodeChar() };
- let key = if utf16 == 0 {
- KeyEvent(
- match i32::from(key_event.wVirtualKeyCode) {
- winuser::VK_LEFT => K::Left,
- winuser::VK_RIGHT => K::Right,
- winuser::VK_UP => K::Up,
- winuser::VK_DOWN => K::Down,
- winuser::VK_DELETE => K::Delete,
- winuser::VK_HOME => K::Home,
- winuser::VK_END => K::End,
- winuser::VK_PRIOR => K::PageUp,
- winuser::VK_NEXT => K::PageDown,
- winuser::VK_INSERT => K::Insert,
- winuser::VK_F1 => K::F(1),
- winuser::VK_F2 => K::F(2),
- winuser::VK_F3 => K::F(3),
- winuser::VK_F4 => K::F(4),
- winuser::VK_F5 => K::F(5),
- winuser::VK_F6 => K::F(6),
- winuser::VK_F7 => K::F(7),
- winuser::VK_F8 => K::F(8),
- winuser::VK_F9 => K::F(9),
- winuser::VK_F10 => K::F(10),
- winuser::VK_F11 => K::F(11),
- winuser::VK_F12 => K::F(12),
- // winuser::VK_BACK is correctly handled because the key_event.UnicodeChar
- // is also set.
- _ => continue,
- },
- mods,
- )
- } else if utf16 == 27 {
- KeyEvent(K::Esc, mods)
- } else {
- if (0xD800..0xDC00).contains(&utf16) {
- surrogate = utf16;
- continue;
- }
- let orc = if surrogate == 0 {
- decode_utf16(Some(utf16)).next()
- } else {
- decode_utf16([surrogate, utf16].iter().cloned()).next()
- };
- let rc = if let Some(rc) = orc {
- rc
- } else {
- return Err(error::ReadlineError::Eof);
- };
- let c = rc?;
- KeyEvent::new(c, mods)
- };
- debug!(target: "rustyline", "key: {:?}", key);
- return Ok(key);
- }
- }
-
- fn read_pasted_text(&mut self) -> Result<String> {
- Ok(clipboard_win::get_clipboard_string()?)
- }
-}
-
-pub struct ConsoleRenderer {
- out: OutputStreamType,
- handle: HANDLE,
- cols: usize, // Number of columns in terminal
- buffer: String,
- colors_enabled: bool,
- bell_style: BellStyle,
-}
-
-impl ConsoleRenderer {
- fn new(
- handle: HANDLE,
- out: OutputStreamType,
- colors_enabled: bool,
- bell_style: BellStyle,
- ) -> ConsoleRenderer {
- // Multi line editing is enabled by ENABLE_WRAP_AT_EOL_OUTPUT mode
- let (cols, _) = get_win_size(handle);
- ConsoleRenderer {
- out,
- handle,
- cols,
- buffer: String::with_capacity(1024),
- colors_enabled,
- bell_style,
- }
- }
-
- fn get_console_screen_buffer_info(&self) -> Result<CONSOLE_SCREEN_BUFFER_INFO> {
- let mut info = unsafe { mem::zeroed() };
- check(unsafe { wincon::GetConsoleScreenBufferInfo(self.handle, &mut info) })?;
- Ok(info)
- }
-
- fn set_console_cursor_position(&mut self, pos: COORD) -> Result<()> {
- check(unsafe { wincon::SetConsoleCursorPosition(self.handle, pos) })
- }
-
- fn clear(&mut self, length: DWORD, pos: COORD, attr: WORD) -> Result<()> {
- let mut _count = 0;
- check(unsafe {
- wincon::FillConsoleOutputCharacterA(self.handle, ' ' as CHAR, length, pos, &mut _count)
- })?;
- check(unsafe {
- wincon::FillConsoleOutputAttribute(self.handle, attr, length, pos, &mut _count)
- })
- }
-
- fn set_cursor_visible(&mut self, visible: BOOL) -> Result<()> {
- set_cursor_visible(self.handle, visible)
- }
-
- // You can't have both ENABLE_WRAP_AT_EOL_OUTPUT and
- // ENABLE_VIRTUAL_TERMINAL_PROCESSING. So we need to wrap manually.
- fn wrap_at_eol(&mut self, s: &str, mut col: usize) -> usize {
- let mut esc_seq = 0;
- for c in s.graphemes(true) {
- if c == "\n" {
- col = 0;
- self.buffer.push_str(c);
- } else {
- let cw = width(c, &mut esc_seq);
- col += cw;
- if col > self.cols {
- self.buffer.push('\n');
- col = cw;
- }
- self.buffer.push_str(c);
- }
- }
- if col == self.cols {
- self.buffer.push('\n');
- col = 0;
- }
- col
- }
-
- // position at the start of the prompt, clear to end of previous input
- fn clear_old_rows(&mut self, info: &CONSOLE_SCREEN_BUFFER_INFO, layout: &Layout) -> Result<()> {
- let current_row = layout.cursor.row;
- let old_rows = layout.end.row;
- let mut coord = info.dwCursorPosition;
- coord.X = 0;
- coord.Y -= current_row as i16;
- self.set_console_cursor_position(coord)?;
- self.clear(
- (info.dwSize.X * (old_rows as i16 + 1)) as DWORD,
- coord,
- info.wAttributes,
- )
- }
-}
-
-fn set_cursor_visible(handle: HANDLE, visible: BOOL) -> Result<()> {
- let mut info = unsafe { mem::zeroed() };
- check(unsafe { wincon::GetConsoleCursorInfo(handle, &mut info) })?;
- if info.bVisible == visible {
- return Ok(());
- }
- info.bVisible = visible;
- check(unsafe { wincon::SetConsoleCursorInfo(handle, &info) })
-}
-
-impl Renderer for ConsoleRenderer {
- type Reader = ConsoleRawReader;
-
- fn move_cursor(&mut self, old: Position, new: Position) -> Result<()> {
- let mut cursor = self.get_console_screen_buffer_info()?.dwCursorPosition;
- if new.row > old.row {
- cursor.Y += (new.row - old.row) as i16;
- } else {
- cursor.Y -= (old.row - new.row) as i16;
- }
- if new.col > old.col {
- cursor.X += (new.col - old.col) as i16;
- } else {
- cursor.X -= (old.col - new.col) as i16;
- }
- self.set_console_cursor_position(cursor)
- }
-
- fn refresh_line(
- &mut self,
- prompt: &str,
- line: &LineBuffer,
- hint: Option<&str>,
- old_layout: &Layout,
- new_layout: &Layout,
- highlighter: Option<&dyn Highlighter>,
- ) -> Result<()> {
- let default_prompt = new_layout.default_prompt;
- let cursor = new_layout.cursor;
- let end_pos = new_layout.end;
-
- self.buffer.clear();
- let mut col = 0;
- if let Some(highlighter) = highlighter {
- // TODO handle ansi escape code (SetConsoleTextAttribute)
- // append the prompt
- col = self.wrap_at_eol(&highlighter.highlight_prompt(prompt, default_prompt), col);
- // append the input line
- col = self.wrap_at_eol(&highlighter.highlight(line, line.pos()), col);
- } else {
- // append the prompt
- self.buffer.push_str(prompt);
- // append the input line
- self.buffer.push_str(line);
- }
- // append hint
- if let Some(hint) = hint {
- if let Some(highlighter) = highlighter {
- self.wrap_at_eol(&highlighter.highlight_hint(hint), col);
- } else {
- self.buffer.push_str(hint);
- }
- }
- let info = self.get_console_screen_buffer_info()?;
- self.set_cursor_visible(FALSE)?; // just to avoid flickering
- let handle = self.handle;
- scopeguard::defer! {
- let _ = set_cursor_visible(handle, TRUE);
- }
- // position at the start of the prompt, clear to end of previous input
- self.clear_old_rows(&info, old_layout)?;
- // display prompt, input line and hint
- self.write_and_flush(self.buffer.as_bytes())?;
-
- // position the cursor
- let mut coord = self.get_console_screen_buffer_info()?.dwCursorPosition;
- coord.X = cursor.col as i16;
- coord.Y -= (end_pos.row - cursor.row) as i16;
- self.set_console_cursor_position(coord)?;
-
- Ok(())
- }
-
- fn write_and_flush(&self, buf: &[u8]) -> Result<()> {
- match self.out {
- OutputStreamType::Stdout => {
- io::stdout().write_all(buf)?;
- io::stdout().flush()?;
- }
- OutputStreamType::Stderr => {
- io::stderr().write_all(buf)?;
- io::stderr().flush()?;
- }
- }
- Ok(())
- }
-
- /// Characters with 2 column width are correctly handled (not split).
- fn calculate_position(&self, s: &str, orig: Position) -> Position {
- let mut pos = orig;
- for c in s.graphemes(true) {
- if c == "\n" {
- pos.col = 0;
- pos.row += 1;
- } else {
- let cw = c.width();
- pos.col += cw;
- if pos.col > self.cols {
- pos.row += 1;
- pos.col = cw;
- }
- }
- }
- if pos.col == self.cols {
- pos.col = 0;
- pos.row += 1;
- }
- pos
- }
-
- fn beep(&mut self) -> Result<()> {
- match self.bell_style {
- BellStyle::Audible => {
- io::stderr().write_all(b"\x07")?;
- io::stderr().flush()?;
- Ok(())
- }
- _ => Ok(()),
- }
- }
-
- /// Clear the screen. Used to handle ctrl+l
- fn clear_screen(&mut self) -> Result<()> {
- let info = self.get_console_screen_buffer_info()?;
- let coord = COORD { X: 0, Y: 0 };
- check(unsafe { wincon::SetConsoleCursorPosition(self.handle, coord) })?;
- let n = info.dwSize.X as DWORD * info.dwSize.Y as DWORD;
- self.clear(n, coord, info.wAttributes)
- }
-
- fn sigwinch(&self) -> bool {
- SIGWINCH
- .compare_exchange(true, false, Ordering::SeqCst, Ordering::SeqCst)
- .unwrap_or(false)
- }
-
- /// Try to get the number of columns in the current terminal,
- /// or assume 80 if it fails.
- fn update_size(&mut self) {
- let (cols, _) = get_win_size(self.handle);
- self.cols = cols;
- }
-
- fn get_columns(&self) -> usize {
- self.cols
- }
-
- /// Try to get the number of rows in the current terminal,
- /// or assume 24 if it fails.
- fn get_rows(&self) -> usize {
- let (_, rows) = get_win_size(self.handle);
- rows
- }
-
- fn colors_enabled(&self) -> bool {
- self.colors_enabled
- }
-
- fn move_cursor_at_leftmost(&mut self, _: &mut ConsoleRawReader) -> Result<()> {
- self.write_and_flush(b"")?; // we must do this otherwise the cursor position is not reported correctly
- let mut info = self.get_console_screen_buffer_info()?;
- if info.dwCursorPosition.X == 0 {
- return Ok(());
- }
- debug!(target: "rustyline", "initial cursor location: {:?}, {:?}", info.dwCursorPosition.X, info.dwCursorPosition.Y);
- info.dwCursorPosition.X = 0;
- info.dwCursorPosition.Y += 1;
- let res = self.set_console_cursor_position(info.dwCursorPosition);
- if let Err(error::ReadlineError::Io(ref e)) = res {
- if e.raw_os_error() == Some(winerror::ERROR_INVALID_PARAMETER as i32) {
- warn!(target: "rustyline", "invalid cursor position: ({:?}, {:?}) in ({:?}, {:?})", info.dwCursorPosition.X, info.dwCursorPosition.Y, info.dwSize.X, info.dwSize.Y);
- println!();
- return Ok(());
- }
- }
- res
- }
-}
-
-static SIGWINCH: AtomicBool = AtomicBool::new(false);
-
-#[cfg(not(test))]
-pub type Terminal = Console;
-
-#[derive(Clone, Debug)]
-pub struct Console {
- stdin_isatty: bool,
- stdin_handle: HANDLE,
- stdstream_isatty: bool,
- stdstream_handle: HANDLE,
- pub(crate) color_mode: ColorMode,
- ansi_colors_supported: bool,
- stream_type: OutputStreamType,
- bell_style: BellStyle,
-}
-
-impl Console {
- fn colors_enabled(&self) -> bool {
- // TODO ANSI Colors & Windows <10
- match self.color_mode {
- ColorMode::Enabled => self.stdstream_isatty && self.ansi_colors_supported,
- ColorMode::Forced => true,
- ColorMode::Disabled => false,
- }
- }
-}
-
-impl Term for Console {
- type Mode = ConsoleMode;
- type Reader = ConsoleRawReader;
- type Writer = ConsoleRenderer;
-
- fn new(
- color_mode: ColorMode,
- stream_type: OutputStreamType,
- _tab_stop: usize,
- bell_style: BellStyle,
- _enable_bracketed_paste: bool,
- ) -> Console {
- use std::ptr;
- let stdin_handle = get_std_handle(STDIN_FILENO);
- let stdin_isatty = match stdin_handle {
- Ok(handle) => {
- // If this function doesn't fail then fd is a TTY
- get_console_mode(handle).is_ok()
- }
- Err(_) => false,
- };
-
- let stdstream_handle = get_std_handle(if stream_type == OutputStreamType::Stdout {
- STDOUT_FILENO
- } else {
- STDERR_FILENO
- });
- let stdstream_isatty = match stdstream_handle {
- Ok(handle) => {
- // If this function doesn't fail then fd is a TTY
- get_console_mode(handle).is_ok()
- }
- Err(_) => false,
- };
-
- Console {
- stdin_isatty,
- stdin_handle: stdin_handle.unwrap_or(ptr::null_mut()),
- stdstream_isatty,
- stdstream_handle: stdstream_handle.unwrap_or(ptr::null_mut()),
- color_mode,
- ansi_colors_supported: false,
- stream_type,
- bell_style,
- }
- }
-
- /// Checking for an unsupported TERM in windows is a no-op
- fn is_unsupported(&self) -> bool {
- false
- }
-
- fn is_stdin_tty(&self) -> bool {
- self.stdin_isatty
- }
-
- fn is_output_tty(&self) -> bool {
- self.stdstream_isatty
- }
-
- // pub fn install_sigwinch_handler(&mut self) {
- // See ReadConsoleInputW && WINDOW_BUFFER_SIZE_EVENT
- // }
-
- /// Enable RAW mode for the terminal.
- fn enable_raw_mode(&mut self) -> Result<Self::Mode> {
- if !self.stdin_isatty {
- Err(io::Error::new(
- io::ErrorKind::Other,
- "no stdio handle available for this process",
- ))?;
- }
- let original_stdin_mode = get_console_mode(self.stdin_handle)?;
- // Disable these modes
- let mut raw = original_stdin_mode
- & !(wincon::ENABLE_LINE_INPUT
- | wincon::ENABLE_ECHO_INPUT
- | wincon::ENABLE_PROCESSED_INPUT);
- // Enable these modes
- raw |= wincon::ENABLE_EXTENDED_FLAGS;
- raw |= wincon::ENABLE_INSERT_MODE;
- raw |= wincon::ENABLE_QUICK_EDIT_MODE;
- raw |= wincon::ENABLE_WINDOW_INPUT;
- check(unsafe { consoleapi::SetConsoleMode(self.stdin_handle, raw) })?;
-
- let original_stdstream_mode = if self.stdstream_isatty {
- let original_stdstream_mode = get_console_mode(self.stdstream_handle)?;
-
- let mut mode = original_stdstream_mode;
- if mode & wincon::ENABLE_WRAP_AT_EOL_OUTPUT == 0 {
- mode |= wincon::ENABLE_WRAP_AT_EOL_OUTPUT;
- debug!(target: "rustyline", "activate ENABLE_WRAP_AT_EOL_OUTPUT");
- unsafe {
- assert!(consoleapi::SetConsoleMode(self.stdstream_handle, mode) != 0);
- }
- }
- // To enable ANSI colors (Windows 10 only):
- // https://docs.microsoft.com/en-us/windows/console/setconsolemode
- self.ansi_colors_supported = mode & wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING != 0;
- if self.ansi_colors_supported {
- if self.color_mode == ColorMode::Disabled {
- mode &= !wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING;
- debug!(target: "rustyline", "deactivate ENABLE_VIRTUAL_TERMINAL_PROCESSING");
- unsafe {
- assert!(consoleapi::SetConsoleMode(self.stdstream_handle, mode) != 0);
- }
- } else {
- debug!(target: "rustyline", "ANSI colors already enabled");
- }
- } else if self.color_mode != ColorMode::Disabled {
- mode |= wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING;
- self.ansi_colors_supported =
- unsafe { consoleapi::SetConsoleMode(self.stdstream_handle, mode) != 0 };
- debug!(target: "rustyline", "ansi_colors_supported: {}", self.ansi_colors_supported);
- }
- Some(original_stdstream_mode)
- } else {
- None
- };
-
- Ok(ConsoleMode {
- original_stdin_mode,
- stdin_handle: self.stdin_handle,
- original_stdstream_mode,
- stdstream_handle: self.stdstream_handle,
- })
- }
-
- fn create_reader(&self, _: &Config) -> Result<ConsoleRawReader> {
- ConsoleRawReader::create()
- }
-
- fn create_writer(&self) -> ConsoleRenderer {
- ConsoleRenderer::new(
- self.stdstream_handle,
- self.stream_type,
- self.colors_enabled(),
- self.bell_style,
- )
- }
-}
-
-unsafe impl Send for Console {}
-unsafe impl Sync for Console {}
-
-#[cfg(test)]
-mod test {
- use super::Console;
-
- #[test]
- fn test_send() {
- fn assert_send<T: Send>() {}
- assert_send::<Console>();
- }
-
- #[test]
- fn test_sync() {
- fn assert_sync<T: Sync>() {}
- assert_sync::<Console>();
- }
-}
diff --git a/vendor/rustyline-8.2.0/src/undo.rs b/vendor/rustyline-8.2.0/src/undo.rs
deleted file mode 100644
index 5629678..0000000
--- a/vendor/rustyline-8.2.0/src/undo.rs
+++ /dev/null
@@ -1,488 +0,0 @@
-//! Undo API
-use std::fmt::Debug;
-
-use crate::keymap::RepeatCount;
-use crate::line_buffer::{ChangeListener, DeleteListener, Direction, LineBuffer};
-use log::debug;
-use unicode_segmentation::UnicodeSegmentation;
-
-enum Change {
- Begin,
- End,
- Insert {
- idx: usize,
- text: String,
- }, // QuotedInsert, SelfInsert, Yank
- Delete {
- idx: usize,
- text: String,
- }, /* BackwardDeleteChar, BackwardKillWord, DeleteChar,
- * KillLine, KillWholeLine, KillWord,
- * UnixLikeDiscard, ViDeleteTo */
- Replace {
- idx: usize,
- old: String,
- new: String,
- }, /* CapitalizeWord, Complete, DowncaseWord, Replace, TransposeChars, TransposeWords,
- * UpcaseWord, YankPop */
-}
-
-impl Change {
- fn undo(&self, line: &mut LineBuffer) {
- match *self {
- Change::Begin | Change::End => {
- unreachable!();
- }
- Change::Insert { idx, ref text } => {
- line.delete_range(idx..idx + text.len());
- }
- Change::Delete { idx, ref text } => {
- line.insert_str(idx, text);
- line.set_pos(idx + text.len());
- }
- Change::Replace {
- idx,
- ref old,
- ref new,
- } => {
- line.replace(idx..idx + new.len(), old);
- }
- }
- }
-
- #[cfg(test)]
- fn redo(&self, line: &mut LineBuffer) {
- match *self {
- Change::Begin | Change::End => {
- unreachable!();
- }
- Change::Insert { idx, ref text } => {
- line.insert_str(idx, text);
- }
- Change::Delete { idx, ref text } => {
- line.delete_range(idx..idx + text.len());
- }
- Change::Replace {
- idx,
- ref old,
- ref new,
- } => {
- line.replace(idx..idx + old.len(), new);
- }
- }
- }
-
- fn insert_seq(&self, indx: usize) -> bool {
- if let Change::Insert { idx, ref text } = *self {
- idx + text.len() == indx
- } else {
- false
- }
- }
-
- fn delete_seq(&self, indx: usize, len: usize) -> bool {
- if let Change::Delete { idx, .. } = *self {
- // delete or backspace
- idx == indx || idx == indx + len
- } else {
- false
- }
- }
-
- fn replace_seq(&self, indx: usize) -> bool {
- if let Change::Replace { idx, ref new, .. } = *self {
- idx + new.len() == indx
- } else {
- false
- }
- }
-}
-
-pub struct Changeset {
- undo_group_level: u32,
- undos: Vec<Change>, // undoable changes
- redos: Vec<Change>, // undone changes, redoable
-}
-
-impl Changeset {
- pub fn new() -> Self {
- Self {
- undo_group_level: 0,
- undos: Vec::new(),
- redos: Vec::new(),
- }
- }
-
- pub fn begin(&mut self) -> usize {
- debug!(target: "rustyline", "Changeset::begin");
- self.redos.clear();
- let mark = self.undos.len();
- self.undos.push(Change::Begin);
- self.undo_group_level += 1;
- mark
- }
-
- /// Returns `true` when changes happen between the last call to `begin` and
- /// this `end`.
- pub fn end(&mut self) -> bool {
- debug!(target: "rustyline", "Changeset::end");
- self.redos.clear();
- let mut touched = false;
- while self.undo_group_level > 0 {
- self.undo_group_level -= 1;
- if let Some(&Change::Begin) = self.undos.last() {
- // empty Begin..End
- self.undos.pop();
- } else {
- self.undos.push(Change::End);
- touched = true;
- }
- }
- touched
- }
-
- fn insert_char(idx: usize, c: char) -> Change {
- let mut text = String::new();
- text.push(c);
- Change::Insert { idx, text }
- }
-
- pub fn insert(&mut self, idx: usize, c: char) {
- debug!(target: "rustyline", "Changeset::insert({}, {:?})", idx, c);
- self.redos.clear();
- if !c.is_alphanumeric() || !self.undos.last().map_or(false, |lc| lc.insert_seq(idx)) {
- self.undos.push(Self::insert_char(idx, c));
- return;
- }
- // merge consecutive char insertions when char is alphanumeric
- let mut last_change = self.undos.pop().unwrap();
- if let Change::Insert { ref mut text, .. } = last_change {
- text.push(c);
- } else {
- unreachable!();
- }
- self.undos.push(last_change);
- }
-
- pub fn insert_str<S: AsRef<str> + Into<String> + Debug>(&mut self, idx: usize, string: S) {
- debug!(target: "rustyline", "Changeset::insert_str({}, {:?})", idx, string);
- self.redos.clear();
- if string.as_ref().is_empty() {
- return;
- }
- self.undos.push(Change::Insert {
- idx,
- text: string.into(),
- });
- }
-
- pub fn delete<S: AsRef<str> + Into<String> + Debug>(&mut self, indx: usize, string: S) {
- debug!(target: "rustyline", "Changeset::delete({}, {:?})", indx, string);
- self.redos.clear();
- if string.as_ref().is_empty() {
- return;
- }
-
- if !Self::single_char(string.as_ref())
- || !self
- .undos
- .last()
- .map_or(false, |lc| lc.delete_seq(indx, string.as_ref().len()))
- {
- self.undos.push(Change::Delete {
- idx: indx,
- text: string.into(),
- });
- return;
- }
- // merge consecutive char deletions when char is alphanumeric
- let mut last_change = self.undos.pop().unwrap();
- if let Change::Delete {
- ref mut idx,
- ref mut text,
- } = last_change
- {
- if *idx == indx {
- text.push_str(string.as_ref());
- } else {
- text.insert_str(0, string.as_ref());
- *idx = indx;
- }
- } else {
- unreachable!();
- }
- self.undos.push(last_change);
- }
-
- fn single_char(s: &str) -> bool {
- let mut graphemes = s.graphemes(true);
- graphemes.next().map_or(false, |grapheme| {
- grapheme.chars().all(char::is_alphanumeric)
- }) && graphemes.next().is_none()
- }
-
- pub fn replace<S: AsRef<str> + Into<String> + Debug>(&mut self, indx: usize, old_: S, new_: S) {
- debug!(target: "rustyline", "Changeset::replace({}, {:?}, {:?})", indx, old_, new_);
- self.redos.clear();
-
- if !self.undos.last().map_or(false, |lc| lc.replace_seq(indx)) {
- self.undos.push(Change::Replace {
- idx: indx,
- old: old_.into(),
- new: new_.into(),
- });
- return;
- }
-
- // merge consecutive char replacements
- let mut last_change = self.undos.pop().unwrap();
- if let Change::Replace {
- ref mut old,
- ref mut new,
- ..
- } = last_change
- {
- old.push_str(old_.as_ref());
- new.push_str(new_.as_ref());
- } else {
- unreachable!();
- }
- self.undos.push(last_change);
- }
-
- pub fn undo(&mut self, line: &mut LineBuffer, n: RepeatCount) -> bool {
- debug!(target: "rustyline", "Changeset::undo");
- let mut count = 0;
- let mut waiting_for_begin = 0;
- let mut undone = false;
- loop {
- if let Some(change) = self.undos.pop() {
- match change {
- Change::Begin => {
- waiting_for_begin -= 1;
- }
- Change::End => {
- waiting_for_begin += 1;
- }
- _ => {
- change.undo(line);
- undone = true;
- }
- };
- self.redos.push(change);
- } else {
- break;
- }
- if waiting_for_begin <= 0 {
- count += 1;
- if count >= n {
- break;
- }
- }
- }
- undone
- }
-
- pub fn truncate(&mut self, len: usize) {
- debug!(target: "rustyline", "Changeset::truncate({})", len);
- self.undos.truncate(len);
- }
-
- #[cfg(test)]
- pub fn redo(&mut self, line: &mut LineBuffer) -> bool {
- let mut waiting_for_end = 0;
- let mut redone = false;
- loop {
- if let Some(change) = self.redos.pop() {
- match change {
- Change::Begin => {
- waiting_for_end += 1;
- }
- Change::End => {
- waiting_for_end -= 1;
- }
- _ => {
- change.redo(line);
- redone = true;
- }
- };
- self.undos.push(change);
- } else {
- break;
- }
- if waiting_for_end <= 0 {
- break;
- }
- }
- redone
- }
-
- pub fn last_insert(&self) -> Option<String> {
- for change in self.undos.iter().rev() {
- match change {
- Change::Insert { ref text, .. } => return Some(text.to_owned()),
- Change::Replace { ref new, .. } => return Some(new.to_owned()),
- Change::End => {
- continue;
- }
- _ => {
- return None;
- }
- }
- }
- None
- }
-}
-
-impl DeleteListener for Changeset {
- fn start_killing(&mut self) {}
-
- fn delete(&mut self, idx: usize, string: &str, _: Direction) {
- self.delete(idx, string);
- }
-
- fn stop_killing(&mut self) {}
-}
-impl ChangeListener for Changeset {
- fn insert_char(&mut self, idx: usize, c: char) {
- self.insert(idx, c);
- }
-
- fn insert_str(&mut self, idx: usize, string: &str) {
- self.insert_str(idx, string);
- }
-
- fn replace(&mut self, idx: usize, old: &str, new: &str) {
- self.replace(idx, old, new);
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::Changeset;
- use crate::line_buffer::LineBuffer;
-
- #[test]
- fn test_insert_chars() {
- let mut cs = Changeset::new();
- cs.insert(0, 'H');
- cs.insert(1, 'i');
- assert_eq!(1, cs.undos.len());
- assert_eq!(0, cs.redos.len());
- cs.insert(0, ' ');
- assert_eq!(2, cs.undos.len());
- }
-
- #[test]
- fn test_insert_strings() {
- let mut cs = Changeset::new();
- cs.insert_str(0, "Hello");
- cs.insert_str(5, ", ");
- assert_eq!(2, cs.undos.len());
- assert_eq!(0, cs.redos.len());
- }
-
- #[test]
- fn test_undo_insert() {
- let mut buf = LineBuffer::init("", 0, None);
- buf.insert_str(0, "Hello");
- buf.insert_str(5, ", world!");
- let mut cs = Changeset::new();
- assert_eq!(buf.as_str(), "Hello, world!");
-
- cs.insert_str(5, ", world!");
-
- cs.undo(&mut buf, 1);
- assert_eq!(0, cs.undos.len());
- assert_eq!(1, cs.redos.len());
- assert_eq!(buf.as_str(), "Hello");
-
- cs.redo(&mut buf);
- assert_eq!(1, cs.undos.len());
- assert_eq!(0, cs.redos.len());
- assert_eq!(buf.as_str(), "Hello, world!");
- }
-
- #[test]
- fn test_undo_delete() {
- let mut buf = LineBuffer::init("", 0, None);
- buf.insert_str(0, "Hello");
- let mut cs = Changeset::new();
- assert_eq!(buf.as_str(), "Hello");
-
- cs.delete(5, ", world!");
-
- cs.undo(&mut buf, 1);
- assert_eq!(buf.as_str(), "Hello, world!");
-
- cs.redo(&mut buf);
- assert_eq!(buf.as_str(), "Hello");
- }
-
- #[test]
- fn test_delete_chars() {
- let mut buf = LineBuffer::init("", 0, None);
- buf.insert_str(0, "Hlo");
-
- let mut cs = Changeset::new();
- cs.delete(1, "e");
- cs.delete(1, "l");
- assert_eq!(1, cs.undos.len());
-
- cs.undo(&mut buf, 1);
- assert_eq!(buf.as_str(), "Hello");
- }
-
- #[test]
- fn test_backspace_chars() {
- let mut buf = LineBuffer::init("", 0, None);
- buf.insert_str(0, "Hlo");
-
- let mut cs = Changeset::new();
- cs.delete(2, "l");
- cs.delete(1, "e");
- assert_eq!(1, cs.undos.len());
-
- cs.undo(&mut buf, 1);
- assert_eq!(buf.as_str(), "Hello");
- }
-
- #[test]
- fn test_undo_replace() {
- let mut buf = LineBuffer::init("", 0, None);
- buf.insert_str(0, "Hello, world!");
- let mut cs = Changeset::new();
- assert_eq!(buf.as_str(), "Hello, world!");
-
- buf.replace(1..5, "i");
- assert_eq!(buf.as_str(), "Hi, world!");
- cs.replace(1, "ello", "i");
-
- cs.undo(&mut buf, 1);
- assert_eq!(buf.as_str(), "Hello, world!");
-
- cs.redo(&mut buf);
- assert_eq!(buf.as_str(), "Hi, world!");
- }
-
- #[test]
- fn test_last_insert() {
- let mut cs = Changeset::new();
- cs.begin();
- cs.delete(0, "Hello");
- cs.insert_str(0, "Bye");
- cs.end();
- let insert = cs.last_insert();
- assert_eq!(Some("Bye".to_owned()), insert);
- }
-
- #[test]
- fn test_end() {
- let mut cs = Changeset::new();
- cs.begin();
- assert!(!cs.end());
- cs.begin();
- cs.insert_str(0, "Hi");
- assert!(cs.end());
- }
-}
diff --git a/vendor/rustyline-8.2.0/src/validate.rs b/vendor/rustyline-8.2.0/src/validate.rs
deleted file mode 100644
index b29c682..0000000
--- a/vendor/rustyline-8.2.0/src/validate.rs
+++ /dev/null
@@ -1,147 +0,0 @@
-//! Input validation API (Multi-line editing)
-
-use crate::keymap::Invoke;
-use crate::Result;
-
-/// Input validation result
-#[non_exhaustive]
-pub enum ValidationResult {
- /// Incomplete input
- Incomplete,
- /// Validation fails with an optional error message. User must fix the
- /// input.
- Invalid(Option<String>),
- /// Validation succeeds with an optional message
- Valid(Option<String>),
-}
-
-impl ValidationResult {
- pub(crate) fn is_valid(&self) -> bool {
- matches!(self, ValidationResult::Valid(_))
- }
-
- pub(crate) fn has_message(&self) -> bool {
- matches!(
- self,
- ValidationResult::Valid(Some(_)) | ValidationResult::Invalid(Some(_))
- )
- }
-}
-
-/// Give access to user input.
-pub struct ValidationContext<'i> {
- i: &'i mut dyn Invoke,
-}
-
-impl<'i> ValidationContext<'i> {
- pub(crate) fn new(i: &'i mut dyn Invoke) -> Self {
- ValidationContext { i }
- }
-
- /// Returns user input.
- pub fn input(&self) -> &str {
- self.i.input()
- }
-
- // TODO
- //fn invoke(&mut self, cmd: Cmd) -> Result<?> {
- // self.i.invoke(cmd)
- //}
-}
-
-/// This trait provides an extension interface for determining whether
-/// the current input buffer is valid. Rustyline uses the method
-/// provided by this trait to decide whether hitting the enter key
-/// will end the current editing session and return the current line
-/// buffer to the caller of `Editor::readline` or variants.
-pub trait Validator {
- /// Takes the currently edited `input` and returns a
- /// `ValidationResult` indicating whether it is valid or not along
- /// with an option message to display about the result. The most
- /// common validity check to implement is probably whether the
- /// input is complete or not, for instance ensuring that all
- /// delimiters are fully balanced.
- ///
- /// If you implement more complex validation checks it's probably
- /// a good idea to also implement a `Hinter` to provide feedback
- /// about what is invalid.
- ///
- /// For auto-correction like a missing closing quote or to reject invalid
- /// char while typing, the input will be mutable (TODO).
- fn validate(&self, ctx: &mut ValidationContext) -> Result<ValidationResult> {
- let _ = ctx;
- Ok(ValidationResult::Valid(None))
- }
-
- /// Configure whether validation is performed while typing or only
- /// when user presses the Enter key.
- ///
- /// Default is `false`.
- ///
- /// This feature is not yet implemented, so this function is currently a
- /// no-op
- fn validate_while_typing(&self) -> bool {
- false
- }
-}
-
-impl Validator for () {}
-
-impl<'v, V: ?Sized + Validator> Validator for &'v V {
- fn validate(&self, ctx: &mut ValidationContext) -> Result<ValidationResult> {
- (**self).validate(ctx)
- }
-
- fn validate_while_typing(&self) -> bool {
- (**self).validate_while_typing()
- }
-}
-
-/// Simple matching bracket validator.
-#[derive(Default)]
-pub struct MatchingBracketValidator {
- _priv: (),
-}
-
-impl MatchingBracketValidator {
- /// Constructor
- pub fn new() -> Self {
- Self { _priv: () }
- }
-}
-
-impl Validator for MatchingBracketValidator {
- fn validate(&self, ctx: &mut ValidationContext) -> Result<ValidationResult> {
- Ok(validate_brackets(ctx.input()))
- }
-}
-
-fn validate_brackets(input: &str) -> ValidationResult {
- let mut stack = vec![];
- for c in input.chars() {
- match c {
- '(' | '[' | '{' => stack.push(c),
- ')' | ']' | '}' => match (stack.pop(), c) {
- (Some('('), ')') | (Some('['), ']') | (Some('{'), '}') => {}
- (Some(wanted), _) => {
- return ValidationResult::Invalid(Some(format!(
- "Mismatched brackets: {:?} is not properly closed",
- wanted
- )))
- }
- (None, c) => {
- return ValidationResult::Invalid(Some(format!(
- "Mismatched brackets: {:?} is unpaired",
- c
- )))
- }
- },
- _ => {}
- }
- }
- if stack.is_empty() {
- ValidationResult::Valid(None)
- } else {
- ValidationResult::Incomplete
- }
-}