From 3a87edc0c1d517b1b79fec076e61ad50557bf5bb Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 22 Oct 2019 16:36:05 -0700 Subject: [PATCH 1/2] Remove special casing of stdin, stdout, and stderr in WASI FS --- CHANGELOG.md | 1 + lib/wasi-tests/tests/wasitests/fd_close.rs | 18 ++ lib/wasi-tests/tests/wasitests/mod.rs | 1 + lib/wasi-tests/wasitests/fd_close.out | 2 + lib/wasi-tests/wasitests/fd_close.rs | 54 ++++++ lib/wasi-tests/wasitests/fd_close.wasm | Bin 0 -> 82928 bytes lib/wasi/src/state/mod.rs | 196 ++++++++++++++++++--- lib/wasi/src/state/types.rs | 4 + lib/wasi/src/syscalls/mod.rs | 79 ++++++++- 9 files changed, 324 insertions(+), 31 deletions(-) create mode 100644 lib/wasi-tests/tests/wasitests/fd_close.rs create mode 100644 lib/wasi-tests/wasitests/fd_close.out create mode 100644 lib/wasi-tests/wasitests/fd_close.rs create mode 100755 lib/wasi-tests/wasitests/fd_close.wasm diff --git a/CHANGELOG.md b/CHANGELOG.md index 49d90aaae..936238a6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Blocks of changes will separated by version increments. ## **[Unreleased]** +- [#897](https://github.com/wasmerio/wasmer/pull/897) Removes special casing of stdin, stdout, and stderr in WASI. Closing these files now works. Removes `stdin`, `stdout`, and `stderr` from `WasiFS`, replaced by the methods `stdout`, `stdout_mut`, and so on. - [#863](https://github.com/wasmerio/wasmer/pull/863) Fix min and max for cases involving NaN and negative zero when using the LLVM backend. ## 0.8.0 - 2019-10-02 diff --git a/lib/wasi-tests/tests/wasitests/fd_close.rs b/lib/wasi-tests/tests/wasitests/fd_close.rs new file mode 100644 index 000000000..8bff35789 --- /dev/null +++ b/lib/wasi-tests/tests/wasitests/fd_close.rs @@ -0,0 +1,18 @@ +// !!! THIS IS A GENERATED FILE !!! +// ANY MANUAL EDITS MAY BE OVERWRITTEN AT ANY TIME +// Files autogenerated with cargo build (build/wasitests.rs). + +#[test] +fn test_fd_close() { + assert_wasi_output!( + "../../wasitests/fd_close.wasm", + "fd_close", + vec![], + vec![( + ".".to_string(), + ::std::path::PathBuf::from("wasitests/test_fs/hamlet") + ),], + vec![], + "../../wasitests/fd_close.out" + ); +} diff --git a/lib/wasi-tests/tests/wasitests/mod.rs b/lib/wasi-tests/tests/wasitests/mod.rs index e469511fd..75a91d6f0 100644 --- a/lib/wasi-tests/tests/wasitests/mod.rs +++ b/lib/wasi-tests/tests/wasitests/mod.rs @@ -9,6 +9,7 @@ mod close_preopen_fd; mod create_dir; mod envvar; mod fd_allocate; +mod fd_close; mod fd_pread; mod fd_read; mod fd_sync; diff --git a/lib/wasi-tests/wasitests/fd_close.out b/lib/wasi-tests/wasitests/fd_close.out new file mode 100644 index 000000000..c42fc06c2 --- /dev/null +++ b/lib/wasi-tests/wasitests/fd_close.out @@ -0,0 +1,2 @@ +Successfully closed stderr! +Successfully closed stdin! diff --git a/lib/wasi-tests/wasitests/fd_close.rs b/lib/wasi-tests/wasitests/fd_close.rs new file mode 100644 index 000000000..3d2104be6 --- /dev/null +++ b/lib/wasi-tests/wasitests/fd_close.rs @@ -0,0 +1,54 @@ +// Args: +// mapdir: .:wasitests/test_fs/hamlet + +use std::fs; +#[cfg(target_os = "wasi")] +use std::os::wasi::prelude::AsRawFd; +use std::path::PathBuf; + +#[cfg(target_os = "wasi")] +#[link(wasm_import_module = "wasi_unstable")] +extern "C" { + fn fd_close(fd: u32) -> u16; +} + +fn main() { + #[cfg(not(target_os = "wasi"))] + let mut base = PathBuf::from("wasitests/test_fs/hamlet"); + #[cfg(target_os = "wasi")] + let mut base = PathBuf::from("."); + + base.push("act3/scene3.txt"); + let file = fs::File::open(&base).expect("could not open file"); + + #[cfg(target_os = "wasi")] + { + let stdout_fd = std::io::stdout().as_raw_fd(); + let stderr_fd = std::io::stderr().as_raw_fd(); + let stdin_fd = std::io::stdin().as_raw_fd(); + + let result = unsafe { fd_close(stderr_fd) }; + if result == 0 { + println!("Successfully closed stderr!") + } else { + println!("Could not close stderr"); + } + let result = unsafe { fd_close(stdin_fd) }; + if result == 0 { + println!("Successfully closed stdin!") + } else { + println!("Could not close stdin"); + } + let result = unsafe { fd_close(stdout_fd) }; + if result == 0 { + println!("Successfully closed stdout!") + } else { + println!("Could not close stdout"); + } + } + #[cfg(not(target_os = "wasi"))] + { + println!("Successfully closed stderr!"); + println!("Successfully closed stdin!"); + } +} diff --git a/lib/wasi-tests/wasitests/fd_close.wasm b/lib/wasi-tests/wasitests/fd_close.wasm new file mode 100755 index 0000000000000000000000000000000000000000..a40a1bfda1eda6d84e0eedb1399d17925b4cca86 GIT binary patch literal 82928 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 z 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, /// for fds still open after the file has been deleted pub orphan_fds: HashMap, - - pub stdout: Box, - pub stderr: Box, - pub stdin: Box, } impl WasiFs { @@ -155,11 +165,11 @@ impl WasiFs { next_fd: Cell::new(3), inode_counter: Cell::new(1024), orphan_fds: HashMap::new(), - - stdin: Box::new(Stdin), - stdout: Box::new(Stdout), - stderr: Box::new(Stderr), }; + wasi_fs.create_stdin(); + wasi_fs.create_stdout(); + wasi_fs.create_stderr(); + // create virtual root let root_inode = { let all_rights = 0x1FFFFFFF; @@ -291,6 +301,67 @@ impl WasiFs { Ok(wasi_fs) } + /// Get the `WasiFile` object at stdout + pub fn stdout(&self) -> Result<&Option>, WasiFsError> { + self.std_dev_get(__WASI_STDOUT_FILENO) + } + /// Get the `WasiFile` object at stdout mutably + pub fn stdout_mut(&mut self) -> Result<&mut Option>, WasiFsError> { + self.std_dev_get_mut(__WASI_STDOUT_FILENO) + } + + /// Get the `WasiFile` object at stderr + pub fn stderr(&self) -> Result<&Option>, WasiFsError> { + self.std_dev_get(__WASI_STDERR_FILENO) + } + /// Get the `WasiFile` object at stderr mutably + pub fn stderr_mut(&mut self) -> Result<&mut Option>, WasiFsError> { + self.std_dev_get_mut(__WASI_STDERR_FILENO) + } + + /// Get the `WasiFile` object at stdin + pub fn stdin(&self) -> Result<&Option>, WasiFsError> { + self.std_dev_get(__WASI_STDIN_FILENO) + } + /// Get the `WasiFile` object at stdin mutably + pub fn stdin_mut(&mut self) -> Result<&mut Option>, WasiFsError> { + self.std_dev_get_mut(__WASI_STDIN_FILENO) + } + + /// Internal helper function to get a standard device handle. + /// Expects one of `__WASI_STDIN_FILENO`, `__WASI_STDOUT_FILENO`, `__WASI_STDERR_FILENO`. + fn std_dev_get(&self, fd: __wasi_fd_t) -> Result<&Option>, WasiFsError> { + if let Some(fd) = self.fd_map.get(&fd) { + if let Kind::File { ref handle, .. } = self.inodes[fd.inode].kind { + Ok(handle) + } else { + // Our public API should ensure that this is not possible + unreachable!("Non-file found in standard device location") + } + } else { + // this should only trigger if we made a mistake in this crate + Err(WasiFsError::NoDevice) + } + } + /// Internal helper function to mutably get a standard device handle. + /// Expects one of `__WASI_STDIN_FILENO`, `__WASI_STDOUT_FILENO`, `__WASI_STDERR_FILENO`. + fn std_dev_get_mut( + &mut self, + fd: __wasi_fd_t, + ) -> Result<&mut Option>, WasiFsError> { + if let Some(fd) = self.fd_map.get_mut(&fd) { + if let Kind::File { ref mut handle, .. } = self.inodes[fd.inode].kind { + Ok(handle) + } else { + // Our public API should ensure that this is not possible + unreachable!("Non-file found in standard device location") + } + } else { + // this should only trigger if we made a mistake in this crate + Err(WasiFsError::NoDevice) + } + } + fn get_next_inode_index(&mut self) -> u64 { let next = self.inode_counter.get(); self.inode_counter.set(next + 1); @@ -358,21 +429,16 @@ impl WasiFs { fd: __wasi_fd_t, file: Box, ) -> Result>, WasiFsError> { + let mut ret = Some(file); match fd { __WASI_STDIN_FILENO => { - let mut ret = file; - std::mem::swap(&mut self.stdin, &mut ret); - Ok(Some(ret)) + std::mem::swap(self.stdin_mut()?, &mut ret); } __WASI_STDOUT_FILENO => { - let mut ret = file; - std::mem::swap(&mut self.stdout, &mut ret); - Ok(Some(ret)) + std::mem::swap(self.stdout_mut()?, &mut ret); } __WASI_STDERR_FILENO => { - let mut ret = file; - std::mem::swap(&mut self.stderr, &mut ret); - Ok(Some(ret)) + std::mem::swap(self.stderr_mut()?, &mut ret); } _ => { let base_fd = self.get_fd(fd).map_err(WasiFsError::from_wasi_err)?; @@ -380,14 +446,14 @@ impl WasiFs { match &mut self.inodes[base_inode].kind { Kind::File { ref mut handle, .. } => { - let mut ret = Some(file); std::mem::swap(handle, &mut ret); - Ok(ret) } _ => return Err(WasiFsError::NotAFile), } } } + + Ok(ret) } /// refresh size from filesystem @@ -733,6 +799,17 @@ impl WasiFs { } pub fn fdstat(&self, fd: __wasi_fd_t) -> Result<__wasi_fdstat_t, __wasi_errno_t> { + match fd { + __WASI_STDOUT_FILENO => { + return Ok(__wasi_fdstat_t { + fs_filetype: __WASI_FILETYPE_CHARACTER_DEVICE, + fs_flags: 0, + fs_rights_base: ALL_RIGHTS, + fs_rights_inheriting: ALL_RIGHTS, + }) + } + _ => (), + } let fd = self.get_fd(fd)?; debug!("fdstat: {:?}", fd); @@ -773,8 +850,18 @@ impl WasiFs { pub fn flush(&mut self, fd: __wasi_fd_t) -> Result<(), __wasi_errno_t> { match fd { __WASI_STDIN_FILENO => (), - __WASI_STDOUT_FILENO => self.stdout.flush().map_err(|_| __WASI_EIO)?, - __WASI_STDERR_FILENO => self.stderr.flush().map_err(|_| __WASI_EIO)?, + __WASI_STDOUT_FILENO => self + .stdout_mut() + .map_err(WasiFsError::into_wasi_err)? + .as_mut() + .and_then(|f| f.flush().ok()) + .ok_or(__WASI_EIO)?, + __WASI_STDERR_FILENO => self + .stderr_mut() + .map_err(WasiFsError::into_wasi_err)? + .as_mut() + .and_then(|f| f.flush().ok()) + .ok_or(__WASI_EIO)?, _ => { let fd = self.fd_map.get(&fd).ok_or(__WASI_EBADF)?; if fd.rights & __WASI_RIGHT_FD_DATASYNC == 0 { @@ -881,13 +968,78 @@ impl WasiFs { }; self.inodes.insert(InodeVal { - stat: stat, + stat, is_preopened: true, name: "/".to_string(), kind: root_kind, }) } + fn create_stdout(&mut self) { + self.create_std_dev_inner( + Box::new(Stdout), + "stdout", + __WASI_STDOUT_FILENO, + STDOUT_DEFAULT_RIGHTS, + __WASI_FDFLAG_APPEND, + ); + } + fn create_stdin(&mut self) { + self.create_std_dev_inner( + Box::new(Stdin), + "stdin", + __WASI_STDIN_FILENO, + STDIN_DEFAULT_RIGHTS, + 0, + ); + } + fn create_stderr(&mut self) { + self.create_std_dev_inner( + Box::new(Stderr), + "stderr", + __WASI_STDERR_FILENO, + STDERR_DEFAULT_RIGHTS, + __WASI_FDFLAG_APPEND, + ); + } + + fn create_std_dev_inner( + &mut self, + handle: Box, + name: &'static str, + raw_fd: __wasi_fd_t, + rights: __wasi_rights_t, + fd_flags: __wasi_fdflags_t, + ) { + let stat = __wasi_filestat_t { + st_filetype: __WASI_FILETYPE_CHARACTER_DEVICE, + st_ino: self.get_next_inode_index(), + ..__wasi_filestat_t::default() + }; + let kind = Kind::File { + handle: Some(handle), + path: "".into(), + }; + let inode = self.inodes.insert(InodeVal { + stat, + is_preopened: true, + name: name.to_string(), + kind, + }); + self.fd_map.insert( + raw_fd, + Fd { + rights, + rights_inheriting: 0, + flags: fd_flags, + // since we're not calling open on this, we don't need open flags + open_flags: 0, + offset: 0, + inode, + }, + ); + } + pub fn get_stat_for_kind(&self, kind: &Kind) -> Option<__wasi_filestat_t> { let md = match kind { Kind::File { handle, path } => match handle { diff --git a/lib/wasi/src/state/types.rs b/lib/wasi/src/state/types.rs index 2f97a5fe3..5eb55c670 100644 --- a/lib/wasi/src/state/types.rs +++ b/lib/wasi/src/state/types.rs @@ -49,6 +49,8 @@ pub enum WasiFsError { NotConnected, /// The requested file or directory could not be found EntityNotFound, + /// The requested device couldn't be accessed + NoDevice, /// Caller was not allowed to perform this operation PermissionDenied, /// The operation did not complete within the given amount of time @@ -80,6 +82,7 @@ impl WasiFsError { __WASI_EINTR => WasiFsError::Interrupted, __WASI_EINVAL => WasiFsError::InvalidInput, __WASI_ENOTCONN => WasiFsError::NotConnected, + __WASI_ENODEV => WasiFsError::NoDevice, __WASI_ENOENT => WasiFsError::EntityNotFound, __WASI_EPERM => WasiFsError::PermissionDenied, __WASI_ETIMEDOUT => WasiFsError::TimedOut, @@ -105,6 +108,7 @@ impl WasiFsError { WasiFsError::InvalidFd => __WASI_EBADF, WasiFsError::InvalidInput => __WASI_EINVAL, WasiFsError::IOError => __WASI_EIO, + WasiFsError::NoDevice => __WASI_ENODEV, WasiFsError::NotAFile => __WASI_EINVAL, WasiFsError::NotConnected => __WASI_ENOTCONN, WasiFsError::EntityNotFound => __WASI_ENOENT, diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index 90dbfd458..37a6486c3 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -374,6 +374,7 @@ pub fn fd_allocate( /// If `fd` is invalid or not open pub fn fd_close(ctx: &mut Ctx, fd: __wasi_fd_t) -> __wasi_errno_t { debug!("wasi::fd_close"); + debug!("=> fd={}", fd); let state = get_wasi_state(ctx); let fd_entry = wasi_try!(state.fs.get_fd(fd)).clone(); @@ -662,7 +663,15 @@ pub fn fd_pread( let state = get_wasi_state(ctx); let bytes_read = match fd { - __WASI_STDIN_FILENO => wasi_try!(read_bytes(&mut state.fs.stdin, memory, iov_cells)), + __WASI_STDIN_FILENO => { + if let Some(ref mut stdin) = + wasi_try!(state.fs.stdin_mut().map_err(WasiFsError::into_wasi_err)) + { + wasi_try!(read_bytes(stdin, memory, iov_cells)) + } else { + return __WASI_EBADF; + } + } __WASI_STDOUT_FILENO => return __WASI_EINVAL, __WASI_STDERR_FILENO => return __WASI_EINVAL, _ => { @@ -802,8 +811,24 @@ pub fn fd_pwrite( let bytes_written = match fd { __WASI_STDIN_FILENO => return __WASI_EINVAL, - __WASI_STDOUT_FILENO => wasi_try!(write_bytes(&mut state.fs.stdout, memory, iovs_arr_cell)), - __WASI_STDERR_FILENO => wasi_try!(write_bytes(&mut state.fs.stderr, memory, iovs_arr_cell)), + __WASI_STDOUT_FILENO => { + if let Some(ref mut stdout) = + wasi_try!(state.fs.stdout_mut().map_err(WasiFsError::into_wasi_err)) + { + wasi_try!(write_bytes(stdout, memory, iovs_arr_cell)) + } else { + return __WASI_EBADF; + } + } + __WASI_STDERR_FILENO => { + if let Some(ref mut stderr) = + wasi_try!(state.fs.stderr_mut().map_err(WasiFsError::into_wasi_err)) + { + wasi_try!(write_bytes(stderr, memory, iovs_arr_cell)) + } else { + return __WASI_EBADF; + } + } _ => { let fd_entry = wasi_try!(state.fs.fd_map.get_mut(&fd).ok_or(__WASI_EBADF)); @@ -872,7 +897,15 @@ pub fn fd_read( let state = get_wasi_state(ctx); let bytes_read = match fd { - __WASI_STDIN_FILENO => wasi_try!(read_bytes(&mut state.fs.stdin, memory, iovs_arr_cell)), + __WASI_STDIN_FILENO => { + if let Some(ref mut stdin) = + wasi_try!(state.fs.stdin_mut().map_err(WasiFsError::into_wasi_err)) + { + wasi_try!(read_bytes(stdin, memory, iovs_arr_cell)) + } else { + return __WASI_EBADF; + } + } __WASI_STDOUT_FILENO | __WASI_STDERR_FILENO => return __WASI_EINVAL, _ => { let fd_entry = wasi_try!(state.fs.fd_map.get_mut(&fd).ok_or(__WASI_EBADF)); @@ -1211,8 +1244,24 @@ pub fn fd_write( let bytes_written = match fd { __WASI_STDIN_FILENO => return __WASI_EINVAL, - __WASI_STDOUT_FILENO => wasi_try!(write_bytes(&mut state.fs.stdout, memory, iovs_arr_cell)), - __WASI_STDERR_FILENO => wasi_try!(write_bytes(&mut state.fs.stderr, memory, iovs_arr_cell)), + __WASI_STDOUT_FILENO => { + if let Some(ref mut stdout) = + wasi_try!(state.fs.stdout_mut().map_err(WasiFsError::into_wasi_err)) + { + wasi_try!(write_bytes(stdout, memory, iovs_arr_cell)) + } else { + return __WASI_EBADF; + } + } + __WASI_STDERR_FILENO => { + if let Some(ref mut stderr) = + wasi_try!(state.fs.stderr_mut().map_err(WasiFsError::into_wasi_err)) + { + wasi_try!(write_bytes(stderr, memory, iovs_arr_cell)) + } else { + return __WASI_EBADF; + } + } _ => { let state = get_wasi_state(ctx); let fd_entry = wasi_try!(state.fs.fd_map.get_mut(&fd).ok_or(__WASI_EBADF)); @@ -2292,9 +2341,21 @@ pub fn poll_oneoff( if let Some(fd) = fd { let wasi_file_ref: &dyn WasiFile = match fd { - __WASI_STDERR_FILENO => state.fs.stderr.as_ref(), - __WASI_STDIN_FILENO => state.fs.stdin.as_ref(), - __WASI_STDOUT_FILENO => state.fs.stdout.as_ref(), + __WASI_STDERR_FILENO => wasi_try!( + wasi_try!(state.fs.stderr().map_err(WasiFsError::into_wasi_err)).as_ref(), + __WASI_EBADF + ) + .as_ref(), + __WASI_STDIN_FILENO => wasi_try!( + wasi_try!(state.fs.stdin().map_err(WasiFsError::into_wasi_err)).as_ref(), + __WASI_EBADF + ) + .as_ref(), + __WASI_STDOUT_FILENO => wasi_try!( + wasi_try!(state.fs.stdout().map_err(WasiFsError::into_wasi_err)).as_ref(), + __WASI_EBADF + ) + .as_ref(), _ => { let fd_entry = wasi_try!(state.fs.get_fd(fd)); let inode = fd_entry.inode; From 5353af79ad4918c3da94ebe4890c3e20898ed3ba Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 22 Oct 2019 17:29:19 -0700 Subject: [PATCH 2/2] Improve fd_close wasi test: explicitly close file --- lib/wasi-tests/wasitests/fd_close.out | 1 + lib/wasi-tests/wasitests/fd_close.rs | 9 +++++++++ lib/wasi-tests/wasitests/fd_close.wasm | Bin 82928 -> 83077 bytes 3 files changed, 10 insertions(+) diff --git a/lib/wasi-tests/wasitests/fd_close.out b/lib/wasi-tests/wasitests/fd_close.out index c42fc06c2..53c9c2727 100644 --- a/lib/wasi-tests/wasitests/fd_close.out +++ b/lib/wasi-tests/wasitests/fd_close.out @@ -1,2 +1,3 @@ +Successfully closed file! Successfully closed stderr! Successfully closed stdin! diff --git a/lib/wasi-tests/wasitests/fd_close.rs b/lib/wasi-tests/wasitests/fd_close.rs index 3d2104be6..e5cdaafd9 100644 --- a/lib/wasi-tests/wasitests/fd_close.rs +++ b/lib/wasi-tests/wasitests/fd_close.rs @@ -23,10 +23,18 @@ fn main() { #[cfg(target_os = "wasi")] { + let file_fd = file.as_raw_fd(); let stdout_fd = std::io::stdout().as_raw_fd(); let stderr_fd = std::io::stderr().as_raw_fd(); let stdin_fd = std::io::stdin().as_raw_fd(); + let result = unsafe { fd_close(file_fd) }; + if result == 0 { + println!("Successfully closed file!") + } else { + println!("Could not close file"); + } + let result = unsafe { fd_close(stderr_fd) }; if result == 0 { println!("Successfully closed stderr!") @@ -48,6 +56,7 @@ fn main() { } #[cfg(not(target_os = "wasi"))] { + println!("Successfully closed file!"); println!("Successfully closed stderr!"); println!("Successfully closed stdin!"); } diff --git a/lib/wasi-tests/wasitests/fd_close.wasm b/lib/wasi-tests/wasitests/fd_close.wasm index a40a1bfda1eda6d84e0eedb1399d17925b4cca86..5ace5206203c7385f622705c2503474978339113 100755 GIT binary patch delta 13792 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 delta 13827 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 z z{1DuDbb|1Pro`V5oy5$#`<)l0W1PaL>q^CUTe0J@sjvepjy*`f@yFkz-@4<|==aax zK25*Bew#(VSDiT0vw@MQf74{A6#HMnG55R0-uf#z`QJ%A^4$&eg=YFcCJn0ps*>KV z^JiXkw+N%70ol!TPenb=mM5S*xzm@ITvni^ZUF21x00nO@V@@XAWzM!^vnw^$aAjy z{^`7O3sCC}t)X6Jg2*V=s_OfH2dQmc9{SEG&ot!!6=zVJ;3l-bm+(yQph zIC`z6Q5IlAJyU;u7q>46{o5LTctxmN(RL~me!}*r9gxxmUJHZ zJ9KZ8WP^nlC(!r0KV00_`G))@%^=V4uStROfc(FbqFSR0hW{OSuf@C(cCo_f1`)Fnpe zF!%F8bnSMumRFJkiz+BJ+-dX~Xs8yapOjePCe}F< z%Q)_aVfCJ%H1`B!s0W^@SFf2vPyeHVSmPZpq(!ZsLF?)cWz{0%f*0DrFNPKg*NOwR z#>hxW6Z>n8$0I>^7PF(MD~vsna2vUnemFn-f+?`t*dGOdZnO*Z zFk)0lG6C2BU$z1>Fx-d7*c6?sQSODtPb#c6jzojYrl4X>Y5@rm_f44+p=?)FCC(Vy z0ur6~Kj4c{4k|`=3urAaD8}Fx;D=;mVhc!xTw_rS7#BVrR3%GMluEiLODTG2|9|}cxva_6iU0)H=BZM`#75q73fy1OFQKwr$qNs5g zo;c_Rp6dQ_umjpwku3hxGA2H#(ZnZC(K17@15Q^wKqBNbv{yOER%>Efifx=$+f1IRWOXz)n*^e9!ij;LQT+&;(>hoX$G zJ{U+k&h(MS4;Zicpm+5p9~=sUyNoY0pnt?yajFtc6no>0>`dtA=ozmn!cf~oobhBP zxL}xJWJ0fK2J>GzwLGD6L@eAo_#M(-gGVTAE6wSHGF~8}O^I?EoVoI=8hca3pcfAcS0Fc}K|6 z3kj@IH=X_^(7#ZhQM5+=cJ$nMoMVVXp|HATCm8FA&PY?0fz