From a6b7715f4b3e53defd2dad73e84e717ed553d6eb Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 4 Jun 2019 13:23:52 +0200 Subject: [PATCH] vendor: Move to the rust-vmm vmm-sys-util package Locked to 60fe35be but no longer dependent on liujing2 repo. Signed-off-by: Samuel Ortiz --- .cargo/config | 8 - Cargo.lock | 18 +- devices/Cargo.toml | 2 +- net_gen/Cargo.toml | 2 +- net_util/Cargo.toml | 2 +- pci/Cargo.toml | 2 +- qcow/Cargo.toml | 2 +- vendor/.sources | 2 +- .../vmm-sys-util/.buildkite/pipeline.yml | 75 -- .../vmm-sys-util/.cargo-checksum.json | 1 - .../vmm-sys-util/Cargo.toml | 9 - .../vmm-sys-util/LICENSE-APACHE | 201 ----- .../vmm-sys-util/LICENSE-BSD-3-Clause | 27 - .../vmm-sys-util/README.md | 2 - .../vmm-sys-util/src/errno.rs | 80 -- .../vmm-sys-util/src/eventfd.rs | 150 ---- .../vmm-sys-util/src/file_traits.rs | 39 - .../vmm-sys-util/src/ioctl.rs | 225 ------ .../vmm-sys-util/src/lib.rs | 78 -- .../vmm-sys-util/src/poll.rs | 711 ------------------ .../vmm-sys-util/src/seek_hole.rs | 215 ------ .../vmm-sys-util/src/signal.rs | 420 ----------- .../vmm-sys-util/src/syslog.rs | 643 ---------------- .../vmm-sys-util/src/tempdir.rs | 104 --- .../vmm-sys-util/src/terminal.rs | 155 ---- .../vmm-sys-util/src/timerfd.rs | 173 ----- .../vmm-sys-util/src/write_zeroes.rs | 172 ----- vm-virtio/Cargo.toml | 2 +- vmm/Cargo.toml | 2 +- 29 files changed, 17 insertions(+), 3505 deletions(-) delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/.buildkite/pipeline.yml delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/.cargo-checksum.json delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/Cargo.toml delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/LICENSE-APACHE delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/LICENSE-BSD-3-Clause delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/README.md delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/errno.rs delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/eventfd.rs delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/file_traits.rs delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/ioctl.rs delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/lib.rs delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/poll.rs delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/seek_hole.rs delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/signal.rs delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/syslog.rs delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/tempdir.rs delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/terminal.rs delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/timerfd.rs delete mode 100644 vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/write_zeroes.rs diff --git a/.cargo/config b/.cargo/config index 1aa478e6b..0d2f0845d 100644 --- a/.cargo/config +++ b/.cargo/config @@ -6,11 +6,6 @@ git = "https://github.com/bjzhjing/linux-loader" rev = "2b95f1e1958a2b6399b590f64344cab5b4a6d608" replace-with = "vendor+https://github.com/bjzhjing/linux-loader" -[source."https://github.com/liujing2/vmm-sys-util"] -git = "https://github.com/liujing2/vmm-sys-util" -branch = "master" -replace-with = "vendor+https://github.com/liujing2/vmm-sys-util" - [source."https://github.com/rust-vmm/vm-memory"] git = "https://github.com/rust-vmm/vm-memory" rev = "281b8bd6cd2927f7a65130194b203a1c2b0ad2e3" @@ -27,9 +22,6 @@ directory = "./vendor/registry-40351f815f426200" [source."vendor+https://github.com/bjzhjing/linux-loader"] directory = "./vendor/git-4af8f4552cd0d200" -[source."vendor+https://github.com/liujing2/vmm-sys-util"] -directory = "./vendor/git-ccfa5f04f3f14300" - [source."vendor+https://github.com/rust-vmm/vm-memory"] directory = "./vendor/git-89548d8276566400" diff --git a/Cargo.lock b/Cargo.lock index fbe607d25..294fc2566 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,7 +97,7 @@ dependencies = [ "epoll 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "vm-memory 0.1.0 (git+https://github.com/rust-vmm/vm-memory)", - "vmm-sys-util 0.1.0 (git+https://github.com/liujing2/vmm-sys-util)", + "vmm-sys-util 0.1.0 (git+https://github.com/rust-vmm/vmm-sys-util)", ] [[package]] @@ -161,7 +161,7 @@ dependencies = [ name = "net_gen" version = "0.1.0" dependencies = [ - "vmm-sys-util 0.1.0 (git+https://github.com/liujing2/vmm-sys-util)", + "vmm-sys-util 0.1.0 (git+https://github.com/rust-vmm/vmm-sys-util)", ] [[package]] @@ -172,7 +172,7 @@ dependencies = [ "net_gen 0.1.0", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "vmm-sys-util 0.1.0 (git+https://github.com/liujing2/vmm-sys-util)", + "vmm-sys-util 0.1.0 (git+https://github.com/rust-vmm/vmm-sys-util)", ] [[package]] @@ -192,7 +192,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "vm-allocator 0.1.0", "vm-memory 0.1.0 (git+https://github.com/rust-vmm/vm-memory)", - "vmm-sys-util 0.1.0 (git+https://github.com/liujing2/vmm-sys-util)", + "vmm-sys-util 0.1.0 (git+https://github.com/rust-vmm/vmm-sys-util)", ] [[package]] @@ -211,7 +211,7 @@ dependencies = [ "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "remain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "vmm-sys-util 0.1.0 (git+https://github.com/liujing2/vmm-sys-util)", + "vmm-sys-util 0.1.0 (git+https://github.com/rust-vmm/vmm-sys-util)", ] [[package]] @@ -468,7 +468,7 @@ dependencies = [ "virtio-bindings 0.1.0", "vm-allocator 0.1.0", "vm-memory 0.1.0 (git+https://github.com/rust-vmm/vm-memory)", - "vmm-sys-util 0.1.0 (git+https://github.com/liujing2/vmm-sys-util)", + "vmm-sys-util 0.1.0 (git+https://github.com/rust-vmm/vmm-sys-util)", ] [[package]] @@ -489,13 +489,13 @@ dependencies = [ "vm-allocator 0.1.0", "vm-memory 0.1.0 (git+https://github.com/rust-vmm/vm-memory)", "vm-virtio 0.1.0", - "vmm-sys-util 0.1.0 (git+https://github.com/liujing2/vmm-sys-util)", + "vmm-sys-util 0.1.0 (git+https://github.com/rust-vmm/vmm-sys-util)", ] [[package]] name = "vmm-sys-util" version = "0.1.0" -source = "git+https://github.com/liujing2/vmm-sys-util#700a05b942cf904fca9cf1ac3e825e58c9dc9ea9" +source = "git+https://github.com/rust-vmm/vmm-sys-util#60fe35bea0bdce8b36c6186a740878880f944bdc" dependencies = [ "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -574,7 +574,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum vm-memory 0.1.0 (git+https://github.com/rust-vmm/vm-memory)" = "" "checksum vm-memory 0.1.0 (git+https://github.com/rust-vmm/vm-memory?rev=281b8bd6cd2927f7a65130194b203a1c2b0ad2e3)" = "" -"checksum vmm-sys-util 0.1.0 (git+https://github.com/liujing2/vmm-sys-util)" = "" +"checksum vmm-sys-util 0.1.0 (git+https://github.com/rust-vmm/vmm-sys-util)" = "" "checksum vmm-sys-util 0.1.0 (git+https://github.com/rust-vmm/vmm-sys-util?rev=60fe35bea0bdce8b36c6186a740878880f944bdc)" = "" "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" diff --git a/devices/Cargo.toml b/devices/Cargo.toml index aa9059eb5..a5a5c3ad1 100644 --- a/devices/Cargo.toml +++ b/devices/Cargo.toml @@ -8,7 +8,7 @@ byteorder = ">=1.2.1" epoll = "=4.0.1" libc = ">=0.2.39" vm-memory = { git = "https://github.com/rust-vmm/vm-memory" } -vmm-sys-util = { git = "https://github.com/liujing2/vmm-sys-util" } +vmm-sys-util = { git = "https://github.com/rust-vmm/vmm-sys-util" } [dev-dependencies] tempfile = ">=3.0.2" diff --git a/net_gen/Cargo.toml b/net_gen/Cargo.toml index 3510589a1..5a280b647 100644 --- a/net_gen/Cargo.toml +++ b/net_gen/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" authors = ["The Chromium OS Authors"] [dependencies] -vmm-sys-util = { git = "https://github.com/liujing2/vmm-sys-util" } +vmm-sys-util = { git = "https://github.com/rust-vmm/vmm-sys-util" } diff --git a/net_util/Cargo.toml b/net_util/Cargo.toml index 74b646650..60db22842 100644 --- a/net_util/Cargo.toml +++ b/net_util/Cargo.toml @@ -9,7 +9,7 @@ rand = ">=0.6.5" serde = ">=1.0.27" net_gen = { path = "../net_gen" } -vmm-sys-util = { git = "https://github.com/liujing2/vmm-sys-util" } +vmm-sys-util = { git = "https://github.com/rust-vmm/vmm-sys-util" } [dev-dependencies] lazy_static = ">=1.1.0" diff --git a/pci/Cargo.toml b/pci/Cargo.toml index da143ac07..968175f70 100644 --- a/pci/Cargo.toml +++ b/pci/Cargo.toml @@ -13,4 +13,4 @@ kvm-ioctls = "0.1.0" libc = ">=0.2.39" log = "*" vm-memory = { git = "https://github.com/rust-vmm/vm-memory" } -vmm-sys-util = { git = "https://github.com/liujing2/vmm-sys-util" } +vmm-sys-util = { git = "https://github.com/rust-vmm/vmm-sys-util" } diff --git a/qcow/Cargo.toml b/qcow/Cargo.toml index 4dad40199..8d376220a 100755 --- a/qcow/Cargo.toml +++ b/qcow/Cargo.toml @@ -13,4 +13,4 @@ byteorder = "*" libc = "*" log = "*" remain = "*" -vmm-sys-util = { git = "https://github.com/liujing2/vmm-sys-util" } +vmm-sys-util = { git = "https://github.com/rust-vmm/vmm-sys-util" } diff --git a/vendor/.sources b/vendor/.sources index a69966d68..d92841ace 100644 --- a/vendor/.sources +++ b/vendor/.sources @@ -1 +1 @@ -["git-3e7c44ea7d5fd800","git-4af8f4552cd0d200","git-89548d8276566400","git-bad78e1967b13e00","git-bda1448fb2afcb00","git-ccfa5f04f3f14300","registry-40351f815f426200"] \ No newline at end of file +["git-3e7c44ea7d5fd800","git-4af8f4552cd0d200","git-643dc7ede01ca600","git-89548d8276566400","git-bad78e1967b13e00","git-bda1448fb2afcb00","registry-40351f815f426200"] \ No newline at end of file diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/.buildkite/pipeline.yml b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/.buildkite/pipeline.yml deleted file mode 100644 index f62c2a4fc..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/.buildkite/pipeline.yml +++ /dev/null @@ -1,75 +0,0 @@ -steps: - - label: "build-gnu-x86" - commands: - - cargo build --release - retry: - automatic: false - agents: - platform: x86_64.metal - plugins: - - docker#v3.0.1: - image: "fandree/rust-vmm-dev" - always-pull: true - - - label: "build-gnu-arm" - commands: - - cargo build --release - retry: - automatic: false - agents: - platform: arm.metal - plugins: - - docker#v3.0.1: - image: "fandree/rust-vmm-dev" - always-pull: true - - - label: "style" - command: cargo fmt --all -- --check - retry: - automatic: false - agents: - platform: x86_64.metal - plugins: - - docker#v3.0.1: - image: "fandree/rust-vmm-dev" - always-pull: true - - - label: "unittests-gnu-x86" - commands: - - cargo test - retry: - automatic: false - agents: - platform: x86_64.metal - plugins: - - docker#v3.0.1: - privileged: true - image: "fandree/rust-vmm-dev" - always-pull: true - tmpfs: [ "/tmp:exec" ] - - - label: "unittests-gnu-arm" - commands: - - cargo test - retry: - automatic: false - agents: - platform: arm.metal - plugins: - - docker#v3.0.1: - privileged: true - image: "fandree/rust-vmm-dev" - always-pull: true - tmpfs: [ "/tmp:exec" ] - - - label: "clippy-x86" - commands: - - cargo clippy --all -- -D warnings - retry: - automatic: false - agents: - platform: x86_64.metal - plugins: - - docker#v3.0.1: - image: "fandree/rust-vmm-dev" - always-pull: true diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/.cargo-checksum.json b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/.cargo-checksum.json deleted file mode 100644 index 2bd61c742..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{".buildkite/pipeline.yml":"0194df2d3534e3c6938ba2945e05696a12b8ed63d4941b3a4173c5bcf6e587c4","Cargo.toml":"d19b52349ada25dbbae4e2bea4850cf1b09ea546d5efee03ddfbbf9f184c0c72","LICENSE-APACHE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","LICENSE-BSD-3-Clause":"a6d3ebd1c2f37d4fd83d0676621f695fc0cc2d8c6e646cdbb831b46e0650c208","README.md":"94512ed84e8e89faba431d9107e85d229363c187705ab9244f0ab5269b5961b5","src/errno.rs":"b93845c200fc596b0ef2414671d965cf5c4fdbf6bba6e5e5f0d032a32c73f8ac","src/eventfd.rs":"7bd871242f49c14d8783714e6814456f51a9c280dcadf1625e1bd2313d2b5f7f","src/file_traits.rs":"398c529e7ebce143ecb9f9bd2f5f47ea3e953ac34cc211ad71cdcf1898cc7d38","src/ioctl.rs":"5c4abf75e7b6786e7da3191ac1e4460e1ec7d073a53331a6d9597bb9ccc3f88a","src/lib.rs":"ee0818e0ca6fdc340c52d514eeb2e3aeb4f7ba8e4e522bb946cdbce4779926f1","src/poll.rs":"1498c14ba022ede57c4faf17bee49cf5ac9d1c8d3883db441697ee224dac7818","src/seek_hole.rs":"de43f21bc2c5d9eb7f06e21e3c20f93476bf6016e4d041df71a02b9e54b3c3ca","src/signal.rs":"724f679cb62d268a5ec8f0704a8d6b01882f302f508c189e82054657ed8b31bf","src/syslog.rs":"fbf4bde16b1059b5b39c5318e8bb918dc431e8e0ccbc82c0d765b9ce4a8d5f96","src/tempdir.rs":"4993460e81f7df6398e0f2b07cc3d81e728aa7e0559c7f3d83b6df1876bc3776","src/terminal.rs":"85efb1df641730fa1981bac6fd65bd75f7d532bb8680a56e94d6d006eeb363e9","src/timerfd.rs":"fd3c52e3918d881c16cb1498f8f66253ee758275a6a66ed8eb11c78e69f69e55","src/write_zeroes.rs":"c2951bbdb3ab07727eda29e9a91a51e427fdf6fed0b611ea6a3732edbd9a1246"},"package":null} \ No newline at end of file diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/Cargo.toml b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/Cargo.toml deleted file mode 100644 index bb697b6c3..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "vmm-sys-util" -version = "0.1.0" -authors = ["Jing Liu "] -license = "Apache-2.0" - -[dependencies] -libc = ">=0.2.39" - diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/LICENSE-APACHE b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/LICENSE-APACHE deleted file mode 100644 index 261eeb9e9..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/LICENSE-APACHE +++ /dev/null @@ -1,201 +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 - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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/git-ccfa5f04f3f14300/vmm-sys-util/LICENSE-BSD-3-Clause b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/LICENSE-BSD-3-Clause deleted file mode 100644 index 8bafca303..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/LICENSE-BSD-3-Clause +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2017 The Chromium OS Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/README.md b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/README.md deleted file mode 100644 index 383aa42db..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# vmm-sys-util -This crate is a collection of modules that provides helpers and utilities. diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/errno.rs b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/errno.rs deleted file mode 100644 index 89bbbb6b1..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/errno.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2019 Intel Corporation. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -// -// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -// -// Portions Copyright 2017 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-BSD-3-Clause file. - -use std::fmt::{Display, Formatter}; -use std::io; -use std::result; - -use libc::__errno_location; - -/// An error number, retrieved from [`errno`](http://man7.org/linux/man-pages/man3/errno.3.html), -/// set by a libc function that returned an error. -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct Error(i32); -pub type Result = result::Result; - -impl Error { - /// Constructs a new error with the given `errno`. - pub fn new(e: i32) -> Error { - Error(e) - } - - /// Constructs an error from the current `errno`. - /// - /// The result of this only has any meaning just after a libc call that returned a value - /// indicating `errno` was set. - pub fn last() -> Error { - Error(unsafe { *__errno_location() }) - } - - /// Gets the `errno` for this error. - pub fn errno(self) -> i32 { - self.0 - } -} - -impl Display for Error { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - io::Error::from_raw_os_error(self.0).fmt(f) - } -} - -impl From for Error { - fn from(e: io::Error) -> Self { - Error::new(e.raw_os_error().unwrap_or_default()) - } -} - -/// Returns the last `errno` as a [`Result`] that is always an error. -/// -/// [`Result`]: type.Result.html -pub fn errno_result() -> Result { - Err(Error::last()) -} - -#[cfg(test)] -mod tests { - use super::*; - use libc; - use std::fs::File; - use std::io::{self, Write}; - use std::os::unix::io::FromRawFd; - - #[test] - pub fn test_invalid_fd() { - let mut file = unsafe { File::from_raw_fd(-1) }; - assert!(file.write(b"test").is_err()); - let last_err = errno_result::().unwrap_err(); - assert_eq!(last_err, Error::new(libc::EBADF)); - assert_eq!(last_err.errno(), libc::EBADF); - assert_eq!(last_err, Error::from(io::Error::last_os_error())); - assert_eq!(last_err, Error::last()); - } -} diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/eventfd.rs b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/eventfd.rs deleted file mode 100644 index ff0542735..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/eventfd.rs +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2019 Intel Corporation. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -// -// Copyright 2017 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-BSD-3-Clause file. - -use std::fs::File; -use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; -use std::{io, mem, result}; - -use libc::{c_void, dup, eventfd, read, write}; - -/// A safe wrapper around a Linux eventfd (man 2 eventfd). -pub struct EventFd { - eventfd: File, -} - -impl EventFd { - /// Creates a new blocking EventFd with an initial value. - /// - /// `flag`: The initial value. Refer to Linux eventfd(2). - pub fn new(flag: i32) -> result::Result { - // This is safe because eventfd merely allocated an eventfd for - // our process and we handle the error case. - let ret = unsafe { eventfd(0, flag) }; - if ret < 0 { - Err(io::Error::last_os_error()) - } else { - // This is safe because we checked ret for success and know - // the kernel gave us an fd that we own. - Ok(EventFd { - eventfd: unsafe { File::from_raw_fd(ret) }, - }) - } - } - - /// Adds `v` to the eventfd's count, does not block if the result will overflow the count - pub fn write(&self, v: u64) -> result::Result<(), io::Error> { - // This is safe because we made this fd and the pointer we pass - // can not overflow because we give the syscall's size parameter properly. - let ret = unsafe { - write( - self.as_raw_fd(), - &v as *const u64 as *const c_void, - mem::size_of::(), - ) - }; - if ret <= 0 { - Err(io::Error::last_os_error()) - } else { - Ok(()) - } - } - - /// Tries to read from the eventfd, does not block if the counter is zero - pub fn read(&self) -> result::Result { - let mut buf: u64 = 0; - let ret = unsafe { - // This is safe because we made this fd and the pointer we - // pass can not overflow because we give the syscall's size parameter properly. - read( - self.as_raw_fd(), - &mut buf as *mut u64 as *mut c_void, - mem::size_of::(), - ) - }; - if ret < 0 { - Err(io::Error::last_os_error()) - } else { - Ok(buf) - } - } - - /// Clones this EventFd, internally creating a new file descriptor. The new EventFd will share - /// the same underlying count within the kernel. - pub fn try_clone(&self) -> result::Result { - // This is safe because we made this fd and properly check that it returns without error. - let ret = unsafe { dup(self.as_raw_fd()) }; - if ret < 0 { - Err(io::Error::last_os_error()) - } else { - // This is safe because we checked ret for success and know the kernel gave us an fd that we - // own. - Ok(EventFd { - eventfd: unsafe { File::from_raw_fd(ret) }, - }) - } - } -} - -impl AsRawFd for EventFd { - fn as_raw_fd(&self) -> RawFd { - self.eventfd.as_raw_fd() - } -} - -impl FromRawFd for EventFd { - unsafe fn from_raw_fd(fd: RawFd) -> Self { - EventFd { - eventfd: File::from_raw_fd(fd), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use libc::EFD_NONBLOCK; - - #[test] - fn test_new() { - EventFd::new(EFD_NONBLOCK).unwrap(); - EventFd::new(0).unwrap(); - } - - #[test] - fn test_read_write() { - let evt = EventFd::new(EFD_NONBLOCK).unwrap(); - evt.write(55).unwrap(); - assert_eq!(evt.read().unwrap(), 55); - } - - #[test] - fn test_write_overflow() { - let evt = EventFd::new(EFD_NONBLOCK).unwrap(); - evt.write(std::u64::MAX - 1).unwrap(); - let r = evt.write(1); - match r { - Err(ref inner) if inner.kind() == io::ErrorKind::WouldBlock => (), - _ => panic!("Unexpected"), - } - } - #[test] - fn test_read_nothing() { - let evt = EventFd::new(EFD_NONBLOCK).unwrap(); - let r = evt.read(); - match r { - Err(ref inner) if inner.kind() == io::ErrorKind::WouldBlock => (), - _ => panic!("Unexpected"), - } - } - #[test] - fn test_clone() { - let evt = EventFd::new(EFD_NONBLOCK).unwrap(); - let evt_clone = evt.try_clone().unwrap(); - evt.write(923).unwrap(); - assert_eq!(evt_clone.read().unwrap(), 923); - } -} diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/file_traits.rs b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/file_traits.rs deleted file mode 100644 index a2fa77b87..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/file_traits.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2018 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-BSD-3-Clause file. -// -// SPDX-License-Identifier: BSD-3-Clause - -use std::fs::File; -use std::io::Result; - -/// A trait for flushing the contents of a file to disk. -/// This is equivalent to File's `sync_all` method, but -/// wrapped in a trait so that it can be implemented for -/// other types. -pub trait FileSync { - // Flush buffers related to this file to disk. - fn fsync(&mut self) -> Result<()>; -} - -impl FileSync for File { - fn fsync(&mut self) -> Result<()> { - self.sync_all() - } -} - -/// A trait for setting the size of a file. -/// This is equivalent to File's `set_len` method, but -/// wrapped in a trait so that it can be implemented for -/// other types. -pub trait FileSetLen { - // Set the size of this file. - // This is the moral equivalent of `ftruncate()`. - fn set_len(&self, _len: u64) -> Result<()>; -} - -impl FileSetLen for File { - fn set_len(&self, len: u64) -> Result<()> { - File::set_len(self, len) - } -} diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/ioctl.rs b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/ioctl.rs deleted file mode 100644 index 0adc3b1d4..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/ioctl.rs +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright 2019 Intel Corporation. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -// -// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -// -// Portions Copyright 2017 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-BSD-3-Clause file. - -//! Macros and wrapper functions for dealing with ioctls. -use libc; -use std::os::raw::{c_int, c_uint, c_ulong, c_void}; -use std::os::unix::io::AsRawFd; - -/// Raw macro to declare the expression that calculates an ioctl number -#[macro_export] -macro_rules! ioctl_expr { - ($dir:expr, $ty:expr, $nr:expr, $size:expr) => { - (($dir << $crate::ioctl::_IOC_DIRSHIFT) - | ($ty << $crate::ioctl::_IOC_TYPESHIFT) - | ($nr << $crate::ioctl::_IOC_NRSHIFT) - | ($size << $crate::ioctl::_IOC_SIZESHIFT)) as ::std::os::raw::c_ulong - }; -} - -/// Raw macro to declare a function that returns an ioctl number. -#[macro_export] -macro_rules! ioctl_ioc_nr { - ($name:ident, $dir:expr, $ty:expr, $nr:expr, $size:expr) => { - #[allow(non_snake_case)] - #[allow(clippy::cast_lossless)] - pub fn $name() -> ::std::os::raw::c_ulong { - ioctl_expr!($dir, $ty, $nr, $size) - } - }; - ($name:ident, $dir:expr, $ty:expr, $nr:expr, $size:expr, $($v:ident),+) => { - #[allow(non_snake_case)] - #[allow(clippy::cast_lossless)] - pub fn $name($($v: ::std::os::raw::c_uint),+) -> ::std::os::raw::c_ulong { - ioctl_expr!($dir, $ty, $nr, $size) - } - }; -} - -/// Declare an ioctl that transfers no data. -#[macro_export] -macro_rules! ioctl_io_nr { - ($name:ident, $ty:expr, $nr:expr) => { - ioctl_ioc_nr!($name, $crate::ioctl::_IOC_NONE, $ty, $nr, 0); - }; - ($name:ident, $ty:expr, $nr:expr, $($v:ident),+) => { - ioctl_ioc_nr!($name, $crate::ioctl::_IOC_NONE, $ty, $nr, 0, $($v),+); - }; -} - -/// Declare an ioctl that reads data. -#[macro_export] -macro_rules! ioctl_ior_nr { - ($name:ident, $ty:expr, $nr:expr, $size:ty) => { - ioctl_ioc_nr!( - $name, - $crate::ioctl::_IOC_READ, - $ty, - $nr, - ::std::mem::size_of::<$size>() as u32 - ); - }; - ($name:ident, $ty:expr, $nr:expr, $size:ty, $($v:ident),+) => { - ioctl_ioc_nr!( - $name, - $crate::ioctl::_IOC_READ, - $ty, - $nr, - ::std::mem::size_of::<$size>() as u32, - $($v),+ - ); - }; -} - -/// Declare an ioctl that writes data. -#[macro_export] -macro_rules! ioctl_iow_nr { - ($name:ident, $ty:expr, $nr:expr, $size:ty) => { - ioctl_ioc_nr!( - $name, - $crate::ioctl::_IOC_WRITE, - $ty, - $nr, - ::std::mem::size_of::<$size>() as u32 - ); - }; - ($name:ident, $ty:expr, $nr:expr, $size:ty, $($v:ident),+) => { - ioctl_ioc_nr!( - $name, - $crate::ioctl::_IOC_WRITE, - $ty, - $nr, - ::std::mem::size_of::<$size>() as u32, - $($v),+ - ); - }; -} - -/// Declare an ioctl that reads and writes data. -#[macro_export] -macro_rules! ioctl_iowr_nr { - ($name:ident, $ty:expr, $nr:expr, $size:ty) => { - ioctl_ioc_nr!( - $name, - $crate::ioctl::_IOC_READ | $crate::ioctl::_IOC_WRITE, - $ty, - $nr, - ::std::mem::size_of::<$size>() as u32 - ); - }; - ($name:ident, $ty:expr, $nr:expr, $size:ty, $($v:ident),+) => { - ioctl_ioc_nr!( - $name, - $crate::ioctl::_IOC_READ | $crate::ioctl::_IOC_WRITE, - $ty, - $nr, - ::std::mem::size_of::<$size>() as u32, - $($v),+ - ); - }; -} - -pub const _IOC_NRBITS: c_uint = 8; -pub const _IOC_TYPEBITS: c_uint = 8; -pub const _IOC_SIZEBITS: c_uint = 14; -pub const _IOC_DIRBITS: c_uint = 2; -pub const _IOC_NRMASK: c_uint = 255; -pub const _IOC_TYPEMASK: c_uint = 255; -pub const _IOC_SIZEMASK: c_uint = 16383; -pub const _IOC_DIRMASK: c_uint = 3; -pub const _IOC_NRSHIFT: c_uint = 0; -pub const _IOC_TYPESHIFT: c_uint = 8; -pub const _IOC_SIZESHIFT: c_uint = 16; -pub const _IOC_DIRSHIFT: c_uint = 30; -pub const _IOC_NONE: c_uint = 0; -pub const _IOC_WRITE: c_uint = 1; -pub const _IOC_READ: c_uint = 2; -pub const IOC_IN: c_uint = 1_073_741_824; -pub const IOC_OUT: c_uint = 2_147_483_648; -pub const IOC_INOUT: c_uint = 3_221_225_472; -pub const IOCSIZE_MASK: c_uint = 1_073_676_288; -pub const IOCSIZE_SHIFT: c_uint = 16; - -// The type of the `req` parameter is different for the `musl` library. This will enable -// successful build for other non-musl libraries. -#[cfg(target_env = "musl")] -type IoctlRequest = c_int; -#[cfg(not(target_env = "musl"))] -type IoctlRequest = c_ulong; - -/// Run an ioctl with no arguments. -pub unsafe fn ioctl(fd: &F, req: c_ulong) -> c_int { - libc::ioctl(fd.as_raw_fd(), req as IoctlRequest, 0) -} - -/// Run an ioctl with a single value argument. -pub unsafe fn ioctl_with_val(fd: &F, req: c_ulong, arg: c_ulong) -> c_int { - libc::ioctl(fd.as_raw_fd(), req as IoctlRequest, arg) -} - -/// Run an ioctl with an immutable reference. -pub unsafe fn ioctl_with_ref(fd: &F, req: c_ulong, arg: &T) -> c_int { - libc::ioctl( - fd.as_raw_fd(), - req as IoctlRequest, - arg as *const T as *const c_void, - ) -} - -/// Run an ioctl with a mutable reference. -pub unsafe fn ioctl_with_mut_ref(fd: &F, req: c_ulong, arg: &mut T) -> c_int { - libc::ioctl( - fd.as_raw_fd(), - req as IoctlRequest, - arg as *mut T as *mut c_void, - ) -} - -/// Run an ioctl with a raw pointer. -pub unsafe fn ioctl_with_ptr(fd: &F, req: c_ulong, arg: *const T) -> c_int { - libc::ioctl(fd.as_raw_fd(), req as IoctlRequest, arg as *const c_void) -} - -/// Run an ioctl with a mutable raw pointer. -pub unsafe fn ioctl_with_mut_ptr(fd: &F, req: c_ulong, arg: *mut T) -> c_int { - libc::ioctl(fd.as_raw_fd(), req as IoctlRequest, arg as *mut c_void) -} - -#[cfg(test)] -mod tests { - const TUNTAP: ::std::os::raw::c_uint = 0x54; - const VHOST: ::std::os::raw::c_uint = 0xAF; - const EVDEV: ::std::os::raw::c_uint = 0x45; - - const KVMIO: ::std::os::raw::c_uint = 0xAE; - - ioctl_io_nr!(KVM_CREATE_VM, KVMIO, 0x01); - ioctl_ior_nr!(TUNGETFEATURES, TUNTAP, 0xcf, ::std::os::raw::c_uint); - ioctl_iow_nr!(TUNSETQUEUE, TUNTAP, 0xd9, ::std::os::raw::c_int); - ioctl_io_nr!(VHOST_SET_OWNER, VHOST, 0x01); - ioctl_iowr_nr!(VHOST_GET_VRING_BASE, VHOST, 0x12, ::std::os::raw::c_int); - ioctl_iowr_nr!(KVM_GET_MSR_INDEX_LIST, KVMIO, 0x2, ::std::os::raw::c_int); - - ioctl_ior_nr!(EVIOCGBIT, EVDEV, 0x20 + evt, [u8; 128], evt); - ioctl_io_nr!(FAKE_IOCTL_2_ARG, EVDEV, 0x01 + x + y, x, y); - - #[test] - fn test_ioctl_macros() { - assert_eq!(0x0000_AE01, KVM_CREATE_VM()); - assert_eq!(0x0000_AF01, VHOST_SET_OWNER()); - assert_eq!(0x8004_54CF, TUNGETFEATURES()); - assert_eq!(0x4004_54D9, TUNSETQUEUE()); - assert_eq!(0xC004_AE02, KVM_GET_MSR_INDEX_LIST()); - assert_eq!(0xC004_AF12, VHOST_GET_VRING_BASE()); - - assert_eq!(0x8080_4522, EVIOCGBIT(2)); - assert_eq!(0x0000_4509, FAKE_IOCTL_2_ARG(3, 5)); - } -} diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/lib.rs b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/lib.rs deleted file mode 100644 index 883e4a53d..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/lib.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2019 Intel Corporation. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -extern crate libc; - -mod tempdir; - -#[macro_use] -pub mod ioctl; - -pub mod errno; -pub mod eventfd; -pub mod file_traits; -pub mod seek_hole; -pub mod signal; -pub mod terminal; -pub mod timerfd; -pub mod write_zeroes; - -#[macro_use] -pub mod syslog; - -pub mod poll; - -pub use crate::tempdir::*; -pub use errno::*; -pub use eventfd::*; -pub use poll::*; - -use std::os::unix::io::AsRawFd; - -pub use crate::file_traits::{FileSetLen, FileSync}; -pub use crate::seek_hole::SeekHole; -pub use crate::write_zeroes::{PunchHole, WriteZeroes}; - -pub enum FallocateMode { - PunchHole, - ZeroRange, -} - -/// Safe wrapper for `fallocate()`. -pub fn fallocate( - file: &dyn AsRawFd, - mode: FallocateMode, - keep_size: bool, - offset: u64, - len: u64, -) -> Result<()> { - let offset = if offset > libc::off64_t::max_value() as u64 { - return Err(Error::new(libc::EINVAL)); - } else { - offset as libc::off64_t - }; - - let len = if len > libc::off64_t::max_value() as u64 { - return Err(Error::new(libc::EINVAL)); - } else { - len as libc::off64_t - }; - - let mut mode = match mode { - FallocateMode::PunchHole => libc::FALLOC_FL_PUNCH_HOLE, - FallocateMode::ZeroRange => libc::FALLOC_FL_ZERO_RANGE, - }; - - if keep_size { - mode |= libc::FALLOC_FL_KEEP_SIZE; - } - - // Safe since we pass in a valid fd and fallocate mode, validate offset and len, - // and check the return value. - let ret = unsafe { libc::fallocate64(file.as_raw_fd(), mode, offset, len) }; - if ret < 0 { - errno_result() - } else { - Ok(()) - } -} diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/poll.rs b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/poll.rs deleted file mode 100644 index 4eb49a429..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/poll.rs +++ /dev/null @@ -1,711 +0,0 @@ -// Copyright 2019 Intel Corporation. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -// -// Copyright 2017 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-BSD-3-Clause file. - -use std::cell::{Cell, Ref, RefCell}; -use std::cmp::min; -use std::fs::File; -use std::i32; -use std::i64; -use std::marker::PhantomData; -use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -use std::ptr::null_mut; -use std::slice; -use std::thread; -use std::time::Duration; - -use libc::{ - c_int, epoll_create1, epoll_ctl, epoll_event, epoll_wait, EINTR, EPOLLHUP, EPOLLIN, EPOLLOUT, - EPOLL_CLOEXEC, EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD, -}; - -use crate::{errno_result, Error, Result}; - -macro_rules! handle_eintr_errno { - ($x:expr) => {{ - let mut res; - loop { - res = $x; - if res != -1 || Error::last() != Error::new(EINTR) { - break; - } - } - res - }}; -} - -const POLL_CONTEXT_MAX_EVENTS: usize = 16; - -/// EpollEvents wraps raw epoll_events, it should only be used with EpollContext. -pub struct EpollEvents(RefCell<[epoll_event; POLL_CONTEXT_MAX_EVENTS]>); - -impl EpollEvents { - pub fn new() -> EpollEvents { - EpollEvents(RefCell::new( - [epoll_event { events: 0, u64: 0 }; POLL_CONTEXT_MAX_EVENTS], - )) - } -} - -impl Default for EpollEvents { - fn default() -> Self { - Self::new() - } -} - -/// Trait for a token that can be associated with an `fd` in a `PollContext`. -/// -/// Simple enums that have no or primitive variant data can use the `#[derive(PollToken)]` -/// custom derive to implement this trait. -pub trait PollToken { - /// Converts this token into a u64 that can be turned back into a token via `from_raw_token`. - fn as_raw_token(&self) -> u64; - - /// Converts a raw token as returned from `as_raw_token` back into a token. - /// - /// It is invalid to give a raw token that was not returned via `as_raw_token` from the same - /// `Self`. The implementation can expect that this will never happen as a result of its usage - /// in `PollContext`. - fn from_raw_token(data: u64) -> Self; -} - -impl PollToken for usize { - fn as_raw_token(&self) -> u64 { - *self as u64 - } - - fn from_raw_token(data: u64) -> Self { - data as Self - } -} - -impl PollToken for u64 { - fn as_raw_token(&self) -> u64 { - *self as u64 - } - - fn from_raw_token(data: u64) -> Self { - data as Self - } -} - -impl PollToken for u32 { - fn as_raw_token(&self) -> u64 { - u64::from(*self) - } - - fn from_raw_token(data: u64) -> Self { - data as Self - } -} - -impl PollToken for u16 { - fn as_raw_token(&self) -> u64 { - u64::from(*self) - } - - fn from_raw_token(data: u64) -> Self { - data as Self - } -} - -impl PollToken for u8 { - fn as_raw_token(&self) -> u64 { - u64::from(*self) - } - - fn from_raw_token(data: u64) -> Self { - data as Self - } -} - -impl PollToken for () { - fn as_raw_token(&self) -> u64 { - 0 - } - - fn from_raw_token(_data: u64) -> Self {} -} - -/// An event returned by `PollContext::wait`. -pub struct PollEvent<'a, T> { - event: &'a epoll_event, - token: PhantomData, // Needed to satisfy usage of T -} - -impl<'a, T: PollToken> PollEvent<'a, T> { - /// Gets the token associated in `PollContext::add` with this event. - pub fn token(&self) -> T { - T::from_raw_token(self.event.u64) - } - - /// True if the `fd` associated with this token in `PollContext::add` is readable. - pub fn readable(&self) -> bool { - self.event.events & (EPOLLIN as u32) != 0 - } - - /// True if the `fd` associated with this token in `PollContext::add` has been hungup on. - pub fn hungup(&self) -> bool { - self.event.events & (EPOLLHUP as u32) != 0 - } -} - -/// An iterator over some (sub)set of events returned by `PollContext::wait`. -pub struct PollEventIter<'a, I, T> -where - I: Iterator, -{ - mask: u32, - iter: I, - tokens: PhantomData<[T]>, // Needed to satisfy usage of T -} - -impl<'a, I, T> Iterator for PollEventIter<'a, I, T> -where - I: Iterator, - T: PollToken, -{ - type Item = PollEvent<'a, T>; - fn next(&mut self) -> Option { - let mask = self.mask; - self.iter - .find(|event| (event.events & mask) != 0) - .map(|event| PollEvent { - event, - token: PhantomData, - }) - } -} - -/// The list of event returned by `PollContext::wait`. -pub struct PollEvents<'a, T> { - count: usize, - events: Ref<'a, [epoll_event; POLL_CONTEXT_MAX_EVENTS]>, - tokens: PhantomData<[T]>, // Needed to satisfy usage of T -} - -impl<'a, T: PollToken> PollEvents<'a, T> { - /// Copies the events to an owned structure so the reference to this (and by extension - /// `PollContext`) can be dropped. - pub fn to_owned(&self) -> PollEventsOwned { - PollEventsOwned { - count: self.count, - events: RefCell::new(*self.events), - tokens: PhantomData, - } - } - - /// Iterates over each event. - pub fn iter(&self) -> PollEventIter, T> { - PollEventIter { - mask: 0xffff_ffff, - iter: self.events[..self.count].iter(), - tokens: PhantomData, - } - } - - /// Iterates over each readable event. - pub fn iter_readable(&self) -> PollEventIter, T> { - PollEventIter { - mask: EPOLLIN as u32, - iter: self.events[..self.count].iter(), - tokens: PhantomData, - } - } - - /// Iterates over each hungup event. - pub fn iter_hungup(&self) -> PollEventIter, T> { - PollEventIter { - mask: EPOLLHUP as u32, - iter: self.events[..self.count].iter(), - tokens: PhantomData, - } - } -} - -/// A deep copy of the event records from `PollEvents`. -pub struct PollEventsOwned { - count: usize, - events: RefCell<[epoll_event; POLL_CONTEXT_MAX_EVENTS]>, - tokens: PhantomData, // Needed to satisfy usage of T -} - -impl PollEventsOwned { - /// Takes a reference to the events so that they can be iterated via methods in `PollEvents`. - pub fn as_ref(&self) -> PollEvents { - PollEvents { - count: self.count, - events: self.events.borrow(), - tokens: PhantomData, - } - } -} - -/// Watching events taken by PollContext. -pub struct WatchingEvents(u32); - -impl WatchingEvents { - /// Returns empty Events. - #[inline(always)] - pub fn empty() -> WatchingEvents { - WatchingEvents(0) - } - - /// Build Events from raw epoll events (defined in epoll_ctl(2)). - #[inline(always)] - pub fn new(raw: u32) -> WatchingEvents { - WatchingEvents(raw) - } - - /// Set read events. - #[inline(always)] - pub fn set_read(self) -> WatchingEvents { - WatchingEvents(self.0 | EPOLLIN as u32) - } - - /// Set write events. - #[inline(always)] - pub fn set_write(self) -> WatchingEvents { - WatchingEvents(self.0 | EPOLLOUT as u32) - } - - /// Get the underlying epoll events. - pub fn get_raw(&self) -> u32 { - self.0 - } -} - -/// EpollContext wraps linux epoll. It provides similar interface to PollContext. -/// It is thread safe while PollContext is not. It requires user to pass in a reference of -/// EpollEvents while PollContext does not. Always use PollContext if you don't need to access the -/// same epoll from different threads. -pub struct EpollContext { - epoll_ctx: File, - // Needed to satisfy usage of T - tokens: PhantomData<[T]>, -} - -impl EpollContext { - /// Creates a new `EpollContext`. - pub fn new() -> Result> { - // Safe because we check the return value. - let epoll_fd = unsafe { epoll_create1(EPOLL_CLOEXEC) }; - if epoll_fd < 0 { - return errno_result(); - } - Ok(EpollContext { - epoll_ctx: unsafe { File::from_raw_fd(epoll_fd) }, - tokens: PhantomData, - }) - } - - /// Adds the given `fd` to this context and associates the given `token` with the `fd`'s - /// readable events. - /// - /// A `fd` can only be added once and does not need to be kept open. If the `fd` is dropped and - /// there were no duplicated file descriptors (i.e. adding the same descriptor with a different - /// FD number) added to this context, events will not be reported by `wait` anymore. - pub fn add(&self, fd: &AsRawFd, token: T) -> Result<()> { - self.add_fd_with_events(fd, WatchingEvents::empty().set_read(), token) - } - - /// Adds the given `fd` to this context, watching for the specified events and associates the - /// given 'token' with those events. - /// - /// A `fd` can only be added once and does not need to be kept open. If the `fd` is dropped and - /// there were no duplicated file descriptors (i.e. adding the same descriptor with a different - /// FD number) added to this context, events will not be reported by `wait` anymore. - pub fn add_fd_with_events(&self, fd: &AsRawFd, events: WatchingEvents, token: T) -> Result<()> { - let mut evt = epoll_event { - events: events.get_raw(), - u64: token.as_raw_token(), - }; - // Safe because we give a valid epoll FD and FD to watch, as well as a valid epoll_event - // structure. Then we check the return value. - let ret = unsafe { - epoll_ctl( - self.epoll_ctx.as_raw_fd(), - EPOLL_CTL_ADD, - fd.as_raw_fd(), - &mut evt, - ) - }; - if ret < 0 { - return errno_result(); - }; - Ok(()) - } - - /// If `fd` was previously added to this context, the watched events will be replaced with - /// `events` and the token associated with it will be replaced with the given `token`. - pub fn modify(&self, fd: &AsRawFd, events: WatchingEvents, token: T) -> Result<()> { - let mut evt = epoll_event { - events: events.0, - u64: token.as_raw_token(), - }; - // Safe because we give a valid epoll FD and FD to modify, as well as a valid epoll_event - // structure. Then we check the return value. - let ret = unsafe { - epoll_ctl( - self.epoll_ctx.as_raw_fd(), - EPOLL_CTL_MOD, - fd.as_raw_fd(), - &mut evt, - ) - }; - if ret < 0 { - return errno_result(); - }; - Ok(()) - } - - /// Deletes the given `fd` from this context. - /// - /// If an `fd`'s token shows up in the list of hangup events, it should be removed using this - /// method or by closing/dropping (if and only if the fd was never dup()'d/fork()'d) the `fd`. - /// Failure to do so will cause the `wait` method to always return immediately, causing ~100% - /// CPU load. - pub fn delete(&self, fd: &AsRawFd) -> Result<()> { - // Safe because we give a valid epoll FD and FD to stop watching. Then we check the return - // value. - let ret = unsafe { - epoll_ctl( - self.epoll_ctx.as_raw_fd(), - EPOLL_CTL_DEL, - fd.as_raw_fd(), - null_mut(), - ) - }; - if ret < 0 { - return errno_result(); - }; - Ok(()) - } - - /// Waits for any events to occur in FDs that were previously added to this context. - /// - /// The events are level-triggered, meaning that if any events are unhandled (i.e. not reading - /// for readable events and not closing for hungup events), subsequent calls to `wait` will - /// return immediately. The consequence of not handling an event perpetually while calling - /// `wait` is that the callers loop will degenerated to busy loop polling, pinning a CPU to - /// ~100% usage. - pub fn wait<'a>(&self, events: &'a EpollEvents) -> Result> { - self.wait_timeout(events, Duration::new(i64::MAX as u64, 0)) - } - - /// Like `wait` except will only block for a maximum of the given `timeout`. - /// - /// This may return earlier than `timeout` with zero events if the duration indicated exceeds - /// system limits. - pub fn wait_timeout<'a>( - &self, - events: &'a EpollEvents, - timeout: Duration, - ) -> Result> { - let timeout_millis = if timeout.as_secs() as i64 == i64::max_value() { - // We make the convenient assumption that 2^63 seconds is an effectively unbounded time - // frame. This is meant to mesh with `wait` calling us with no timeout. - -1 - } else { - // In cases where we the number of milliseconds would overflow an i32, we substitute the - // maximum timeout which is ~24.8 days. - let millis = timeout - .as_secs() - .checked_mul(1_000) - .and_then(|ms| ms.checked_add(u64::from(timeout.subsec_nanos()) / 1_000_000)) - .unwrap_or(i32::max_value() as u64); - min(i32::max_value() as u64, millis) as i32 - }; - let ret = { - let mut epoll_events = events.0.borrow_mut(); - let max_events = epoll_events.len() as c_int; - // Safe because we give an epoll context and a properly sized epoll_events array - // pointer, which we trust the kernel to fill in properly. - unsafe { - handle_eintr_errno!(epoll_wait( - self.epoll_ctx.as_raw_fd(), - &mut epoll_events[0], - max_events, - timeout_millis - )) - } - }; - if ret < 0 { - return errno_result(); - } - let epoll_events = events.0.borrow(); - let events = PollEvents { - count: ret as usize, - events: epoll_events, - tokens: PhantomData, - }; - Ok(events) - } -} - -impl AsRawFd for EpollContext { - fn as_raw_fd(&self) -> RawFd { - self.epoll_ctx.as_raw_fd() - } -} - -impl IntoRawFd for EpollContext { - fn into_raw_fd(self) -> RawFd { - self.epoll_ctx.into_raw_fd() - } -} - -/// Used to poll multiple objects that have file descriptors. -/// -/// # Example -/// -/// ``` -/// # use vmm_sys_util::{Result, EventFd, PollContext, PollEvents}; -/// # fn test() -> Result<()> { -/// let evt1 = EventFd::new(0)?; -/// let evt2 = EventFd::new(0)?; -/// evt2.write(1)?; -/// -/// let ctx: PollContext = PollContext::new()?; -/// ctx.add(&evt1, 1)?; -/// ctx.add(&evt2, 2)?; -/// -/// let pollevents: PollEvents = ctx.wait()?; -/// let tokens: Vec = pollevents.iter_readable().map(|e| e.token()).collect(); -/// assert_eq!(&tokens[..], &[2]); -/// # Ok(()) -/// # } -/// ``` -pub struct PollContext { - epoll_ctx: EpollContext, - - // We use a RefCell here so that the `wait` method only requires an immutable self reference - // while returning the events (encapsulated by PollEvents). Without the RefCell, `wait` would - // hold a mutable reference that lives as long as its returned reference (i.e. the PollEvents), - // even though that reference is immutable. This is terribly inconvenient for the caller because - // the borrow checking would prevent them from using `delete` and `add` while the events are in - // scope. - events: EpollEvents, - - // Hangup busy loop detection variables. See `check_for_hungup_busy_loop`. - hangups: Cell, - max_hangups: Cell, -} - -impl PollContext { - /// Creates a new `PollContext`. - pub fn new() -> Result> { - Ok(PollContext { - epoll_ctx: EpollContext::new()?, - events: EpollEvents::new(), - hangups: Cell::new(0), - max_hangups: Cell::new(0), - }) - } - - /// Adds the given `fd` to this context and associates the given `token` with the `fd`'s - /// readable events. - /// - /// A `fd` can only be added once and does not need to be kept open. If the `fd` is dropped and - /// there were no duplicated file descriptors (i.e. adding the same descriptor with a different - /// FD number) added to this context, events will not be reported by `wait` anymore. - pub fn add(&self, fd: &AsRawFd, token: T) -> Result<()> { - self.add_fd_with_events(fd, WatchingEvents::empty().set_read(), token) - } - - /// Adds the given `fd` to this context, watching for the specified events and associates the - /// given 'token' with those events. - /// - /// A `fd` can only be added once and does not need to be kept open. If the `fd` is dropped and - /// there were no duplicated file descriptors (i.e. adding the same descriptor with a different - /// FD number) added to this context, events will not be reported by `wait` anymore. - pub fn add_fd_with_events(&self, fd: &AsRawFd, events: WatchingEvents, token: T) -> Result<()> { - self.epoll_ctx.add_fd_with_events(fd, events, token)?; - self.hangups.set(0); - self.max_hangups.set(self.max_hangups.get() + 1); - Ok(()) - } - - /// If `fd` was previously added to this context, the watched events will be replaced with - /// `events` and the token associated with it will be replaced with the given `token`. - pub fn modify(&self, fd: &AsRawFd, events: WatchingEvents, token: T) -> Result<()> { - self.epoll_ctx.modify(fd, events, token) - } - - /// Deletes the given `fd` from this context. - /// - /// If an `fd`'s token shows up in the list of hangup events, it should be removed using this - /// method or by closing/dropping (if and only if the fd was never dup()'d/fork()'d) the `fd`. - /// Failure to do so will cause the `wait` method to always return immediately, causing ~100% - /// CPU load. - pub fn delete(&self, fd: &AsRawFd) -> Result<()> { - self.epoll_ctx.delete(fd)?; - self.hangups.set(0); - self.max_hangups.set(self.max_hangups.get() - 1); - Ok(()) - } - - // This method determines if the the user of wait is misusing the `PollContext` by leaving FDs - // in this `PollContext` that have been shutdown or hungup on. Such an FD will cause `wait` to - // return instantly with a hungup event. If that FD is perpetually left in this context, a busy - // loop burning ~100% of one CPU will silently occur with no human visible malfunction. - // - // How do we know if the client of this context is ignoring hangups? A naive implementation - // would trigger if consecutive wait calls yield hangup events, but there are legitimate cases - // for this, such as two distinct sockets becoming hungup across two consecutive wait calls. A - // smarter implementation would only trigger if `delete` wasn't called between waits that - // yielded hangups. Sadly `delete` isn't the only way to remove an FD from this context. The - // other way is for the client to close the hungup FD, which automatically removes it from this - // context. Assuming that the client always uses close, this implementation would too eagerly - // trigger. - // - // The implementation used here keeps an upper bound of FDs in this context using a counter - // hooked into add/delete (which is imprecise because close can also remove FDs without us - // knowing). The number of consecutive (no add or delete in between) hangups yielded by wait - // calls is counted and compared to the upper bound. If the upper bound is exceeded by the - // consecutive hangups, the implementation triggers the check and logs. - // - // This implementation has false negatives because the upper bound can be completely too high, - // in the worst case caused by only using close instead of delete. However, this method has the - // advantage of always triggering eventually genuine busy loop cases, requires no dynamic - // allocations, is fast and constant time to compute, and has no false positives. - fn check_for_hungup_busy_loop(&self, new_hangups: usize) { - let old_hangups = self.hangups.get(); - let max_hangups = self.max_hangups.get(); - if old_hangups <= max_hangups && old_hangups + new_hangups > max_hangups { - warn!( - "busy poll wait loop with hungup FDs detected on thread {}", - thread::current().name().unwrap_or("") - ); - // This panic is helpful for tests of this functionality. - #[cfg(test)] - panic!("hungup busy loop detected"); - } - self.hangups.set(old_hangups + new_hangups); - } - - /// Waits for any events to occur in FDs that were previously added to this context. - /// - /// The events are level-triggered, meaning that if any events are unhandled (i.e. not reading - /// for readable events and not closing for hungup events), subsequent calls to `wait` will - /// return immediately. The consequence of not handling an event perpetually while calling - /// `wait` is that the callers loop will degenerated to busy loop polling, pinning a CPU to - /// ~100% usage. - /// - /// # Panics - /// Panics if the returned `PollEvents` structure is not dropped before subsequent `wait` calls. - pub fn wait(&self) -> Result> { - self.wait_timeout(Duration::new(i64::MAX as u64, 0)) - } - - /// Like `wait` except will only block for a maximum of the given `timeout`. - /// - /// This may return earlier than `timeout` with zero events if the duration indicated exceeds - /// system limits. - pub fn wait_timeout(&self, timeout: Duration) -> Result> { - let events = self.epoll_ctx.wait_timeout(&self.events, timeout)?; - let hangups = events.iter_hungup().count(); - self.check_for_hungup_busy_loop(hangups); - Ok(events) - } -} - -impl AsRawFd for PollContext { - fn as_raw_fd(&self) -> RawFd { - self.epoll_ctx.as_raw_fd() - } -} - -impl IntoRawFd for PollContext { - fn into_raw_fd(self) -> RawFd { - self.epoll_ctx.into_raw_fd() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::eventfd::EventFd; - use std::os::unix::net::UnixStream; - use std::time::Instant; - - #[test] - fn test_poll_context() { - let evt1 = EventFd::new(0).unwrap(); - let evt2 = EventFd::new(0).unwrap(); - evt1.write(1).unwrap(); - evt2.write(1).unwrap(); - let ctx: PollContext = PollContext::new().unwrap(); - ctx.add(&evt1, 1).unwrap(); - ctx.add(&evt2, 2).unwrap(); - - let mut evt_count = 0; - while evt_count < 2 { - for event in ctx.wait().unwrap().iter_readable() { - evt_count += 1; - match event.token() { - 1 => { - evt1.read().unwrap(); - ctx.delete(&evt1).unwrap(); - } - 2 => { - evt2.read().unwrap(); - ctx.delete(&evt2).unwrap(); - } - _ => panic!("unexpected token"), - }; - } - } - assert_eq!(evt_count, 2); - } - - #[test] - fn test_poll_context_overflow() { - const EVT_COUNT: usize = POLL_CONTEXT_MAX_EVENTS * 2 + 1; - let ctx: PollContext = PollContext::new().unwrap(); - let mut evts = Vec::with_capacity(EVT_COUNT); - for i in 0..EVT_COUNT { - let evt = EventFd::new(0).unwrap(); - evt.write(1).unwrap(); - ctx.add(&evt, i).unwrap(); - evts.push(evt); - } - let mut evt_count = 0; - while evt_count < EVT_COUNT { - for event in ctx.wait().unwrap().iter_readable() { - evts[event.token()].read().unwrap(); - evt_count += 1; - } - } - } - - #[test] - #[should_panic] - fn test_poll_context_hungup() { - let (s1, s2) = UnixStream::pair().unwrap(); - let ctx: PollContext = PollContext::new().unwrap(); - ctx.add(&s1, 1).unwrap(); - - // Causes s1 to receive hangup events, which we purposefully ignore to trip the detection - // logic in `PollContext`. - drop(s2); - - // Should easily panic within this many iterations. - for _ in 0..1000 { - ctx.wait().unwrap(); - } - } - - #[test] - fn test_poll_context_timeout() { - let ctx: PollContext = PollContext::new().unwrap(); - let dur = Duration::from_millis(10); - let start_inst = Instant::now(); - ctx.wait_timeout(dur).unwrap(); - assert!(start_inst.elapsed() >= dur); - } - -} diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/seek_hole.rs b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/seek_hole.rs deleted file mode 100644 index 12ac2e9bb..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/seek_hole.rs +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright 2018 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-BSD-3-Clause file. -// -// SPDX-License-Identifier: BSD-3-Clause - -use std::fs::File; -use std::io::{Error, Result}; -use std::os::unix::io::AsRawFd; - -#[cfg(target_env = "musl")] -use libc::{c_int, lseek64, ENXIO}; - -#[cfg(target_env = "gnu")] -use libc::{lseek64, ENXIO, SEEK_DATA, SEEK_HOLE}; - -/// A trait for seeking to the next hole or non-hole position in a file. -pub trait SeekHole { - /// Seek to the first hole in a file at a position greater than or equal to `offset`. - /// If no holes exist after `offset`, the seek position will be set to the end of the file. - /// If `offset` is at or after the end of the file, the seek position is unchanged, and None is returned. - /// Returns the current seek position after the seek or an error. - fn seek_hole(&mut self, offset: u64) -> Result>; - - /// Seek to the first data in a file at a position greater than or equal to `offset`. - /// If no data exists after `offset`, the seek position is unchanged, and None is returned. - /// Returns the current offset after the seek or an error. - fn seek_data(&mut self, offset: u64) -> Result>; -} - -#[cfg(target_env = "musl")] -pub const SEEK_DATA: c_int = 3; -#[cfg(target_env = "musl")] -pub const SEEK_HOLE: c_int = 4; - -/// Safe wrapper for `libc::lseek64()` -fn lseek(file: &mut File, offset: i64, whence: i32) -> Result> { - // This is safe because we pass a known-good file descriptor. - let res = unsafe { lseek64(file.as_raw_fd(), offset, whence) }; - - if res < 0 { - // Convert ENXIO into None; pass any other error as-is. - let err = Error::last_os_error(); - if let Some(errno) = Error::raw_os_error(&err) { - if errno == ENXIO { - return Ok(None); - } - } - Err(err) - } else { - Ok(Some(res as u64)) - } -} - -impl SeekHole for File { - fn seek_hole(&mut self, offset: u64) -> Result> { - lseek(self, offset as i64, SEEK_HOLE) - } - - fn seek_data(&mut self, offset: u64) -> Result> { - lseek(self, offset as i64, SEEK_DATA) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::TempDir; - use std::fs::File; - use std::io::{Seek, SeekFrom, Write}; - use std::path::PathBuf; - - fn seek_cur(file: &mut File) -> u64 { - file.seek(SeekFrom::Current(0)).unwrap() - } - - #[test] - fn seek_data() { - let tempdir = TempDir::new("/tmp/seek_data_test").unwrap(); - let mut path = PathBuf::from(tempdir.as_path().unwrap()); - path.push("test_file"); - let mut file = File::create(&path).unwrap(); - - // Empty file - assert_eq!(file.seek_data(0).unwrap(), None); - assert_eq!(seek_cur(&mut file), 0); - - // File with non-zero length consisting entirely of a hole - file.set_len(0x10000).unwrap(); - assert_eq!(file.seek_data(0).unwrap(), None); - assert_eq!(seek_cur(&mut file), 0); - - // seek_data at or after the end of the file should return None - assert_eq!(file.seek_data(0x10000).unwrap(), None); - assert_eq!(seek_cur(&mut file), 0); - assert_eq!(file.seek_data(0x10001).unwrap(), None); - assert_eq!(seek_cur(&mut file), 0); - - // Write some data to [0x10000, 0x20000) - let b = [0x55u8; 0x10000]; - file.seek(SeekFrom::Start(0x10000)).unwrap(); - file.write_all(&b).unwrap(); - assert_eq!(file.seek_data(0).unwrap(), Some(0x10000)); - assert_eq!(seek_cur(&mut file), 0x10000); - - // seek_data within data should return the same offset - assert_eq!(file.seek_data(0x10000).unwrap(), Some(0x10000)); - assert_eq!(seek_cur(&mut file), 0x10000); - assert_eq!(file.seek_data(0x10001).unwrap(), Some(0x10001)); - assert_eq!(seek_cur(&mut file), 0x10001); - assert_eq!(file.seek_data(0x1FFFF).unwrap(), Some(0x1FFFF)); - assert_eq!(seek_cur(&mut file), 0x1FFFF); - - // Extend the file to add another hole after the data - file.set_len(0x30000).unwrap(); - assert_eq!(file.seek_data(0).unwrap(), Some(0x10000)); - assert_eq!(seek_cur(&mut file), 0x10000); - assert_eq!(file.seek_data(0x1FFFF).unwrap(), Some(0x1FFFF)); - assert_eq!(seek_cur(&mut file), 0x1FFFF); - assert_eq!(file.seek_data(0x20000).unwrap(), None); - assert_eq!(seek_cur(&mut file), 0x1FFFF); - } - - #[test] - #[allow(clippy::cyclomatic_complexity)] - fn seek_hole() { - let tempdir = TempDir::new("/tmp/seek_hole_test").unwrap(); - let mut path = PathBuf::from(tempdir.as_path().unwrap()); - path.push("test_file"); - let mut file = File::create(&path).unwrap(); - - // Empty file - assert_eq!(file.seek_hole(0).unwrap(), None); - assert_eq!(seek_cur(&mut file), 0); - - // File with non-zero length consisting entirely of a hole - file.set_len(0x10000).unwrap(); - assert_eq!(file.seek_hole(0).unwrap(), Some(0)); - assert_eq!(seek_cur(&mut file), 0); - assert_eq!(file.seek_hole(0xFFFF).unwrap(), Some(0xFFFF)); - assert_eq!(seek_cur(&mut file), 0xFFFF); - - // seek_hole at or after the end of the file should return None - file.seek(SeekFrom::Start(0)).unwrap(); - assert_eq!(file.seek_hole(0x10000).unwrap(), None); - assert_eq!(seek_cur(&mut file), 0); - assert_eq!(file.seek_hole(0x10001).unwrap(), None); - assert_eq!(seek_cur(&mut file), 0); - - // Write some data to [0x10000, 0x20000) - let b = [0x55u8; 0x10000]; - file.seek(SeekFrom::Start(0x10000)).unwrap(); - file.write_all(&b).unwrap(); - - // seek_hole within a hole should return the same offset - assert_eq!(file.seek_hole(0).unwrap(), Some(0)); - assert_eq!(seek_cur(&mut file), 0); - assert_eq!(file.seek_hole(0xFFFF).unwrap(), Some(0xFFFF)); - assert_eq!(seek_cur(&mut file), 0xFFFF); - - // seek_hole within data should return the next hole (EOF) - file.seek(SeekFrom::Start(0)).unwrap(); - assert_eq!(file.seek_hole(0x10000).unwrap(), Some(0x20000)); - assert_eq!(seek_cur(&mut file), 0x20000); - file.seek(SeekFrom::Start(0)).unwrap(); - assert_eq!(file.seek_hole(0x10001).unwrap(), Some(0x20000)); - assert_eq!(seek_cur(&mut file), 0x20000); - file.seek(SeekFrom::Start(0)).unwrap(); - assert_eq!(file.seek_hole(0x1FFFF).unwrap(), Some(0x20000)); - assert_eq!(seek_cur(&mut file), 0x20000); - - // seek_hole at EOF after data should return None - file.seek(SeekFrom::Start(0)).unwrap(); - assert_eq!(file.seek_hole(0x20000).unwrap(), None); - assert_eq!(seek_cur(&mut file), 0); - - // Extend the file to add another hole after the data - file.set_len(0x30000).unwrap(); - assert_eq!(file.seek_hole(0).unwrap(), Some(0)); - assert_eq!(seek_cur(&mut file), 0); - assert_eq!(file.seek_hole(0xFFFF).unwrap(), Some(0xFFFF)); - assert_eq!(seek_cur(&mut file), 0xFFFF); - file.seek(SeekFrom::Start(0)).unwrap(); - assert_eq!(file.seek_hole(0x10000).unwrap(), Some(0x20000)); - assert_eq!(seek_cur(&mut file), 0x20000); - file.seek(SeekFrom::Start(0)).unwrap(); - assert_eq!(file.seek_hole(0x1FFFF).unwrap(), Some(0x20000)); - assert_eq!(seek_cur(&mut file), 0x20000); - file.seek(SeekFrom::Start(0)).unwrap(); - assert_eq!(file.seek_hole(0x20000).unwrap(), Some(0x20000)); - assert_eq!(seek_cur(&mut file), 0x20000); - file.seek(SeekFrom::Start(0)).unwrap(); - assert_eq!(file.seek_hole(0x20001).unwrap(), Some(0x20001)); - assert_eq!(seek_cur(&mut file), 0x20001); - - // seek_hole at EOF after a hole should return None - file.seek(SeekFrom::Start(0)).unwrap(); - assert_eq!(file.seek_hole(0x30000).unwrap(), None); - assert_eq!(seek_cur(&mut file), 0); - - // Write some data to [0x20000, 0x30000) - file.seek(SeekFrom::Start(0x20000)).unwrap(); - file.write_all(&b).unwrap(); - - // seek_hole within [0x20000, 0x30000) should now find the hole at EOF - assert_eq!(file.seek_hole(0x20000).unwrap(), Some(0x30000)); - assert_eq!(seek_cur(&mut file), 0x30000); - file.seek(SeekFrom::Start(0)).unwrap(); - assert_eq!(file.seek_hole(0x20001).unwrap(), Some(0x30000)); - assert_eq!(seek_cur(&mut file), 0x30000); - file.seek(SeekFrom::Start(0)).unwrap(); - assert_eq!(file.seek_hole(0x30000).unwrap(), None); - assert_eq!(seek_cur(&mut file), 0); - } -} diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/signal.rs b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/signal.rs deleted file mode 100644 index 71d88b723..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/signal.rs +++ /dev/null @@ -1,420 +0,0 @@ -// Copyright 2019 Intel Corporation. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -// -// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -// -// Portions Copyright 2017 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-BSD-3-Clause file. - -use libc::{ - c_int, c_void, pthread_kill, pthread_sigmask, pthread_t, sigaction, sigaddset, sigemptyset, - siginfo_t, sigismember, sigpending, sigset_t, sigtimedwait, timespec, EAGAIN, EINTR, EINVAL, - SIGHUP, SIGSYS, SIG_BLOCK, SIG_UNBLOCK, -}; - -use errno; -use std::fmt::{self, Display}; -use std::io; -use std::mem; -use std::os::unix::thread::JoinHandleExt; -use std::ptr::{null, null_mut}; -use std::result; -use std::thread::JoinHandle; - -#[derive(Debug)] -pub enum Error { - /// Couldn't create a sigset. - CreateSigset(errno::Error), - /// The wrapped signal has already been blocked. - SignalAlreadyBlocked(c_int), - /// Failed to check if the requested signal is in the blocked set already. - CompareBlockedSignals(errno::Error), - /// The signal could not be blocked. - BlockSignal(errno::Error), - /// The signal mask could not be retrieved. - RetrieveSignalMask(i32), - /// The signal could not be unblocked. - UnblockSignal(errno::Error), - /// Failed to wait for given signal. - ClearWaitPending(errno::Error), - /// Failed to get pending signals. - ClearGetPending(errno::Error), - /// Failed to check if given signal is in the set of pending signals. - ClearCheckPending(errno::Error), -} - -impl Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::Error::*; - - match self { - CreateSigset(e) => write!(f, "couldn't create a sigset: {}", e), - SignalAlreadyBlocked(num) => write!(f, "signal {} already blocked", num), - CompareBlockedSignals(e) => write!( - f, - "failed to check whether requested signal is in the blocked set: {}", - e, - ), - BlockSignal(e) => write!(f, "signal could not be blocked: {}", e), - RetrieveSignalMask(errno) => write!( - f, - "failed to retrieve signal mask: {}", - io::Error::from_raw_os_error(*errno), - ), - UnblockSignal(e) => write!(f, "signal could not be unblocked: {}", e), - ClearWaitPending(e) => write!(f, "failed to wait for given signal: {}", e), - ClearGetPending(e) => write!(f, "failed to get pending signals: {}", e), - ClearCheckPending(e) => write!( - f, - "failed to check whether given signal is in the pending set: {}", - e, - ), - } - } -} - -pub type SignalResult = result::Result; -type SiginfoHandler = extern "C" fn(num: c_int, info: *mut siginfo_t, _unused: *mut c_void) -> (); - -pub enum SignalHandler { - Siginfo(SiginfoHandler), - // TODO add a`SimpleHandler` when `libc` adds `sa_handler` support to `sigaction`. -} - -impl SignalHandler { - fn set_flags(act: &mut sigaction, flag: c_int) { - act.sa_flags = flag; - } -} -/// Fills a `sigaction` structure from of the signal handler. -/// Refer to http://man7.org/linux/man-pages/man7/signal.7.html -impl Into for SignalHandler { - fn into(self) -> sigaction { - let mut act: sigaction = unsafe { mem::zeroed() }; - match self { - SignalHandler::Siginfo(function) => { - act.sa_sigaction = function as *const () as usize; - } - } - act - } -} - -extern "C" { - fn __libc_current_sigrtmin() -> c_int; - fn __libc_current_sigrtmax() -> c_int; -} - -/// Returns the minimum (inclusive) real-time signal number. -#[allow(non_snake_case)] -fn SIGRTMIN() -> c_int { - unsafe { __libc_current_sigrtmin() } -} - -/// Returns the maximum (inclusive) real-time signal number. -#[allow(non_snake_case)] -fn SIGRTMAX() -> c_int { - unsafe { __libc_current_sigrtmax() } -} - -/// Verifies that a signal number is valid: for VCPU signals, it needs to be enclosed within the OS -/// limits for realtime signals, and the remaining ones need to be between the minimum (SIGHUP) and -/// maximum (SIGSYS) values. -pub fn validate_signal_num(num: c_int, for_vcpu: bool) -> errno::Result { - if for_vcpu { - let actual_num = num + SIGRTMIN(); - if actual_num <= SIGRTMAX() { - return Ok(actual_num); - } - } else if SIGHUP <= num && num <= SIGSYS { - return Ok(num); - } - Err(errno::Error::new(EINVAL)) -} - -/// Registers `handler` as the signal handler of signum `num`. -/// -/// Uses `sigaction` to register the handler. -/// -/// This is considered unsafe because the given handler will be called asynchronously, interrupting -/// whatever the thread was doing and therefore must only do async-signal-safe operations. -/// flags: SA_SIGINFO or SA_RESTART if wants to restart after signal received. -pub unsafe fn register_signal_handler( - num: i32, - handler: SignalHandler, - for_vcpu: bool, - flag: c_int, -) -> errno::Result<()> { - let num = validate_signal_num(num, for_vcpu)?; - let mut act: sigaction = handler.into(); - SignalHandler::set_flags(&mut act, flag); - match sigaction(num, &act, null_mut()) { - 0 => Ok(()), - _ => errno::errno_result(), - } -} - -/// Creates `sigset` from an array of signal numbers. -/// -/// This is a helper function used when we want to manipulate signals. -pub fn create_sigset(signals: &[c_int]) -> errno::Result { - // sigset will actually be initialized by sigemptyset below. - let mut sigset: sigset_t = unsafe { mem::zeroed() }; - - // Safe - return value is checked. - let ret = unsafe { sigemptyset(&mut sigset) }; - if ret < 0 { - return errno::errno_result(); - } - - for signal in signals { - // Safe - return value is checked. - let ret = unsafe { sigaddset(&mut sigset, *signal) }; - if ret < 0 { - return errno::errno_result(); - } - } - - Ok(sigset) -} - -/// Retrieves the signal mask of the current thread as a vector of c_ints. -pub fn get_blocked_signals() -> SignalResult> { - let mut mask = Vec::new(); - - // Safe - return values are checked. - unsafe { - let mut old_sigset: sigset_t = mem::zeroed(); - let ret = pthread_sigmask(SIG_BLOCK, null(), &mut old_sigset as *mut sigset_t); - if ret < 0 { - return Err(Error::RetrieveSignalMask(ret)); - } - - for num in 0..=SIGRTMAX() { - if sigismember(&old_sigset, num) > 0 { - mask.push(num); - } - } - } - - Ok(mask) -} - -/// Masks given signal. -/// -/// If signal is already blocked the call will fail with Error::SignalAlreadyBlocked -/// result. -pub fn block_signal(num: c_int) -> SignalResult<()> { - let sigset = create_sigset(&[num]).map_err(Error::CreateSigset)?; - - // Safe - return values are checked. - unsafe { - let mut old_sigset: sigset_t = mem::zeroed(); - let ret = pthread_sigmask(SIG_BLOCK, &sigset, &mut old_sigset as *mut sigset_t); - if ret < 0 { - return Err(Error::BlockSignal(errno::Error::last())); - } - let ret = sigismember(&old_sigset, num); - if ret < 0 { - return Err(Error::CompareBlockedSignals(errno::Error::last())); - } else if ret > 0 { - return Err(Error::SignalAlreadyBlocked(num)); - } - } - Ok(()) -} - -/// Unmasks given signal. -pub fn unblock_signal(num: c_int) -> SignalResult<()> { - let sigset = create_sigset(&[num]).map_err(Error::CreateSigset)?; - - // Safe - return value is checked. - let ret = unsafe { pthread_sigmask(SIG_UNBLOCK, &sigset, null_mut()) }; - if ret < 0 { - return Err(Error::UnblockSignal(errno::Error::last())); - } - Ok(()) -} - -/// Clears pending signal. -pub fn clear_signal(num: c_int) -> SignalResult<()> { - let sigset = create_sigset(&[num]).map_err(Error::CreateSigset)?; - - while { - // This is safe as we are rigorously checking return values - // of libc calls. - unsafe { - let mut siginfo: siginfo_t = mem::zeroed(); - let ts = timespec { - tv_sec: 0, - tv_nsec: 0, - }; - // Attempt to consume one instance of pending signal. If signal - // is not pending, the call will fail with EAGAIN or EINTR. - let ret = sigtimedwait(&sigset, &mut siginfo, &ts); - if ret < 0 { - let e = errno::Error::last(); - match e.errno() { - EAGAIN | EINTR => {} - _ => { - return Err(Error::ClearWaitPending(errno::Error::last())); - } - } - } - - // This sigset will be actually filled with `sigpending` call. - let mut chkset: sigset_t = mem::zeroed(); - // See if more instances of the signal are pending. - let ret = sigpending(&mut chkset); - if ret < 0 { - return Err(Error::ClearGetPending(errno::Error::last())); - } - - let ret = sigismember(&chkset, num); - if ret < 0 { - return Err(Error::ClearCheckPending(errno::Error::last())); - } - - // This is do-while loop condition. - ret != 0 - } - } {} - - Ok(()) -} - -/// Trait for threads that can be signalled via `pthread_kill`. -/// -/// Note that this is only useful for signals between SIGRTMIN and SIGRTMAX because these are -/// guaranteed to not be used by the C runtime. -/// -/// This is marked unsafe because the implementation of this trait must guarantee that the returned -/// pthread_t is valid and has a lifetime at least that of the trait object. -pub unsafe trait Killable { - fn pthread_handle(&self) -> pthread_t; - - /// Sends the signal `num + SIGRTMIN` to this killable thread. - /// - /// The value of `num + SIGRTMIN` must not exceed `SIGRTMAX`. - fn kill(&self, num: i32) -> errno::Result<()> { - let num = validate_signal_num(num, true)?; - - // Safe because we ensure we are using a valid pthread handle, a valid signal number, and - // check the return result. - let ret = unsafe { pthread_kill(self.pthread_handle(), num) }; - if ret < 0 { - return errno::errno_result(); - } - Ok(()) - } -} - -// Safe because we fulfill our contract of returning a genuine pthread handle. -unsafe impl Killable for JoinHandle { - fn pthread_handle(&self) -> pthread_t { - self.as_pthread_t() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use libc::SA_SIGINFO; - use std::thread; - use std::time::Duration; - - static mut SIGNAL_HANDLER_CALLED: bool = false; - - extern "C" fn handle_signal(_: c_int, _: *mut siginfo_t, _: *mut c_void) { - unsafe { - SIGNAL_HANDLER_CALLED = true; - } - } - - #[test] - fn test_register_signal_handler() { - unsafe { - // testing bad value - assert!(register_signal_handler( - SIGRTMAX(), - SignalHandler::Siginfo(handle_signal), - true, - SA_SIGINFO - ) - .is_err()); - format!( - "{:?}", - register_signal_handler( - SIGRTMAX(), - SignalHandler::Siginfo(handle_signal), - true, - SA_SIGINFO - ) - ); - assert!(register_signal_handler( - 0, - SignalHandler::Siginfo(handle_signal), - true, - SA_SIGINFO - ) - .is_ok()); - assert!(register_signal_handler( - libc::SIGSYS, - SignalHandler::Siginfo(handle_signal), - false, - SA_SIGINFO - ) - .is_ok()); - } - } - - #[test] - #[allow(clippy::empty_loop)] - fn test_killing_thread() { - let killable = thread::spawn(|| thread::current().id()); - let killable_id = killable.join().unwrap(); - assert_ne!(killable_id, thread::current().id()); - - // We install a signal handler for the specified signal; otherwise the whole process will - // be brought down when the signal is received, as part of the default behaviour. Signal - // handlers are global, so we install this before starting the thread. - unsafe { - register_signal_handler(0, SignalHandler::Siginfo(handle_signal), true, SA_SIGINFO) - .expect("failed to register vcpu signal handler"); - } - - let killable = thread::spawn(|| loop {}); - - let res = killable.kill(SIGRTMAX()); - assert!(res.is_err()); - format!("{:?}", res); - - unsafe { - assert!(!SIGNAL_HANDLER_CALLED); - } - - assert!(killable.kill(0).is_ok()); - - // We're waiting to detect that the signal handler has been called. - const MAX_WAIT_ITERS: u32 = 20; - let mut iter_count = 0; - loop { - thread::sleep(Duration::from_millis(100)); - - if unsafe { SIGNAL_HANDLER_CALLED } { - break; - } - - iter_count += 1; - // timeout if we wait too long - assert!(iter_count <= MAX_WAIT_ITERS); - } - - // Our signal handler doesn't do anything which influences the killable thread, so the - // previous signal is effectively ignored. If we were to join killable here, we would block - // forever as the loop keeps running. Since we don't join, the thread will become detached - // as the handle is dropped, and will be killed when the process/main thread exits. - } -} diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/syslog.rs b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/syslog.rs deleted file mode 100644 index d09b56a88..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/syslog.rs +++ /dev/null @@ -1,643 +0,0 @@ -// Copyright 2019 Intel Corporation. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -// -// Copyright 2017 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-BSD-3-Clause file. - -//! Facilities for sending log message to syslog. -//! -//! Every function exported by this module is thread-safe. Each function will silently fail until -//! `syslog::init()` is called and returns `Ok`. -//! -//! # Examples -//! -//! ``` -//! #[macro_use] -//! extern crate vmm_sys_util; -//! -//! use vmm_sys_util::syslog::init; -//! fn main() { -//! if let Err(e) = init() { -//! println!("failed to initiailize syslog: {}", e); -//! return; -//! } -//! warn!("this is your {} warning", "final"); -//! error!("something went horribly wrong: {}", "out of RAMs"); -//! } -//! ``` - -use std::env; -use std::ffi::CString; -use std::ffi::{OsStr, OsString}; -use std::fmt::{self, Display}; -use std::fs::File; -use std::io; -use std::io::{stderr, Cursor, ErrorKind, Write}; -use std::mem; -use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; -use std::os::unix::net::UnixDatagram; -use std::path::PathBuf; -use std::ptr::null; -use std::str::from_utf8; -use std::sync::{Mutex as StdMutex, MutexGuard, Once, ONCE_INIT}; - -use libc::{ - c_char, c_long, closelog, fcntl, gethostname, localtime_r, openlog, pid_t, syscall, time, - time_t, tm, F_GETFD, LOG_NDELAY, LOG_PERROR, LOG_PID, LOG_USER, -}; - -/// Temporary define linux-x86_64 syscall value here. -#[allow(non_upper_case_globals)] -pub const SYS_getpid: c_long = 39; - -const SYSLOG_PATH: &str = "/dev/log"; - -/// The priority (i.e. severity) of a syslog message. -/// -/// See syslog man pages for information on their semantics. -#[derive(Copy, Clone, Debug)] -pub enum Priority { - Emergency = 0, - Alert = 1, - Critical = 2, - Error = 3, - Warning = 4, - Notice = 5, - Info = 6, - Debug = 7, -} - -impl fmt::Display for Priority { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Priority::Emergency => write!(f, "EMERGENCY"), - Priority::Alert => write!(f, "ALERT"), - Priority::Critical => write!(f, "CRITICAL"), - Priority::Error => write!(f, "ERROR"), - Priority::Warning => write!(f, "WARNING"), - Priority::Notice => write!(f, "NOTICE"), - Priority::Info => write!(f, "INFO"), - Priority::Debug => write!(f, "DEBUG"), - } - } -} - -/// The facility of a syslog message. -/// -/// See syslog man pages for information on their semantics. -pub enum Facility { - Kernel = 0, - User = 1 << 3, - Mail = 2 << 3, - Daemon = 3 << 3, - Auth = 4 << 3, - Syslog = 5 << 3, - Lpr = 6 << 3, - News = 7 << 3, - Uucp = 8 << 3, - Local0 = 16 << 3, - Local1 = 17 << 3, - Local2 = 18 << 3, - Local3 = 19 << 3, - Local4 = 20 << 3, - Local5 = 21 << 3, - Local6 = 22 << 3, - Local7 = 23 << 3, -} - -/// Errors returned by `syslog::init()`. -#[derive(Debug)] -pub enum Error { - /// Initialization was never attempted. - NeverInitialized, - /// Initialization has previously failed and can not be retried. - Poisoned, - /// Error while creating socket. - Socket(io::Error), - /// Error while attempting to connect socket. - Connect(io::Error), - // There was an error using `open` to get the lowest file descriptor. - GetLowestFd(io::Error), - // The guess of libc's file descriptor for the syslog connection was invalid. - InvalidFd, -} - -impl Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::Error::*; - - match self { - NeverInitialized => write!(f, "initialization was never attempted"), - Poisoned => write!(f, "initialization previously failed and cannot be retried"), - Socket(e) => write!(f, "failed to create socket: {}", e), - Connect(e) => write!(f, "failed to connect socket: {}", e), - GetLowestFd(e) => write!(f, "failed to get lowest file descriptor: {}", e), - InvalidFd => write!(f, "guess of fd for syslog connection was invalid"), - } - } -} - -fn get_hostname() -> Result { - let mut hostname: [u8; 256] = [b'\0'; 256]; - // Safe because we give a valid pointer to a buffer of the indicated length and check for the - // result. - let ret = unsafe { gethostname(hostname.as_mut_ptr() as *mut c_char, hostname.len()) }; - if ret == -1 { - return Err(()); - } - - let len = hostname.iter().position(|&v| v == b'\0').ok_or(())?; - - Ok(from_utf8(&hostname[..len]).map_err(|_| ())?.to_string()) -} - -fn get_proc_name() -> Option { - env::args_os() - .next() - .map(PathBuf::from) - .and_then(|s| s.file_name().map(OsStr::to_os_string)) - .map(OsString::into_string) - .and_then(Result::ok) -} - -// Uses libc's openlog function to get a socket to the syslogger. By getting the socket this way, as -// opposed to connecting to the syslogger directly, libc's internal state gets initialized for other -// libraries (e.g. minijail) that make use of libc's syslog function. Note that this function -// depends on no other threads or signal handlers being active in this process because they might -// create FDs. -// -// TODO(zachr): Once https://android-review.googlesource.com/470998 lands, there won't be any -// libraries in use that hard depend on libc's syslogger. Remove this and go back to making the -// connection directly once minjail is ready. -fn openlog_and_get_socket() -> Result { - // closelog first in case there was already a file descriptor open. Safe because it takes no - // arguments and just closes an open file descriptor. Does nothing if the file descriptor - // was not already open. - unsafe { - closelog(); - } - - let file_path = CString::new("/dev/null").unwrap(); - unsafe { - // Ordinarily libc's FD for the syslog connection can't be accessed, but we can guess that the - // FD that openlog will be getting is the lowest unused FD. To guarantee that an FD is opened in - // this function we use the LOG_NDELAY to tell openlog to connect to the syslog now. To get the - // lowest unused FD, we open a dummy file (which the manual says will always return the lowest - // fd), and then close that fd. VoilĂ , we now know the lowest numbered FD. The call to openlog - // will make use of that FD, and then we just wrap a `UnixDatagram` around it for ease of use. - let fd = libc::open(file_path.as_ptr(), libc::O_RDONLY); - if fd < 0 { - let err = io::Error::last_os_error(); - return Err(Error::GetLowestFd(err)); - } - - // Safe because openlog accesses no pointers because `ident` is null, only valid flags are - // used, and it returns no error. - openlog(null(), LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_USER); - // For safety, ensure the fd we guessed is valid. The `fcntl` call itself only reads the - // file descriptor table of the current process, which is trivially safe. - if fcntl(fd, F_GETFD) >= 0 { - Ok(UnixDatagram::from_raw_fd(fd)) - } else { - Err(Error::InvalidFd) - } - } -} - -struct State { - stderr: bool, - socket: Option, - file: Option, - hostname: Option, - proc_name: Option, -} - -impl State { - fn new() -> Result { - let s = openlog_and_get_socket()?; - Ok(State { - stderr: true, - socket: Some(s), - file: None, - hostname: get_hostname().ok(), - proc_name: get_proc_name(), - }) - } -} - -static STATE_ONCE: Once = ONCE_INIT; -static mut STATE: *const StdMutex = 0 as *const _; - -fn new_mutex_ptr(inner: T) -> *const StdMutex { - Box::into_raw(Box::new(StdMutex::new(inner))) -} - -/// Initialize the syslog connection and internal variables. -/// -/// This should only be called once per process before any other threads have been spawned or any -/// signal handlers have been registered. Every call made after the first will have no effect -/// besides return `Ok` or `Err` appropriately. -pub fn init() -> Result<(), Error> { - let mut err = Error::Poisoned; - STATE_ONCE.call_once(|| match State::new() { - // Safe because STATE mutation is guarded by `Once`. - Ok(state) => unsafe { STATE = new_mutex_ptr(state) }, - Err(e) => err = e, - }); - - if unsafe { STATE.is_null() } { - Err(err) - } else { - Ok(()) - } -} - -fn lock() -> Result, Error> { - // Safe because we assume that STATE is always in either a valid or NULL state. - let state_ptr = unsafe { STATE }; - if state_ptr.is_null() { - return Err(Error::NeverInitialized); - } - // Safe because STATE only mutates once and we checked for NULL. - let state = unsafe { &*state_ptr }; - let guard = match state.lock() { - Ok(guard) => guard, - _ => panic!("mutex is poisoned"), - }; - Ok(guard) -} - -// Attempts to lock and retrieve the state. Returns from the function silently on failure. -macro_rules! lock { - () => { - match lock() { - Ok(s) => s, - _ => return, - }; - }; -} - -/// Replaces the hostname reported in each syslog message. -/// -/// The default hostname is whatever `gethostname()` returned when `vmm_sys_util::syslog::init()` was first -/// called. -/// -/// Does nothing if syslog was never initialized. -pub fn set_hostname>(hostname: T) { - let mut state = lock!(); - state.hostname = Some(hostname.into()); -} - -/// Replaces the process name reported in each syslog message. -/// -/// The default process name is the _file name_ of `argv[0]`. For example, if this program was -/// invoked as -/// -/// ```bash -/// $ path/to/app --delete everything -/// ``` -/// -/// the default process name would be _app_. -/// -/// Does nothing if syslog was never initialized. -pub fn set_proc_name>(proc_name: T) { - let mut state = lock!(); - state.proc_name = Some(proc_name.into()); -} - -/// Enables or disables echoing log messages to the syslog. -/// -/// The default behavior is **enabled**. -/// -/// If `enable` goes from `true` to `false`, the syslog connection is closed. The connection is -/// reopened if `enable` is set to `true` after it became `false`. -/// -/// Returns an error if syslog was never initialized or the syslog connection failed to be -/// established. -/// -/// # Arguments -/// * `enable` - `true` to enable echoing to syslog, `false` to disable echoing to syslog. -pub fn echo_syslog(enable: bool) -> Result<(), Error> { - let state_ptr = unsafe { STATE }; - if state_ptr.is_null() { - return Err(Error::NeverInitialized); - } - let mut state = lock().map_err(|_| Error::Poisoned)?; - - match state.socket.take() { - Some(_) if enable => {} - Some(s) => { - // Because `openlog_and_get_socket` actually just "borrows" the syslog FD, this module - // does not own the syslog connection and therefore should not destroy it. - mem::forget(s); - } - None if enable => { - let s = openlog_and_get_socket()?; - state.socket = Some(s); - } - _ => {} - } - Ok(()) -} - -/// Replaces the optional `File` to echo log messages to. -/// -/// The default behavior is to not echo to a file. Passing `None` to this function restores that -/// behavior. -/// -/// Does nothing if syslog was never initialized. -/// -/// # Arguments -/// * `file` - `Some(file)` to echo to `file`, `None` to disable echoing to the file previously passed to `echo_file`. -pub fn echo_file(file: Option) { - let mut state = lock!(); - state.file = file; -} - -/// Enables or disables echoing log messages to the `std::io::stderr()`. -/// -/// The default behavior is **enabled**. -/// -/// Does nothing if syslog was never initialized. -/// -/// # Arguments -/// * `enable` - `true` to enable echoing to stderr, `false` to disable echoing to stderr. -pub fn echo_stderr(enable: bool) { - let mut state = lock!(); - state.stderr = enable; -} - -/// Retrieves the file descriptors owned by the global syslogger. -/// -/// Does nothing if syslog was never initialized. If their are any file descriptors, they will be -/// pushed into `fds`. -/// -/// Note that the `stderr` file descriptor is never added, as it is not owned by syslog. -#[allow(clippy::redundant_closure)] -pub fn push_fds(fds: &mut Vec) { - let state = lock!(); - fds.extend(state.socket.iter().map(|s| s.as_raw_fd())); - fds.extend(state.file.iter().map(|f| f.as_raw_fd())); -} - -/// Should only be called after `init()` was called. -fn send_buf(socket: &UnixDatagram, buf: &[u8]) { - const SEND_RETRY: usize = 2; - - for _ in 0..SEND_RETRY { - match socket.send(&buf[..]) { - Ok(_) => break, - Err(e) => match e.kind() { - ErrorKind::ConnectionRefused - | ErrorKind::ConnectionReset - | ErrorKind::ConnectionAborted - | ErrorKind::NotConnected => { - let res = socket.connect(SYSLOG_PATH); - if res.is_err() { - break; - } - } - _ => {} - }, - } - } -} - -fn get_localtime() -> tm { - unsafe { - // Safe because tm is just a struct of plain data. - let mut tm: tm = mem::zeroed(); - let mut now: time_t = 0; - // Safe because we give time a valid pointer and can never fail. - time(&mut now as *mut _); - // Safe because we give localtime_r valid pointers and can never fail. - localtime_r(&now, &mut tm as *mut _); - tm - } -} - -/// Records a log message with the given details. -/// -/// Note that this will fail silently if syslog was not initialized. -/// -/// # Arguments -/// * `pri` - The `Priority` (i.e. severity) of the log message. -/// * `fac` - The `Facility` of the log message. Usually `Facility::User` should be used. -/// * `file_name` - Name of the file that generated the log. -/// * `line` - Line number within `file_name` that generated the log. -/// * `args` - The log's message to record, in the form of `format_args!()` return value -/// -/// # Examples -/// -/// ``` -/// # use vmm_sys_util::syslog::{init, log, Priority, Facility}; -/// # fn main() { -/// # if let Err(e) = init() { -/// # println!("failed to initiailize syslog: {}", e); -/// # return; -/// # } -/// log(Priority::Error, -/// Facility::User, -/// file!(), -/// line!(), -/// format_args!("hello syslog")); -/// # } -/// ``` -#[allow(clippy::redundant_closure)] -pub fn log(pri: Priority, fac: Facility, file_name: &str, line: u32, args: fmt::Arguments) { - const MONTHS: [&str; 12] = [ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", - ]; - - let mut state = lock!(); - let mut buf = [0u8; 1024]; - if let Some(ref socket) = state.socket { - let tm = get_localtime(); - let prifac = (pri as u8) | (fac as u8); - let (res, len) = { - let mut buf_cursor = Cursor::new(&mut buf[..]); - ( - write!( - &mut buf_cursor, - "<{}>{} {:02} {:02}:{:02}:{:02} {} {}[{}]: [{}:{}] {}", - prifac, - MONTHS[tm.tm_mon as usize], - tm.tm_mday, - tm.tm_hour, - tm.tm_min, - tm.tm_sec, - state.hostname.as_ref().map(|s| s.as_ref()).unwrap_or("-"), - state.proc_name.as_ref().map(|s| s.as_ref()).unwrap_or("-"), - unsafe { syscall(SYS_getpid as c_long) as pid_t }, - //getpid(), - file_name, - line, - args - ), - buf_cursor.position() as usize, - ) - }; - - if res.is_ok() { - send_buf(&socket, &buf[..len]); - } - } - - let (res, len) = { - let mut buf_cursor = Cursor::new(&mut buf[..]); - ( - writeln!(&mut buf_cursor, "[{}:{}:{}] {}", pri, file_name, line, args), - buf_cursor.position() as usize, - ) - }; - if res.is_ok() { - if let Some(ref mut file) = state.file { - let _ = file.write_all(&buf[..len]); - } - if state.stderr { - let _ = stderr().write_all(&buf[..len]); - } - } -} - -/// A macro for logging at an arbitrary priority level. -/// -/// Note that this will fail silently if syslog was not initialized. -#[macro_export] -macro_rules! log { - ($pri:expr, $($args:tt)+) => ({ - $crate::syslog::log($pri, $crate::syslog::Facility::User, file!(), line!(), format_args!($($args)+)) - }) -} - -/// A macro for logging an error. -/// -/// Note that this will fail silently if syslog was not initialized. -#[macro_export] -macro_rules! error { - ($($args:tt)+) => (log!($crate::syslog::Priority::Error, $($args)*)) -} - -/// A macro for logging a warning. -/// -/// Note that this will fail silently if syslog was not initialized. -#[macro_export] -macro_rules! warn { - ($($args:tt)+) => (log!($crate::syslog::Priority::Warning, $($args)*)) -} - -/// A macro for logging info. -/// -/// Note that this will fail silently if syslog was not initialized. -#[macro_export] -macro_rules! info { - ($($args:tt)+) => (log!($crate::syslog::Priority::Info, $($args)*)) -} - -/// A macro for logging debug information. -/// -/// Note that this will fail silently if syslog was not initialized. -#[macro_export] -macro_rules! debug { - ($($args:tt)+) => (log!($crate::syslog::Priority::Debug, $($args)*)) -} - -#[cfg(test)] -mod tests { - use super::*; - use libc::{shm_open, shm_unlink, O_CREAT, O_EXCL, O_RDWR}; - - use std::ffi::CStr; - use std::io::{Read, Seek, SeekFrom}; - use std::os::unix::io::FromRawFd; - - #[test] - fn test_init_syslog() { - init().unwrap(); - } - - #[test] - fn test_fds() { - init().unwrap(); - let mut fds = Vec::new(); - push_fds(&mut fds); - assert!(!fds.is_empty()); - for fd in fds { - assert!(fd >= 0); - } - } - - #[test] - fn test_syslog_log() { - init().unwrap(); - log( - Priority::Error, - Facility::User, - file!(), - line!(), - format_args!("hello syslog"), - ); - } - - #[test] - fn test_proc_name() { - init().unwrap(); - log( - Priority::Error, - Facility::User, - file!(), - line!(), - format_args!("before proc name"), - ); - set_proc_name("sys_util-test"); - log( - Priority::Error, - Facility::User, - file!(), - line!(), - format_args!("after proc name"), - ); - } - - #[test] - #[allow(clippy::zero_prefixed_literal)] - fn test_syslog_file() { - init().unwrap(); - let shm_name = CStr::from_bytes_with_nul(b"/crosvm_shm\0").unwrap(); - let mut file = unsafe { - shm_unlink(shm_name.as_ptr()); - let fd = shm_open(shm_name.as_ptr(), O_RDWR | O_CREAT | O_EXCL, 0666); - assert!(fd >= 0, "error creating shared memory;"); - File::from_raw_fd(fd) - }; - - let syslog_file = file.try_clone().expect("error cloning shared memory file"); - echo_file(Some(syslog_file)); - - const TEST_STR: &str = "hello shared memory file"; - log( - Priority::Error, - Facility::User, - file!(), - line!(), - format_args!("{}", TEST_STR), - ); - - file.seek(SeekFrom::Start(0)) - .expect("error seeking shared memory file"); - let mut buf = String::new(); - file.read_to_string(&mut buf) - .expect("error reading shared memory file"); - assert!(buf.contains(TEST_STR)); - } - - #[test] - fn test_macros() { - init().unwrap(); - error!("this is an error {}", 3); - warn!("this is a warning {}", "uh oh"); - info!("this is info {}", true); - debug!("this is debug info {:?}", Some("helpful stuff")); - } -} diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/tempdir.rs b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/tempdir.rs deleted file mode 100644 index 7256998e8..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/tempdir.rs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2017 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-BSD-3-Clause file. -// -// SPDX-License-Identifier: BSD-3-Clause - -use std::ffi::CString; -use std::ffi::OsStr; -use std::ffi::OsString; -use std::fs; -use std::os::unix::ffi::OsStringExt; -use std::path::Path; -use std::path::PathBuf; - -use libc; - -use crate::{errno_result, Result}; - -/// Create and remove a temporary directory. The directory will be maintained for the lifetime of -/// the `TempDir` object. -pub struct TempDir { - path: Option, -} - -impl TempDir { - /// Creates a new tempory directory. - /// The directory will be removed when the object goes out of scope. - /// - /// # Examples - /// - /// ``` - /// # use std::path::Path; - /// # use std::path::PathBuf; - /// # use vmm_sys_util::TempDir; - /// # fn test_create_temp_dir() -> Result<(), ()> { - /// let t = TempDir::new("/tmp/testdir").map_err(|_| ())?; - /// assert!(t.as_path().unwrap().exists()); - /// # Ok(()) - /// # } - /// ``` - pub fn new>(prefix: P) -> Result { - let mut dir_string = prefix.as_ref().to_os_string(); - dir_string.push("XXXXXX"); - // unwrap this result as the internal bytes can't have a null with a valid path. - let dir_name = CString::new(dir_string.into_vec()).unwrap(); - let mut dir_bytes = dir_name.into_bytes_with_nul(); - let ret = unsafe { - // Creating the directory isn't unsafe. The fact that it modifies the guts of the path - // is also OK because it only overwrites the last 6 Xs added above. - libc::mkdtemp(dir_bytes.as_mut_ptr() as *mut libc::c_char) - }; - if ret.is_null() { - return errno_result(); - } - dir_bytes.pop(); // Remove the null becasue from_vec can't handle it. - Ok(TempDir { - path: Some(PathBuf::from(OsString::from_vec(dir_bytes))), - }) - } - - /// Removes the temporary directory. Calling this is optional as dropping a `TempDir` object - /// will also remove the directory. Calling remove explicitly allows for better error handling. - pub fn remove(mut self) -> Result<()> { - let path = self.path.take(); - path.map_or(Ok(()), fs::remove_dir_all)?; - Ok(()) - } - - /// Returns the path to the tempdir if it is currently valid - pub fn as_path(&self) -> Option<&Path> { - self.path.as_ref().map(|ref p| p.as_path()) - } -} - -impl Drop for TempDir { - fn drop(&mut self) { - if let Some(ref p) = self.path { - // Nothing can be done here if this returns an error. - let _ = fs::remove_dir_all(p); - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn create_dir() { - let t = TempDir::new("/tmp/asdf").unwrap(); - let path = t.as_path().unwrap(); - assert!(path.exists()); - assert!(path.is_dir()); - assert!(path.starts_with("/tmp/")); - } - - #[test] - fn remove_dir() { - let t = TempDir::new("/tmp/asdf").unwrap(); - let path = t.as_path().unwrap().to_owned(); - assert!(t.remove().is_ok()); - assert!(!path.exists()); - } -} diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/terminal.rs b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/terminal.rs deleted file mode 100644 index 2d6177d1d..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/terminal.rs +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2019 Intel Corporation. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -// -// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -// -// Copyright 2017 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-BSD-3-Clause file. - -use std::io::StdinLock; -use std::mem::zeroed; -use std::os::unix::io::RawFd; - -use libc::{ - c_int, fcntl, isatty, read, tcgetattr, tcsetattr, termios, ECHO, F_GETFL, F_SETFL, ICANON, - ISIG, O_NONBLOCK, STDIN_FILENO, TCSANOW, -}; - -use crate::errno::{errno_result, Result}; - -fn modify_mode(fd: RawFd, f: F) -> Result<()> { - // Safe because we check the return value of isatty. - if unsafe { isatty(fd) } != 1 { - return Ok(()); - } - - // The following pair are safe because termios gets totally overwritten by tcgetattr and we - // check the return result. - let mut termios: termios = unsafe { zeroed() }; - let ret = unsafe { tcgetattr(fd, &mut termios as *mut _) }; - if ret < 0 { - return errno_result(); - } - let mut new_termios = termios; - f(&mut new_termios); - // Safe because the syscall will only read the extent of termios and we check the return result. - let ret = unsafe { tcsetattr(fd, TCSANOW, &new_termios as *const _) }; - if ret < 0 { - return errno_result(); - } - - Ok(()) -} - -fn get_flags(fd: RawFd) -> Result { - // Safe because no third parameter is expected and we check the return result. - let ret = unsafe { fcntl(fd, F_GETFL) }; - if ret < 0 { - return errno_result(); - } - Ok(ret) -} - -fn set_flags(fd: RawFd, flags: c_int) -> Result<()> { - // Safe because we supply the third parameter and we check the return result. - let ret = unsafe { fcntl(fd, F_SETFL, flags) }; - if ret < 0 { - return errno_result(); - } - Ok(()) -} - -/// Trait for file descriptors that are TTYs, according to `isatty(3)`. -/// -/// This is marked unsafe because the implementation must promise that the returned RawFd is a valid -/// fd and that the lifetime of the returned fd is at least that of the trait object. -pub unsafe trait Terminal { - /// Gets the file descriptor of the TTY. - fn tty_fd(&self) -> RawFd; - - /// Set this terminal's mode to canonical mode (`ICANON | ECHO | ISIG`). - fn set_canon_mode(&self) -> Result<()> { - modify_mode(self.tty_fd(), |t| t.c_lflag |= ICANON | ECHO | ISIG) - } - - /// Set this terminal's mode to raw mode (`!(ICANON | ECHO | ISIG)`). - fn set_raw_mode(&self) -> Result<()> { - modify_mode(self.tty_fd(), |t| t.c_lflag &= !(ICANON | ECHO | ISIG)) - } - - /// Sets the non-blocking mode of this terminal's file descriptor. - /// - /// If `non_block` is `true`, then `read_raw` will not block. If `non_block` is `false`, then - /// `read_raw` may block if there is nothing to read. - fn set_non_block(&self, non_block: bool) -> Result<()> { - let old_flags = get_flags(self.tty_fd())?; - let new_flags = if non_block { - old_flags | O_NONBLOCK - } else { - old_flags & !O_NONBLOCK - }; - if new_flags != old_flags { - set_flags(self.tty_fd(), new_flags)? - } - Ok(()) - } - - /// Reads up to `out.len()` bytes from this terminal without any buffering. - /// - /// This may block, depending on if non-blocking was enabled with `set_non_block` or if there - /// are any bytes to read. If there is at least one byte that is readable, this will not block. - fn read_raw(&self, out: &mut [u8]) -> Result { - // Safe because read will only modify the pointer up to the length we give it and we check - // the return result. - let ret = unsafe { read(self.tty_fd(), out.as_mut_ptr() as *mut _, out.len()) }; - if ret < 0 { - return errno_result(); - } - - Ok(ret as usize) - } -} - -// Safe because we return a genuine terminal fd that never changes and shares our lifetime. -unsafe impl<'a> Terminal for StdinLock<'a> { - fn tty_fd(&self) -> RawFd { - STDIN_FILENO - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::fs::File; - use std::io; - use std::os::unix::io::AsRawFd; - use std::path::Path; - - unsafe impl Terminal for File { - fn tty_fd(&self) -> RawFd { - self.as_raw_fd() - } - } - - #[test] - fn test_a_tty() { - let stdin_handle = io::stdin(); - let stdin = stdin_handle.lock(); - - assert!(stdin.set_canon_mode().is_ok()); - assert!(stdin.set_raw_mode().is_ok()); - assert!(stdin.set_raw_mode().is_ok()); - assert!(stdin.set_canon_mode().is_ok()); - assert!(stdin.set_non_block(true).is_ok()); - let mut out = [0u8; 0]; - assert!(stdin.read_raw(&mut out[..]).is_ok()); - } - - #[test] - fn test_a_non_tty() { - let file = File::open(Path::new("/dev/zero")).unwrap(); - assert!(file.set_canon_mode().is_ok()); - } -} diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/timerfd.rs b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/timerfd.rs deleted file mode 100644 index 4e2903e52..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/timerfd.rs +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2019 Intel Corporation. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -// -// Copyright 2018 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-BSD-3-clause file. - -use std::fs::File; -use std::mem; -use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -use std::ptr; -use std::time::Duration; - -use libc::{self, timerfd_create, timerfd_gettime, timerfd_settime, CLOCK_MONOTONIC, TFD_CLOEXEC}; - -use crate::errno::{errno_result, Result}; - -/// A safe wrapper around a Linux timerfd (man 2 timerfd_create). -pub struct TimerFd(File); - -impl TimerFd { - /// Creates a new [`TimerFd`](struct.TimerFd.html). - /// - /// The timer is initally disarmed and must be armed by calling [`reset`](fn.reset.html). - pub fn new() -> Result { - // Safe because this doesn't modify any memory and we check the return value. - let ret = unsafe { timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC) }; - if ret < 0 { - return errno_result(); - } - - // Safe because we uniquely own the file descriptor. - Ok(TimerFd(unsafe { File::from_raw_fd(ret) })) - } - - /// Sets the timer to expire after `dur`. - /// - /// If `interval` is not `None` it represents the period for repeated expirations after the - /// initial expiration. Otherwise the timer will expire just once. Cancels any existing duration and repeating interval. - pub fn reset(&mut self, dur: Duration, interval: Option) -> Result<()> { - // Safe because we are zero-initializing a struct with only primitive member fields. - let mut spec: libc::itimerspec = unsafe { mem::zeroed() }; - spec.it_value.tv_sec = dur.as_secs() as libc::time_t; - // nsec always fits in i32 because subsec_nanos is defined to be less than one billion. - let nsec = dur.subsec_nanos() as i32; - spec.it_value.tv_nsec = libc::c_long::from(nsec); - - if let Some(int) = interval { - spec.it_interval.tv_sec = int.as_secs() as libc::time_t; - // nsec always fits in i32 because subsec_nanos is defined to be less than one billion. - let nsec = int.subsec_nanos() as i32; - spec.it_interval.tv_nsec = libc::c_long::from(nsec); - } - - // Safe because this doesn't modify any memory and we check the return value. - let ret = unsafe { timerfd_settime(self.as_raw_fd(), 0, &spec, ptr::null_mut()) }; - if ret < 0 { - return errno_result(); - } - - Ok(()) - } - - /// Waits until the timer expires. - /// - /// The return value represents the number of times the timer - /// has expired since the last time `wait` was called. If the timer has not yet expired once - /// this call will block until it does. - pub fn wait(&mut self) -> Result { - let mut count = 0u64; - - // Safe because this will only modify |buf| and we check the return value. - let ret = unsafe { - libc::read( - self.as_raw_fd(), - &mut count as *mut _ as *mut libc::c_void, - mem::size_of_val(&count), - ) - }; - if ret < 0 { - return errno_result(); - } - - // The bytes in the buffer are guaranteed to be in native byte-order so we don't need to - // use from_le or from_be. - Ok(count) - } - - /// Returns `true` if the timer is currently armed. - pub fn is_armed(&self) -> Result { - // Safe because we are zero-initializing a struct with only primitive member fields. - let mut spec: libc::itimerspec = unsafe { mem::zeroed() }; - - // Safe because timerfd_gettime is trusted to only modify `spec`. - let ret = unsafe { timerfd_gettime(self.as_raw_fd(), &mut spec) }; - if ret < 0 { - return errno_result(); - } - - Ok(spec.it_value.tv_sec != 0 || spec.it_value.tv_nsec != 0) - } - - /// Disarms the timer. - pub fn clear(&mut self) -> Result<()> { - // Safe because we are zero-initializing a struct with only primitive member fields. - let spec: libc::itimerspec = unsafe { mem::zeroed() }; - - // Safe because this doesn't modify any memory and we check the return value. - let ret = unsafe { timerfd_settime(self.as_raw_fd(), 0, &spec, ptr::null_mut()) }; - if ret < 0 { - return errno_result(); - } - - Ok(()) - } -} - -impl AsRawFd for TimerFd { - fn as_raw_fd(&self) -> RawFd { - self.0.as_raw_fd() - } -} - -impl FromRawFd for TimerFd { - unsafe fn from_raw_fd(fd: RawFd) -> Self { - TimerFd(File::from_raw_fd(fd)) - } -} - -impl IntoRawFd for TimerFd { - fn into_raw_fd(self) -> RawFd { - self.0.into_raw_fd() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::thread::sleep; - use std::time::{Duration, Instant}; - - #[test] - fn test_one_shot() { - let mut tfd = TimerFd::new().expect("failed to create timerfd"); - assert_eq!(tfd.is_armed().unwrap(), false); - - let dur = Duration::from_millis(200); - let now = Instant::now(); - tfd.reset(dur, None).expect("failed to arm timer"); - - assert_eq!(tfd.is_armed().unwrap(), true); - - let count = tfd.wait().expect("unable to wait for timer"); - - assert_eq!(count, 1); - assert!(now.elapsed() >= dur); - } - - #[test] - fn test_repeating() { - let mut tfd = TimerFd::new().expect("failed to create timerfd"); - - let dur = Duration::from_millis(200); - let interval = Duration::from_millis(100); - tfd.reset(dur, Some(interval)).expect("failed to arm timer"); - - sleep(dur * 3); - - let count = tfd.wait().expect("unable to wait for timer"); - assert!(count >= 5, "count = {}", count); - } - -} diff --git a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/write_zeroes.rs b/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/write_zeroes.rs deleted file mode 100644 index 98195d8f3..000000000 --- a/vendor/git-ccfa5f04f3f14300/vmm-sys-util/src/write_zeroes.rs +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2018 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-BSD-3-Clause file. -// -// SPDX-License-Identifier: BSD-3-Clause - -use std::cmp::min; -use std::fs::File; -use std::io::{self, Seek, SeekFrom, Write}; - -use crate::fallocate; -use crate::FallocateMode; - -/// A trait for deallocating space in a file. -pub trait PunchHole { - /// Replace a range of bytes with a hole. - fn punch_hole(&mut self, offset: u64, length: u64) -> io::Result<()>; -} - -impl PunchHole for File { - fn punch_hole(&mut self, offset: u64, length: u64) -> io::Result<()> { - fallocate(self, FallocateMode::PunchHole, true, offset, length as u64) - .map_err(|e| io::Error::from_raw_os_error(e.errno())) - } -} - -/// A trait for writing zeroes to a stream. -pub trait WriteZeroes { - /// Write `length` bytes of zeroes to the stream, returning how many bytes were written. - fn write_zeroes(&mut self, length: usize) -> io::Result; -} - -impl WriteZeroes for T { - fn write_zeroes(&mut self, length: usize) -> io::Result { - // Try to punch a hole first. - let offset = self.seek(SeekFrom::Current(0))?; - if let Ok(()) = self.punch_hole(offset, length as u64) { - // Advance the seek cursor as if we had done a real write(). - self.seek(SeekFrom::Current(length as i64))?; - return Ok(length); - } - - // fall back to write() - - // punch_hole() failed; fall back to writing a buffer of zeroes - // until we have written up to length. - let buf_size = min(length, 0x10000); - let buf = vec![0u8; buf_size]; - let mut nwritten: usize = 0; - while nwritten < length { - let remaining = length - nwritten; - let write_size = min(remaining, buf_size); - nwritten += self.write(&buf[0..write_size])?; - } - Ok(length) - } -} - -#[cfg(test)] -#[allow(clippy::unused_io_amount)] -mod tests { - use super::*; - use std::fs::OpenOptions; - use std::io::{Read, Seek, SeekFrom}; - use std::path::PathBuf; - - use crate::TempDir; - - #[test] - fn simple_test() { - let tempdir = TempDir::new("/tmp/write_zeroes_test").unwrap(); - let mut path = PathBuf::from(tempdir.as_path().unwrap()); - path.push("file"); - let mut f = OpenOptions::new() - .read(true) - .write(true) - .create(true) - .open(&path) - .unwrap(); - f.set_len(16384).unwrap(); - - // Write buffer of non-zero bytes to offset 1234 - let orig_data = [0x55u8; 5678]; - f.seek(SeekFrom::Start(1234)).unwrap(); - f.write(&orig_data).unwrap(); - - // Read back the data plus some overlap on each side - let mut readback = [0u8; 16384]; - f.seek(SeekFrom::Start(0)).unwrap(); - f.read(&mut readback).unwrap(); - // Bytes before the write should still be 0 - for read in readback[0..1234].iter() { - assert_eq!(*read, 0); - } - // Bytes that were just written should be 0x55 - for read in readback[1234..(1234 + 5678)].iter() { - assert_eq!(*read, 0x55); - } - // Bytes after the written area should still be 0 - for read in readback[(1234 + 5678)..].iter() { - assert_eq!(*read, 0); - } - - // Overwrite some of the data with zeroes - f.seek(SeekFrom::Start(2345)).unwrap(); - f.write_zeroes(4321).expect("write_zeroes failed"); - // Verify seek position after write_zeroes() - assert_eq!(f.seek(SeekFrom::Current(0)).unwrap(), 2345 + 4321); - - // Read back the data and verify that it is now zero - f.seek(SeekFrom::Start(0)).unwrap(); - f.read(&mut readback).unwrap(); - // Bytes before the write should still be 0 - for read in readback[0..1234].iter() { - assert_eq!(*read, 0); - } - // Original data should still exist before the write_zeroes region - for read in readback[1234..2345].iter() { - assert_eq!(*read, 0x55); - } - // The write_zeroes region should now be zero - for read in readback[2345..(2345 + 4321)].iter() { - assert_eq!(*read, 0); - } - // Original data should still exist after the write_zeroes region - for read in readback[(2345 + 4321)..(1234 + 5678)].iter() { - assert_eq!(*read, 0x55); - } - // The rest of the file should still be 0 - for read in readback[(1234 + 5678)..].iter() { - assert_eq!(*read, 0); - } - } - - #[test] - fn large_write_zeroes() { - let tempdir = TempDir::new("/tmp/write_zeroes_test").unwrap(); - let mut path = PathBuf::from(tempdir.as_path().unwrap()); - path.push("file"); - let mut f = OpenOptions::new() - .read(true) - .write(true) - .create(true) - .open(&path) - .unwrap(); - f.set_len(16384).unwrap(); - - // Write buffer of non-zero bytes - let orig_data = [0x55u8; 0x20000]; - f.seek(SeekFrom::Start(0)).unwrap(); - f.write(&orig_data).unwrap(); - - // Overwrite some of the data with zeroes - f.seek(SeekFrom::Start(0)).unwrap(); - f.write_zeroes(0x10001).expect("write_zeroes failed"); - // Verify seek position after write_zeroes() - assert_eq!(f.seek(SeekFrom::Current(0)).unwrap(), 0x10001); - - // Read back the data and verify that it is now zero - let mut readback = [0u8; 0x20000]; - f.seek(SeekFrom::Start(0)).unwrap(); - f.read(&mut readback).unwrap(); - // The write_zeroes region should now be zero - for read in readback[0..0x10001].iter() { - assert_eq!(*read, 0); - } - // Original data should still exist after the write_zeroes region - for read in readback[0x10001..0x20000].iter() { - assert_eq!(*read, 0x55); - } - } -} diff --git a/vm-virtio/Cargo.toml b/vm-virtio/Cargo.toml index 36793308d..df02e050f 100644 --- a/vm-virtio/Cargo.toml +++ b/vm-virtio/Cargo.toml @@ -16,7 +16,7 @@ pci = { path = "../pci" } tempfile = ">=3.0.2" virtio-bindings = { path = "../virtio-bindings" } vm-allocator = { path = "../vm-allocator" } -vmm-sys-util = { git = "https://github.com/liujing2/vmm-sys-util" } +vmm-sys-util = { git = "https://github.com/rust-vmm/vmm-sys-util" } [dependencies.vm-memory] git = "https://github.com/rust-vmm/vm-memory" diff --git a/vmm/Cargo.toml b/vmm/Cargo.toml index bcc38f38d..803344634 100755 --- a/vmm/Cargo.toml +++ b/vmm/Cargo.toml @@ -18,7 +18,7 @@ qcow = { path = "../qcow" } linux-loader = { git = "https://github.com/bjzhjing/linux-loader" } vm-virtio = { path = "../vm-virtio" } vm-allocator = { path = "../vm-allocator" } -vmm-sys-util = { git = "https://github.com/liujing2/vmm-sys-util" } +vmm-sys-util = { git = "https://github.com/rust-vmm/vmm-sys-util" } [dependencies.vm-memory] git = "https://github.com/rust-vmm/vm-memory"