Extract common interface from lucet-wasi
This commit is contained in:
22
Cargo.toml
Normal file
22
Cargo.toml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
[package]
|
||||||
|
name = "wasi-common"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Adam C. Foltzer <acfoltzer@fastly.com>", "Jakub Konka <kubkon@jakubkonka.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
cast = "0.2"
|
||||||
|
clap = "2.23"
|
||||||
|
failure = "0.1"
|
||||||
|
human-size = "0.4"
|
||||||
|
libc = "0.2"
|
||||||
|
nix = "0.13"
|
||||||
|
rand = "0.6"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
bindgen = "0.49.0"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "wasi_common"
|
||||||
|
crate-type = ["rlib", "staticlib", "cdylib"]
|
||||||
220
LICENSE
Normal file
220
LICENSE
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
--- LLVM Exceptions to the Apache 2.0 License ----
|
||||||
|
|
||||||
|
As an exception, if, as a result of your compiling your source code, portions
|
||||||
|
of this Software are embedded into an Object form of such source code, you
|
||||||
|
may redistribute such embedded portions in such Object form without complying
|
||||||
|
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
|
||||||
|
|
||||||
|
In addition, if you combine or link compiled forms of this Software with
|
||||||
|
software that is licensed under the GPLv2 ("Combined Software") and if a
|
||||||
|
court of competent jurisdiction determines that the patent provision (Section
|
||||||
|
3), the indemnity provision (Section 9) or other Section of the License
|
||||||
|
conflicts with the conditions of the GPLv2, you may retroactively and
|
||||||
|
prospectively choose to deem waived or otherwise exclude such Section(s) of
|
||||||
|
the License, but only in their entirety and only with respect to the Combined
|
||||||
|
Software.
|
||||||
|
|
||||||
24
LICENSE.cloudabi-utils
Normal file
24
LICENSE.cloudabi-utils
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
All code is distributed under the following license:
|
||||||
|
|
||||||
|
Copyright (c) 2015 Nuxi, https://nuxi.nl/
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. 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.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||||
219
LICENSE.wasmtime
Normal file
219
LICENSE.wasmtime
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
--- LLVM Exceptions to the Apache 2.0 License ----
|
||||||
|
|
||||||
|
As an exception, if, as a result of your compiling your source code, portions
|
||||||
|
of this Software are embedded into an Object form of such source code, you
|
||||||
|
may redistribute such embedded portions in such Object form without complying
|
||||||
|
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
|
||||||
|
|
||||||
|
In addition, if you combine or link compiled forms of this Software with
|
||||||
|
software that is licensed under the GPLv2 ("Combined Software") and if a
|
||||||
|
court of competent jurisdiction determines that the patent provision (Section
|
||||||
|
3), the indemnity provision (Section 9) or other Section of the License
|
||||||
|
conflicts with the conditions of the GPLv2, you may retroactively and
|
||||||
|
prospectively choose to deem waived or otherwise exclude such Section(s) of
|
||||||
|
the License, but only in their entirety and only with respect to the Combined
|
||||||
|
Software.
|
||||||
44
README.md
Normal file
44
README.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# wasi-common
|
||||||
|
|
||||||
|
This repo strips away those bits of [lucet-wasi](https://github.com/fastly/lucet/tree/master/lucet-wasi)
|
||||||
|
which can potentially be encapsulated in a separated crate with potential plug'n'play use in both
|
||||||
|
[Lucet](https://github.com/fastly/lucet)
|
||||||
|
and [Wasmtime](https://github.com/CraneStation/wasmtime) projects.
|
||||||
|
|
||||||
|
This repo is strictly experimental.
|
||||||
|
|
||||||
|
## Supported syscalls
|
||||||
|
|
||||||
|
We support a subset of the [WASI
|
||||||
|
API](https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md), though we are adding
|
||||||
|
new syscalls on a regular basis. We currently implement:
|
||||||
|
|
||||||
|
- `__wasi_args_get`
|
||||||
|
- `__wasi_args_sizes_get`
|
||||||
|
- `__wasi_clock_res_get`
|
||||||
|
- `__wasi_clock_time_get`
|
||||||
|
- `__wasi_environ_get`
|
||||||
|
- `__wasi_environ_sizes_get`
|
||||||
|
- `__wasi_fd_close`
|
||||||
|
- `__wasi_fd_fdstat_get`
|
||||||
|
- `__wasi_fd_fdstat_set_flags`
|
||||||
|
- `__wasi_fd_prestat_dir_name`
|
||||||
|
- `__wasi_fd_prestat_get`
|
||||||
|
- `__wasi_fd_read`
|
||||||
|
- `__wasi_fd_seek`
|
||||||
|
- `__wasi_fd_write`
|
||||||
|
- `__wasi_path_open`
|
||||||
|
- `__wasi_proc_exit`
|
||||||
|
- `__wasi_random_get`
|
||||||
|
|
||||||
|
This is enough to run basic C and Rust programs, including those that use command-line arguments,
|
||||||
|
environment variables, stdio, and basic file operations.
|
||||||
|
|
||||||
|
## Third-Party Code
|
||||||
|
|
||||||
|
`src/wasm32.rs` is copied from
|
||||||
|
[wasmtime](https://github.com/CraneStation/wasmtime/blob/master/wasmtime-wasi/src/wasm32.rs), along
|
||||||
|
with the associated `LICENSE.wasmtime` file.
|
||||||
|
|
||||||
|
Significant parts of our syscall implementations are derived from the C implementations in
|
||||||
|
`cloudabi-utils`. See `LICENSE.cloudabi-utils` for license information.
|
||||||
96
build.rs
Normal file
96
build.rs
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
use std::env;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
|
fn wasi_sdk() -> PathBuf {
|
||||||
|
Path::new(&env::var("WASI_SDK").unwrap_or("/opt/wasi-sdk".to_owned())).to_path_buf()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wasi_sysroot() -> PathBuf {
|
||||||
|
match env::var("WASI_SYSROOT") {
|
||||||
|
Ok(wasi_sysroot) => Path::new(&wasi_sysroot).to_path_buf(),
|
||||||
|
Err(_) => {
|
||||||
|
let mut path = wasi_sdk();
|
||||||
|
path.push("share");
|
||||||
|
path.push("sysroot");
|
||||||
|
path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wasm_clang_root() -> PathBuf {
|
||||||
|
match env::var("CLANG_ROOT") {
|
||||||
|
Ok(clang) => Path::new(&clang).to_path_buf(),
|
||||||
|
Err(_) => {
|
||||||
|
let mut path = wasi_sdk();
|
||||||
|
path.push("lib");
|
||||||
|
path.push("clang");
|
||||||
|
path.push("8.0.0");
|
||||||
|
path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let wasi_sysroot = wasi_sysroot();
|
||||||
|
let wasm_clang_root = wasm_clang_root();
|
||||||
|
assert!(
|
||||||
|
wasi_sysroot.exists(),
|
||||||
|
"wasi-sysroot not present at {:?}",
|
||||||
|
wasi_sysroot
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
wasm_clang_root.exists(),
|
||||||
|
"clang-root not present at {:?}",
|
||||||
|
wasm_clang_root
|
||||||
|
);
|
||||||
|
|
||||||
|
let wasi_sysroot_core_h = wasi_sysroot.join("include/wasi/core.h");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
wasi_sysroot_core_h.exists(),
|
||||||
|
"wasi-sysroot core.h not present at {:?}",
|
||||||
|
wasi_sysroot_core_h
|
||||||
|
);
|
||||||
|
|
||||||
|
println!("cargo:rerun-if-changed={}", wasi_sysroot_core_h.display());
|
||||||
|
|
||||||
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||||
|
|
||||||
|
let core_h_path = out_path.join("core.h");
|
||||||
|
let core_h = File::create(&core_h_path).unwrap();
|
||||||
|
|
||||||
|
// `bindgen` doesn't understand typed constant macros like `UINT8_C(123)`, so this fun regex
|
||||||
|
// strips them off to yield a copy of `wasi/core.h` with bare constants.
|
||||||
|
let sed_result = Command::new("sed")
|
||||||
|
.arg("-E")
|
||||||
|
.arg(r#"s/U?INT[0-9]+_C\(((0x)?[0-9]+)\)/\1/g"#)
|
||||||
|
.arg(wasi_sysroot_core_h)
|
||||||
|
.stdout(Stdio::from(core_h))
|
||||||
|
.status()
|
||||||
|
.expect("can execute sed");
|
||||||
|
|
||||||
|
if !sed_result.success() {
|
||||||
|
// something failed, but how?
|
||||||
|
match sed_result.code() {
|
||||||
|
Some(code) => panic!("sed failed with code {}", code),
|
||||||
|
None => panic!("sed exited abnormally"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let host_builder = bindgen::Builder::default()
|
||||||
|
.clang_arg("-nostdinc")
|
||||||
|
.clang_arg("-D__wasi__")
|
||||||
|
.clang_arg(format!("-isystem={}/include/", wasi_sysroot.display()))
|
||||||
|
.clang_arg(format!("-I{}/include/", wasm_clang_root.display()))
|
||||||
|
.header(core_h_path.to_str().unwrap())
|
||||||
|
.whitelist_type("__wasi_.*")
|
||||||
|
.whitelist_var("__WASI_.*");
|
||||||
|
|
||||||
|
host_builder
|
||||||
|
.generate()
|
||||||
|
.expect("can generate host bindings")
|
||||||
|
.write_to_file(out_path.join("wasi_host.rs"))
|
||||||
|
.expect("can write host bindings");
|
||||||
|
}
|
||||||
257
src/ctx.rs
Normal file
257
src/ctx.rs
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
use crate::fdentry::FdEntry;
|
||||||
|
use crate::host;
|
||||||
|
use crate::wasm32;
|
||||||
|
|
||||||
|
use failure::{bail, format_err, Error};
|
||||||
|
use nix::unistd::dup;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::ffi::{CStr, CString};
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{stderr, stdin, stdout};
|
||||||
|
use std::os::unix::prelude::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
pub trait VmContext {
|
||||||
|
fn as_wasi_ctx(&self) -> &WasiCtx;
|
||||||
|
fn as_wasi_ctx_mut(&mut self) -> &mut WasiCtx;
|
||||||
|
|
||||||
|
unsafe fn dec_ptr(
|
||||||
|
&mut self,
|
||||||
|
ptr: wasm32::uintptr_t,
|
||||||
|
len: usize,
|
||||||
|
) -> Result<*mut u8, host::__wasi_errno_t>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WasiCtxBuilder {
|
||||||
|
fds: HashMap<host::__wasi_fd_t, FdEntry>,
|
||||||
|
preopens: HashMap<PathBuf, File>,
|
||||||
|
args: Vec<CString>,
|
||||||
|
env: HashMap<CString, CString>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WasiCtxBuilder {
|
||||||
|
/// Builder for a new `WasiCtx`.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let null = dev_null();
|
||||||
|
WasiCtxBuilder {
|
||||||
|
fds: HashMap::new(),
|
||||||
|
preopens: HashMap::new(),
|
||||||
|
args: vec![],
|
||||||
|
env: HashMap::new(),
|
||||||
|
}
|
||||||
|
.fd_dup(0, &null)
|
||||||
|
.fd_dup(1, &null)
|
||||||
|
.fd_dup(2, &null)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn args(mut self, args: &[&str]) -> Self {
|
||||||
|
self.args = args
|
||||||
|
.into_iter()
|
||||||
|
.map(|arg| CString::new(*arg).expect("argument can be converted to a CString"))
|
||||||
|
.collect();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn arg(mut self, arg: &str) -> Self {
|
||||||
|
self.args
|
||||||
|
.push(CString::new(arg).expect("argument can be converted to a CString"));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c_args<S: AsRef<CStr>>(mut self, args: &[S]) -> Self {
|
||||||
|
self.args = args
|
||||||
|
.into_iter()
|
||||||
|
.map(|arg| arg.as_ref().to_owned())
|
||||||
|
.collect();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c_arg<S: AsRef<CStr>>(mut self, arg: S) -> Self {
|
||||||
|
self.args.push(arg.as_ref().to_owned());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inherit_stdio(self) -> Self {
|
||||||
|
self.fd_dup(0, &stdin())
|
||||||
|
.fd_dup(1, &stdout())
|
||||||
|
.fd_dup(2, &stderr())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inherit_env(mut self) -> Self {
|
||||||
|
self.env = std::env::vars()
|
||||||
|
.map(|(k, v)| {
|
||||||
|
// TODO: handle errors, and possibly assert that the key is valid per POSIX
|
||||||
|
(
|
||||||
|
CString::new(k).expect("environment key can be converted to a CString"),
|
||||||
|
CString::new(v).expect("environment value can be converted to a CString"),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn env(mut self, k: &str, v: &str) -> Self {
|
||||||
|
self.env.insert(
|
||||||
|
// TODO: handle errors, and possibly assert that the key is valid per POSIX
|
||||||
|
CString::new(k).expect("environment key can be converted to a CString"),
|
||||||
|
CString::new(v).expect("environment value can be converted to a CString"),
|
||||||
|
);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c_env<S, T>(mut self, k: S, v: T) -> Self
|
||||||
|
where
|
||||||
|
S: AsRef<CStr>,
|
||||||
|
T: AsRef<CStr>,
|
||||||
|
{
|
||||||
|
self.env
|
||||||
|
.insert(k.as_ref().to_owned(), v.as_ref().to_owned());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add an existing file-like object as a file descriptor in the context.
|
||||||
|
///
|
||||||
|
/// When the `WasiCtx` is dropped, all of its associated file descriptors are `close`d. If you
|
||||||
|
/// do not want this to close the existing object, use `WasiCtxBuilder::fd_dup()`.
|
||||||
|
pub fn fd<F: IntoRawFd>(self, wasm_fd: host::__wasi_fd_t, fd: F) -> Self {
|
||||||
|
// safe because we're getting a valid RawFd from the F directly
|
||||||
|
unsafe { self.raw_fd(wasm_fd, fd.into_raw_fd()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add an existing file-like object as a duplicate file descriptor in the context.
|
||||||
|
///
|
||||||
|
/// The underlying file descriptor of this object will be duplicated before being added to the
|
||||||
|
/// context, so it will not be closed when the `WasiCtx` is dropped.
|
||||||
|
///
|
||||||
|
/// TODO: handle `dup` errors
|
||||||
|
pub fn fd_dup<F: AsRawFd>(self, wasm_fd: host::__wasi_fd_t, fd: &F) -> Self {
|
||||||
|
// safe because we're getting a valid RawFd from the F directly
|
||||||
|
unsafe { self.raw_fd(wasm_fd, dup(fd.as_raw_fd()).unwrap()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add an existing file descriptor to the context.
|
||||||
|
///
|
||||||
|
/// When the `WasiCtx` is dropped, this file descriptor will be `close`d. If you do not want to
|
||||||
|
/// close the existing descriptor, use `WasiCtxBuilder::raw_fd_dup()`.
|
||||||
|
pub unsafe fn raw_fd(mut self, wasm_fd: host::__wasi_fd_t, fd: RawFd) -> Self {
|
||||||
|
self.fds.insert(wasm_fd, FdEntry::from_raw_fd(fd));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a duplicate of an existing file descriptor to the context.
|
||||||
|
///
|
||||||
|
/// The file descriptor will be duplicated before being added to the context, so it will not be
|
||||||
|
/// closed when the `WasiCtx` is dropped.
|
||||||
|
///
|
||||||
|
/// TODO: handle `dup` errors
|
||||||
|
pub unsafe fn raw_fd_dup(self, wasm_fd: host::__wasi_fd_t, fd: RawFd) -> Self {
|
||||||
|
self.raw_fd(wasm_fd, dup(fd).unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn preopened_dir<P: AsRef<Path>>(mut self, dir: File, guest_path: P) -> Self {
|
||||||
|
self.preopens.insert(guest_path.as_ref().to_owned(), dir);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(mut self) -> Result<WasiCtx, Error> {
|
||||||
|
// startup code starts looking at fd 3 for preopens
|
||||||
|
let mut preopen_fd = 3;
|
||||||
|
for (guest_path, dir) in self.preopens {
|
||||||
|
if !dir.metadata()?.is_dir() {
|
||||||
|
bail!("preopened file is not a directory");
|
||||||
|
}
|
||||||
|
while self.fds.contains_key(&preopen_fd) {
|
||||||
|
preopen_fd = preopen_fd
|
||||||
|
.checked_add(1)
|
||||||
|
.ok_or(format_err!("not enough file handles"))?;
|
||||||
|
}
|
||||||
|
let mut fe = FdEntry::from_file(dir);
|
||||||
|
fe.preopen_path = Some(guest_path);
|
||||||
|
self.fds.insert(preopen_fd, fe);
|
||||||
|
preopen_fd += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let env = self
|
||||||
|
.env
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| {
|
||||||
|
let mut pair = k.into_bytes();
|
||||||
|
pair.extend_from_slice(b"=");
|
||||||
|
pair.extend_from_slice(v.to_bytes_with_nul());
|
||||||
|
// constructing a new CString from existing CStrings is safe
|
||||||
|
unsafe { CString::from_vec_unchecked(pair) }
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(WasiCtx {
|
||||||
|
fds: self.fds,
|
||||||
|
args: self.args,
|
||||||
|
env,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct WasiCtx {
|
||||||
|
pub fds: HashMap<host::__wasi_fd_t, FdEntry>,
|
||||||
|
pub args: Vec<CString>,
|
||||||
|
pub env: Vec<CString>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WasiCtx {
|
||||||
|
/// Make a new `WasiCtx` with some default settings.
|
||||||
|
///
|
||||||
|
/// - File descriptors 0, 1, and 2 inherit stdin, stdout, and stderr from the host process.
|
||||||
|
///
|
||||||
|
/// - Environment variables are inherited from the host process.
|
||||||
|
///
|
||||||
|
/// To override these behaviors, use `WasiCtxBuilder`.
|
||||||
|
pub fn new(args: &[&str]) -> WasiCtx {
|
||||||
|
WasiCtxBuilder::new()
|
||||||
|
.args(args)
|
||||||
|
.inherit_stdio()
|
||||||
|
.inherit_env()
|
||||||
|
.build()
|
||||||
|
.expect("default options don't fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_fd_entry(
|
||||||
|
&self,
|
||||||
|
fd: host::__wasi_fd_t,
|
||||||
|
rights_base: host::__wasi_rights_t,
|
||||||
|
rights_inheriting: host::__wasi_rights_t,
|
||||||
|
) -> Result<&FdEntry, host::__wasi_errno_t> {
|
||||||
|
if let Some(fe) = self.fds.get(&fd) {
|
||||||
|
// validate rights
|
||||||
|
if !fe.rights_base & rights_base != 0 || !fe.rights_inheriting & rights_inheriting != 0
|
||||||
|
{
|
||||||
|
Err(host::__WASI_ENOTCAPABLE as host::__wasi_errno_t)
|
||||||
|
} else {
|
||||||
|
Ok(fe)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(host::__WASI_EBADF as host::__wasi_errno_t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_fd_entry(
|
||||||
|
&mut self,
|
||||||
|
fe: FdEntry,
|
||||||
|
) -> Result<host::__wasi_fd_t, host::__wasi_errno_t> {
|
||||||
|
// never insert where stdio handles usually are
|
||||||
|
let mut fd = 3;
|
||||||
|
while self.fds.contains_key(&fd) {
|
||||||
|
if let Some(next_fd) = fd.checked_add(1) {
|
||||||
|
fd = next_fd;
|
||||||
|
} else {
|
||||||
|
return Err(host::__WASI_EMFILE as host::__wasi_errno_t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.fds.insert(fd, fe);
|
||||||
|
Ok(fd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dev_null() -> File {
|
||||||
|
File::open("/dev/null").expect("failed to open /dev/null")
|
||||||
|
}
|
||||||
143
src/fdentry.rs
Normal file
143
src/fdentry.rs
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
use crate::host;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::os::unix::prelude::{FileTypeExt, FromRawFd, IntoRawFd, RawFd};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct FdEntry {
|
||||||
|
pub fd_object: FdObject,
|
||||||
|
pub rights_base: host::__wasi_rights_t,
|
||||||
|
pub rights_inheriting: host::__wasi_rights_t,
|
||||||
|
pub preopen_path: Option<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FdEntry {
|
||||||
|
pub fn from_file(file: File) -> FdEntry {
|
||||||
|
unsafe { FdEntry::from_raw_fd(file.into_raw_fd()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRawFd for FdEntry {
|
||||||
|
// TODO: make this a different function with error handling, rather than using the trait method
|
||||||
|
unsafe fn from_raw_fd(rawfd: RawFd) -> FdEntry {
|
||||||
|
let (ty, mut rights_base, rights_inheriting) =
|
||||||
|
determine_type_rights(rawfd).expect("can determine file rights");
|
||||||
|
|
||||||
|
use nix::fcntl::{fcntl, OFlag, F_GETFL};
|
||||||
|
let flags_bits = fcntl(rawfd, F_GETFL).expect("fcntl succeeds");
|
||||||
|
let flags = OFlag::from_bits_truncate(flags_bits);
|
||||||
|
let accmode = flags & OFlag::O_ACCMODE;
|
||||||
|
if accmode == OFlag::O_RDONLY {
|
||||||
|
rights_base &= !host::__WASI_RIGHT_FD_WRITE as host::__wasi_rights_t;
|
||||||
|
} else if accmode == OFlag::O_WRONLY {
|
||||||
|
rights_base &= !host::__WASI_RIGHT_FD_READ as host::__wasi_rights_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
FdEntry {
|
||||||
|
fd_object: FdObject {
|
||||||
|
ty: ty as u8,
|
||||||
|
rawfd,
|
||||||
|
needs_close: true,
|
||||||
|
},
|
||||||
|
rights_base,
|
||||||
|
rights_inheriting,
|
||||||
|
preopen_path: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: can probably make this safe by using fcntl directly rather than going through `File`
|
||||||
|
pub unsafe fn determine_type_rights(
|
||||||
|
rawfd: RawFd,
|
||||||
|
) -> Result<
|
||||||
|
(
|
||||||
|
host::__wasi_filetype_t,
|
||||||
|
host::__wasi_rights_t,
|
||||||
|
host::__wasi_rights_t,
|
||||||
|
),
|
||||||
|
host::__wasi_errno_t,
|
||||||
|
> {
|
||||||
|
let (ty, rights_base, rights_inheriting) = {
|
||||||
|
let file = File::from_raw_fd(rawfd);
|
||||||
|
let ft = file.metadata().unwrap().file_type();
|
||||||
|
// we just make a `File` here for convenience; we don't want it to close when it drops
|
||||||
|
std::mem::forget(file);
|
||||||
|
if ft.is_block_device() {
|
||||||
|
(
|
||||||
|
host::__WASI_FILETYPE_BLOCK_DEVICE,
|
||||||
|
host::RIGHTS_BLOCK_DEVICE_BASE,
|
||||||
|
host::RIGHTS_BLOCK_DEVICE_INHERITING,
|
||||||
|
)
|
||||||
|
} else if ft.is_char_device() {
|
||||||
|
if nix::unistd::isatty(rawfd).unwrap() {
|
||||||
|
(
|
||||||
|
host::__WASI_FILETYPE_CHARACTER_DEVICE,
|
||||||
|
host::RIGHTS_TTY_BASE,
|
||||||
|
host::RIGHTS_TTY_BASE,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
host::__WASI_FILETYPE_CHARACTER_DEVICE,
|
||||||
|
host::RIGHTS_CHARACTER_DEVICE_BASE,
|
||||||
|
host::RIGHTS_CHARACTER_DEVICE_INHERITING,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else if ft.is_dir() {
|
||||||
|
(
|
||||||
|
host::__WASI_FILETYPE_DIRECTORY,
|
||||||
|
host::RIGHTS_DIRECTORY_BASE,
|
||||||
|
host::RIGHTS_DIRECTORY_INHERITING,
|
||||||
|
)
|
||||||
|
} else if ft.is_file() {
|
||||||
|
(
|
||||||
|
host::__WASI_FILETYPE_REGULAR_FILE,
|
||||||
|
host::RIGHTS_REGULAR_FILE_BASE,
|
||||||
|
host::RIGHTS_REGULAR_FILE_INHERITING,
|
||||||
|
)
|
||||||
|
} else if ft.is_socket() {
|
||||||
|
use nix::sys::socket;
|
||||||
|
match socket::getsockopt(rawfd, socket::sockopt::SockType).unwrap() {
|
||||||
|
socket::SockType::Datagram => (
|
||||||
|
host::__WASI_FILETYPE_SOCKET_DGRAM,
|
||||||
|
host::RIGHTS_SOCKET_BASE,
|
||||||
|
host::RIGHTS_SOCKET_INHERITING,
|
||||||
|
),
|
||||||
|
socket::SockType::Stream => (
|
||||||
|
host::__WASI_FILETYPE_SOCKET_STREAM,
|
||||||
|
host::RIGHTS_SOCKET_BASE,
|
||||||
|
host::RIGHTS_SOCKET_INHERITING,
|
||||||
|
),
|
||||||
|
_ => return Err(host::__WASI_EINVAL as host::__wasi_errno_t),
|
||||||
|
}
|
||||||
|
} else if ft.is_fifo() {
|
||||||
|
(
|
||||||
|
host::__WASI_FILETYPE_SOCKET_STREAM,
|
||||||
|
host::RIGHTS_SOCKET_BASE,
|
||||||
|
host::RIGHTS_SOCKET_INHERITING,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return Err(host::__WASI_EINVAL as host::__wasi_errno_t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok((
|
||||||
|
ty as host::__wasi_filetype_t,
|
||||||
|
rights_base,
|
||||||
|
rights_inheriting,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct FdObject {
|
||||||
|
pub ty: host::__wasi_filetype_t,
|
||||||
|
pub rawfd: RawFd,
|
||||||
|
pub needs_close: bool,
|
||||||
|
// TODO: directories
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for FdObject {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self.needs_close {
|
||||||
|
nix::unistd::close(self.rawfd).unwrap_or_else(|e| eprintln!("FdObject::drop(): {}", e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
335
src/host.rs
Normal file
335
src/host.rs
Normal file
@@ -0,0 +1,335 @@
|
|||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/wasi_host.rs"));
|
||||||
|
|
||||||
|
pub type void = ::std::os::raw::c_void;
|
||||||
|
|
||||||
|
pub unsafe fn ciovec_to_nix<'a>(ciovec: &'a __wasi_ciovec_t) -> nix::sys::uio::IoVec<&'a [u8]> {
|
||||||
|
let slice = std::slice::from_raw_parts(ciovec.buf as *const u8, ciovec.buf_len);
|
||||||
|
nix::sys::uio::IoVec::from_slice(slice)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn ciovec_to_nix_mut<'a>(
|
||||||
|
ciovec: &'a mut __wasi_ciovec_t,
|
||||||
|
) -> nix::sys::uio::IoVec<&'a mut [u8]> {
|
||||||
|
let slice = std::slice::from_raw_parts_mut(ciovec.buf as *mut u8, ciovec.buf_len);
|
||||||
|
nix::sys::uio::IoVec::from_mut_slice(slice)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn errno_from_nix(errno: nix::errno::Errno) -> __wasi_errno_t {
|
||||||
|
let e = match errno {
|
||||||
|
nix::errno::Errno::EPERM => __WASI_EPERM,
|
||||||
|
nix::errno::Errno::ENOENT => __WASI_ENOENT,
|
||||||
|
nix::errno::Errno::ESRCH => __WASI_ESRCH,
|
||||||
|
nix::errno::Errno::EINTR => __WASI_EINTR,
|
||||||
|
nix::errno::Errno::EIO => __WASI_EIO,
|
||||||
|
nix::errno::Errno::ENXIO => __WASI_ENXIO,
|
||||||
|
nix::errno::Errno::E2BIG => __WASI_E2BIG,
|
||||||
|
nix::errno::Errno::ENOEXEC => __WASI_ENOEXEC,
|
||||||
|
nix::errno::Errno::EBADF => __WASI_EBADF,
|
||||||
|
nix::errno::Errno::ECHILD => __WASI_ECHILD,
|
||||||
|
nix::errno::Errno::EAGAIN => __WASI_EAGAIN,
|
||||||
|
nix::errno::Errno::ENOMEM => __WASI_ENOMEM,
|
||||||
|
nix::errno::Errno::EACCES => __WASI_EACCES,
|
||||||
|
nix::errno::Errno::EFAULT => __WASI_EFAULT,
|
||||||
|
nix::errno::Errno::EBUSY => __WASI_EBUSY,
|
||||||
|
nix::errno::Errno::EEXIST => __WASI_EEXIST,
|
||||||
|
nix::errno::Errno::EXDEV => __WASI_EXDEV,
|
||||||
|
nix::errno::Errno::ENODEV => __WASI_ENODEV,
|
||||||
|
nix::errno::Errno::ENOTDIR => __WASI_ENOTDIR,
|
||||||
|
nix::errno::Errno::EISDIR => __WASI_EISDIR,
|
||||||
|
nix::errno::Errno::EINVAL => __WASI_EINVAL,
|
||||||
|
nix::errno::Errno::ENFILE => __WASI_ENFILE,
|
||||||
|
nix::errno::Errno::EMFILE => __WASI_EMFILE,
|
||||||
|
nix::errno::Errno::ENOTTY => __WASI_ENOTTY,
|
||||||
|
nix::errno::Errno::ETXTBSY => __WASI_ETXTBSY,
|
||||||
|
nix::errno::Errno::EFBIG => __WASI_EFBIG,
|
||||||
|
nix::errno::Errno::ENOSPC => __WASI_ENOSPC,
|
||||||
|
nix::errno::Errno::ESPIPE => __WASI_ESPIPE,
|
||||||
|
nix::errno::Errno::EROFS => __WASI_EROFS,
|
||||||
|
nix::errno::Errno::EMLINK => __WASI_EMLINK,
|
||||||
|
nix::errno::Errno::EPIPE => __WASI_EPIPE,
|
||||||
|
nix::errno::Errno::EDOM => __WASI_EDOM,
|
||||||
|
nix::errno::Errno::ERANGE => __WASI_ERANGE,
|
||||||
|
nix::errno::Errno::EDEADLK => __WASI_EDEADLK,
|
||||||
|
nix::errno::Errno::ENAMETOOLONG => __WASI_ENAMETOOLONG,
|
||||||
|
nix::errno::Errno::ENOLCK => __WASI_ENOLCK,
|
||||||
|
nix::errno::Errno::ENOSYS => __WASI_ENOSYS,
|
||||||
|
nix::errno::Errno::ENOTEMPTY => __WASI_ENOTEMPTY,
|
||||||
|
nix::errno::Errno::ELOOP => __WASI_ELOOP,
|
||||||
|
nix::errno::Errno::ENOMSG => __WASI_ENOMSG,
|
||||||
|
nix::errno::Errno::EIDRM => __WASI_EIDRM,
|
||||||
|
nix::errno::Errno::ENOLINK => __WASI_ENOLINK,
|
||||||
|
nix::errno::Errno::EPROTO => __WASI_EPROTO,
|
||||||
|
nix::errno::Errno::EMULTIHOP => __WASI_EMULTIHOP,
|
||||||
|
nix::errno::Errno::EBADMSG => __WASI_EBADMSG,
|
||||||
|
nix::errno::Errno::EOVERFLOW => __WASI_EOVERFLOW,
|
||||||
|
nix::errno::Errno::EILSEQ => __WASI_EILSEQ,
|
||||||
|
nix::errno::Errno::ENOTSOCK => __WASI_ENOTSOCK,
|
||||||
|
nix::errno::Errno::EDESTADDRREQ => __WASI_EDESTADDRREQ,
|
||||||
|
nix::errno::Errno::EMSGSIZE => __WASI_EMSGSIZE,
|
||||||
|
nix::errno::Errno::EPROTOTYPE => __WASI_EPROTOTYPE,
|
||||||
|
nix::errno::Errno::ENOPROTOOPT => __WASI_ENOPROTOOPT,
|
||||||
|
nix::errno::Errno::EPROTONOSUPPORT => __WASI_EPROTONOSUPPORT,
|
||||||
|
nix::errno::Errno::EAFNOSUPPORT => __WASI_EAFNOSUPPORT,
|
||||||
|
nix::errno::Errno::EADDRINUSE => __WASI_EADDRINUSE,
|
||||||
|
nix::errno::Errno::EADDRNOTAVAIL => __WASI_EADDRNOTAVAIL,
|
||||||
|
nix::errno::Errno::ENETDOWN => __WASI_ENETDOWN,
|
||||||
|
nix::errno::Errno::ENETUNREACH => __WASI_ENETUNREACH,
|
||||||
|
nix::errno::Errno::ENETRESET => __WASI_ENETRESET,
|
||||||
|
nix::errno::Errno::ECONNABORTED => __WASI_ECONNABORTED,
|
||||||
|
nix::errno::Errno::ECONNRESET => __WASI_ECONNRESET,
|
||||||
|
nix::errno::Errno::ENOBUFS => __WASI_ENOBUFS,
|
||||||
|
nix::errno::Errno::EISCONN => __WASI_EISCONN,
|
||||||
|
nix::errno::Errno::ENOTCONN => __WASI_ENOTCONN,
|
||||||
|
nix::errno::Errno::ETIMEDOUT => __WASI_ETIMEDOUT,
|
||||||
|
nix::errno::Errno::ECONNREFUSED => __WASI_ECONNREFUSED,
|
||||||
|
nix::errno::Errno::EHOSTUNREACH => __WASI_EHOSTUNREACH,
|
||||||
|
nix::errno::Errno::EALREADY => __WASI_EALREADY,
|
||||||
|
nix::errno::Errno::EINPROGRESS => __WASI_EINPROGRESS,
|
||||||
|
nix::errno::Errno::ESTALE => __WASI_ESTALE,
|
||||||
|
nix::errno::Errno::EDQUOT => __WASI_EDQUOT,
|
||||||
|
nix::errno::Errno::ECANCELED => __WASI_ECANCELED,
|
||||||
|
nix::errno::Errno::EOWNERDEAD => __WASI_EOWNERDEAD,
|
||||||
|
nix::errno::Errno::ENOTRECOVERABLE => __WASI_ENOTRECOVERABLE,
|
||||||
|
_ => __WASI_ENOSYS,
|
||||||
|
};
|
||||||
|
e as __wasi_errno_t
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
const O_RSYNC: nix::fcntl::OFlag = nix::fcntl::OFlag::O_RSYNC;
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
const O_RSYNC: nix::fcntl::OFlag = nix::fcntl::OFlag::O_SYNC;
|
||||||
|
|
||||||
|
pub fn nix_from_fdflags(fdflags: __wasi_fdflags_t) -> nix::fcntl::OFlag {
|
||||||
|
use nix::fcntl::OFlag;
|
||||||
|
let mut nix_flags = OFlag::empty();
|
||||||
|
if fdflags & (__WASI_FDFLAG_APPEND as __wasi_fdflags_t) != 0 {
|
||||||
|
nix_flags.insert(OFlag::O_APPEND);
|
||||||
|
}
|
||||||
|
if fdflags & (__WASI_FDFLAG_DSYNC as __wasi_fdflags_t) != 0 {
|
||||||
|
nix_flags.insert(OFlag::O_DSYNC);
|
||||||
|
}
|
||||||
|
if fdflags & (__WASI_FDFLAG_NONBLOCK as __wasi_fdflags_t) != 0 {
|
||||||
|
nix_flags.insert(OFlag::O_NONBLOCK);
|
||||||
|
}
|
||||||
|
if fdflags & (__WASI_FDFLAG_RSYNC as __wasi_fdflags_t) != 0 {
|
||||||
|
nix_flags.insert(O_RSYNC);
|
||||||
|
}
|
||||||
|
if fdflags & (__WASI_FDFLAG_SYNC as __wasi_fdflags_t) != 0 {
|
||||||
|
nix_flags.insert(OFlag::O_SYNC);
|
||||||
|
}
|
||||||
|
nix_flags
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fdflags_from_nix(oflags: nix::fcntl::OFlag) -> __wasi_fdflags_t {
|
||||||
|
use nix::fcntl::OFlag;
|
||||||
|
let mut fdflags = 0;
|
||||||
|
if oflags.contains(OFlag::O_APPEND) {
|
||||||
|
fdflags |= __WASI_FDFLAG_APPEND;
|
||||||
|
}
|
||||||
|
if oflags.contains(OFlag::O_DSYNC) {
|
||||||
|
fdflags |= __WASI_FDFLAG_DSYNC;
|
||||||
|
}
|
||||||
|
if oflags.contains(OFlag::O_NONBLOCK) {
|
||||||
|
fdflags |= __WASI_FDFLAG_NONBLOCK;
|
||||||
|
}
|
||||||
|
if oflags.contains(O_RSYNC) {
|
||||||
|
fdflags |= __WASI_FDFLAG_RSYNC;
|
||||||
|
}
|
||||||
|
if oflags.contains(OFlag::O_SYNC) {
|
||||||
|
fdflags |= __WASI_FDFLAG_SYNC;
|
||||||
|
}
|
||||||
|
fdflags as __wasi_fdflags_t
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nix_from_oflags(oflags: __wasi_oflags_t) -> nix::fcntl::OFlag {
|
||||||
|
use nix::fcntl::OFlag;
|
||||||
|
let mut nix_flags = OFlag::empty();
|
||||||
|
if oflags & (__WASI_O_CREAT as __wasi_oflags_t) != 0 {
|
||||||
|
nix_flags.insert(OFlag::O_CREAT);
|
||||||
|
}
|
||||||
|
if oflags & (__WASI_O_DIRECTORY as __wasi_oflags_t) != 0 {
|
||||||
|
nix_flags.insert(OFlag::O_DIRECTORY);
|
||||||
|
}
|
||||||
|
if oflags & (__WASI_O_EXCL as __wasi_oflags_t) != 0 {
|
||||||
|
nix_flags.insert(OFlag::O_EXCL);
|
||||||
|
}
|
||||||
|
if oflags & (__WASI_O_TRUNC as __wasi_oflags_t) != 0 {
|
||||||
|
nix_flags.insert(OFlag::O_TRUNC);
|
||||||
|
}
|
||||||
|
nix_flags
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn filetype_from_nix(sflags: nix::sys::stat::SFlag) -> __wasi_filetype_t {
|
||||||
|
use nix::sys::stat::SFlag;
|
||||||
|
if sflags.contains(SFlag::S_IFCHR) {
|
||||||
|
__WASI_FILETYPE_CHARACTER_DEVICE as __wasi_filetype_t
|
||||||
|
} else if sflags.contains(SFlag::S_IFBLK) {
|
||||||
|
__WASI_FILETYPE_BLOCK_DEVICE as __wasi_filetype_t
|
||||||
|
} else if sflags.contains(SFlag::S_IFIFO) | sflags.contains(SFlag::S_IFSOCK) {
|
||||||
|
__WASI_FILETYPE_SOCKET_STREAM as __wasi_filetype_t
|
||||||
|
} else if sflags.contains(SFlag::S_IFDIR) {
|
||||||
|
__WASI_FILETYPE_DIRECTORY as __wasi_filetype_t
|
||||||
|
} else if sflags.contains(SFlag::S_IFREG) {
|
||||||
|
__WASI_FILETYPE_REGULAR_FILE as __wasi_filetype_t
|
||||||
|
} else if sflags.contains(SFlag::S_IFLNK) {
|
||||||
|
__WASI_FILETYPE_SYMBOLIC_LINK as __wasi_filetype_t
|
||||||
|
} else {
|
||||||
|
__WASI_FILETYPE_UNKNOWN as __wasi_filetype_t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nix_from_filetype(sflags: __wasi_filetype_t) -> nix::sys::stat::SFlag {
|
||||||
|
use nix::sys::stat::SFlag;
|
||||||
|
let mut nix_sflags = SFlag::empty();
|
||||||
|
if sflags & (__WASI_FILETYPE_CHARACTER_DEVICE as __wasi_filetype_t) != 0 {
|
||||||
|
nix_sflags.insert(SFlag::S_IFCHR);
|
||||||
|
}
|
||||||
|
if sflags & (__WASI_FILETYPE_BLOCK_DEVICE as __wasi_filetype_t) != 0 {
|
||||||
|
nix_sflags.insert(SFlag::S_IFBLK);
|
||||||
|
}
|
||||||
|
if sflags & (__WASI_FILETYPE_SOCKET_STREAM as __wasi_filetype_t) != 0 {
|
||||||
|
nix_sflags.insert(SFlag::S_IFIFO);
|
||||||
|
nix_sflags.insert(SFlag::S_IFSOCK);
|
||||||
|
}
|
||||||
|
if sflags & (__WASI_FILETYPE_DIRECTORY as __wasi_filetype_t) != 0 {
|
||||||
|
nix_sflags.insert(SFlag::S_IFDIR);
|
||||||
|
}
|
||||||
|
if sflags & (__WASI_FILETYPE_REGULAR_FILE as __wasi_filetype_t) != 0 {
|
||||||
|
nix_sflags.insert(SFlag::S_IFREG);
|
||||||
|
}
|
||||||
|
if sflags & (__WASI_FILETYPE_SYMBOLIC_LINK as __wasi_filetype_t) != 0 {
|
||||||
|
nix_sflags.insert(SFlag::S_IFLNK);
|
||||||
|
}
|
||||||
|
nix_sflags
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn filestat_from_nix(filestat: nix::sys::stat::FileStat) -> __wasi_filestat_t {
|
||||||
|
let filetype = nix::sys::stat::SFlag::from_bits_truncate(filestat.st_mode);
|
||||||
|
__wasi_filestat_t {
|
||||||
|
st_dev: filestat.st_dev as __wasi_device_t,
|
||||||
|
st_ino: filestat.st_ino as __wasi_inode_t,
|
||||||
|
st_nlink: filestat.st_nlink as __wasi_linkcount_t,
|
||||||
|
st_size: filestat.st_size as __wasi_filesize_t,
|
||||||
|
st_atim: filestat.st_atime as __wasi_timestamp_t,
|
||||||
|
st_ctim: filestat.st_ctime as __wasi_timestamp_t,
|
||||||
|
st_mtim: filestat.st_mtime as __wasi_timestamp_t,
|
||||||
|
st_filetype: filetype_from_nix(filetype),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rights sets from wasmtime-wasi sandboxed system primitives. Transcribed because bindgen can't
|
||||||
|
// parse the #defines.
|
||||||
|
|
||||||
|
pub const RIGHTS_ALL: __wasi_rights_t = (__WASI_RIGHT_FD_DATASYNC
|
||||||
|
| __WASI_RIGHT_FD_READ
|
||||||
|
| __WASI_RIGHT_FD_SEEK
|
||||||
|
| __WASI_RIGHT_FD_FDSTAT_SET_FLAGS
|
||||||
|
| __WASI_RIGHT_FD_SYNC
|
||||||
|
| __WASI_RIGHT_FD_TELL
|
||||||
|
| __WASI_RIGHT_FD_WRITE
|
||||||
|
| __WASI_RIGHT_FD_ADVISE
|
||||||
|
| __WASI_RIGHT_FD_ALLOCATE
|
||||||
|
| __WASI_RIGHT_PATH_CREATE_DIRECTORY
|
||||||
|
| __WASI_RIGHT_PATH_CREATE_FILE
|
||||||
|
| __WASI_RIGHT_PATH_LINK_SOURCE
|
||||||
|
| __WASI_RIGHT_PATH_LINK_TARGET
|
||||||
|
| __WASI_RIGHT_PATH_OPEN
|
||||||
|
| __WASI_RIGHT_FD_READDIR
|
||||||
|
| __WASI_RIGHT_PATH_READLINK
|
||||||
|
| __WASI_RIGHT_PATH_RENAME_SOURCE
|
||||||
|
| __WASI_RIGHT_PATH_RENAME_TARGET
|
||||||
|
| __WASI_RIGHT_PATH_FILESTAT_GET
|
||||||
|
| __WASI_RIGHT_PATH_FILESTAT_SET_SIZE
|
||||||
|
| __WASI_RIGHT_PATH_FILESTAT_SET_TIMES
|
||||||
|
| __WASI_RIGHT_FD_FILESTAT_GET
|
||||||
|
| __WASI_RIGHT_FD_FILESTAT_SET_SIZE
|
||||||
|
| __WASI_RIGHT_FD_FILESTAT_SET_TIMES
|
||||||
|
| __WASI_RIGHT_PATH_SYMLINK
|
||||||
|
| __WASI_RIGHT_PATH_UNLINK_FILE
|
||||||
|
| __WASI_RIGHT_PATH_REMOVE_DIRECTORY
|
||||||
|
| __WASI_RIGHT_POLL_FD_READWRITE
|
||||||
|
| __WASI_RIGHT_SOCK_SHUTDOWN) as __wasi_rights_t;
|
||||||
|
|
||||||
|
// Block and character device interaction is outside the scope of
|
||||||
|
// CloudABI. Simply allow everything.
|
||||||
|
pub const RIGHTS_BLOCK_DEVICE_BASE: __wasi_rights_t = RIGHTS_ALL;
|
||||||
|
pub const RIGHTS_BLOCK_DEVICE_INHERITING: __wasi_rights_t = RIGHTS_ALL;
|
||||||
|
pub const RIGHTS_CHARACTER_DEVICE_BASE: __wasi_rights_t = RIGHTS_ALL;
|
||||||
|
pub const RIGHTS_CHARACTER_DEVICE_INHERITING: __wasi_rights_t = RIGHTS_ALL;
|
||||||
|
|
||||||
|
// Only allow directory operations on directories. Directories can only
|
||||||
|
// yield file descriptors to other directories and files.
|
||||||
|
pub const RIGHTS_DIRECTORY_BASE: __wasi_rights_t = (__WASI_RIGHT_FD_FDSTAT_SET_FLAGS
|
||||||
|
| __WASI_RIGHT_FD_SYNC
|
||||||
|
| __WASI_RIGHT_FD_ADVISE
|
||||||
|
| __WASI_RIGHT_PATH_CREATE_DIRECTORY
|
||||||
|
| __WASI_RIGHT_PATH_CREATE_FILE
|
||||||
|
| __WASI_RIGHT_PATH_LINK_SOURCE
|
||||||
|
| __WASI_RIGHT_PATH_LINK_TARGET
|
||||||
|
| __WASI_RIGHT_PATH_OPEN
|
||||||
|
| __WASI_RIGHT_FD_READDIR
|
||||||
|
| __WASI_RIGHT_PATH_READLINK
|
||||||
|
| __WASI_RIGHT_PATH_RENAME_SOURCE
|
||||||
|
| __WASI_RIGHT_PATH_RENAME_TARGET
|
||||||
|
| __WASI_RIGHT_PATH_FILESTAT_GET
|
||||||
|
| __WASI_RIGHT_PATH_FILESTAT_SET_SIZE
|
||||||
|
| __WASI_RIGHT_PATH_FILESTAT_SET_TIMES
|
||||||
|
| __WASI_RIGHT_FD_FILESTAT_GET
|
||||||
|
| __WASI_RIGHT_FD_FILESTAT_SET_SIZE
|
||||||
|
| __WASI_RIGHT_FD_FILESTAT_SET_TIMES
|
||||||
|
| __WASI_RIGHT_PATH_SYMLINK
|
||||||
|
| __WASI_RIGHT_PATH_UNLINK_FILE
|
||||||
|
| __WASI_RIGHT_PATH_REMOVE_DIRECTORY
|
||||||
|
| __WASI_RIGHT_POLL_FD_READWRITE)
|
||||||
|
as __wasi_rights_t;
|
||||||
|
pub const RIGHTS_DIRECTORY_INHERITING: __wasi_rights_t =
|
||||||
|
(RIGHTS_DIRECTORY_BASE | RIGHTS_REGULAR_FILE_BASE);
|
||||||
|
|
||||||
|
// Operations that apply to regular files.
|
||||||
|
pub const RIGHTS_REGULAR_FILE_BASE: __wasi_rights_t = (__WASI_RIGHT_FD_DATASYNC
|
||||||
|
| __WASI_RIGHT_FD_READ
|
||||||
|
| __WASI_RIGHT_FD_SEEK
|
||||||
|
| __WASI_RIGHT_FD_FDSTAT_SET_FLAGS
|
||||||
|
| __WASI_RIGHT_FD_SYNC
|
||||||
|
| __WASI_RIGHT_FD_TELL
|
||||||
|
| __WASI_RIGHT_FD_WRITE
|
||||||
|
| __WASI_RIGHT_FD_ADVISE
|
||||||
|
| __WASI_RIGHT_FD_ALLOCATE
|
||||||
|
| __WASI_RIGHT_FD_FILESTAT_GET
|
||||||
|
| __WASI_RIGHT_FD_FILESTAT_SET_SIZE
|
||||||
|
| __WASI_RIGHT_FD_FILESTAT_SET_TIMES
|
||||||
|
| __WASI_RIGHT_POLL_FD_READWRITE)
|
||||||
|
as __wasi_rights_t;
|
||||||
|
pub const RIGHTS_REGULAR_FILE_INHERITING: __wasi_rights_t = 0;
|
||||||
|
|
||||||
|
// Operations that apply to shared memory objects.
|
||||||
|
pub const RIGHTS_SHARED_MEMORY_BASE: __wasi_rights_t = (__WASI_RIGHT_FD_READ
|
||||||
|
| __WASI_RIGHT_FD_WRITE
|
||||||
|
| __WASI_RIGHT_FD_FILESTAT_GET
|
||||||
|
| __WASI_RIGHT_FD_FILESTAT_SET_SIZE)
|
||||||
|
as __wasi_rights_t;
|
||||||
|
pub const RIGHTS_SHARED_MEMORY_INHERITING: __wasi_rights_t = 0;
|
||||||
|
|
||||||
|
// Operations that apply to sockets and socket pairs.
|
||||||
|
pub const RIGHTS_SOCKET_BASE: __wasi_rights_t = (__WASI_RIGHT_FD_READ
|
||||||
|
| __WASI_RIGHT_FD_FDSTAT_SET_FLAGS
|
||||||
|
| __WASI_RIGHT_FD_WRITE
|
||||||
|
| __WASI_RIGHT_FD_FILESTAT_GET
|
||||||
|
| __WASI_RIGHT_POLL_FD_READWRITE
|
||||||
|
| __WASI_RIGHT_SOCK_SHUTDOWN)
|
||||||
|
as __wasi_rights_t;
|
||||||
|
pub const RIGHTS_SOCKET_INHERITING: __wasi_rights_t = RIGHTS_ALL;
|
||||||
|
|
||||||
|
// Operations that apply to TTYs.
|
||||||
|
pub const RIGHTS_TTY_BASE: __wasi_rights_t = (__WASI_RIGHT_FD_READ
|
||||||
|
| __WASI_RIGHT_FD_FDSTAT_SET_FLAGS
|
||||||
|
| __WASI_RIGHT_FD_WRITE
|
||||||
|
| __WASI_RIGHT_FD_FILESTAT_GET
|
||||||
|
| __WASI_RIGHT_POLL_FD_READWRITE)
|
||||||
|
as __wasi_rights_t;
|
||||||
|
pub const RIGHTS_TTY_INHERITING: __wasi_rights_t = 0;
|
||||||
1360
src/hostcalls.rs
Normal file
1360
src/hostcalls.rs
Normal file
File diff suppressed because it is too large
Load Diff
8
src/lib.rs
Normal file
8
src/lib.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
pub mod ctx;
|
||||||
|
pub mod fdentry;
|
||||||
|
pub mod host;
|
||||||
|
pub mod hostcalls;
|
||||||
|
pub mod memory;
|
||||||
|
pub mod wasm32;
|
||||||
|
|
||||||
|
pub use ctx::{WasiCtx, WasiCtxBuilder};
|
||||||
479
src/memory.rs
Normal file
479
src/memory.rs
Normal file
@@ -0,0 +1,479 @@
|
|||||||
|
//! Functions to go back and forth between WASI types in host and wasm32 representations.
|
||||||
|
//!
|
||||||
|
//! This module is an adaptation of the `wasmtime-wasi` module
|
||||||
|
//! [`translate.rs`](https://github.com/CraneStation/wasmtime-wasi/blob/1a6ecf3a0378d71f3fc1ba25ce76a2b43e4166b8/lib/wasi/src/translate.rs);
|
||||||
|
//! its license file `LICENSE.wasmtime-wasi` is included in this project.
|
||||||
|
//!
|
||||||
|
//! Any of these functions that take a `Vmctx` argument are only meant to be called from within a
|
||||||
|
//! hostcall.
|
||||||
|
//!
|
||||||
|
//! This sort of manual encoding will hopefully be obsolete once the IDL is developed.
|
||||||
|
|
||||||
|
use crate::ctx::VmContext;
|
||||||
|
use crate::{host, wasm32};
|
||||||
|
|
||||||
|
use cast;
|
||||||
|
use cast::From as _0;
|
||||||
|
use std::mem::{align_of, size_of};
|
||||||
|
use std::slice;
|
||||||
|
|
||||||
|
macro_rules! bail_errno {
|
||||||
|
( $errno:ident ) => {
|
||||||
|
return Err(host::$errno as host::__wasi_errno_t);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn dec_ptr_to<T>(
|
||||||
|
vmctx: *mut VmContext,
|
||||||
|
ptr: wasm32::uintptr_t,
|
||||||
|
) -> Result<*mut T, host::__wasi_errno_t> {
|
||||||
|
// check that the ptr is aligned
|
||||||
|
if ptr as usize % align_of::<T>() != 0 {
|
||||||
|
bail_errno!(__WASI_EINVAL);
|
||||||
|
}
|
||||||
|
(*vmctx).dec_ptr(ptr, size_of::<T>()).map(|p| p as *mut T)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn dec_pointee<T>(
|
||||||
|
vmctx: *mut VmContext,
|
||||||
|
ptr: wasm32::uintptr_t,
|
||||||
|
) -> Result<T, host::__wasi_errno_t> {
|
||||||
|
dec_ptr_to::<T>(vmctx, ptr).map(|p| p.read())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn enc_pointee<T>(
|
||||||
|
vmctx: *mut VmContext,
|
||||||
|
ptr: wasm32::uintptr_t,
|
||||||
|
t: T,
|
||||||
|
) -> Result<(), host::__wasi_errno_t> {
|
||||||
|
dec_ptr_to::<T>(vmctx, ptr).map(|p| p.write(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn dec_slice_of<T>(
|
||||||
|
vmctx: *mut VmContext,
|
||||||
|
ptr: wasm32::uintptr_t,
|
||||||
|
len: wasm32::size_t,
|
||||||
|
) -> Result<(*mut T, usize), host::__wasi_errno_t> {
|
||||||
|
// check alignment, and that length doesn't overflow
|
||||||
|
if ptr as usize % align_of::<T>() != 0 {
|
||||||
|
return Err(host::__WASI_EINVAL as host::__wasi_errno_t);
|
||||||
|
}
|
||||||
|
let len = dec_usize(len);
|
||||||
|
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(len) {
|
||||||
|
len
|
||||||
|
} else {
|
||||||
|
return Err(host::__WASI_EOVERFLOW as host::__wasi_errno_t);
|
||||||
|
};
|
||||||
|
|
||||||
|
let ptr = (*vmctx).dec_ptr(ptr, len_bytes)? as *mut T;
|
||||||
|
|
||||||
|
Ok((ptr, len))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn enc_slice_of<T>(
|
||||||
|
vmctx: *mut VmContext,
|
||||||
|
slice: &[T],
|
||||||
|
ptr: wasm32::uintptr_t,
|
||||||
|
) -> Result<(), host::__wasi_errno_t> {
|
||||||
|
// check alignment
|
||||||
|
if ptr as usize % align_of::<T>() != 0 {
|
||||||
|
return Err(host::__WASI_EINVAL as host::__wasi_errno_t);
|
||||||
|
}
|
||||||
|
// check that length doesn't overflow
|
||||||
|
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(slice.len()) {
|
||||||
|
len
|
||||||
|
} else {
|
||||||
|
return Err(host::__WASI_EOVERFLOW as host::__wasi_errno_t);
|
||||||
|
};
|
||||||
|
|
||||||
|
// get the pointer into guest memory, and copy the bytes
|
||||||
|
let ptr = (*vmctx).dec_ptr(ptr, len_bytes)? as *mut libc::c_void;
|
||||||
|
libc::memcpy(ptr, slice.as_ptr() as *const libc::c_void, len_bytes);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! dec_enc_scalar {
|
||||||
|
( $ty:ident, $dec:ident, $dec_byref:ident, $enc:ident, $enc_byref:ident) => {
|
||||||
|
pub fn $dec(x: wasm32::$ty) -> host::$ty {
|
||||||
|
host::$ty::from_le(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn $dec_byref(
|
||||||
|
vmctx: *mut VmContext,
|
||||||
|
ptr: wasm32::uintptr_t,
|
||||||
|
) -> Result<host::$ty, host::__wasi_errno_t> {
|
||||||
|
dec_pointee::<wasm32::$ty>(vmctx, ptr).map($dec)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn $enc(x: host::$ty) -> wasm32::$ty {
|
||||||
|
x.to_le()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn $enc_byref(
|
||||||
|
vmctx: *mut VmContext,
|
||||||
|
ptr: wasm32::uintptr_t,
|
||||||
|
x: host::$ty,
|
||||||
|
) -> Result<(), host::__wasi_errno_t> {
|
||||||
|
enc_pointee::<wasm32::$ty>(vmctx, ptr, $enc(x))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn dec_ciovec(
|
||||||
|
vmctx: *mut VmContext,
|
||||||
|
ciovec: &wasm32::__wasi_ciovec_t,
|
||||||
|
) -> Result<host::__wasi_ciovec_t, host::__wasi_errno_t> {
|
||||||
|
let len = dec_usize(ciovec.buf_len);
|
||||||
|
Ok(host::__wasi_ciovec_t {
|
||||||
|
buf: (*vmctx).dec_ptr(ciovec.buf, len)? as *const host::void,
|
||||||
|
buf_len: len,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn dec_ciovec_slice(
|
||||||
|
vmctx: *mut VmContext,
|
||||||
|
ptr: wasm32::uintptr_t,
|
||||||
|
len: wasm32::size_t,
|
||||||
|
) -> Result<Vec<host::__wasi_ciovec_t>, host::__wasi_errno_t> {
|
||||||
|
let slice = dec_slice_of::<wasm32::__wasi_ciovec_t>(vmctx, ptr, len)?;
|
||||||
|
let slice = slice::from_raw_parts(slice.0, slice.1);
|
||||||
|
slice.iter().map(|iov| dec_ciovec(vmctx, iov)).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_clockid_t,
|
||||||
|
dec_clockid,
|
||||||
|
dec_clockid_byref,
|
||||||
|
enc_clockid,
|
||||||
|
enc_clockid_byref
|
||||||
|
);
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_errno_t,
|
||||||
|
dec_errno,
|
||||||
|
dec_errno_byref,
|
||||||
|
enc_errno,
|
||||||
|
enc_errno_byref
|
||||||
|
);
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_exitcode_t,
|
||||||
|
dec_exitcode,
|
||||||
|
dec_exitcode_byref,
|
||||||
|
enc_exitcode,
|
||||||
|
enc_exitcode_byref
|
||||||
|
);
|
||||||
|
dec_enc_scalar!(__wasi_fd_t, dec_fd, dec_fd_byref, enc_fd, enc_fd_byref);
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_fdflags_t,
|
||||||
|
dec_fdflags,
|
||||||
|
dec_fdflags_byref,
|
||||||
|
enc_fdflags,
|
||||||
|
enc_fdflags_byref
|
||||||
|
);
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_device_t,
|
||||||
|
dec_device,
|
||||||
|
dev_device_byref,
|
||||||
|
enc_device,
|
||||||
|
enc_device_byref
|
||||||
|
);
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_inode_t,
|
||||||
|
dec_inode,
|
||||||
|
dev_inode_byref,
|
||||||
|
enc_inode,
|
||||||
|
enc_inode_byref
|
||||||
|
);
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_linkcount_t,
|
||||||
|
dec_linkcount,
|
||||||
|
dev_linkcount_byref,
|
||||||
|
enc_linkcount,
|
||||||
|
enc_linkcount_byref
|
||||||
|
);
|
||||||
|
|
||||||
|
pub fn dec_filestat(filestat: wasm32::__wasi_filestat_t) -> host::__wasi_filestat_t {
|
||||||
|
host::__wasi_filestat_t {
|
||||||
|
st_dev: dec_device(filestat.st_dev),
|
||||||
|
st_ino: dec_inode(filestat.st_ino),
|
||||||
|
st_filetype: dec_filetype(filestat.st_filetype),
|
||||||
|
st_nlink: dec_linkcount(filestat.st_nlink),
|
||||||
|
st_size: dec_filesize(filestat.st_size),
|
||||||
|
st_atim: dec_timestamp(filestat.st_atim),
|
||||||
|
st_mtim: dec_timestamp(filestat.st_mtim),
|
||||||
|
st_ctim: dec_timestamp(filestat.st_ctim),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn dec_filestat_byref(
|
||||||
|
vmctx: *mut VmContext,
|
||||||
|
filestat_ptr: wasm32::uintptr_t,
|
||||||
|
) -> Result<host::__wasi_filestat_t, host::__wasi_errno_t> {
|
||||||
|
dec_pointee::<wasm32::__wasi_filestat_t>(vmctx, filestat_ptr).map(dec_filestat)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enc_filestat(filestat: host::__wasi_filestat_t) -> wasm32::__wasi_filestat_t {
|
||||||
|
wasm32::__wasi_filestat_t {
|
||||||
|
st_dev: enc_device(filestat.st_dev),
|
||||||
|
st_ino: enc_inode(filestat.st_ino),
|
||||||
|
st_filetype: enc_filetype(filestat.st_filetype),
|
||||||
|
st_nlink: enc_linkcount(filestat.st_nlink),
|
||||||
|
st_size: enc_filesize(filestat.st_size),
|
||||||
|
st_atim: enc_timestamp(filestat.st_atim),
|
||||||
|
st_mtim: enc_timestamp(filestat.st_mtim),
|
||||||
|
st_ctim: enc_timestamp(filestat.st_ctim),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn enc_filestat_byref(
|
||||||
|
vmctx: *mut VmContext,
|
||||||
|
filestat_ptr: wasm32::uintptr_t,
|
||||||
|
host_filestat: host::__wasi_filestat_t,
|
||||||
|
) -> Result<(), host::__wasi_errno_t> {
|
||||||
|
let filestat = enc_filestat(host_filestat);
|
||||||
|
enc_pointee::<wasm32::__wasi_filestat_t>(vmctx, filestat_ptr, filestat)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dec_fdstat(fdstat: wasm32::__wasi_fdstat_t) -> host::__wasi_fdstat_t {
|
||||||
|
host::__wasi_fdstat_t {
|
||||||
|
fs_filetype: dec_filetype(fdstat.fs_filetype),
|
||||||
|
fs_flags: dec_fdflags(fdstat.fs_flags),
|
||||||
|
fs_rights_base: dec_rights(fdstat.fs_rights_base),
|
||||||
|
fs_rights_inheriting: dec_rights(fdstat.fs_rights_inheriting),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn dec_fdstat_byref(
|
||||||
|
vmctx: *mut VmContext,
|
||||||
|
fdstat_ptr: wasm32::uintptr_t,
|
||||||
|
) -> Result<host::__wasi_fdstat_t, host::__wasi_errno_t> {
|
||||||
|
dec_pointee::<wasm32::__wasi_fdstat_t>(vmctx, fdstat_ptr).map(dec_fdstat)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enc_fdstat(fdstat: host::__wasi_fdstat_t) -> wasm32::__wasi_fdstat_t {
|
||||||
|
wasm32::__wasi_fdstat_t {
|
||||||
|
fs_filetype: enc_filetype(fdstat.fs_filetype),
|
||||||
|
fs_flags: enc_fdflags(fdstat.fs_flags),
|
||||||
|
__bindgen_padding_0: 0,
|
||||||
|
fs_rights_base: enc_rights(fdstat.fs_rights_base),
|
||||||
|
fs_rights_inheriting: enc_rights(fdstat.fs_rights_inheriting),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn enc_fdstat_byref(
|
||||||
|
vmctx: *mut VmContext,
|
||||||
|
fdstat_ptr: wasm32::uintptr_t,
|
||||||
|
host_fdstat: host::__wasi_fdstat_t,
|
||||||
|
) -> Result<(), host::__wasi_errno_t> {
|
||||||
|
let fdstat = enc_fdstat(host_fdstat);
|
||||||
|
enc_pointee::<wasm32::__wasi_fdstat_t>(vmctx, fdstat_ptr, fdstat)
|
||||||
|
}
|
||||||
|
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_filedelta_t,
|
||||||
|
dec_filedelta,
|
||||||
|
dec_filedelta_byref,
|
||||||
|
enc_filedelta,
|
||||||
|
enc_filedelta_byref
|
||||||
|
);
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_filesize_t,
|
||||||
|
dec_filesize,
|
||||||
|
dec_filesize_byref,
|
||||||
|
enc_filesize,
|
||||||
|
enc_filesize_byref
|
||||||
|
);
|
||||||
|
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_filetype_t,
|
||||||
|
dec_filetype,
|
||||||
|
dec_filetype_byref,
|
||||||
|
enc_filetype,
|
||||||
|
enc_filetype_byref
|
||||||
|
);
|
||||||
|
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_lookupflags_t,
|
||||||
|
dec_lookupflags,
|
||||||
|
dec_lookupflags_byref,
|
||||||
|
enc_lookupflags,
|
||||||
|
enc_lookupflags_byref
|
||||||
|
);
|
||||||
|
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_oflags_t,
|
||||||
|
dec_oflags,
|
||||||
|
dec_oflags_byref,
|
||||||
|
enc_oflags,
|
||||||
|
enc_oflags_byref
|
||||||
|
);
|
||||||
|
|
||||||
|
pub fn dec_prestat(
|
||||||
|
prestat: wasm32::__wasi_prestat_t,
|
||||||
|
) -> Result<host::__wasi_prestat_t, host::__wasi_errno_t> {
|
||||||
|
match prestat.pr_type {
|
||||||
|
wasm32::__WASI_PREOPENTYPE_DIR => {
|
||||||
|
let u = host::__wasi_prestat_t___wasi_prestat_u {
|
||||||
|
dir: host::__wasi_prestat_t___wasi_prestat_u___wasi_prestat_u_dir_t {
|
||||||
|
pr_name_len: dec_usize(unsafe { prestat.u.dir.pr_name_len }),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Ok(host::__wasi_prestat_t {
|
||||||
|
pr_type: host::__WASI_PREOPENTYPE_DIR as host::__wasi_preopentype_t,
|
||||||
|
u,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => Err(host::__WASI_EINVAL as host::__wasi_errno_t),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn dec_prestat_byref(
|
||||||
|
vmctx: *mut VmContext,
|
||||||
|
prestat_ptr: wasm32::uintptr_t,
|
||||||
|
) -> Result<host::__wasi_prestat_t, host::__wasi_errno_t> {
|
||||||
|
dec_pointee::<wasm32::__wasi_prestat_t>(vmctx, prestat_ptr).and_then(dec_prestat)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enc_prestat(
|
||||||
|
prestat: host::__wasi_prestat_t,
|
||||||
|
) -> Result<wasm32::__wasi_prestat_t, host::__wasi_errno_t> {
|
||||||
|
match prestat.pr_type as u32 {
|
||||||
|
host::__WASI_PREOPENTYPE_DIR => {
|
||||||
|
let u = wasm32::__wasi_prestat_t___wasi_prestat_u {
|
||||||
|
dir: wasm32::__wasi_prestat_t___wasi_prestat_u___wasi_prestat_u_dir_t {
|
||||||
|
pr_name_len: enc_usize(unsafe { prestat.u.dir.pr_name_len }),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Ok(wasm32::__wasi_prestat_t {
|
||||||
|
pr_type: wasm32::__WASI_PREOPENTYPE_DIR as wasm32::__wasi_preopentype_t,
|
||||||
|
u,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => Err(host::__WASI_EINVAL as host::__wasi_errno_t),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn enc_prestat_byref(
|
||||||
|
vmctx: *mut VmContext,
|
||||||
|
prestat_ptr: wasm32::uintptr_t,
|
||||||
|
host_prestat: host::__wasi_prestat_t,
|
||||||
|
) -> Result<(), host::__wasi_errno_t> {
|
||||||
|
let prestat = enc_prestat(host_prestat)?;
|
||||||
|
enc_pointee::<wasm32::__wasi_prestat_t>(vmctx, prestat_ptr, prestat)
|
||||||
|
}
|
||||||
|
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_rights_t,
|
||||||
|
dec_rights,
|
||||||
|
dec_rights_byref,
|
||||||
|
enc_rights,
|
||||||
|
enc_rights_byref
|
||||||
|
);
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_timestamp_t,
|
||||||
|
dec_timestamp,
|
||||||
|
dec_timestamp_byref,
|
||||||
|
enc_timestamp,
|
||||||
|
enc_timestamp_byref
|
||||||
|
);
|
||||||
|
|
||||||
|
pub fn dec_usize(size: wasm32::size_t) -> usize {
|
||||||
|
cast::usize(u32::from_le(size))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enc_usize(size: usize) -> wasm32::size_t {
|
||||||
|
wasm32::size_t::cast(size).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn enc_usize_byref(
|
||||||
|
vmctx: *mut VmContext,
|
||||||
|
usize_ptr: wasm32::uintptr_t,
|
||||||
|
host_usize: usize,
|
||||||
|
) -> Result<(), host::__wasi_errno_t> {
|
||||||
|
enc_pointee::<wasm32::size_t>(vmctx, usize_ptr, enc_usize(host_usize))
|
||||||
|
}
|
||||||
|
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_whence_t,
|
||||||
|
dec_whence,
|
||||||
|
dec_whence_byref,
|
||||||
|
enc_whence,
|
||||||
|
enc_whence_byref
|
||||||
|
);
|
||||||
|
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_subclockflags_t,
|
||||||
|
dec_subclockflags,
|
||||||
|
dec_subclockflags_byref,
|
||||||
|
enc_subclockflags,
|
||||||
|
enc_subclockflags_byref
|
||||||
|
);
|
||||||
|
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_eventrwflags_t,
|
||||||
|
dec_eventrwflags,
|
||||||
|
dec_eventrwflags_byref,
|
||||||
|
enc_eventrwflags,
|
||||||
|
enc_eventrwflags_byref
|
||||||
|
);
|
||||||
|
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_eventtype_t,
|
||||||
|
dec_eventtype,
|
||||||
|
dec_eventtype_byref,
|
||||||
|
enc_eventtype,
|
||||||
|
enc_eventtype_byref
|
||||||
|
);
|
||||||
|
|
||||||
|
dec_enc_scalar!(
|
||||||
|
__wasi_userdata_t,
|
||||||
|
dec_userdata,
|
||||||
|
dec_userdata_byref,
|
||||||
|
enc_userdata,
|
||||||
|
enc_userdata_byref
|
||||||
|
);
|
||||||
|
|
||||||
|
pub fn dec_subscription(
|
||||||
|
subscription: &wasm32::__wasi_subscription_t,
|
||||||
|
) -> Result<host::__wasi_subscription_t, host::__wasi_errno_t> {
|
||||||
|
let userdata = dec_userdata(subscription.userdata);
|
||||||
|
let type_ = dec_eventtype(subscription.type_);
|
||||||
|
let u_orig = subscription.__bindgen_anon_1;
|
||||||
|
let u = match type_ {
|
||||||
|
wasm32::__WASI_EVENTTYPE_CLOCK => host::__wasi_subscription_t___wasi_subscription_u {
|
||||||
|
clock: unsafe {
|
||||||
|
host::__wasi_subscription_t___wasi_subscription_u___wasi_subscription_u_clock_t {
|
||||||
|
identifier: dec_userdata(u_orig.clock.identifier),
|
||||||
|
clock_id: dec_clockid(u_orig.clock.clock_id),
|
||||||
|
timeout: dec_timestamp(u_orig.clock.timeout),
|
||||||
|
precision: dec_timestamp(u_orig.clock.precision),
|
||||||
|
flags: dec_subclockflags(u_orig.clock.flags),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wasm32::__WASI_EVENTTYPE_FD_READ | wasm32::__WASI_EVENTTYPE_FD_WRITE => host::__wasi_subscription_t___wasi_subscription_u {
|
||||||
|
fd_readwrite: host::__wasi_subscription_t___wasi_subscription_u___wasi_subscription_u_fd_readwrite_t {
|
||||||
|
fd: dec_fd(unsafe{u_orig.fd_readwrite.fd})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => return Err(wasm32::__WASI_EINVAL)
|
||||||
|
};
|
||||||
|
Ok(host::__wasi_subscription_t { userdata, type_, u })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enc_event(event: host::__wasi_event_t) -> wasm32::__wasi_event_t {
|
||||||
|
let fd_readwrite = unsafe { event.u.fd_readwrite };
|
||||||
|
wasm32::__wasi_event_t {
|
||||||
|
userdata: enc_userdata(event.userdata),
|
||||||
|
type_: enc_eventtype(event.type_),
|
||||||
|
error: enc_errno(event.error),
|
||||||
|
__bindgen_anon_1: wasm32::__wasi_event_t__bindgen_ty_1 {
|
||||||
|
fd_readwrite: wasm32::__wasi_event_t__bindgen_ty_1__bindgen_ty_1 {
|
||||||
|
nbytes: enc_filesize(fd_readwrite.nbytes),
|
||||||
|
flags: enc_eventrwflags(fd_readwrite.flags),
|
||||||
|
__bindgen_padding_0: [0; 3],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
__bindgen_padding_0: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
1367
src/wasm32.rs
Normal file
1367
src/wasm32.rs
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user