wamr_rust_sdk/
wasi_context.rs

1/*
2 * Copyright (C) 2019 Intel Corporation. All rights reserved.
3 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4 */
5
6//! prepare wasi context
7
8use std::{ffi::c_char, ffi::CString, vec::Vec};
9
10#[derive(Debug, Default)]
11struct PreOpen {
12    real_paths: Vec<CString>,
13    mapped_paths: Vec<CString>,
14}
15
16#[derive(Debug, Default)]
17pub struct WasiCtxBuilder {
18    pre_open: PreOpen,
19    allowed_address: Vec<CString>,
20    allowed_dns: Vec<CString>,
21    env: Vec<CString>,
22    // every element is a ptr to an env element
23    env_cstr_ptrs: Vec<*const c_char>,
24    args: Vec<CString>,
25    // every element is a ptr to an args element
26    args_cstr_ptrs: Vec<*const c_char>,
27}
28
29#[derive(Debug, Default)]
30pub struct WasiCtx {
31    pre_open: PreOpen,
32    allowed_address: Vec<CString>,
33    allowed_dns: Vec<CString>,
34    env: Vec<CString>,
35    env_cstr_ptrs: Vec<*const c_char>,
36    args: Vec<CString>,
37    args_cstr_ptrs: Vec<*const c_char>,
38}
39
40impl WasiCtxBuilder {
41    pub fn new() -> WasiCtxBuilder {
42        WasiCtxBuilder::default()
43    }
44
45    pub fn build(self) -> WasiCtx {
46        WasiCtx {
47            pre_open: self.pre_open,
48            allowed_address: self.allowed_address,
49            allowed_dns: self.allowed_dns,
50            env: self.env,
51            env_cstr_ptrs: self.env_cstr_ptrs,
52            args: self.args,
53            args_cstr_ptrs: self.args_cstr_ptrs,
54        }
55    }
56
57    /// set pre-open directories and files, which are part of WASI arguments, for the module.
58    /// the format of each map entry: <guest-path>::<host-path>
59    ///
60    /// This function should be called before `Instance::new`
61    pub fn set_pre_open_path(
62        mut self,
63        real_paths: Vec<&str>,
64        mapped_paths: Vec<&str>,
65    ) -> WasiCtxBuilder {
66        self.pre_open.real_paths = real_paths
67            .iter()
68            .map(|s| CString::new(s.as_bytes()).unwrap())
69            .collect::<Vec<CString>>();
70
71        self.pre_open.mapped_paths = mapped_paths
72            .iter()
73            .map(|s| CString::new(s.as_bytes()).unwrap())
74            .collect::<Vec<CString>>();
75
76        self
77    }
78
79    /// set environment variables, which are part of WASI arguments, for the module
80    ///
81    /// This function should be called before `Instance::new`
82    ///
83    /// all wasi args of a module will be spread into the environment variables of the module
84    pub fn set_env_vars(mut self, envs: Vec<&str>) -> WasiCtxBuilder {
85        self.env = envs
86            .iter()
87            .map(|s| CString::new(s.as_bytes()).unwrap())
88            .collect::<Vec<CString>>();
89        self.env_cstr_ptrs = self
90            .env
91            .iter()
92            .map(|s| s.as_ptr() as *const c_char)
93            .collect::<Vec<*const c_char>>();
94
95        self
96    }
97
98    /// set allowed ns , which are part of WASI arguments, for the module
99    ///
100    /// This function should be called before `Instance::new`
101    pub fn set_allowed_dns(mut self, dns: Vec<&str>) -> WasiCtxBuilder {
102        self.allowed_dns = dns
103            .iter()
104            .map(|s| CString::new(s.as_bytes()).unwrap())
105            .collect::<Vec<CString>>();
106
107        self
108    }
109
110    /// set allowed ip addresses, which are part of WASI arguments, for the module
111    ///
112    /// This function should be called before `Instance::new`
113    pub fn set_allowed_address(mut self, addresses: Vec<&str>) -> WasiCtxBuilder {
114        self.allowed_address = addresses
115            .iter()
116            .map(|s| CString::new(s.as_bytes()).unwrap())
117            .collect::<Vec<CString>>();
118
119        self
120    }
121
122    /// set arguments, which are part of WASI arguments, for the module
123    ///
124    /// This function should be called before `Instance::new`
125    pub fn set_arguments(mut self, args: Vec<&str>) -> WasiCtxBuilder {
126        self.args = args
127            .iter()
128            .map(|s| CString::new(s.as_bytes()).unwrap())
129            .collect::<Vec<CString>>();
130        self.args_cstr_ptrs = self
131            .args
132            .iter()
133            .map(|s| s.as_ptr() as *const c_char)
134            .collect::<Vec<*const c_char>>();
135
136        self
137    }
138}
139
140impl WasiCtx {
141    pub fn get_preopen_real_paths(&self) -> &Vec<CString> {
142        &self.pre_open.real_paths
143    }
144
145    pub fn get_preopen_mapped_paths(&self) -> &Vec<CString> {
146        &self.pre_open.mapped_paths
147    }
148
149    pub fn get_allowed_address(&self) -> &Vec<CString> {
150        &self.allowed_address
151    }
152
153    pub fn get_allowed_dns(&self) -> &Vec<CString> {
154        &self.allowed_dns
155    }
156
157    pub fn get_env_vars(&self) -> &Vec<CString> {
158        &self.env
159    }
160
161    pub fn get_env_vars_ptrs(&self) -> &Vec<*const c_char> {
162        &self.env_cstr_ptrs
163    }
164
165    pub fn get_arguments(&self) -> &Vec<CString> {
166        &self.args
167    }
168
169    pub fn get_arguments_ptrs(&self) -> &Vec<*const c_char> {
170        &self.args_cstr_ptrs
171    }
172}
173
174#[cfg(test)]
175mod tests {
176    use super::*;
177
178    #[test]
179    fn test_wasi_ctx_build() {
180        let wasi_ctx = WasiCtxBuilder::new()
181            .set_pre_open_path(vec!["a/b/c"], vec!["/dog/cat/rabbit"])
182            .set_allowed_address(vec!["1.2.3.4"])
183            .set_allowed_dns(vec![])
184            .set_env_vars(vec!["path=/usr/local/bin", "HOME=/home/xxx"])
185            .set_arguments(vec!["arg1", "arg2"])
186            .build();
187
188        let mut preopen_iter = wasi_ctx.get_preopen_real_paths().iter();
189        assert_eq!(preopen_iter.next().unwrap().to_str().unwrap(), "a/b/c");
190        assert_eq!(preopen_iter.next(), None);
191
192        let mut preopen_iter = wasi_ctx.get_preopen_mapped_paths().iter();
193        assert_eq!(
194            preopen_iter.next().unwrap().to_str().unwrap(),
195            "/dog/cat/rabbit"
196        );
197        assert_eq!(preopen_iter.next(), None);
198
199        let mut allowed_address_iter = wasi_ctx.get_allowed_address().iter();
200        assert_eq!(
201            allowed_address_iter.next().unwrap().to_str().unwrap(),
202            "1.2.3.4"
203        );
204        assert_eq!(allowed_address_iter.next(), None);
205
206        let mut env_vars_iter = wasi_ctx.get_env_vars().iter();
207        assert_eq!(
208            env_vars_iter.next().unwrap().to_str().unwrap(),
209            "path=/usr/local/bin"
210        );
211        assert_eq!(
212            env_vars_iter.next().unwrap().to_str().unwrap(),
213            "HOME=/home/xxx"
214        );
215        assert_eq!(env_vars_iter.next(), None);
216    }
217}