/src/WasmEdge/lib/host/wasi/environ.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // SPDX-License-Identifier: Apache-2.0 |
2 | | // SPDX-FileCopyrightText: 2019-2024 Second State INC |
3 | | |
4 | | #include "host/wasi/environ.h" |
5 | | #include "common/errcode.h" |
6 | | #include "common/spdlog.h" |
7 | | #include "host/wasi/vfs.h" |
8 | | #include "host/wasi/vinode.h" |
9 | | |
10 | | using namespace std::literals; |
11 | | |
12 | | namespace WasmEdge { |
13 | | namespace Host { |
14 | | namespace WASI { |
15 | | |
16 | | namespace { |
17 | | static inline constexpr const __wasi_rights_t kPreOpenBaseRightsReadOnly = |
18 | | __WASI_RIGHTS_PATH_OPEN | __WASI_RIGHTS_FD_READDIR | |
19 | | __WASI_RIGHTS_PATH_READLINK | __WASI_RIGHTS_PATH_FILESTAT_GET | |
20 | | __WASI_RIGHTS_FD_FILESTAT_GET; |
21 | | static inline constexpr const __wasi_rights_t kPreOpenInheritingRightsReadOnly = |
22 | | __WASI_RIGHTS_FD_DATASYNC | __WASI_RIGHTS_FD_READ | __WASI_RIGHTS_FD_SEEK | |
23 | | __WASI_RIGHTS_FD_FDSTAT_SET_FLAGS | __WASI_RIGHTS_FD_SYNC | |
24 | | __WASI_RIGHTS_FD_TELL | __WASI_RIGHTS_FD_ADVISE | |
25 | | __WASI_RIGHTS_PATH_CREATE_DIRECTORY | __WASI_RIGHTS_PATH_CREATE_FILE | |
26 | | __WASI_RIGHTS_PATH_LINK_SOURCE | __WASI_RIGHTS_PATH_LINK_TARGET | |
27 | | __WASI_RIGHTS_PATH_OPEN | __WASI_RIGHTS_FD_READDIR | |
28 | | __WASI_RIGHTS_PATH_READLINK | __WASI_RIGHTS_PATH_RENAME_SOURCE | |
29 | | __WASI_RIGHTS_PATH_RENAME_TARGET | __WASI_RIGHTS_PATH_FILESTAT_GET | |
30 | | __WASI_RIGHTS_FD_FILESTAT_GET | __WASI_RIGHTS_FD_FILESTAT_SET_TIMES | |
31 | | __WASI_RIGHTS_PATH_SYMLINK | __WASI_RIGHTS_PATH_REMOVE_DIRECTORY | |
32 | | __WASI_RIGHTS_PATH_UNLINK_FILE | __WASI_RIGHTS_POLL_FD_READWRITE; |
33 | | static inline constexpr const __wasi_rights_t kPreOpenBaseRights = |
34 | | __WASI_RIGHTS_PATH_CREATE_DIRECTORY | __WASI_RIGHTS_PATH_CREATE_FILE | |
35 | | __WASI_RIGHTS_PATH_LINK_SOURCE | __WASI_RIGHTS_PATH_LINK_TARGET | |
36 | | __WASI_RIGHTS_PATH_OPEN | __WASI_RIGHTS_FD_READDIR | |
37 | | __WASI_RIGHTS_PATH_READLINK | __WASI_RIGHTS_PATH_RENAME_SOURCE | |
38 | | __WASI_RIGHTS_PATH_RENAME_TARGET | __WASI_RIGHTS_PATH_FILESTAT_GET | |
39 | | __WASI_RIGHTS_PATH_FILESTAT_SET_TIMES | __WASI_RIGHTS_FD_FILESTAT_GET | |
40 | | __WASI_RIGHTS_FD_FILESTAT_SET_TIMES | __WASI_RIGHTS_PATH_SYMLINK | |
41 | | __WASI_RIGHTS_PATH_REMOVE_DIRECTORY | __WASI_RIGHTS_PATH_UNLINK_FILE | |
42 | | __WASI_RIGHTS_PATH_FILESTAT_SET_SIZE; |
43 | | static inline constexpr const __wasi_rights_t kPreOpenInheritingRights = |
44 | | __WASI_RIGHTS_FD_DATASYNC | __WASI_RIGHTS_FD_READ | __WASI_RIGHTS_FD_SEEK | |
45 | | __WASI_RIGHTS_FD_FDSTAT_SET_FLAGS | __WASI_RIGHTS_FD_SYNC | |
46 | | __WASI_RIGHTS_FD_TELL | __WASI_RIGHTS_FD_WRITE | __WASI_RIGHTS_FD_ADVISE | |
47 | | __WASI_RIGHTS_FD_ALLOCATE | __WASI_RIGHTS_PATH_CREATE_DIRECTORY | |
48 | | __WASI_RIGHTS_PATH_CREATE_FILE | __WASI_RIGHTS_PATH_LINK_SOURCE | |
49 | | __WASI_RIGHTS_PATH_LINK_TARGET | __WASI_RIGHTS_PATH_OPEN | |
50 | | __WASI_RIGHTS_FD_READDIR | __WASI_RIGHTS_PATH_READLINK | |
51 | | __WASI_RIGHTS_PATH_RENAME_SOURCE | __WASI_RIGHTS_PATH_RENAME_TARGET | |
52 | | __WASI_RIGHTS_PATH_FILESTAT_GET | __WASI_RIGHTS_PATH_FILESTAT_SET_SIZE | |
53 | | __WASI_RIGHTS_PATH_FILESTAT_SET_TIMES | __WASI_RIGHTS_FD_FILESTAT_GET | |
54 | | __WASI_RIGHTS_FD_FILESTAT_SET_SIZE | __WASI_RIGHTS_FD_FILESTAT_SET_TIMES | |
55 | | __WASI_RIGHTS_PATH_SYMLINK | __WASI_RIGHTS_PATH_REMOVE_DIRECTORY | |
56 | | __WASI_RIGHTS_PATH_UNLINK_FILE | __WASI_RIGHTS_POLL_FD_READWRITE | |
57 | | __WASI_RIGHTS_SOCK_SHUTDOWN; |
58 | | static inline constexpr const __wasi_rights_t kStdInDefaultRights = |
59 | | __WASI_RIGHTS_FD_ADVISE | __WASI_RIGHTS_FD_FILESTAT_GET | |
60 | | __WASI_RIGHTS_FD_READ | __WASI_RIGHTS_POLL_FD_READWRITE; |
61 | | static inline constexpr const __wasi_rights_t kStdOutDefaultRights = |
62 | | __WASI_RIGHTS_FD_ADVISE | __WASI_RIGHTS_FD_DATASYNC | |
63 | | __WASI_RIGHTS_FD_FILESTAT_GET | __WASI_RIGHTS_FD_SYNC | |
64 | | __WASI_RIGHTS_FD_WRITE | __WASI_RIGHTS_POLL_FD_READWRITE; |
65 | | static inline constexpr const __wasi_rights_t kStdErrDefaultRights = |
66 | | kStdOutDefaultRights; |
67 | | static inline constexpr const __wasi_rights_t kNoInheritingRights = |
68 | | static_cast<__wasi_rights_t>(0); |
69 | | static inline constexpr const auto kReadOnly = "readonly"sv; |
70 | | |
71 | | } // namespace |
72 | | |
73 | | void Environ::init(Span<const std::string> Dirs, std::string ProgramName, |
74 | 0 | Span<const std::string> Args, Span<const std::string> Envs) { |
75 | 0 | { |
76 | | // Open dir for WASI environment. |
77 | 0 | std::vector<std::shared_ptr<VINode>> PreopenedDirs; |
78 | 0 | PreopenedDirs.reserve(Dirs.size()); |
79 | 0 | for (const auto &Dir : Dirs) { |
80 | 0 | const auto Pos = Dir.find(':'); |
81 | 0 | std::string HostDir = |
82 | 0 | (Pos == std::string::npos) ? Dir : Dir.substr(Pos + 1); |
83 | | // Handle the readonly flag |
84 | 0 | bool ReadOnly = false; |
85 | 0 | if (const auto ROPos = HostDir.find(':'); ROPos != std::string::npos) { |
86 | 0 | const auto Mode = HostDir.substr(ROPos + 1); |
87 | 0 | HostDir = HostDir.substr(0, ROPos); |
88 | 0 | if (kReadOnly == Mode) { |
89 | 0 | ReadOnly = true; |
90 | 0 | } |
91 | 0 | } |
92 | 0 | std::string GuestDir = VINode::canonicalGuest( |
93 | 0 | (Pos == std::string::npos) ? std::string_view(Dir) |
94 | 0 | : std::string_view(Dir).substr(0, Pos)); |
95 | 0 | if (GuestDir.size() == 0) { |
96 | 0 | GuestDir = '/'; |
97 | 0 | } |
98 | 0 | const auto BaseRights = |
99 | 0 | ReadOnly ? kPreOpenBaseRightsReadOnly : kPreOpenBaseRights; |
100 | 0 | const auto InheritingRights = ReadOnly ? kPreOpenInheritingRightsReadOnly |
101 | 0 | : kPreOpenInheritingRights; |
102 | 0 | if (auto Res = VINode::bind(BaseRights, InheritingRights, |
103 | 0 | std::move(GuestDir), std::move(HostDir)); |
104 | 0 | unlikely(!Res)) { |
105 | 0 | spdlog::error("Bind guest directory failed:{}"sv, Res.error()); |
106 | 0 | continue; |
107 | 0 | } else { |
108 | 0 | PreopenedDirs.emplace_back(std::move(*Res)); |
109 | 0 | } |
110 | 0 | } |
111 | |
|
112 | 0 | std::sort(PreopenedDirs.begin(), PreopenedDirs.end()); |
113 | |
|
114 | 0 | FdMap.emplace(0, VINode::stdIn(kStdInDefaultRights, kNoInheritingRights)); |
115 | 0 | FdMap.emplace(1, VINode::stdOut(kStdOutDefaultRights, kNoInheritingRights)); |
116 | 0 | FdMap.emplace(2, VINode::stdErr(kStdErrDefaultRights, kNoInheritingRights)); |
117 | |
|
118 | 0 | int NewFd = 3; |
119 | 0 | for (auto &PreopenedDir : PreopenedDirs) { |
120 | 0 | FdMap.emplace(NewFd++, std::move(PreopenedDir)); |
121 | 0 | } |
122 | 0 | } |
123 | |
|
124 | 0 | Arguments.resize(Args.size() + 1); |
125 | 0 | Arguments.front() = std::move(ProgramName); |
126 | 0 | std::copy(Args.begin(), Args.end(), Arguments.begin() + 1); |
127 | 0 | Arguments.shrink_to_fit(); |
128 | |
|
129 | 0 | EnvironVariables.resize(Envs.size()); |
130 | 0 | std::copy(Envs.begin(), Envs.end(), EnvironVariables.begin()); |
131 | 0 | EnvironVariables.shrink_to_fit(); |
132 | |
|
133 | 0 | ExitCode = 0; |
134 | 0 | } |
135 | | |
136 | 0 | void Environ::fini() noexcept { |
137 | 0 | EnvironVariables.clear(); |
138 | 0 | Arguments.clear(); |
139 | 0 | FdMap.clear(); |
140 | 0 | } |
141 | | |
142 | 0 | Environ::~Environ() noexcept { fini(); } |
143 | | |
144 | | } // namespace WASI |
145 | | } // namespace Host |
146 | | } // namespace WasmEdge |