Coverage Report

Created: 2025-07-01 06:18

/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